Python技术迷

年薪90万,税后到手也就68万,天天加班到凌晨一点,回家还被老婆数落:你这是拿命换钱,值当吗?

刚看到个贴子,说有哥们年薪90万,税后到手68万,天天加班到凌晨一点,回家还被老婆说“拿命换钱不值”,一年到头竟然只存20万出头。

Image

网友回帖我看了,有的说赶紧辞职保命要紧,有的说装什么穷,一年存20万不少了。怎么说呢,我觉得关键不是钱多钱少,而是这家人谁都没搞清:我到底在为谁拼、拼到什么程度算够。

天天干到一点,人身体总要还债的;老婆一个人管全家的开销和情绪,也迟早会爆炸。与其吵“值不值”,不如夫妻俩把账摊开算一算:房贷、父母、孩子、自己想要的生活,各自排个优先级,再决定是换工作、降杠杆,还是干脆休整一段。

钱重要,但命更重要,关系也重要。能一起算账、一起扛事的家庭,比任何年薪数字都更抗风险。

力

算法题:自定义字符串排序

昨天加班到快十一点,在公司楼下便利店买水的时候,隔壁组一个小伙子跟我吐槽:“东哥,Python 排序都写麻了,结果被一个‘自定义字符串排序’干懵了……” 我一听,这不就是典型面试题嘛,正好拿来跟你们唠一唠。

给你两个字符串:

  • order:排序规则,比如 "cba"
  • s:随便乱放的字符串,比如 "abcd"

要求把 s 重新排个序,让它尽量按照 order 的顺序来排。 举个具体的:

  • order = "cba"
  • s = "abcd"

那结果应该是:"cbad"

因为在 order 里,c 在最前,然后是 b,然后是 a,d 在规则里没出现,就随便丢后面就行,一般默认扔到最后,保持原来的相对顺序也可以。

我当时在便利店就跟他说,你既然用 Python,那就别跟排序硬刚,用好人家给的现成轮子就行。

思路很简单:

  1. 先把 order 变成一个“优先级表”,类似:{'c': 0, 'b': 1, 'a': 2}
  2. 排序 s 的时候,根据这个优先级表给每个字符一个“权重”
  3. 不在 order 里的,就给个很大的权重,让它们自动排在最后

代码直接上:

defcustom_sort_string(order: str, s: str) -> str:
# 1. 规则字符串里的每个字符,给一个优先级,数字越小越靠前
    rank = {ch: i for i, ch in enumerate(order)}

# 2. 用 sorted 排 s,key 决定排序依据
#    不在 rank 里的字符,用 len(order) 当默认优先级,自动排到后面
defsort_key(ch: str) -> int:
return rank.get(ch, len(order))

    sorted_chars = sorted(s, key=sort_key)
return"".join(sorted_chars)


if __name__ == "__main__":
    print(custom_sort_string("cba", "abcd"))  # cbad

你看,逻辑其实就一句话:“根据我自己定义的优先级排序”,剩下都交给 sorted 这个内置函数干。

时间复杂度呢,也别背公式,按套路来:

  • 建 rank 表:扫一遍 order,O(len(order))
  • 排序:sorted 是快排/TimSort 这一类,复杂度差不多 O(n log n),这里的 n = len(s)
  • 所以整体就是:O(len(order) + len(s) log len(s))

一般面试说到这就够了,正常业务场景也完全能打。

但是有时候面试官爱较真,会问一句:“能不能更快,不用排序?” 那咱就再较真一下。

想象一下,这题的本质是:按 order 规定的顺序,把 s 里的字符分组拼起来。

那我干嘛非要“比较大小”呢?我可以直接数啊:

  1. 先统计 s 里面每个字符出现了几次
  2. 按 order 的顺序,把这些字符按次数拼出来
  3. 最后再把那些不在 order 里的字符,原样补上

用 Python 写出来是这样:

from collections import Counter

defcustom_sort_string_fast(order: str, s: str) -> str:
# 1. 统计 s 每个字符的出现次数
    cnt = Counter(s)

    res = []

# 2. 先按照 order 的顺序,把在规则里的字符拼完
for ch in order:
if ch in cnt:
            res.append(ch * cnt[ch])
del cnt[ch]  # 用完就删,后面剩的就是“不在 order 里的”

# 3. 把剩下那些没有规则的字符,随便追加上去
for ch, c in cnt.items():
        res.append(ch * c)

return"".join(res)


if __name__ == "__main__":
    print(custom_sort_string_fast("cba", "abcd"))  # cbad

这个版本的时间复杂度就很好看了:

  • 统计次数:扫一遍 s,O(len(s))
  • 按 order 拼接:O(len(order))
  • 拼剩下的:最多再扫一次字符种类数,通常远小于 len(s)
  • 总体可以看成:O(len(s) + len(order)),没有排序那一层 log n 了

面试官要是问你“为什么更快”,你就一句话:“前面那个是基于比较的排序,这个是计数型的,直接用次数+规则拼接”,就显得挺有数。

-END-

我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html

🔥虎哥私藏精品🔥

虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB