很讨厌狮子大开口候选人收到候选人一份简历,目前13k*13薪 要求年包30+,70%涨幅 。。
给我看乐了。
HR收到一份简历,候选人现在大概一年十来万出头,结果开口就要年包30万以上,差不多涨七成。发帖的人直接破防:你要这么多,那就在原公司好好待着,别出来折腾了。
但这事吧,也挺职场的。公司当然希望人便宜点,最好经验满格、工资别涨太狠;候选人出来面试,也不是出来做公益的。谁都想往上够一够,这没啥丢人的。
离谱的点可能不是“要高薪”,而是你得拿得出能匹配的钱。你真有硬东西,能扛项目、能解决问题,开高点也正常。要是简历平平,面试一聊也没啥亮点,上来就报个狠价,那确实容易把人整沉默。
输入是 " 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 里结果本身肯定要占空间,这个躲不掉。
这题不要往复杂了想。它考的不是翻转技巧,而是你能不能把“多空格 + 倒序单词 + 边界处理”这几个脏活处理干净。代码不长,但写得稳不稳,一眼就能看出来。