Python技术迷

公司来了位阿里出来的高级开发,月薪3万+,才几天就离职了。他说以为降薪进来压力会小点,但领导觉得他是组里薪资最高的,应该承担更多

刚看到个贴子,说有个阿里出来的高级开发,拿着3万+的月薪,本以为降薪换个环境能轻松点,结果才几天就扛不住离职了😮。原因是领导觉得他薪资最高,就该扛最多活,结果任务压得比在阿里还狠。

Image

我觉得这事吧,说到底是“薪资=期待”的逻辑。很多网友也吐槽过:工资高,老板自然要压榨出更多价值。但问题是,人家是跨行业,还在适应期,就这么硬塞重担,确实很容易劝退。换句话说,职场里价值没兑现前,光凭薪资给你贴个“强者”标签,注定要翻车。

网友们的回复我看了看,有人觉得他玻璃心,有人觉得公司管理僵化。我更认同后者,公司用人还是要讲“匹配度”,不是谁价高就无限透支。人才跳槽,本就图一个环境合适、心态平衡,如果把人逼得连缓冲期都不给,那留不住也正常。【备注:文末可领最新资料】

面试题:最大递增三元组

昨天晚上十一点多,在公司楼下吹风,手机一震,我们组那个小李问我:哥,那个“最大递增三元组”咋写啊?我脑子一抽就懂了——就是数组里找 i<j<k 且 a[i]<a[j]<a[k] 的三个数,让它们的“和”尽量大,对吧,对吧。别整花活儿,先把思路捋顺。

我一般先用最顺手的办法验证直觉:中间这个数 a[j] 挺关键的,你左边得挑一个比它小但尽量大的(越大越赚),右边挑一个比它大的里最大的(直接拿右侧最大值,如果它都不比 a[j] 大,那这 j 没戏)。所以你看,右边很好做,提前算个后缀最大值就行;左边难点在“找左侧小于 a[j] 的最大值”。Python 没有内置平衡树嘛,我就先用个有序列表 + bisect,写起来快,就是最坏 O(n²),但面试里先 AC 再说,嘿嘿。

下面这个先跑通版本,能给出最大和,还有那组三元值:

from bisect import bisect_left, insort

defmax_sum_increasing_triplet_simple(nums):
    n = len(nums)
if n < 3:
return0, None# 没三元组就算了

# 右侧后缀最大值,右边挑最大的那个做 a[k]
    suf_max = [0]*n
    cur = float('-inf')
for i in range(n-1, -1, -1):
        cur = max(cur, nums[i])
        suf_max[i] = cur

    best_sum = 0
    best_triplet = None

    seen = []  # 左侧有序列表
# j 放在中间,左右至少各一个位置
for j in range(1, n-1):
# 右边必须有比它更大的,直接看 suf_max[j+1]
        right_max = suf_max[j+1]
if right_max <= nums[j]:
# 右侧都不比它大,这个 j 不行
            insort(seen, nums[j])
continue

# 左边找 < nums[j] 的最大值:前驱
        pos = bisect_left(seen, nums[j])  # 第一个 >= nums[j] 的位置
if pos == 0:
# 左侧没有更小的
            insort(seen, nums[j])
continue
        left_best = seen[pos-1]

        s = left_best + nums[j] + right_max
if s > best_sum:
            best_sum = s
            best_triplet = (left_best, nums[j], right_max)

        insort(seen, nums[j])

return best_sum, best_triplet

# 小测
if __name__ == "__main__":
    arr = [2, 5, 3, 1, 4, 9]
    print(max_sum_increasing_triplet_simple(arr))  # 期望 (2,4,9) 或 (5,? ,9) 这类,和最大

有人会说,这个插入是 O(n) 呀,是是是,我知道,最坏 O(n²)。但思路特别清楚,对吧。等你要提速,再上“坐标压缩 + 树状数组(BIT)”这一套,把“左侧前驱的最大值”变成“查询前缀最大”。右侧还是用后缀最大,不用动。整体就 O(n log n) 了,稳。

我刚回到工位就把优化版敲了下,注意两个点:一是 BIT 里存“值的最大值”,不是计数;二是坐标压缩后,查询 idx(val)-1 这个前缀。

defcompress(values):
    uniq = sorted(set(values))
    rank = {v:i+1for i,v in enumerate(uniq)}  # BIT 从 1 开始
return rank

classBITMax:
def__init__(self, n):
        self.n = n
        self.bit = [float('-inf')] * (n+1)

defupdate(self, i, val):
while i <= self.n:
if val > self.bit[i]:
                self.bit[i] = val
            i += i & -i

defquery(self, i):
        res = float('-inf')
while i > 0:
if self.bit[i] > res:
                res = self.bit[i]
            i -= i & -i
return res

defmax_sum_increasing_triplet(nums):
    n = len(nums)
if n < 3:
return0, None

# 右侧后缀最大
    suf_max = [0]*n
    cur = float('-inf')
for i in range(n-1, -1, -1):
        cur = max(cur, nums[i])
        suf_max[i] = cur

    rank = compress(nums)
    bit = BITMax(len(rank))

    best_sum = 0
    best_triplet = None

# i 从左到右扫,同时维护“左侧见过的值”的前缀最大
# j 做中间
# 先把第一个元素放到 BIT 里作为“左侧可选”
    bit.update(rank[nums[0]], nums[0])

for j in range(1, n-1):
# 右边必须存在比 a[j] 大的
        right_max = suf_max[j+1]
if right_max <= nums[j]:
            bit.update(rank[nums[j]], nums[j])
continue

# 左侧 < a[j] 的最大值
        left_best = bit.query(rank[nums[j]] - 1)
if left_best == float('-inf'):
            bit.update(rank[nums[j]], nums[j])
continue

        s = left_best + nums[j] + right_max
if s > best_sum:
            best_sum = s
            best_triplet = (left_best, nums[j], right_max)

        bit.update(rank[nums[j]], nums[j])

return best_sum, best_triplet

# 再测
if __name__ == "__main__":
    arr = [2, 5, 3, 1, 4, 9]
    print(max_sum_increasing_triplet(arr))

对了对了,两个坑别踩:如果数组单调不升,答案就是 0、None,别强装;还有重复值没关系,严格递增要求是“<”,前驱查的是小于它的最大值就行。行了我去泡杯茶,等会儿有人要我看日志我再回来……

-END-

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

🔥虎哥私藏精品🔥

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