Python技术迷

很讨厌狮子大开口候选人收到候选人一份简历,目前13k*13薪 要求年包30+,70%涨幅~

刚刷到这个,真有点职场味了。

候选人现在13k,13薪,一年差不多17万。人家跳槽开口要30万+,听着是涨得猛,70%多,HR直接破防:你这狮子大开口,不如在原公司好好待着,别出来。

Image

但这事吧,也没必要上来就骂候选人。跳槽本来就是重新定价,嫌贵可以不聊,预算接不住就说接不住。最尴尬的是,一边想要别人经验、能力、稳定性都到位,一边又希望人家按原价打包过来。

候选人报价高,不代表他一定值;公司给不起,也不丢人。丢人的是把市场谈判说成道德问题,好像人家多要钱就是犯错了。打工人出来面试,不就是为了涨点钱吗,不然图啥,图换个地方继续受气啊。

今日算法题

字符串里混着几个数字,要求把数字替换成 number。

这题第一眼很容易写歪,尤其是 Python 里有人上来就想:

s = s.replace('0', 'number')
s = s.replace('1', 'number')
...

这种写法我一般不太信。不是不能过,是味道不对。你扫了 10 遍字符串,题目要考的也不是把 API 背熟,而是看你有没有意识到:字符串一旦开始频繁改,就别原地折腾了,重新拼一份更稳。

题目大概是这样:输入一个字符串,只包含小写字母和数字。碰到数字,就替换成字符串 number;碰到字母,原样保留。

比如:

输入:
a1b2c3

输出:
anumberbnumbercnumber

再来一个:

输入:
abc

输出:
abc

没有数字就不动,这个也别漏。很多人写的时候只盯着替换场景,结果边界输入一来,代码反而显得慌。

这题在 Python 里,我会这么写:

defpatch_digits(raw: str) -> str:
    parts = []

for ch in raw:
if'0' <= ch <= '9':
            parts.append("number")
else:
            parts.append(ch)

return''.join(parts)


if __name__ == "__main__":
    line = input().strip()
    print(patch_digits(line))

代码没什么花活,就一件事:从左到右扫一遍。

这里我没用 ch.isdigit(),不是它不能用,而是线上处理脏数据的时候,我更习惯把判断条件写窄一点。isdigit() 在一些 Unicode 字符上也会返回 True,算法题一般没这坑,但写习惯了之后,边界会更清楚。

比如你只认普通数字字符,那就老老实实写:

'0' <= ch <= '9'

看着笨一点,但不会误伤。

这题的关键不在“替换”两个字,而在“别一边遍历一边改原字符串”。

Python 的字符串是不可变对象。你每次做拼接,背后都可能创建一个新的字符串。小数据看不出来,大一点就开始浪费。

比如这种写法:

ans = ""

for ch in raw:
if'0' <= ch <= '9':
        ans += "number"
else:
        ans += ch

能跑,但我一般不推荐。尤其是刷题时看起来简洁,实际复杂度容易被隐藏。循环里反复 +=,字符串越来越长,拷贝成本也跟着上来。

更稳的方式就是先用列表收集碎片,最后一次性 join。

parts.append("number")
parts.append(ch)
return''.join(parts)

这个写法在 Python 里很常见,也更像真实项目里处理日志字段、清洗文本、拼导出内容时的写法。

复杂度也比较直接。

字符串长度是 n,遍历一次,所以时间复杂度是 O(n)。

额外用了一个列表保存结果,替换后结果可能变长。最坏情况下,原字符串全是数字,比如:

12345

每个字符都变成 number,最终长度会变成原来的 6 倍左右,所以空间复杂度按结果长度算,也是 O(n) 级别。

这里有个小细节,别把“替换数字”理解成替换整个连续数字段。

比如:

a12b

按题意通常是每一个数字字符都替换成 number,所以结果是:

anumbernumberb

不是:

anumberb

这个地方如果没读清楚,很容易写成正则匹配连续数字:

# 这个不是本题要的效果
re.sub(r'\d+', 'number', raw)

正则当然能干活,但这题没必要。越简单的题,越别急着掏复杂工具。扫一遍,判断一个字符,放进结果列表,就够了。

最后这版代码我会直接交,不再加什么多余封装:

s = input().strip()

buf = []
for c in s:
if'0' <= c <= '9':
        buf.append("number")
else:
        buf.append(c)

print(''.join(buf))

这种题写到这里就可以停了。再讲一堆字符串底层实现,反而把一道干净的小题讲脏了。