「这是我参与2022首次更文挑战的第26天,活动详情查看:2022首次更文挑战」。
给定一个未排序的整数数组,返回最长的连续序列长度
要求时间复杂度:O(n)
一、分析
设计2张表:
- 连续区间的头表(哈希表)
- 连续区间的尾表(哈希表)
一个一个的遍历,比如遇到100,生成100~100的连续区间,以100作头,连续区间的头表里,以100作为key,value为连续区间的长度,key=100,value=1。以100作为尾,连续区间的尾表里,以100作为key,value为连续区间的长度,key=100,value=1。然后在尾表里查是否有哪个连续区间以99作为尾结束,没有,宣告这个区间没办法合并,再在头表里查是否有哪个连续区间以101作为头开始,没有,宣告这个区间没办法合并。...99 | 100~100 | 101...
此时进来一个3,连续区间的头表和尾表都没有key=3,value=1,则直接放进去,然后在尾表里查是否有哪个区间以2作为尾结束,没有,再在头表里查询是否有哪些连续区间以4作为头开始,没有,宣告这个区间没办法合并。
此时进来一个4,依次类推,头表key=4,value=1,尾表key=4,value=1。然后在尾表查是否有哪个区间以3作为尾结束,这是有,则进行合并,从尾表中获取key=3,value=1(代表连续区间的长度),头表中获取key=3,3和4连接,长度变为2,更新头表中key=3,value=2。尾表key=4,value更新为2,即value=2。
......依次类推
每个数来的时候建立自己的区间(头区间、尾区间),看看能否合并其他区间的头、其他区间的尾,最后的连续区间长度就是返回头区间或尾区间中max(value)
二、实现
public static int longestConsecutive(int[] nums) {
HashMap<Integer, Integer> map = new HashMap<>();
int len = 0;
for (int num : nums) {
if (!map.containsKey(num)) {
map.put(num, 1);
int preLen = map.containsKey(num - 1) ? map.get(num - 1) : 0;
int posLen = map.containsKey(num + 1) ? map.get(num + 1) : 0;
int all = preLen + posLen + 1;
map.put(num - preLen, all);
map.put(num + posLen, all);
len = Math.max(len, all);
}
}
return len;
}
三、总结
可以采用两张哈希表,也可以采用一张哈希表,哈希表的操作时间复杂度为O(1)