题目
Given an unsorted array of integers, find the length of the longest consecutive elements sequence.
For example,
Given [100,
4, 200, 1, 3, 2]
,
The longest consecutive elements sequence is [1,
2, 3, 4]
. Return its length: 4
.
Your algorithm should run in O(n) complexity.
思路一:先排序,再遍历
时间复杂度是:O(nlogn+n)
代码如下:
class Solution {
public:
int longestConsecutive(vector<int> &num) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
if(num.size()<2)
return num.size();
sort(num.begin(),num.end());
int max = 1;
int tmp = 1;
int i=1;
while(i<num.size())
{
if(num[i]==num[i-1]+1)
{
tmp = tmp+1;
}
if(num[i]>num[i-1]+1)
{
max = tmp>max?tmp:max;
tmp = 1;
}
i = i+1;
}
max = tmp>max?tmp:max;
return max;
}
};
此代码是完全可以通过 Juge Small 和 Juge Large 的。但是题目要求 是 Unsorted 和 O(N)。
思路二:Hash 思想
具体想法:
1、一边遍历vector,一边建立HashTable表。
2、对于当前的第i个元素,如果Map里面未出现,将其加入到Map中,并设置length=1:
(1)检测其左边的连续序列的左边界值 low:low = num[i]-1-mymap[num[i]-1]+1 这是已得到的当前元素的左连续序列的左边界元素,
并更新该low元素和当前元素的lenth:mymap[num[i]] = mymap[low]+1; mymap[low] = mymap[low]+1; (即更新该元素的左连续序列左右边界长度值length+1)
(2)检查其右边的连续序列的右边界值high,此时分两种情况:
(A)如果当前元素没有左连续序列部分,即左边界为当前元素,则做类似于(1)的操作来处理右连续序列;
(B)若有,则将当前元素插入到左连续序列 low = num[i]-mymap[num[i]]+1 和 右连续序列 high = num[i]+1+mymap[num[i]+1]-1 之间,
并更新左边界low 和右边界high 的lenth长度:mymap[low] = mymap[low]+mymap[high]; mymap[high] = mymap[low];
实现代码:
class Solution {
public:
int longestConsecutive(vector<int> &num) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
if(num.size()<2)
return num.size();
int max = 1;
unordered_map<long,int> mymap;
int low,high;
for(int i=0;i<num.size();i++)
{
if(mymap.find(num[i])!=mymap.end())
continue ;
mymap[num[i]]=1;
if(mymap.find(num[i]-1)!=mymap.end())
{
low = num[i]-1-mymap[num[i]-1]+1;
mymap[num[i]] = mymap[low]+1;
mymap[low] = mymap[low]+1;
max = mymap[low]>max?mymap[low]:max;
}
if(mymap.find(num[i]+1)!=mymap.end())
{
if(mymap[num[i]]==1)
{
high = num[i]+1+mymap[num[i]+1]-1;
mymap[num[i]] = mymap[high]+1;
mymap[high] = mymap[high]+1;
max = mymap[high]>max?mymap[high]:max;
}
else
{
low = num[i]-mymap[num[i]]+1;
high = num[i]+1+mymap[num[i]+1]-1;
mymap[low] = mymap[low]+mymap[high];
mymap[high] = mymap[low];
max = mymap[high]>max?mymap[high]:max;
}
}
}
return max;
}
};
还可以进一步简化:因为如果 mymap[num[i]]==1 和 mymap[num[i]]>1 都有 low = num[i]-mymap[num[i]]+1 ,所以可以合并处理。
class Solution {
public:
int longestConsecutive(vector<int> &num) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
if(num.size()<2)
return num.size();
int max = 1;
unordered_map<long,int> mymap;
int low,high;
for(int i=0;i<num.size();i++)
{
if(mymap.find(num[i])!=mymap.end())
continue ;
mymap[num[i]]=1;
if(mymap.find(num[i]-1)!=mymap.end())
{
low = num[i]-1-mymap[num[i]-1]+1;
mymap[num[i]] = mymap[low]+1;
mymap[low] = mymap[low]+1;
max = mymap[low]>max?mymap[low]:max;
}
if(mymap.find(num[i]+1)!=mymap.end())
{
low = num[i]-mymap[num[i]]+1;
high = num[i]+1+mymap[num[i]+1]-1;
mymap[low] = mymap[low]+mymap[high];
mymap[high] = mymap[low];
max = mymap[high]>max?mymap[high]:max;
}
}
return max;
}
};
Run Status: Accepted!
Program Runtime: 88
milli secs
最新:
public class Solution {
public int longestConsecutive(int[] nums) {
if(nums.length == 0){
return 0;
}
Set<Integer> hash = new HashSet<>();
int max = 0;
for(int e : nums){
hash.add(e);
}
for(int e : nums){
int lenth = 1;
int left = e-1;
while(hash.contains(left)){
lenth ++;
hash.remove(left); // if you have not this line, it will cause Time Limit Exceeded
left --;
}
int right = e+1;
while(hash.contains(right)){
lenth ++;
hash.remove(right); // if you have not this line, it will cause Time Limit Exceeded
right ++;
}
max = Math.max(max, lenth);
}
return max;
}
}