Python技术迷

昨天review代码,看到一哥们用极其风骚的stream流配合各种lambda表达式,把原本需要十行代码的逻辑,硬压缩成一行

昨天review代码的时候看到个贴子,真是让我哭笑不得😂。有个同事非得秀操作,把一个本来十行能写清楚的逻辑,用stream加lambda硬怼成了一行,还在注释里得瑟写着“优雅”。

Image

说实话,这不是优雅,这是“自我加密”。代码写给人看的,不是写给编译器当谜语玩的。网友们也有人说短小精悍才显水平,但我更认同另一种声音:维护成本才是关键。今天你觉得自己潇洒,一个月后debug的时候,可能连你自己都想爆粗口。

职场上最怕的就是这种“聪明过头”的表现。写代码就像写文章,该分段要分段,该加注释要加注释。炫技能赢一时掌声,但清晰才是长期的优雅。毕竟工作不是炫技舞台,是团队协作。

能让后来人一眼懂的代码,才是真的牛。【备注:文末可领最新资料】

面试题:最大公约数遍历

“最大公约数遍历”这道题,说人话就是:给你一个数组,两个位置能连边当且仅当它们的数有公共质因子(gcd > 1)。问整张图是不是一整块,能不能“从某个点走到所有人”。要是数组里混进了 1……嗯,1 没有质因子,谁也连不上,除非数组就它一个人。

直接两两算 gcd 建图会炸(n²),不干这个。换个角度:谁跟谁能连,看“共同质因子”。那我把每个数分解成若干个质因子,把“因子”为节点的“中转站”,把拥有这个因子的下标全 union 到一起。最后看看所有下标是不是在同一个并查集集合里,OK 就 True。

分解怎么做?两种路子:

  • 小数据直接试除到 √x。
  • 大数据更稳的是先筛一遍最小质因子(SPF),然后 O(log x) 拆一个数。
from math import isqrt
from collections import defaultdict

classDSU:
def__init__(self, n):
        self.p = list(range(n))
        self.r = [0]*n
        self.cnt = n
deffind(self, x):
while self.p[x] != x:
            self.p[x] = self.p[self.p[x]]
            x = self.p[x]
return x
defunion(self, a, b):
        pa, pb = self.find(a), self.find(b)
if pa == pb: return
if self.r[pa] < self.r[pb]:
            pa, pb = pb, pa
        self.p[pb] = pa
if self.r[pa] == self.r[pb]:
            self.r[pa] += 1
        self.cnt -= 1

defbuild_spf(mx):
    spf = list(range(mx+1))
for i in range(2, isqrt(mx)+1):
if spf[i] == i:
            step = i
            start = i*i
for j in range(start, mx+1, step):
if spf[j] == j:
                    spf[j] = i
return spf

deffactors(x, spf):
    res = set()
while x > 1:
        p = spf[x]
        res.add(p)
while x % p == 0:
            x //= p
return res

defcan_traverse(nums):
    n = len(nums)
if n == 1: 
returnTrue
if any(x == 1for x in nums):  # 有 1 则一定断链
returnFalse

    mx = max(nums)
    spf = build_spf(mx)
    dsu = DSU(n)
    first_idx_of_prime = {}

for i, x in enumerate(nums):
        ps = factors(x, spf)
for p in ps:
if p in first_idx_of_prime:
                dsu.union(i, first_idx_of_prime[p])
else:
                first_idx_of_prime[p] = i

# 检查是否所有节点连通
    root0 = dsu.find(0)
return all(dsu.find(i) == root0 for i in range(n))

# 小测一把
if __name__ == "__main__":
    print(can_traverse([2,3,6]))        # True,2<->6, 3<->6
    print(can_traverse([3,9,5,10]))     # True,3<->9, 5<->10,且 9<->?<-10 经 5、10 与 3、9 也会并上
    print(can_traverse([1,2,3]))        # False,有 1
    print(can_traverse([4,9,25]))       # False,分别是 2²、3²、5²,互不相连

整体复杂度主要在分解上:预处理 SPF 是 O(M log log M),M 是数组最大值;之后每个数分解大概 O(log M),合并接近 O(α(n))。坑点就俩:一是出现 1 直接判 False(除非 n=1),二是分解时要去重质因子(同一质因子别重复 union)。其他倒是挺顺滑的。你把这套丢到线上题库,一般一把过,嗯就这样我去泡杯咖啡先。

-END-

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

🔥虎哥私藏精品🔥

虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB,点击下方公众号回复关键字 python 全部免费领