程序员老公摆烂,彻底废了,被优化后三个月没找到工作,最后跑去送快递了,原本一个月两万现在才四五千,不知道他怎么能干下去的!
刚看到个贴子,说一程序员老公被优化,三个月找不到工作,现在去送快递,一个月四五千,老婆嫌他“废了”,动不动就想离婚。
我觉得这事不能只盯着工资数字看。程序员这两年行情大家都懂,高薪岗位本来就不稳,他从两万掉到四五千,更多是行业寒冬,不一定是人不行。起码他没躺家里打游戏,还愿意去送快递,把家先顶住,这一点不该被否定。
但话说回来,如果他真不学习、不转型,只想着混日子,那老婆急也能理解,毕竟一家人的未来不是靠同情心撑着的。我的看法是:这会儿最该做的是两个人坐下来,把账算清,把路想明,互相督促,而不是动不动就用“离婚”当情绪出口。
算法题:全局倒置与局部倒置
写这道「全局倒置与局部倒置」的时候,我第一反应是:这不就是看“局部小问题会不会演变成系统级事故”嘛,很有架构味儿。
给你一个长度为 n 的数组 A,它是 0 ~ n-1 的一个排列。
全局倒置:一对下标 (i, j),i < j,且A[i] > A[j]局部倒置:只看相邻的一对 (i, i+1),A[i] > A[i+1]
题目问:这个数组里 所有的全局倒置是不是都恰好是局部倒置? 换句话说:有没有那种“隔着一个或多个元素”的远距离逆序对。
举个例子:
A = [1, 0, 2]局部倒置: (0,1)->1 > 0全局倒置只有这一对,所以 ✅ A = [1, 2, 0]局部倒置:没有(相邻都没逆序) 全局倒置: (0,2)->1 > 0,(1,2)->2 > 0出现了“跨一步”的倒置,所以 ❌
因为 A 是 0 ~ n-1 的排列,每个数本来“理想位置”就是它自己:值为 v 的理应在下标 v 上。
如果我们只允许局部倒置,也就是只允许跟相邻的元素换位置,那么一个元素最多能被挪动 1 格。 所以有一个非常漂亮的结论:
如果数组中所有元素都满足
|A[i] - i| <= 1, 那么所有全局倒置都是局部倒置; 一旦有元素离它“该在的位置”超过 1 格,一定会产生非局部倒置。
非常适合写成一次遍历的代码。
核心:扫一遍数组,看有没有元素“位移超过 1”。
defis_ideal_permutation(nums):""" 判断数组 nums 是否满足: 所有全局倒置都是局部倒置 """for i, v in enumerate(nums):# 如果某个元素离它“该在的位置”超过 1# 肯定存在一个非局部倒置if abs(v - i) > 1:returnFalsereturnTrueif __name__ == "__main__": print(is_ideal_permutation([1, 0, 2])) # True print(is_ideal_permutation([1, 2, 0])) # False这个解法的优点:
一次遍历,时间复杂度 O(n) 只用几个变量,空间复杂度 O(1) 逻辑和题意高度贴合,面试讲起来也很顺。
上面的解法偏结论式,如果你更喜欢“从定义推”的思路,可以这样想:
非局部倒置就是:存在 i < j - 1,且A[i] > A[j]那就对每个 j >= 2,看左边0 ~ j-2里的最大值是不是大于A[j]。
代码如下:
defis_ideal_permutation_prefix_max(nums): n = len(nums)if n <= 2:returnTrue# 长度 0/1/2 不可能出现非局部倒置 max_prefix = nums[0]for j in range(2, n):# 如果前面 [0..j-2] 的最大值已经比 nums[j] 大# 说明存在 i <= j-2,让 (i, j) 构成非局部倒置if max_prefix > nums[j]:returnFalse# 维护 [0..j-1] 之前的最大值,给下一个 j 用 max_prefix = max(max_prefix, nums[j-1])returnTrue这个写法更接近“按定义排查非法全局倒置”的过程,同样是 O(n) / O(1),只是思路不同。
这题表面是在数“倒置对”,本质是在做一件事:用局部信息约束全局行为。
如果你只允许“局部小错”(局部倒置),就必须保证 单个元素的漂移被严格限制; 一旦元素随意乱跑(位移 > 1),全局就会出现不可控的问题(非局部倒置)。
在工程和架构里,一样要警惕这种情况: 局部看起来没问题,接口也都对,但某个模块“跑得太远”,全局就乱了。
写到这里,这道题就既有“算法的味儿”,也有一点“架构的意味”了。 如果你在面试中能把上面的两种解法 + 这个小类比讲清楚,这道题基本是稳拿。
虎哥作为一名老码农,整理了《python高级架构师资料合集》,总量高达650GB