躲过了两次裁员,终于成为腾讯员工了!!!
刚刷到这个,真有点职场玄学那味儿了。
喜马拉雅这波员工估计挺复杂的,本来前面躲了两轮裁员,心里可能天天悬着,结果一转头,公司被腾讯收了,审批也过了,直接从“会不会被优化”变成“我成腾讯员工了”。
最搞的是脉脉上那句调侃,躲过两次裁员,总算熬成腾讯人。你看,打工人有时候真不是靠规划,纯靠命硬。
以前是担心工牌哪天刷不开,现在可能开始琢磨腾讯福利、职级、年包了。HR看完都得沉默,领导估计也不好意思再画饼了。
这事最离谱的地方就是,本来以为是在逃生,结果跑着跑着进大厂了。谁看了不说一句:这班上得,剧情比短剧还会反转。
数组里这个位置,我一般不会真把它当“中间”看。
比如这个数组:
[2, 3, -1, 8, 4]
位置 3 上是 8,它左边是:
2 + 3 + (-1) = 4
它右边是:
4
左右相等,所以位置 3 就是要找的位置。
注意,这题坑人的地方不在代码长,而在“中间”两个字。它不是长度的一半,也不是下标在正中央,而是找一个下标,让它左边所有数的和,等于右边所有数的和。
我见过不少人第一眼就写成这样:
defmiddle_index(nums):
for i in range(len(nums)):
left = sum(nums[:i])
right = sum(nums[i + 1:])
if left == right:
return i
return-1
这代码能跑,样例也过。
但我不太喜欢这种写法。不是因为它丑,是因为它每走一个位置都重新算一遍和。数组一长,sum(nums[:i]) 和 sum(nums[i+1:]) 就开始反复扫数据。
这题真正应该抓住的是一个关系。
假设数组总和是 total,当前下标是 i,左边和是 left,当前值是 nums[i]。
那右边和就不用重新算了:
right = total - left - nums[i]
只要判断:
left == total - left - nums[i]
就行。
代码我一般会这么写:
deffind_middle_index(nums):
total = sum(nums)
left_sum = 0
for idx, value in enumerate(nums):
right_sum = total - left_sum - value
if left_sum == right_sum:
return idx
left_sum += value
return-1
拿刚才那个数组跑一遍:
nums = [2, 3, -1, 8, 4]
print(find_middle_index(nums))
输出:
3
这里有个顺序别写反。
判断完当前下标以后,才能把当前值加到 left_sum 里。因为题目要求的是“当前位置左边”的和,不包含当前位置本身。
这地方如果手快写成这样:
left_sum += value
if left_sum == total - left_sum - value:
return idx
基本就偏了。看着只挪了一行,但语义已经变了,当前位置的值被算进左边去了。
再看两个边界。
第一个,答案在最左边:
print(find_middle_index([0, 5, -5]))
输出:
0
下标 0 左边没有元素,左边和按 0 算。右边是 5 + (-5),也是 0。
第二个,根本找不到:
print(find_middle_index([1, 2, 3]))
输出:
-1
整题复杂度也很干净。
数组先求一次总和,再从左到右扫一次,所以时间复杂度是 O(n)。除了几个变量,没有额外开数组,空间复杂度是 O(1)。
这题我更建议记判断式,不要背代码:
左边和 == 总和 - 左边和 - 当前值
只要这个式子没写错,代码基本不会跑偏。