36被裁 找工作无望了 过了 35就是死刑 自寻出路了华5本硕 太难了 一副好牌被我打得稀烂感
刚刷到这个,心里真有点堵。
36岁,华五本硕,放哪看都不算差,结果一被裁,投出去的简历跟扔海里一样。以前总觉得“35岁危机”是网上吓唬人,真轮到自己,才发现很多公司连聊都懒得聊,先看年龄,再看你能不能加班,能力反而排后面。
最难受的还不是没工作,是你回头一看,学历有了,班也没少加,年轻时候觉得再混几年就稳了。现在公司一句优化,人直接被清场。
说什么一副好牌打烂了,其实很多打工人哪有出牌的机会,牌桌都是别人掀的。36岁又不算老,可招聘软件上那道线,画得跟判决书似的,看得人真窝火。
最长和谐子序列,别一上来就写双指针
数组 [1,3,2,2,5,2,3,7] 丢进来,答案是 5。
取出的子序列是 [3,2,2,2,3],最大值为 3,最小值为 2,两者相差正好等于 1。
这道题看着像滑动窗口,我第一眼也会想到排序加双指针。但再看一遍题目,会发现“子序列”不要求元素连续,原数组里的顺序也不影响最终长度。既然只关心数字出现了多少次,排序就显得有点重了。
题目的关键限制只有一个:子序列中的最大值和最小值必须相差 恰好为 1。
这里有个容易写错的地方。数组 [2,2,2,2] 不能返回 4,因为最大值和最小值相差 0,不是 1。看到四个相同数字就直接累加,这种代码测试样例少的时候还真不容易暴露。
处理方式很直接:先用 HashMap 统计每个数字出现的次数。假设当前数字是 x,只要数组中还存在 x + 1,那么这两个数字就能组成一个和谐子序列,长度就是它们出现次数之和。
代码不用写得太绕:
import java.util.HashMap;
import java.util.Map;
publicclassHarmoniousSequence{
publicintfindLongest(int[] nums){
if (nums == null || nums.length < 2) {
return0;
}
Map<Integer, Integer> frequency = new HashMap<>();
for (int value : nums) {
frequency.merge(value, 1, Integer::sum);
}
int longest = 0;
for (Map.Entry<Integer, Integer> item : frequency.entrySet()) {
int current = item.getKey();
// 防止 current + 1 在极端情况下发生整数溢出
if (current == Integer.MAX_VALUE) {
continue;
}
Integer nextCount = frequency.get(current + 1);
if (nextCount == null) {
continue;
}
int candidate = item.getValue() + nextCount;
longest = Math.max(longest, candidate);
}
return longest;
}
}
拿开头的数组跑一下,频次大致是:
1 -> 1
2 -> 3
3 -> 2
5 -> 1
7 -> 1
遍历到 1 时,可以和 2 组合,长度是 4。
遍历到 2 时,可以和 3 组合,长度是 5。
遍历到 3 时,找不到 4,直接跳过。后面的 5 和 7 也没有相邻数字,最终结果就是 5。
这段代码只扫描了一次数组,又遍历了一次频次表,时间复杂度是 O(n),额外空间复杂度也是 O(n)。
当然,排序后用双指针也能做,时间复杂度是 O(n log n)。但这题没有区间连续性的要求,只为统计两个相邻数值的数量去排序,我一般不会这么写。能用频次表把问题压成一次查找,就没必要先把整个数组重新排一遍。