problem:
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.
solution:
这道题如果没有看到下面那个O(n)的时间复杂度的话将会很简单,因为我们有各种时间复杂度的排序算法,排序之后就可以很容易的得到结果。可是这道题确实是有O(n)的时间复杂度要求,我从开始看到这道题就一直在考虑这个时间复杂度的问题,思来想去跟O(n)时间复杂度能联系起来的,我就想到了桶排序。于是干脆就使用桶排序算法来排序一下。虽然最近也在看算法导论,但是桶排序还真是第一次写。对num中的最大值vmax和最小值vmin,直接声明了一个vmax-vmin+1的向量,将num中的所有数字哈希进去,虽然感觉不是很靠谱,但是还是做了。实现之后,果然碰到了很极端的情况,就是vmax特别大,vmin特别小的情况。这样直接就出现alloc错误了。
想了半天还是不知道怎么做,于是到网上搜了搜。发现竟然是用map,而且是unordered_multimap,而且这个东西还是C++11标准。好吧,高端洋气了一把。之前对map的使用本来就少,这次就仔细研究了unordered_map,unordered_multimap,map,multimap的区别与使用方法。其实区别和使用方法也都很简单,具体参见cplusplus。
看别人的方法的时候,发现用的count,并且看cplusplus上介绍,平均时间复杂度竟然是常数时间,虽然最差情况还是O(n)。好吧,这些长知识了。这个while循环,没有仔细查看,目测平均复杂度也是常数时间(待考证)。
class Solution {
public:
int longestConsecutive(vector<int> &num)
{
int len=num.size();
if (len==0) return 0;
unordered_map<int,int> hs;
for(int i=0;i<len;i++)
{
if (hs.count(num[i]))
hs[num[i]]++;
else
hs.emplace(num[i],1);
}
int lmax=0;
for(int i=0;i<len;i++)
{
int tmp=num[i];
int tmp_max=0;
while(hs.count(tmp))
{
hs.erase(tmp);
tmp++;
tmp_max++;
}
tmp=num[i]-1;
while(hs.count(tmp))
{
hs.erase(tmp);
tmp--;
tmp_max++;
}
lmax=max(lmax,tmp_max);
}
return lmax;
}
};
果然时间复杂度高端的还是哈希。