Python技术迷

奉劝所有成年人,一旦失业,千万不要轻易对外透露自己没有工作。

刚刷到这个帖子,我第一反应是:这话有点扎心,但真不是没道理。

成年人失业这事,最难受的地方不是没班上,而是你一说出口,味儿就变了。

你跟朋友讲,原本只是想喘口气,结果人家转头就当八卦讲。你跟亲戚说,本来想着有人能理解一下,结果饭桌上就开始了:“他最近是不是不太行啊?”“是不是能力不够?”听着都窒息。

Image

当然,也不是所有人都坏。确实有人会安慰你,帮你看机会,真心拉你一把。但这种人太少了,更多人只是嘴上关心,心里看戏。

所以失业这段时间,能低调就低调。简历照投,面试照跑,日子照过。别到处解释自己怎么了,也别急着证明自己不是废了。

打工人有时候不是怕苦,是怕自己最狼狈的时候,被别人拿去当谈资

今日算法题

输入是 "  user   login  failed  ",输出不是 "  failed  login   user",而是:

"failed login user"

这个题最容易写歪的地方不是翻转,是空格。

我见过不少代码第一眼就上来 split(" "),这地方我一般不太信。因为普通空格切出来会带一堆空字符串,后面还得补过滤逻辑,代码越补越脏。

比如这样:

s = "  user   login  failed  "
print(s.split(" "))

结果是:

['', '', 'user', '', '', 'login', '', 'failed', '', '']

这就不是在做算法了,这是在给自己挖坑。

这题真正要处理的就三个点:

字符串前后可能有空格;

单词中间可能有多个空格;

结果里单词之间只能保留一个空格。

如果只是面试刷题,Python 当然可以一行写完:

defreverse_words(s: str) -> str:
return" ".join(reversed(s.split()))

s.split() 不传参数时,会自动按任意连续空白切分,并且丢掉前后的空白。这个写法很干净,线上小工具我也会这么写。

但算法题一般不太会让你这么舒服。面试官多半会追一句:不用内置切分呢?

那就老老实实扫字符串。

我的习惯是从右往左扫。因为题目要把单词顺序反过来,从右边开始找单词,找到一个塞一个,思路不绕。

defreverse_words(s: str) -> str:
    words = []
    right = len(s) - 1

while right >= 0:
# 先跳过右侧空格
while right >= 0and s[right] == " ":
            right -= 1

if right < 0:
break

# 此时 right 指向一个单词的最后一个字符
        left = right
while left >= 0and s[left] != " ":
            left -= 1

        words.append(s[left + 1:right + 1])

# 下一轮从当前单词左边继续找
        right = left - 1

return" ".join(words)

拿几个边界数据跑一下:

cases = [
"the sky is blue",
"  user   login  failed  ",
"single",
"     ",
"a good   example"
]

for text in cases:
    print(f"[{text}] -> [{reverse_words(text)}]")

输出:

[the sky is blue] -> [blue is sky the]
[  user   login  failed  ] -> [failed login user]
[single] -> [single]
[     ] -> []
[a good   example] -> [example good a]

这里有个细节,left 最后会停在空格位置,或者 -1。所以截单词时必须是:

s[left + 1:right + 1]

这地方少写一个 +1,单词前面就会混进空格;right + 1 忘了,最后一个字符又会丢。字符串切片这种 bug 不报错,但结果就是不对,挺烦。

复杂度也没啥花活。每个字符最多被扫一遍,时间复杂度 O(n)。额外用了一个 words 数组存结果,空间复杂度 O(n)。

这题别背模板,记住排查顺序就行:先把空格处理干净,再谈翻转。空格没处理对,后面写得再漂亮也白搭。