靠AI作弊上岸字节的同学,被开了哈哈哈哈
有网友吐槽,说班里有个同学去年秋招进了字节,还是后端SP。当时大家都挺懵的,因为这人平时存在感很低,小组作业基本不咋出力,刷题记录也没多猛。结果面试一路过关,拿offer的时候全班还给他鼓掌,问经验的问经验,约饭的约饭。
结果一入职就露馅了。
到岗没多久,写代码慢还算小事,关键是一些很基础的问题也卡半天。mentor让改个小bug,半天憋不出来,组里估计也不是傻子,很快就发现不对劲。后来才传出来,他面试时大概率靠AI辅助“表演”过关。
大厂不是考试,进去以后每天都要交东西。你简历能包装,回答能背,AI能帮你糊弄几轮,但代码不会陪你演戏啊。HR看完都得沉默。
面试题:亲密字符串
两个字符串摆在那儿,ab 和 ba,一眼就知道能换一次变过去。
但 aa 和 aa 这种输入,很多人第一版代码会写错。因为题目说的是“交换两个位置上的字符”,不是“可以不交换”。如果字符串里有重复字符,交换两个相同字符,表面上看没变,但这次交换是成立的。
这个细节不盯住,提交基本会挂在这里。
题目叫“亲密字符串”,给两个字符串 s 和 goal,判断能不能只交换 s 中两个字符,让它变成 goal。
我一般不会上来就统计字符频率,这题没必要。先看差异位置,比堆一堆 map 清楚。
比如:
s = abcd
goal = abdc
只有两个位置不一样:
c != d
d != c
把这两个位置一换,正好能对上。
再看这个:
s = abcd
goal = badc
不一样的位置有 4 个。一次交换最多影响两个位置,直接判死刑,不用继续算。
代码可以这样写:
classSolution{
publicbooleanbuddyStrings(String s, String goal){
if (s == null || goal == null || s.length() != goal.length()) {
returnfalse;
}
int n = s.length();
if (s.equals(goal)) {
boolean[] seen = newboolean[256];
for (int i = 0; i < n; i++) {
char c = s.charAt(i);
if (seen[c]) {
returntrue;
}
seen[c] = true;
}
returnfalse;
}
int first = -1;
int second = -1;
for (int i = 0; i < n; i++) {
if (s.charAt(i) == goal.charAt(i)) {
continue;
}
if (first == -1) {
first = i;
} elseif (second == -1) {
second = i;
} else {
returnfalse;
}
}
if (second == -1) {
returnfalse;
}
return s.charAt(first) == goal.charAt(second)
&& s.charAt(second) == goal.charAt(first);
}
}
这里有两个分支要分开看。
第一种,s 和 goal 本来就相等。
这个时候别急着返回 true。比如:
s = ab
goal = ab
a 和 b 换一下就变成 ba,反而错了。所以它不是亲密字符串。
但这个可以:
s = aa
goal = aa
两个 a 交换一下,结果还是 aa,这才算。
所以相等时,只需要判断字符串里有没有重复字符。
第二种,s 和 goal 不相等。
那就把所有不同的位置记下来。一次交换只能修复两个位置,所以不同位置必须刚好是两个。多了不行,少了也不行。
最后检查交叉关系:
s[first] == goal[second]
s[second] == goal[first]
这个判断比统计字符更贴近题目本身。
比如:
s = ab
goal = ba
first = 0,second = 1。
交叉一看:
s[0] == goal[1] -> a == a
s[1] == goal[0] -> b == b
成立。
这题的坑不在算法复杂度,复杂度就是 O(n),空间也很小。真正容易翻车的是把“交换一次”理解成“最多交换一次”。
这俩差得挺大。尤其是 ab / ab 和 aa / aa,一个 false,一个 true。写完代码别跑大样例,先拿这两个喂一下。