相亲才认识两个月就定了婚期,感觉好恍惚,这周要去拍婚纱照,六月份就要结婚,彩礼15万~
有网友吐槽,认识两个月,彩礼15万,女方说后面再添钱买辆车带回来,男方这边全款房还要加名。流程看着都挺顺,心里却一直发虚,这种恍惚其实很正常。
不是舍不得花钱,也不一定是不想结。更像是事情推进得太快,人还没来得及把“相亲对象”切换成“结婚对象”。前面聊条件,后面谈日子,中间那段真正了解彼此脾气、消费观、家里边界感的时间,反而被压得很短。
怕的从来不是结婚本身,怕的是一套流程走完,才发现两个人只是把账算明白了,日子还没看清。
算法题:最长和谐子序列
这题一上来最容易拐错地方。
很多人看到“最长和谐子序列”,脑子里先冒出来的是双指针、滑动窗口,甚至还想保留原顺序去做子序列搜索。结果代码越写越别扭。这个题我第一眼就不太信“子序列”这三个字,因为它根本不要求连续,真正有用的信息只有一句:最大值和最小值恰好相差 1。
那味道就变了。顺序不重要,位置不重要,谁出现了几次才重要。
比如数组:
[1,3,2,2,5,2,3,7]
和谐子序列可以取 [3,2,2,2,3],长度是 5。这里你会发现,真正起作用的就是 2 出现了 3 次,3 出现了 2 次,最后答案就是 3 + 2。
所以这题别往“找子序列”上钻,先统计频次。
最笨的写法,是枚举每个数 x,再去扫一遍数组统计 x 和 x+1 的个数,能做,但没必要,时间复杂度直接干到 O(n^2),数据一大就没意思了。
这题顺手的写法就是 HashMap。
import java.util.HashMap;
import java.util.Map;
classSolution{
publicintfindLHS(int[] nums){
Map<Integer, Integer> cnt = new HashMap<>();
for (int num : nums) {
cnt.put(num, cnt.getOrDefault(num, 0) + 1);
}
int ans = 0;
for (Map.Entry<Integer, Integer> entry : cnt.entrySet()) {
int x = entry.getKey();
int c1 = entry.getValue();
if (cnt.containsKey(x + 1)) {
int c2 = cnt.get(x + 1);
ans = Math.max(ans, c1 + c2);
}
}
return ans;
}
}
这段代码没什么花活,就两步。
先统计每个数字出现次数。 再看某个数字 x 的时候,x+1 在不在;在的话,这俩拼起来就是一个合法和谐子序列,长度就是频次之和。
这里有个细节挺多人会漏: 如果数组里只有一个值,比如 [4,4,4,4],答案不是 4,而是 0。因为最大值和最小值差的是 0,不是 1。所以代码里一定要判断 x+1 是否存在,不能直接拿当前最大频次当答案。
再拿两个例子过一下:
nums = [1,1,1,1]
只有 1,没有 2,返回 0。
nums = [1,2,2,1]
1 有 2 个,2 有 2 个,答案就是 4。
这题的核心不在算法多复杂,而在于别被题目名字带偏。它挂着“子序列”的牌子,实际上考的是频次统计。很多题就这个路数,名字唬人,解法很朴素。
时间复杂度是 O(n),空间复杂度也是 O(n)。这种题在面试里不算难,但特别适合看一个人会不会先把题意掰正。题没读顺,代码基本也写不顺。