程序员老鬼

某大厂程序员:高中同学聚会,混的最好就俩人。我,大厂3-1,年薪百万;另一个老家省厅副处级,能平起平坐么?

这哥们是不是在大厂待久了,真把职级当官阶了。

高中同学聚会,聊谁混得好很正常,吹两句工资也没啥。年薪百万,3-1,放在打工人里确实不差,已经能让一桌人多夹两筷子菜了。

但你非要拿这个去跟省厅副处比“平起平坐”,味儿一下就不对了。

Image

大厂再高,本质还是公司里的螺丝钉,只是这颗螺丝钉镀了点金。今天项目好,股票好,绩效好,你风光;明天组织一调整,老板换个口味,工牌都可能凉半截。

副处那边不是工资单好不好看的问题,人家是在体制内爬出来的位子,资源、稳定性、圈层,根本不是一个赛道。

所以网友怼得也狠:谁给你的勇气?真觉得“年薪百万”这四个字一摆,啥桌都能坐上主位。

今日面试题

反转字符串,别上来就 new 一个新字符串

["h","e","l","l","o"] 要变成 ["o","l","l","e","h"]。

这个题第一眼很简单,简单到不少人会直接写:

StringBuilder sb = new StringBuilder(str);
return sb.reverse().toString();

写业务代码这么干没啥问题,赶工的时候我也不会嫌弃它。

但算法题不一样。题目要你反转的是字符数组,而且通常会强调:原地修改,不要额外开数组。

这时候再 new 一个对象,就有点不讲武德了。

这题我一般就看两件事:

第一,能不能想到左右指针。

第二,边界会不会写乱。

代码就几行:

classSolution{
publicvoidreverseString(char[] text){
if (text == null || text.length < 2) {
return;
        }

int left = 0;
int right = text.length - 1;

while (left < right) {
char tmp = text[left];
            text[left] = text[right];
            text[right] = tmp;

            left++;
            right--;
        }
    }
}

这段代码没什么花活。

left 从左边走,right 从右边走,两边字符交换。交换完之后,左指针右移,右指针左移。直到两个指针碰头,或者交错,就停。

拿 "hello" 跑一下:

h e l l o
^       ^
o e l l h

o e l l h
  ^   ^
o l l e h

中间那个 l 不用管,长度是奇数的时候,它本来就在最终位置上。

有些人这里会写成:

while (left <= right)

这个我不太喜欢。

不是说一定错,奇数长度时中间字符自己跟自己交换一次,结果也对。但没必要。算法题里多做一次无意义操作,虽然不至于超时,但习惯不好。你写多了,后面碰到链表、数组窗口这种题,很容易把边界搞炸。

再看空数组和单字符:

char[] a = {};
char[] b = {'x'};

这两种直接 return。即使不写前面的判断,right = length - 1 后,循环也不会进去。但我一般还是留着这句:

if (text == null || text.length < 2) return;

原因很简单,业务代码里传 null 太常见了。算法平台可能不传,线上接口可不一定。

这个题真正要记住的不是“反转字符串”这几个字,而是这个交换模型:

while (left < right) {
    swap(left, right);
    left++;
    right--;
}

数组反转、回文判断、旋转数组的一部分,都会反复用到它。

比如判断一个字符数组是不是回文,只是把“交换”换成“比较”:

booleancheckPalindrome(char[] text){
if (text == null) {
returnfalse;
    }

int left = 0;
int right = text.length - 1;

while (left < right) {
if (text[left] != text[right]) {
returnfalse;
        }
        left++;
        right--;
    }
returntrue;
}

这个题不用递归。

递归当然能写,但没必要。每递归一层都要压栈,字符串长一点就不划算。面试里写递归版,除非题目明确要求,否则我会觉得你在把简单题复杂化。

反转字符串这题,能用两个指针原地交换写干净,就够了。边界别抖,别额外开数组,别为了炫技把代码绕远。真正线上排问题的时候,最怕的就是这种本来三行能看懂的逻辑,被写成一坨“很聪明”的代码。