程序员老鬼

公司宣布全员大小周,不同意可以离职。我问面试的人可以接受吗,结果她说:只要工资在8000以上,不要说大小周了,996都可以接受!

这也太真实了。

公司那边先来一句,全员改大小周,接受就干,不接受就走。你说这话听着就挺硬的,跟通知你明天食堂换菜单差不多,一点商量味儿没有。

结果更扎心的是,楼主去问面试的人能不能接受,人家倒也不装,直接说工资到8000以上,别说大小周,996她都能扛。

Image

这话听完真不知道该笑还是该沉默。

一边是公司越来越敢压,一边是打工人越来越能忍。不是大家突然热爱加班了,是房租、吃饭、通勤、家里那点事,都在后面推着你走。

老板听了估计心里一乐,HR听了也省事了。可打工人看完,血压是真有点上来。8000块钱,买的到底是时间,还是命硬啊。

面试题:找到数组的中间位置

数组中间位置这个题,坑不在代码长,坑在你一上来就想两边同时扫。

题目说的是:找到一个下标 i,让它左边所有元素的和,等于右边所有元素的和。

比如:

nums = [2, 3, -1, 8, 4]

下标 3 的值是 8。

它左边是:

2 + 3 + (-1) = 4

右边是:

4

左右相等,所以答案就是 3。

这题我一般不会先写双指针。双指针看着聪明,其实方向不对,因为数组里可能有负数。负数一出来,左边变大、右边变小这种判断就不可靠了。

更稳的写法是先算总和。

假设当前走到位置 i,左边的和叫 left,数组总和叫 total。

那右边的和就不用重新算了:

right = total - left - nums[i]

只要:

left == right

说明当前位置就是中间位置。

代码可以这么写:

publicclassMiddleIndexFinder{

publicintfindMiddleIndex(int[] nums){
if (nums == null || nums.length == 0) {
return -1;
        }

int total = 0;
for (int num : nums) {
            total += num;
        }

int left = 0;

for (int i = 0; i < nums.length; i++) {
int right = total - left - nums[i];

if (left == right) {
return i;
            }

            left += nums[i];
        }

return -1;
    }
}

这里有个细节,left += nums[i] 必须放在判断后面。

因为题目要的是当前位置左边的和,不包含 nums[i] 自己。这个地方如果手快写反了,测试一些普通数组可能还看不出来,一碰到边界就炸。

比如这个:

nums = [1, -1, 4]

下标 2 左边是:

1 + (-1) = 0

右边没有元素,也是 0,所以答案是 2。

再看一个边界:

nums = [0, 0, 0]

第一个位置左边是 0,右边也是 0,所以直接返回 0。题目如果要求返回最左边的中间位置,这个写法刚好符合。

这个算法扫了两次数组。

一次算总和,一次找位置。

时间复杂度是 O(n),空间复杂度是 O(1)。

别为了省那一次遍历去写一堆绕来绕去的逻辑,不值。数组题很多时候就是这样,先把账算清楚,再往下走,代码反而干净。