部门裁掉了两个后端程序员,月薪都是2.5万,然后把俩人的活儿全甩给我,一个不落,结果我工资一分没涨
最近刷到一篇帖子,有位兄弟在网上吐槽:他们部门裁掉了两个后端程序员,月薪都是2.5万,然后把俩人的活儿全甩给他,一个不落,结果工资一分没涨💀。
评论区网友笑嘻嘻地说:“很好,以后你就是后端负责人了。”我看完只想回一句:负责人不等于负薪人啊。
我觉得这事要搁我身上,我先得问清楚:我是临时接锅还是永久接盘?临时的,那还行,啃两个月扛一下也不是不能忍;要是长期干,麻烦你HR先来谈个涨薪方案,别拿感情当工资发啊。
程序员也不是CPU,双核干四核的活儿还能不烧机?更何况这不是优化,而是压榨。
最烦的就是公司一边砍人,一边说“团队更精干了”,其实就是省钱方式变高级了。你说我该咋办?我建议是:先干活别怂,私下更新简历,没准下个岗位,真能给你配俩实习生当助理。【备注:文末可领最新资料】
算法题:给表达式添加运算符
“给表达式添加运算符”这道题,第一次看到的时候,我还以为是考小学数学四则运算,结果仔细一看,哦豁,是 LeetCode 上那个著名的回溯题。
题目大概意思是这样的:
给你一个只包含数字的字符串,比如 "123",你要在它中间添加 +、-、* 三种运算符(注意不能改变原有的顺序,也不能加括号),让它变成一个合法的数学表达式,最终的结果等于给定的 target。
听起来是不是有点像在编一个小计算器,还是带自动匹配功能的那种?
这题我一开始是想着用暴力法硬刚的——把所有可能的符号组合全部生成出来,再一个个算,看看哪几个能凑出结果。但脑子冷静下来之后,我就知道,这是妥妥的回溯题型,直接暴力会被测试用例教做人。
下面是我写的一个回溯解法代码框架,Java实现,非常直接👇
public List<String> addOperators(String num, int target) {
List<String> result = newArrayList<>();
dfs(num, target, 0, 0, 0, "", result);
return result;
}
privatevoiddfs(String num, int target, int index, long calc, long prevOperand, String path, List<String> result) {
if (index == num.length()) {
if (calc == target) {
result.add(path);
}
return;
}
for (inti= index; i < num.length(); i++) {
// 防止前导零,例如 "05" 这种情况是不合法的
if (i != index && num.charAt(index) == '0') break;
StringcurrentStr= num.substring(index, i + 1);
longcurrent= Long.parseLong(currentStr);
if (index == 0) {
// 第一个数,直接加入
dfs(num, target, i + 1, current, current, currentStr, result);
} else {
// 加法
dfs(num, target, i + 1, calc + current, current, path + "+" + currentStr, result);
// 减法
dfs(num, target, i + 1, calc - current, -current, path + "-" + currentStr, result);
// 乘法,需要回退之前的值再乘
dfs(num, target, i + 1, calc - prevOperand + prevOperand * current, prevOperand * current, path + "*" + currentStr, result);
}
}
}思路讲一下哈,不然你光看代码跟看🀄一样:
1. index是我们当前走到字符串的哪一位。2. calc是我们目前计算出来的值。3. prevOperand是我们上一个操作符作用的数,这个在处理*的时候用到,确保我们能把2+3*4这种表达式算对(因为要先把上一个数撤销再乘)。4. 字符串 path是我们当前拼接出来的表达式。
乘法这里是个坑点,比如表达式是 "2+3*4",你如果直接算成 (2+3)*4=20 就挂了,应该是 2+(3*4)=14,所以得回滚之前的加法,再加上乘法结果,这就是:
calc - prevOperand + (prevOperand * current)我刚学算法那会儿,这种“先撤销、再加回来”的操作总让我感觉像在写 bug 修复日志:
昨天加的逻辑今天看是错的,先撤销;然后再补上今天的版本。
再说个特别容易踩的坑:前导零。
比如字符串 "105",如果你生成出 "1+05",抱歉,这是不合法的,因为 "05" 本身就不该存在。这个时候我们就得跳过所有以 0 开头、长度大于1的组合,这就是:
if (i != index && num.charAt(index) == '0') break;有一次我忘了写这句,调试了半天,输出一堆奇奇怪怪的表达式,最后才发现是被前导零给坑了😂。
至于回溯的剪枝优化嘛……这题其实不太好剪,因为所有的组合都得尝试一遍,万一你漏了一个刚好是答案的组合,那就没救了。所以这个题,基本属于暴力搜索界的“最优化暴力”。
最后,大家刷这类题的关键,其实是练对“状态”这件事。每个函数参数就是一个“状态”,你得明确你传进去的每个参数分别在维护什么信息。
不然你状态乱了,不仅结果错,debug 也抓狂。
总结一下,这道题很适合用来理解回溯算法中的路径构建+状态维护+边界处理,同时也能让你对运算符优先级和数值处理更敏感一些。就像我们平时改 bug 一样:你不能光看眼前,要想想你这个改动对上下文有啥影响,不然就是一行代码救活了功能,三天后炸了数据库。
谁还不是一边 debug 一边学会谨慎呢?👨💻
——写给还在算法题里摸爬滚打的程序员兄弟姐妹们
最后,我为大家打造了一份deepseek的入门到精通教程,完全免费:https://www.songshuhezi.com/deepseek
也可以看我写的这篇文章《DeepSeek满血复活,直接起飞!》来进行本地搭建。
-END-
以上,就是今天的分享了,看完文章记得右下角点赞,也欢迎在评论区写下你的留言。