48岁,被大厂一脚“优化”回家,结果网友一看:存款800万,社保交满20年,回县城吃利息,等60岁领退休金。评论区先酸了,这哪叫裁员,这叫提前下班。

我看这事,扎心就扎心在对比。普通人听到“被裁员”三个字,脑子里是房贷、孩子学费、下个月社保。到他这儿,变成了县城养老剧本。大厂这行就是这样,年轻时拿命换钱,真换到了,撤得比谁都快;没换到的,才是真的悬。
所以网友一边吐槽,一边又有点羡慕。嘴上说“太惨了”,心里想的估计是:这种裁员,什么时候轮到我。
当然,讨论归讨论,该刷的题还得刷。今天聊的这道面试题就挺有意思,题目叫“删除注释”。
代码跑得好好的,一提交就挂,很多时候不是算法没想明白,是字符串处理写得太想当然。
“删除注释”这题就有点这个味道。看题面像体力活:扫一遍代码,把 // 和 /* ... */ 干掉就完了。真写起来,最容易翻车的地方不是删,而是状态切换。尤其是块注释跨行的时候,上一行没收干净,下一行还得接着吞,脑子里如果没有这个状态,代码八成写乱。
这题我一般不搞花活,老老实实按字符扫,外面挂一个 inBlock 表示当前是不是在块注释里。 不在块注释里时,只看三种情况:
- 遇到
//,这一行后面直接不要了。
- 遇到
/*,进入块注释状态。
- 其他字符,正常塞进当前行缓冲区。
在块注释里就更简单,盯着 */,看见了再出来,别的都跳过。
Java 代码我会写成这样,短一点,逻辑也不绕:
class Solution {
public List<String> removeComments(String[] source) {
List<String> ans = new ArrayList<>();
boolean inBlock = false;
StringBuilder line = new StringBuilder();
for (String s : source) {
if (!inBlock) {
line.setLength(0);
}
for (int i = 0; i < s.length(); i++) {
if (inBlock) {
if (i + 1 < s.length() && s.charAt(i) == '*' && s.charAt(i + 1) == '/') {
inBlock = false;
i++;
}
} else {
if (i + 1 < s.length() && s.charAt(i) == '/' && s.charAt(i + 1) == '/') {
break;
} else if (i + 1 < s.length() && s.charAt(i) == '/' && s.charAt(i + 1) == '*') {
inBlock = true;
i++;
} else {
line.append(s.charAt(i));
}
}
}
if (!inBlock && line.length() > 0) {
ans.add(line.toString());
}
}
return ans;
}
}
这题有两个细节很容易漏。
一个是块注释可能把多行拼成一行。比如第一行注释前有内容,后面几行都是块注释,最后一行注释结束后还有内容,那这些内容其实要拼到同一个 StringBuilder 里。所以我的代码逻辑是:只有在“不处于块注释”并且一整行处理完之后,才决定要不要把这行塞进结果集。
另一个是空行别乱加。注释删完如果这一行啥也不剩,就别硬塞个空串进去,不然结果就脏了。
这题时间复杂度没什么悬念,就是把所有字符扫一遍,O(n)。难点纯粹在细节,尤其是 i + 1 越界、状态切换和跨行拼接。面试里这种题不算难,但特别适合看代码基本功。写得顺的人,状态会很稳;写得乱的人,通常会在 if-else 里绕半天,最后自己都不敢测。说到底,这类字符串处理问题考验的就是对算法细节和边界条件的把控能力。
|