大厂员工:千辛万苦,终于考上公务员上岸了,实现了月薪从25000降到5000的飞跃。
月薪2万5的大厂人,硬是把自己卷成了月薪5000的公务员,这事听着像段子,细品又特别像现实。 你以为人家图工资?真不是。图的是别半夜开会,别周末背锅,别一边熬夜改PPT一边担心下轮优化名单里有自己。大厂给钱是真猛,榨人也是真不手软。
更狠的是上岸这路也不好走。白天上班像被拧干的毛巾,晚上还得刷题、背申论,周末别人睡懒觉,他在那儿掐表做行测,脑子都快刷出火星子了。评论区有人说这是“降薪避险”,也有人说“拿高薪那几年已经赚到了”。我看都对一半。
说白了,这不是工资跳水,这是拿现金流换稳定,拿情绪损耗换个能喘气的日子。钱是少了,命估计能多剩点。大厂工牌一摘,整个人没准都睡踏实了。
算法题:翻转游戏
一看到“翻转游戏”这种题,很多人第一反应是回溯、博弈、状态压缩全往上怼。先别急,这题如果只是基础版,其实没那么重。
题目通常是这样:给你一个只包含 + 和 - 的字符串,每次只能把连续两个 ++ 翻成 --,让你返回所有可能的一步结果。
这种题我一般先盯住一件事:到底是求“所有下一步状态”,还是求“先手能不能赢”。这俩长得像,写法差很多。要是题目只是要所有结果,那就别把自己绕进递归里。
先看最直接的处理方式,顺着字符串扫一遍,谁看到 ++,就把这一段替换成 --,然后收集结果。
defgenerate_moves(current_state: str) -> list[str]:
ans = []
for i in range(len(current_state) - 1):
if current_state[i] == '+'and current_state[i + 1] == '+':
next_state = current_state[:i] + '--' + current_state[i + 2:]
ans.append(next_state)
return ans
比如:
print(generate_moves("++++"))
# ['--++', '+--+', '++--']
这题没什么玄学,本质就是一次线性扫描,时间复杂度 O(n^2)。别一看到字符串拼接就慌,这里最多也就扫 n 次,每次生成一个新串,完全够用。
有些人喜欢先把字符串转列表,再原地改,写完再改回去。也能做,但这题我不太爱那样写。原因很简单:可读性不一定更好,回滚还容易写脏。
比如这样也行:
defgenerate_moves_v2(current_state: str) -> list[str]:
chars = list(current_state)
ans = []
for i in range(len(chars) - 1):
if chars[i] == chars[i + 1] == '+':
chars[i], chars[i + 1] = '-', '-'
ans.append(''.join(chars))
chars[i], chars[i + 1] = '+', '+'
return ans
这种写法更像现场排查时顺手改两位、看结果、再恢复原状。尤其后面如果题目升级成“翻很多次”“递归搜索胜负”,这个写法更顺手。
这题真正容易错的,不是思路,是边界。
比如输入是 "+",那肯定返回空。输入是 "+-++-",只能翻中间那一段,别把不连续的 + 也算进去。还有个低级坑,有人会写成 current_state[i:i+2] == '+',这种一眼就不对,切片长度都错了。
所以这题我觉得拿分点不在“会不会”,而在“别写拧巴”。先把题意分清,再决定是线性枚举,还是递归博弈。