程序员老鬼

靠AI作弊上岸字节的同学,被开了哈哈哈哈

有网友吐槽,说班里有个同学去年秋招进了字节,还是后端SP。当时大家都挺懵的,因为这人平时存在感很低,小组作业基本不咋出力,刷题记录也没多猛。结果面试一路过关,拿offer的时候全班还给他鼓掌,问经验的问经验,约饭的约饭。

结果一入职就露馅了。

Image

到岗没多久,写代码慢还算小事,关键是一些很基础的问题也卡半天。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。写完代码别跑大样例,先拿这两个喂一下。