被公司辞退了,领到了22万补偿金。结果准备入职下一家公司时,原公司HR电话叫我回去,涨薪7000,但要把赔偿金还回去
刚看到个贴子,说楼主被公司辞退拿了22万补偿,结果准备入职下一家公司时,原公司突然又喊他回去,直接给涨薪7000,但条件是——把补偿金还回去。
这本质上就是典型的“用脚投票后,原公司才开始珍惜人”。
企业在你被辞退那一刻就已经做了选择,现在突然回头,是因为发现缺人、用人成本更高,不是因为突然良心发现。
换个角度讲,补偿金是合法合规给的,属于对你离开的补偿,现在让你退回去,说白了就是想两头占便宜。
7000涨薪看着心动,但真正的安全感不是涨一次,而是公司态度能不能稳定。
找工作看长期,别被一时的“回头是岸”晃了眼。做决定的时候,多为自己的职业稳定性想一想,心态稳了,路才走得更稳。【备注:文末可领最新资料】
面试题:两个字符串的删除操作
给你两个字符串 word1 和 word2,你每次操作只能“删掉一个字符”(可以删 word1 里的,也可以删 word2 里的),问最少要删几次,才能让两个字符串变成“完全一样”。
你可以想象有两个名字: 比如 sea 和 eat。
如果想让它们变一样,有很多做法:
从 sea删掉s,变成ea从 eat删掉t,也变成ea
一共删了 2 次,就搞定了,那答案就是 2。
本质上其实就是:通过删字符,把俩串“对齐”成同一个串,删得越少越好。
有个特别好用的思路: 与其想着“删谁”,不如先想:这两个字符串里,能保留的“共同骨架”最多有多长?
这个“共同骨架”,就是两串的 最长公共子序列(LCS),注意是子序列,不要求连续,只要相对顺序不变就行。
比如 sea 和 eat:
它们的最长公共子序列是 ea,长度是 2。
那有啥用呢?
如果最长能保留的共同部分长度是 L, 那剩下的都得删掉:
word1里除了这L个共同字符,剩下len(word1) - L个,都得删word2里同理,删len(word2) - L个
所以总删除次数:
minDelete = (len(word1) - L) + (len(word2) - L)
= len(word1) + len(word2) - 2 * L
所以整个题目就变成一句话:先求出两个字符串的 LCS 长度,再套上面这个公式。
用动态规划求 LCS(Python 实战)
老朋友 DP 出场。 我们搞一个二维数组 dp,定义是:
dp[i][j] = word1 前 i 个字符 和 word2 前 j 个字符 的最长公共子序列长度
注意这里前 i 个,是指子串 word1[:i],下标是从 1 开始算长度,对应字符串下标 i-1。
状态转移分两种情况:
如果当前最后一个字符相等:
word1[i-1] == word2[j-1]那这俩字符可以一起加进公共子序列里:dp[i][j] = dp[i-1][j-1] + 1如果不相等,那就只能“丢掉一个看”:
不是丢字符串里的字符,而是让其中一个“不参与”当前匹配 所以: dp[i][j] = max(dp[i-1][j], dp[i][j-1])
边界:只要有一个前缀长度是 0,那 LCS 长度肯定是 0,所以初始化整行整列为 0 就行(Python 默认就是 0)。
上代码:
defminDistance(word1: str, word2: str) -> int:
m, n = len(word1), len(word2)
# dp[i][j] 表示 word1[:i] 和 word2[:j] 的最长公共子序列长度
dp = [[0] * (n + 1) for _ in range(m + 1)]
for i in range(1, m + 1):
for j in range(1, n + 1):
if word1[i - 1] == word2[j - 1]:
# 当前字符相等,可以一起加入公共子序列
dp[i][j] = dp[i - 1][j - 1] + 1
else:
# 不相等,只能各自少看一个,取更优的那种
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
lcs = dp[m][n]
# 根据公式:总删除次数 = m + n - 2 * LCS
return m + n - 2 * lcs
随手测两下:
print(minDistance("sea", "eat")) # 2
print(minDistance("leetcode", "etco")) # 4
这就是 LeetCode 那道“两个字符串的删除操作”的标准写法之一。
时间复杂度是 O(m * n),空间也是 O(m * n),m 和 n 分别是两个字符串的长度。
如果你特别在意内存,其实还能把 dp 优化成一维滚动数组,但面试 / 刷题一般这样写就够用了。
直接算“最少删除次数”的 DP 写法(备个第二思路)
顺带说一句,这题还可以不用 LCS,直接 DP 最少删除次数,也挺直观的,思路是:
dp[i][j] = 把 word1[:i] 和 word2[:j] 变成一样,所需的最少删除次数
然后:
如果 word1[i-1] == word2[j-1]:这俩字符保留就行,不用删dp[i][j] = dp[i-1][j-1]否则:要么删 word1[i-1],要么删word2[j-1]所以:dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + 1
边界:
dp[0][j] = j,因为 word1 为空,只能把 word2 前 j 个全删了dp[i][0] = i,反之亦然
代码长这样:
defminDistance_direct(word1: str, word2: str) -> int:
m, n = len(word1), len(word2)
dp = [[0] * (n + 1) for _ in range(m + 1)]
# 处理边界:一个为空串时,只能把另一个全删了
for i in range(1, m + 1):
dp[i][0] = i
for j in range(1, n + 1):
dp[0][j] = j
for i in range(1, m + 1):
for j in range(1, n + 1):
if word1[i - 1] == word2[j - 1]:
dp[i][j] = dp[i - 1][j - 1]
else:
# 删 word1[i-1] 或 删 word2[j-1],选更少的一边再 +1
dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + 1
return dp[m][n]
这个方法和 LCS 那个,结果是一样的,只是思路的切入点不同。
整道题你脑子里记三件事就够了:
操作只有“删字符”,目标是把两个字符串变成一样; 可以先找它俩的“共同骨架”(最长公共子序列 LCS),答案是 len1 + len2 - 2 * LCS;LCS / 直接删除次数,都能用二维 DP 搞定,时间复杂度 O(m * n)。
你如果刷题,用第一种 LCS 写法就很好记; 如果想锻炼 DP 建模能力,可以再自己推一遍“直接算最少删除次数”的那个版本,多练几次就顺手了。
-END-
我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html
虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB