Python技术迷

女朋友失业半年了,前两天去ktv应聘服务员了,一天底薪800,有时候表现好5k多,但是我觉得她不爱我了,回来抱抱都不给了

兄弟你这重点是不是有点偏了。

女朋友失业半年,突然去KTV应聘服务员,说一天底薪800,表现好还能五千多。然后他纠结的是啥?回来不给抱了,觉得她不爱他了。

Image

哥们,打工人先不聊感情,就聊工资。什么服务员一天底薪800啊?这要是真的,多少人不得连夜改行。网友那句“谁家收银一天800,长点心吧”,虽然损,但真是说到点上了。

这事最离谱的地方,不是她不抱你,是你到现在还在用恋爱脑理解这份工作。你可以心疼她没工作,也可以担心她压力大,但别把明显不对劲的地方当看不见。

这哥们儿,先别问爱不爱了,先问清楚那800到底咋来的。

算法题:反转单词前缀

这题卡不在反转,卡在你什么时候停

word = "abcdefd",ch = "d"。

要返回什么?

不是把所有 d 前面的都乱翻,也不是见到最后一个 d 再动手,而是第一次遇到 d 的位置,把从开头到这个位置的前缀反过来。

所以结果是:

dcbaefd

这个题看着很小,但我见过有人一上来就写双指针,写着写着把后半段也卷进去了。还有人用 replace,这个就更离谱了,字符串题里 replace 一出现,我一般先怀疑方向跑偏了。

题目真正要处理的就一件事:找到第一个 ch。

找到之后,前缀反转,后缀原样拼回去。

Python 写这个题,最干净的是这样:

classSolution:
defreversePrefix(self, word: str, ch: str) -> str:
        cut = word.find(ch)

if cut == -1:
return word

        left = word[:cut + 1]
        right = word[cut + 1:]

return left[::-1] + right

这里我不会为了“显得算法味重”去硬写循环找下标。

find 返回的是第一次出现的位置,这一点正好贴着题意走。没找到就是 -1,直接原字符串返回。

这几个边界要看一下:

word = "abcd", ch = "z"   -> "abcd"
word = "abcd", ch = "a"   -> "abcd"
word = "abcd", ch = "d"   -> "dcba"
word = "a",    ch = "a"   -> "a"

第二个例子容易看漏。

ch 在第一个字符时,前缀其实只有一个字符,反转之后还是它自己,不需要特殊处理。代码里的 word[:cut + 1] 已经兜住了。

如果面试官不太喜欢你直接用 find,那就换成手写扫描。这个版本更像是在白板上写出来的:

classSolution:
defreversePrefix(self, word: str, ch: str) -> str:
        hit = -1

for i, c in enumerate(word):
if c == ch:
                hit = i
break

if hit < 0:
return word

        buf = list(word)

        l, r = 0, hit
while l < r:
            buf[l], buf[r] = buf[r], buf[l]
            l += 1
            r -= 1

return''.join(buf)

这个写法有个细节:我会先把字符串转成 list。

Python 的字符串不能原地改,你如果在循环里不停做字符串拼接,虽然这题数据量不大也能过,但习惯不好。真到日志清洗、字段脱敏那种脚本里,这种写法迟早拖慢。

这题复杂度也没什么花活。

找字符扫一遍,最坏 O(n)。

反转前缀最多再扫一遍,也是 O(n)。

如果用切片写法,代码短,但会产生新字符串;如果用列表双指针,空间也是 O(n),因为 Python 字符串不可变,这个空间基本省不掉。

我更倾向第一版。

不是因为它更“高级”,而是题意本来就简单。工程里写代码,能让下一眼看明白,就别把它写成谜语。这个题只要记住一句:只处理第一次命中的前缀,后面的字符别碰。