南大计算机博士,毕业两年多,在北京某头部大厂,接着干还是回二线老家央企??
刚刷到这个帖,我第一反应是:这不就是打工人经典分岔路吗。
南大计算机博士,在北京头部大厂,两年多,年包六七十万,听着挺香。但问题是方向不在AI风口,业务也没啥增量,晋升看不到,日常还要oncall。钱是多,可人一直被吊着,心里累也正常。
现在老家二线省会有个央企研究院,钱直接腰斩,二十多到三十万。但人家给的是另一套东西:考核期过了能入编,女友也在本地事业编,未来结婚买房生活都能落地。
这事真不是单纯比工资。北京大厂给的是现金流和平台,老家央企给的是稳定、关系和生活节奏。关键看他还想不想继续在互联网熬。要是已经对业务没感觉,晋升也卡着,那回去未必是退路,可能是及时下车。
数组是这样的:
[2, 6, 4, 8, 10, 9, 15]
只要把中间这一段排一下序,整个数组就有序了:
[6, 4, 8, 10, 9]
题目问的不是怎么排序,而是这段最短子数组到底有多长。
这个题我第一眼不会先去复制一份数组排序。那种写法当然能过,但有点笨,还多吃一份空间。现场写代码我一般先看“哪里破坏了有序性”。
从左往右扫,维护一个当前见过的最大值。
如果当前位置的数比最大值还小,说明它站错了位置,右边界至少要扩到这里。
比如扫到 4 的时候,前面最大值是 6,4 < 6,右边界就出来了。
继续扫到 9,前面最大值是 10,9 < 10,右边界继续往后挪。
这一步能找到右边界。
但左边界还不够。因为左边界要看右侧有没有更小的数。
所以再从右往左扫,维护一个当前见过的最小值。
如果当前位置的数比最小值还大,说明它也站错了,左边界要往这里收。
代码我会这么写,不绕:
classSolution{
publicintfindUnsortedSubarray(int[] nums){
if (nums == null || nums.length < 2) {
return0;
}
int right = -1;
int maxSeen = nums[0];
for (int i = 1; i < nums.length; i++) {
if (nums[i] < maxSeen) {
right = i;
} else {
maxSeen = nums[i];
}
}
if (right == -1) {
return0;
}
int left = 0;
int minSeen = nums[nums.length - 1];
for (int i = nums.length - 2; i >= 0; i--) {
if (nums[i] > minSeen) {
left = i;
} else {
minSeen = nums[i];
}
}
return right - left + 1;
}
}
拿刚才的数组跑一下:
nums = [2, 6, 4, 8, 10, 9, 15]
从左往右:
2 正常
6 正常
4 < 6 right = 2
8 正常
10 正常
9 < 10 right = 5
15 正常
右边界是 5。
从右往左:
15 正常
9 正常
10 > 9 left = 4
8 正常
4 正常
6 > 4 left = 1
2 正常
左边界是 1。
所以长度就是:
5 - 1 + 1 = 5
这题真正容易写错的地方,是只找一个方向。
只从左往右,你只能知道右边界。只从右往左,你只能知道左边界。两个方向都扫一遍,问题就很干净。
时间复杂度 O(n),空间复杂度 O(1)。
不需要排序,也不需要额外数组。这个写法在线上看也舒服,边界少,判断顺序也不容易埋坑。