最长连续序列 longest-consecutive-sequence
题目描述
给定一个无序的整数类型数组,求最长的连续元素序列的长度。
例如:
给出的数组为[100, 4, 200, 1, 3, 2],
最长的连续元素序列为[1, 2, 3, 4]. 返回这个序列的长度:4
你需要给出时间复杂度在O(n)之内的算法
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(N)的思路:散列表
-
关于set和unordered_set的find函数的时间复杂度:
- set底层是红黑树实现的,因此它的find函数时间复杂度:O(logn)
- 而unordered_set底层是哈希表,因此它的find函数时间复杂度:O(1)
- algorithm里的find函数是顺序查找,复杂度为O(n)
-
关于set和unordered_set的erase函数:
- st.erase(it):it为需要删除元素的迭代器,时间复杂度为O(1),可结合find()函数使用。
如st.erase(st.find(100));//利用find()函数找到100,然后用erase删除
- st.erase(value):value为需要删除元素的值,时间复杂度为O(logN)。
如st.erase(100); //删除值为100的元素
- st.erase(it):it为需要删除元素的迭代器,时间复杂度为O(1),可结合find()函数使用。
-
本题思路:
用散列表,首先将数字都映射到散列表上,然后,对于每个数字,找到后就删除,然后向两边同时搜,只要搜到了就删除,最后求出长度。
哈希表搜是O(1),因为每个数字只会添加一次,删除一次,所以复杂度是O(n) -
注意,牛客网中使用unordered_set时要加上头文件#include <unordered_set>
-
本题的散列表使用unordered_set而不是unordered_map的原因:
unordered_set是一个不含重复元素的容器,且本题只需要保留元素本身而不用考虑它的个数。 -
将vector num中的所有元素初始化为unordered_set st的写法:
unordered_set<int> st(num.begin(), num.end());
#include <unordered_set>
class Solution {
public:
int longestConsecutive(vector<int>& num) {
int size = num.size();
if(size <= 1) return size;
//初始化hash表
unordered_set<int> st(num.begin(), num.end());
int res(0);
for(auto n : num) {
//如果没找到该元素,则直接跳过
if(st.find(n) == st.end()) continue;
int left(n), right(n);
//向左寻找
while(st.find(left - 1) != st.end()) {
st.erase(st.find(-- left));
}
//向右寻找
while(st.find(right + 1) != st.end()) {
st.erase(st.find(++ right));
}
res = max(res, right - left + 1);
}
return res;
}
};
时间复杂度为O(NlogN)的思路:先排序,再遍历判断
- cnt用于记录遍历过程中每次记录的最长连续序列长度,res用于记录最终结果的最长连续序列长度
- 如果num[i] == num[i - 1],则跳过,继续判断下一个
- 如果num[i] == num[i - 1] + 1,则res ++
- 否则,res = max(res, cnt), 并重新开始计数cnt = 1
class Solution {
public:
int longestConsecutive(vector<int>& num) {
int size = num.size();
if(size <= 1) return size;
sort(num.begin(), num.end());
int cnt(1), res(1);
for(int i = 1; i < size; i ++) {
if(num[i] == num[i - 1]) {
continue;
} else if(num[i] == num[i - 1] + 1) {
cnt ++;
} else {
res = max(res, cnt);
cnt = 1;
}
}
res = max(res, cnt);
return res;
}
};