公司裁员名单下来了,那个36岁的工程师稳如泰山,反而几个28岁的年轻人走了。
刚看到个贴子,说公司裁员名单出来了,结果那个36岁的工程师稳得一批,反倒走了几个28岁的年轻人。怎么说呢,这事我一点都不意外。
网友的回帖我也瞄了瞄,有说“年龄歧视不存在吗”的,也有说“公司当然选能扛事的”。
但我觉得关键点不是年龄,而是可替代性。有些年轻人确实冲劲足,但业务没沉淀、项目没人记得、走了也不影响流水线,那在裁员里就特别被动。
反倒是那个36岁的工程师,八成是手里有核心模块、出了问题能顶得住,或者在团队里属于“缺了就会塌一角”的那类人。
换个角度讲,职场就像坐地铁,高峰期你挤得再用力,只要没站稳、没扶手,一刹车你还是最先被甩出去。真正稳的人,从来不是因为“年龄大”,而是因为站得住。【备注:文末可领最新资料】
面试题:数组列表中的最大距离
就拿这道「数组列表中的最大距离」聊聊哈,Java 版本的。
题目大概是这样的:
给你一个
List<List<Integer>> arrays里面每个小数组都是升序排好的,比如:
[1, 2, 3][4, 5][1, 2, 3, 4]你要从两个不同的数组里各挑一个数出来,一个是
a,一个是b目标是让
|a - b|尽可能大,返回这个最大值
注意两个点:
一定要是不同的数组,不能同一个数组里选两个数 每个数组是有序的,这是关键优化点
最笨的想法:硬算
最直觉的做法就是:
枚举两个数组 i、j再算它们之间能形成的最大距离 再在所有组合里取最大
但你会发现,有序数组里能形成最大距离的,一定是:
这个数组的最小值(第一个元素) 和另一个数组的最大值(最后一个元素)
所以两两数组之间的最大距离,其实就是这两个候选:
abs(min_i - max_j)abs(max_i - min_j)
问题是,如果你真的两两数组去算,时间复杂度是 O(n^2),数组多一点就爆了。
利用「有序」这件事来优化
既然每个数组都是升序的,那每个数组我们只关心两件事:
最小值:第一个元素 first最大值:最后一个元素 last
接下来想象一下我们从左到右遍历这些数组:
维护一个「目前为止见过的全局最小值」
globalMin维护一个「目前为止见过的全局最大值」
globalMax遍历到当前数组
cur时:它的最小值是 curMin它的最大值是 curMax
那当前数组能和前面那些数组组成的最大距离有两种情况:
用前面数组里的最小值,配上当前数组的最大值
也就是: curMax - globalMin
用前面数组里的最大值,配上当前数组的最小值
也就是: globalMax - curMin
这俩取大的,拿来更新答案。
为什么这样不会踩到「同一个数组」的坑?
因为 globalMin和globalMax都是「之前数组」维护出来的当前数组是后来的,肯定不是同一个 所以天然保证了「来自不同数组」
最后别忘了:
每处理完一个数组,要把:
globalMin = min(globalMin, curMin)globalMax = max(globalMax, curMax)这样后面的数组也能用上它
时间复杂度就是一次线性扫描:O(n),只用常数额外空间。
import java.util.List;publicclassMaxDistanceInArrays{
/**
* 数组列表中的最大距离
* @param arrays 每个内部数组都是升序的
* @return 最大的 |a - b|,a 和 b 来自不同数组
*/
publicintmaxDistance(List<List<Integer>> arrays){
if (arrays == null || arrays.size() < 2) {
// 题目一般不会这样出,但防一手
return0;
}
// 初始化,用第一个数组的首尾
List<Integer> firstArray = arrays.get(0);
int globalMin = firstArray.get(0); // 当前见过的最小值
int globalMax = firstArray.get(firstArray.size() - 1); // 当前见过的最大值
int ans = 0;
// 从第二个数组开始遍历
for (int i = 1; i < arrays.size(); i++) {
List<Integer> cur = arrays.get(i);
int curMin = cur.get(0);
int curMax = cur.get(cur.size() - 1);
// 当前数组和前面所有数组能形成的最大距离
int dist1 = Math.abs(curMax - globalMin);
int dist2 = Math.abs(globalMax - curMin);
ans = Math.max(ans, Math.max(dist1, dist2));
// 更新全局最小值和最大值,给后面的数组用
globalMin = Math.min(globalMin, curMin);
globalMax = Math.max(globalMax, curMax);
}
return ans;
}
}
你可以顺手带个小例子在 main 里测一下,比如:
[[1,2,3],[4,5],[1,2,3,4]]全局最小一路都是 1 全局最大最终是 5 最大距离就是 5 - 1 = 4
其实就一句话:有序数组就看两头。 把「所有数组里的最小」和「所有数组里的最大」用一遍扫描串起来,中间只要确保不是同一个数组就行了,而我们从左往右维护,就顺带把这个条件也满足了。
这个题写顺了之后,以后再看到那种「有序数组 + 距离最大」的,大概率也是同一类套路。后面你要是想顺带看下「最大 j - i 且 A[j] ≥ A[i]」那个版本,也可以再搞一篇完全不一样的解法。
-END-
我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html