给定一个未排序的整数数组,找出最长连续序列的长度。
说明
要求你的算法复杂度为O(n)
样例
给出数组[100, 4, 200, 1, 3, 2],这个最长的连续序列是 [1, 2, 3, 4],返回所求长度 4
先上一个无脑能AC的
1 int longestConsecutive(vector<int> &num) { 2 // write your code here 3 set<int> sorted(num.begin(), num.end()); 4 set<int>::iterator it; 5 int max_len=1,len; 6 int pre; 7 for(it=sorted.begin();it!=sorted.end();it++){ 8 if(it==sorted.begin()){ 9 len=1; 10 } 11 else if(*it-1==pre){ 12 len++; 13 } 14 else{ 15 len=1; 16 } 17 max_len=max(max_len,len); 18 pre=*it; 19 } 20 return max_len; 21 }
大体思路还是先排序再无脑统计最大长度
利用set有序的特性,将vector转成set再统计。可惜时间复杂度是O(nlogn)-> set的插入查看删除操作是O(logn),进行n次
所以我们需要进行优化,一个非常常用的用来降低时间复杂度的做法就是用空间换时间
如果不用set,用hashmap呢?
hashmap的插入查看删除操作是O(1),那么n次就是O(n),符合题意
vector里面的元素作为key,元素所在连续序列的长度作为value
对于元素i,我们就需要找i+1,i-1,如果有将i的value更新为i+1 & i-1的value和并加一,相当于连接了这三个连续的数,
同时还需要将这个连续数列的首位两端也更新,下面贴一个insidel的解法,感谢原作者
1 int longestConsecutive(vector<int> &num) { 2 // write your code here 3 unordered_map<int,int> len; 4 int max=0; 5 for(auto i:num) 6 { 7 if(len[i]==0)//避免重复元素 8 { 9 int l=len[i-1],r=len[i+1]; 10 len[i]=l+r+1; 11 len[i+r]=l+r+1; 12 len[i-l]=l+r+1; 13 max=max>len[i]?max:len[i]; 14 } 15 } 16 return max; 17 }
Ps:以后也尽量向这种c++11的代码风格靠近。