一、介绍
1.题目描述
题目链接:https://leetcode-cn.com/problems/longest-consecutive-sequence/submissions/
给定一个未排序的整数数组 nums
,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为 O(n)
的算法解决此问题。
2.测试样例
[100,4,200,1,3,2] # 4
[0,3,7,2,5,8,4,6,0,1] # 9
[9,1,4,7,3,-1,0,5,8,-1,6] # 7
二、题解
1、哈希map🟢
思路:定义map记录出现过的数字,出现过则存入map标为1,在map中找最长连续序列
以[100,4,200,1,3,2]为例
- 遍历一次数组后,map中存储[1:1,2:1,3:1,4:1,100:1,200:1]
- 遍历map
- 遇1,长度1,记录k=1,看接下来是否有2
- 遇2,长度2,记录k=2,看接下来是否有3
- ……
- 遇100,更新当前答案=4,记录k=100,看接下来是否有101
- ……
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
int n=nums.size();
map<int,int> mp;
for(int i=0;i<n;i++) mp[nums[i]]=1; // 存储出现的数字
map<int,int>::iterator it=mp.begin();
int ans=0,temp_ans=0,k=it->first;
while(it!=mp.end()){
if(temp_ans==0) temp_ans++; // 对于第一个数
else if(k+1==it->first){ // 如果连续,个数+1
temp_ans++;
k++;
}
else{ // 如果不连续,更新答案,重置个数
ans=max(ans,temp_ans);
temp_ans=1;
k=it->first;
}
it++;
}
ans=max(ans,temp_ans); // 从某段开始到末尾都连续,结束后应更新答案
return ans;
}
};
2、哈希set🟡
官方用的是一个更高效简便的方法。
思路:① 将数字存入到set中,set是一个元素不重复的集合。② 遍历 set,当遇到连续序列中最小的元素时(即set中没有更小的连续元素),递增统计连续序列的个数。
以[100,3,2,4,200,1,3,2]为例
- 遍历一次数组后,set中存储[100,3,2,4,200,1]
- 遍历set
- 遇100,∵无元素99,∴是该连续序列的最小元素,向后查找连续序列,无101,总长度1 , 更新答案ans=max(ans,1)
- 遇3,∵有元素2,∴非该连续序列中最小的元素,跳过;
- ……遇2、4,与3同理
- ……遇200,与100同理
- 遇1,∵无元素0,∴是该连续序列的最小元素,向后查找连续序列,有234,总长度4,更新答案ans=max(ans,4)
参考链接:
https://leetcode-cn.com/problems/longest-consecutive-sequence/solution/zui-chang-lian-xu-xu-lie-by-leetcode-solution/
其实该方法用map也可以实现,不过原理相同,就不再写一次了
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
int n=nums.size();
unordered_set<int> st; // 集合记录所有不重复元素
for(int i=0;i<n;i++) st.insert(nums[i]);
int ans=0,ans_temp=0;
for (const int& num : st){
if(!st.count(num-1)){ // 当前连续序列中没有更小数,即当前数为该连续序列的最小数
int k=num;
ans_temp=1;
while(st.count(k+1)){ // 统计连续序列长度
k++;
ans_temp++;
}
ans=max(ans,ans_temp); // 更新答案
}
}
return ans;
}
};