组里新来的 00后,试用期工资8k,住家里没房贷。 昨天项目上线,全组人都在,6点01分他准时背着包走了。。。
刚看到个贴子,说组里来个00后,新人试用期8k住家里,项目上线当天,活干完六点一到就背包走人,老同事一问,人家回一句“活干完不走留着过年?”楼主当场无语,心里有点酸。
网友回复也挺有意思,有的骂这小孩不讲团队精神,有的说准点下班天经地义,凭什么被道德绑架。
我觉得这事吧,关键不是00后多嚣张,而是我们这代人太习惯“多干就是好员工”了。说白了,合同写几点下班,就有权几点走,前提是把份内事做好。羡慕人家潇洒,不如学学人家的边界感:该干的认真干,额外的事要么给钱要么给时间。
当然,年轻人也别被“整顿职场”冲昏头,真本事、真价值才是底气。
算法题:相隔为 1 的编辑距离
有次产品跟我说,想做个「弱密码提示」,比如用户把密码从 abc123 改成 abc124,这俩其实只差了一个字符,他就想提示一句「你这新密码和旧密码几乎一样」。当时我脑子里蹦出来的就是——这不就是典型的「相隔为 1 的编辑距离」嘛。
所谓编辑距离,你可以简单理解成: 把字符串 A 变成字符串 B,最少要做几次「单字符的操作」。
操作一般就三种:
插入一个字符: ab→acb删除一个字符: acb→ab替换一个字符: abc→adc
题目里的「相隔为 1 的编辑距离」,意思是: 只允许做 一次 操作,就能把一个串变成另一个串。多一次少一次都不行。
举几个例子你感受下:
"abc"和"abx":改c -> x,一次替换 ✅"abc"和"abxc":插入x,一次插入 ✅"abc"和"ac":删掉b,一次删除 ✅"abc"和"abc":不用改,编辑距离是 0 ❌(我们要的是恰好 1)"abc"和"axyd":至少 2 步 ❌
这种题蛮适合「按长度分类」来想:
两个字符串长度差大于 1 比如
abc和a、abc和abcde这种, 不管你怎么插删改,一次肯定够不到,直接返回False就行。长度刚好相等 这种场景下,只能通过「替换」来实现一次编辑。 那就一位一位对比,数一下有几个位置不同:
如果不同的位置 刚好 1 个 → 编辑距离是 1 ✅ 如果是 0 个(完全一样)或者大于 1 个 → 不是 1 ❌
长度相差正好 1 这个是重点,也是最容易写错的地方。 比如 abc 和 abxc、abc 和 bc、abc 和 abcd 这种。
这里你可以这么想:
还得注意一个小细节: 如果一路对比都没遇到不一样的字符,但长度差 1,比如:
abc和ab这种情况其实也是编辑距离 1——在短串尾部插入/删掉一个字符就行。
你只能「跳过」长串的当前这个字符一次 超过一次不对齐,就说明至少要 2 次编辑了
一定是「长的那个串」做了一次插入/删除
换个角度看:用两个指针,从头往后扫,如果遇到不一样的字符:
Python 版本一:直接按长度分类写
先写个清爽一点的版本,逻辑展开写清楚:
defis_one_edit_distance(s: str, t: str) -> bool:
# 保证 s 是较短的那个,省得分情况写两遍
if len(s) > len(t):
s, t = t, s
len_s, len_t = len(s), len(t)
# 长度差大于 1,肯定不是
if len_t - len_s > 1:
returnFalse
# 情况一:长度相等,只能通过“替换”
if len_s == len_t:
diff_cnt = 0
for ch1, ch2 in zip(s, t):
if ch1 != ch2:
diff_cnt += 1
if diff_cnt > 1:
returnFalse
# 必须刚好一个不同,0 个不同说明距离是 0
return diff_cnt == 1
# 情况二:长度相差 1,只能“插入/删除”
i = j = 0# i 指向短串 s,j 指向长串 t
found_diff = False
while i < len_s and j < len_t:
if s[i] == t[j]:
i += 1
j += 1
else:
# 第一次遇到不一样的字符,可以“跳过”长串当前字符
if found_diff:
# 已经跳过过一次了,再遇到不对齐就说明 > 1 次编辑
returnFalse
found_diff = True
j += 1# 相当于在短串位置插入/删除了一个字符
# 如果循环结束还没发现不一样的,那就是短串是长串的前缀,
# 比如 s = "ab", t = "abc",这种情况编辑距离也是 1
returnTrue
这个函数做的事就是: 判断 s 和 t 的编辑距离是不是 恰好等于 1,是就返回 True,否则 False。
时间复杂度是 O(n),空间 O(1),面试官一般也就要这个水平。
Python 版本二:写一个简单的测试
写完函数最好自己跑几组对比一下,不然很容易在边界条件栽跟头:
deftest_is_one_edit_distance():
cases = [
("abc", "abx", True), # 替换一个
("abc", "abc", False), # 距离 0
("ab", "cab", True), # 在前面插入
("ab", "acb", True), # 中间插入
("ab", "a", True), # 删除一个
("", "a", True), # 空串和单字符
("", "", False), # 两个空串,距离 0
("abc", "axyd", False), # 至少两次编辑
("abc", "abcd", True), # 尾部插入
("abc", "abxyz", False), # 长度差>1
]
for s, t, expected in cases:
got = is_one_edit_distance(s, t)
print(s, t, got, "OK"if got == expected else"FAIL")
if __name__ == "__main__":
test_is_one_edit_distance()
你真跑一遍,大概率就能对这题的所有坑有感觉了:
完全相等要排除 长度差必须 ≤ 1 相差 1 的时候要好好处理「光是尾巴不同」这种情况
这些如果不写测试,很容易漏一个。
顺便说一句实际用法
像开头说的那种「新旧密码太像了」的需求,基本就是:
ifnot is_one_edit_distance(old_pwd, new_pwd) and old_pwd != new_pwd:
# 两次差别比较大,可以放行
...
else:
# 太像了,给个提示
...
或者在拼音纠错、搜索联想、简单的拼写检查里,也经常会用到「编辑距离 = 1」这个判断, 完整的编辑距离用动态规划会复杂不少,这种「只关心等不等于 1」的场景,就用上面这个 O(n) 的小函数,够用还省事。
行,差不多就这样,你可以先把这段代码抄过去跑一跑,看下是不是符合你心里对这道题的预期。
-END-
我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html
虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB