程序员老鬼

很讨厌狮子大开口候选人收到候选人一份简历,目前13k*13薪 要求年包30+,70%涨幅 。。

给我看乐了。

HR收到一份简历,候选人现在大概一年十来万出头,结果开口就要年包30万以上,差不多涨七成。发帖的人直接破防:你要这么多,那就在原公司好好待着,别出来折腾了。

Image

但这事吧,也挺职场的。公司当然希望人便宜点,最好经验满格、工资别涨太狠;候选人出来面试,也不是出来做公益的。谁都想往上够一够,这没啥丢人的。

离谱的点可能不是“要高薪”,而是你得拿得出能匹配的钱。你真有硬东西,能扛项目、能解决问题,开高点也正常。要是简历平平,面试一聊也没啥亮点,上来就报个狠价,那确实容易把人整沉默。

今日面试题

输入是 "  the   sky is blue  ",结果不是把整个字符串倒过来,而是要变成 "blue is sky the"。

这题第一眼很容易写歪。

我见过不少人上来就 split(" "),然后再倒序拼接。样例当然能过,但一遇到连续空格,就开始多出一堆空字符串。再加上首尾空格,代码里全是各种 if (!word.equals("")),看着就不太舒服。

这类字符串题,我一般先不急着调库,先把规则拆开:

原字符串里的单词顺序要反过来;

单词里面的字符顺序不能动;

多余空格要干掉;

最终单词之间只保留一个空格。

也就是说,真正要处理的不是“翻转字符串”,而是“从右往左把一个个单词捞出来”。

比如这个字符串:

"  hello   java  world "

从右边开始扫,先拿到 world,再拿到 java,最后拿到 hello。

这样写的好处是,不需要先清洗字符串,也不需要额外存一个单词数组。扫到空格就跳过,扫到单词就截出来拼上。

代码我会这么写:

publicclassReverseWords{

public String reverseWords(String text){
if (text == null || text.length() == 0) {
return"";
        }

        StringBuilder ans = new StringBuilder();
int p = text.length() - 1;

while (p >= 0) {
while (p >= 0 && text.charAt(p) == ' ') {
                p--;
            }

if (p < 0) {
break;
            }

int tail = p;

while (p >= 0 && text.charAt(p) != ' ') {
                p--;
            }

if (ans.length() > 0) {
                ans.append(' ');
            }

            ans.append(text, p + 1, tail + 1);
        }

return ans.toString();
    }
}

这段代码最关键的地方,其实就两个指针位置。

p 负责从右往左扫。

当它遇到空格时,直接跳过去。因为题目不关心原来有几个空格,首尾空格也没价值。

当它遇到非空格时,说明一个单词的尾巴找到了:

int tail = p;

然后继续往左扫,直到扫到空格,单词的范围就出来了:

text[p + 1, tail + 1)

这里要注意 Java 的 StringBuilder.append(CharSequence s, int start, int end),右边界是不包含的。所以 tail + 1 不能少。

我写这题时最不喜欢的一种代码是这样的:

String[] arr = s.trim().split("\\s+");

不是说不能用,业务代码里这么写挺正常。但算法题里,它把两个动作都藏起来了:去空格、识别单词。面试官真要追问空间复杂度,或者让你不用正则,马上就得重写。

手动扫描虽然土一点,但边界清楚。

看几个输入:

"the sky is blue"      -> "blue is sky the"
"  hello world  "      -> "world hello"
"a good   example"     -> "example good a"
"     "                -> ""

最后这个全空格的情况,很多代码会漏。上面的写法里,第一轮跳空格后 p < 0,直接 break,返回空字符串,不需要额外补丁。

时间复杂度是 O(n),每个字符最多被扫一遍。

空间上除了结果字符串,没有再维护单词数组。严格讲 Java 里结果本身肯定要占空间,这个躲不掉。

这题不要往复杂了想。它考的不是翻转技巧,而是你能不能把“多空格 + 倒序单词 + 边界处理”这几个脏活处理干净。代码不长,但写得稳不稳,一眼就能看出来。