Python技术迷

刚升小组长,下属比我年纪还大,怎么管?上个月刚被提成小组长,手下3个人,两个比我大3岁,一个还是老员工。

刚看到个贴子,说自己刚升小组长,带三个人,两个还比自己大,安排工作老感觉他们不太服,纠结是请吃饭还是先立规矩。

Image

我觉得这事吧,关键真不是年龄,而是你能不能在“角色”上站稳。你是小组长,就代表公司给了你这块牌子,你要做的是:把目标、分工、标准讲清楚,而不是先急着当好人。

规矩一定要有,但别上来就端着,可以用“商量式立规矩”——开个小会,先说团队要完成什么,再一起定流程和要求,让他们参与进去,比你单方面宣布好用多了。

请吃饭也能有,但不要带着“求人你们多多关照”的心态,而是边吃边聊各自擅长啥、以前怎么做,更像一场信息交流。网友有的让他硬刚,有的让他猛示好,我比较认同的是:软硬结合,业务上有担当,态度上懂尊重。

算法题:四数之和

昨天晚上十一点多,在公司楼下啃着一盒还凉着的麻辣烫,我在那儿刷题,手机一抬头,看到个老熟人:四数之和。心里一想:哎哟,这不就是两数之和、三数之和全家桶最后一个嘛。

大概意思就是: 给你一个整数数组 nums,再给你一个目标值 target,让你从数组里挑四个数出来,四个数的和等于 target,而且结果里不能有重复的四元组。

比如:

nums = [1, 0, -1, 0, -2, 2]
target = 0

可能的答案里会有:

[-2, -1, 1, 2]
[-2,  0, 0, 2]
[-1,  0, 0, 1]

注意几点小坑:

  • 四个数要按值算重复,比如 [-1,0,0,1] 只算一组,位置不管
  • 四元组里面一般会按从小到大排一下,方便去重

我一开始想的也很“暴力”——四层 for 循环,硬找:

for i in range(n):
for j in range(i+1, n):
for k in range(j+1, n):
for h in range(k+1, n):
if nums[i] + nums[j] + nums[k] + nums[h] == target:
                    ...

这个时间复杂度是啥水平呢? 四层循环,O(n^4),数组一大立马爆炸,面试官都能当场看你 CPU 冒烟。

所以这个写法,理解题还行,上线肯定不行。

老套路了,你们知道吧,三数之和怎么写,这个题就差不多,只是多了一层循环。

整体思路我用人话说下:

  1. 先排序,这样方便去重、也方便用双指针

  2. 第一层循环定第一个数 a = nums[i]

  3. 第二层循环定第二个数 b = nums[j]

  4. 剩下的两个数,就在区间 [j+1, n-1] 里用 左右指针 去扫

  • left = j + 1
  • right = n - 1
  • 当前四数之和:total = nums[i] + nums[j] + nums[left] + nums[right]
  • 如果 total < target,说明要大一点,left += 1

  • 如果 total > target,说明要小一点,right -= 1

  • 如果刚好等于,收集一组,然后左右一起缩,并且跳过相同元素,防止重复

  • 中间有几个非常重要的“去重动作”,不然结果里一堆重复四元组,看着都头大:

    • 第一层循环:if i > 0 and nums[i] == nums[i-1]: continue

    • 第二层循环:if j > i+1 and nums[j] == nums[j-1]: continue

    • 找到一组解后:

      • left 往右移动时跳过相同值
      • right 往左移动时也跳过相同值

    别说了,代码给你整全一点,你可以直接拿去跑:

    from typing import List

    deffour_sum(nums: List[int], target: int) -> List[List[int]]:
    # 先排序,方便双指针和去重
        nums.sort()
        n = len(nums)
        res = []

    for i in range(n):
    # 第一个数去重,避免相同起点重复计算
    if i > 0and nums[i] == nums[i - 1]:
    continue

    for j in range(i + 1, n):
    # 第二个数去重,同样的道理
    if j > i + 1and nums[j] == nums[j - 1]:
    continue

    # 现在我们要在 [j+1, n-1] 里找两个数
                left = j + 1
                right = n - 1

    while left < right:
                    total = nums[i] + nums[j] + nums[left] + nums[right]

    if total == target:
                        res.append([nums[i], nums[j], nums[left], nums[right]])

    # 左右同时移动,并跳过相同的数,防止重复组合
                        left_val = nums[left]
                        right_val = nums[right]

    while left < right and nums[left] == left_val:
                            left += 1
    while left < right and nums[right] == right_val:
                            right -= 1

    elif total < target:
    # 和太小,left 往右走,让总和变大
                        left += 1
    else:
    # 和太大,right 往左走,让总和变小
                        right -= 1

    return res

    if __name__ == "__main__":
        nums = [1, 0, -1, 0, -2, 2]
        target = 0
        print(four_sum(nums, target))

    你可以自己随便换几组数据试一下,比如全是 0 的、带重复数字的、数组特别短的,顺便感受一下去重逻辑是不是生效了。

    简单算下:

    • 外面两层循环 i、j:大概 O(n^2)
    • 里面一圈双指针,每次 while 至少移动一个指针:整段区间只会被扫一遍,所以是 O(n)
    • 乘在一起:**整体时间复杂度 O(n^3)**,空间复杂度主要是排序 O(log n) 的栈 + 结果集

    理论上还可以加一点“剪枝”优化,比如:

    • 如果 nums[i] + nums[i+1] + nums[i+2] + nums[i+3] > target,后面只会更大,可以直接 break
    • 如果 nums[i] + nums[n-1] + nums[n-2] + nums[n-3] < target,那 i 这个起点肯定不行,可以 continue

    面试的时候,你嘴上提一句“可以再做个上下界剪枝”,加分的。

    行啦,四数之和差不多就这点事,多写几遍你就会发现:题目换成三数、k 数,整体都是一套思路。 我先去给麻辣烫热一下,你有别的算法题也可以丢过来一起唠。

    -END-

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

    🔥虎哥私藏精品🔥

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