128. Longest Consecutive Sequence
unordered_map
我们也可以采用哈希表来做,刚开始哈希表为空,然后遍历所有数字,如果该数字不在哈希表中,那么我们分别看其左右两个数字是否在哈希表中,如果在,则返回其哈希表中映射值,若不在,则返回0,然后我们将left+right+1作为当前数字的映射,并更新res结果,然后更新d-left和d-right的映射值,参见代码如下:
use unordered_map to store the sequence length for current number. 29 ms
int longestConsecutive(vector<int>& nums) {
unordered_map<int, int> m;
int maxLength = 0;
for (int x: nums) {
if (m.find(x) != m.end()) continue;
auto it = m.find(x-1);
int left = it == m.end() ? 0: it->second;
it = m.find(x+1);
int right = it == m.end() ? 0 : it->second;
int size = 1+right+left;
m[x] = size;
maxLength = max(maxLength, size);
m[x+right] = size;
m[x-left] = size;
}
return maxLength;
}
unordered_set
这道题要求求最长连续序列,并给定了O(n)复杂度限制,我们的思路是,使用一个集合set存入所有的数字,然后遍历数组中的每个数字,如果其在集合中存在,那么将其移除,然后分别用两个变量pre和next算出其前一个数跟后一个数,然后在集合中循环查找,如果pre在集合中,那么将pre移除集合,然后pre再自减1,直至pre不在集合之中,对next采用同样的方法,那么next-pre-1就是当前数字的最长连续序列,更新res即可。代码如下:
16ms 查询完直接erase
int longestConsecutive(vector<int>& nums) {
int res = 0;
unordered_set<int> s(nums.begin(), nums.end());
for (int val : nums) {
if (!s.count(val)) continue;
s.erase(val);
int pre = val - 1, next = val + 1;
while (s.count(pre)) s.erase(pre--);
while (s.count(next)) s.erase(next++);
res = max(res, next - pre - 1);
}
return res;
}
19ms
int longestConsecutive(vector<int>& nums) {
unordered_set<int> mySet(nums.begin(), nums.end());
int result = 0;
for (int i=0; i<nums.size(); i++)
{
//don't compare if the element is not the beginning of a sequence.
if (mySet.find(nums[i]-1) != mySet.end()) continue;
//we found an element that could be a beginning of a sequence, now loop thru the hash set for a sequence.
int length = 0;
while (mySet.find(nums[i]++) != mySet.end())
length++;
result = max(result, length);
}
return result;
}
sort
Time Complexity: O(nlogn +n)
int longestConsecutive(vector<int>& nums) {
sort(nums.begin(), nums.end());
int maxLength = 1, currentLength = 1;
for (int i = 1; i < nums.size(); ++i) {
if (nums[i] == nums[i-1]) continue;
if (nums[i] == nums[i-1]+1) {
++currentLength;
} else {
maxLength = max(maxLength, currentLength);
currentLength = 1;
}
}
return max(maxLength, currentLength);
}
union-find
class Solution {
private:
int size = 0;
int *id, *sz;
int root(int i) {
while (i != id[i]) {
id[i] = id[id[i]];
i = id[i];
}
return i;
}
bool connected(int p, int q) {
return root(p) == root(q);
}
void union_(int p, int q) {
cout << "hi2\n";
int i = root(p);
int j = root(q);
if (i == j) return;
if (sz[i] < sz[j]) {
id[i] = j;
sz[j] += sz[i];
} else {
id[j] = i;
sz[i] += sz[j];
}
}
int maxSz() {
int res = 0;
for (int i = 0; i < size; ++i)
res = max(res, sz[i]);
return res;
}
public:
int longestConsecutive(vector<int>& nums) {
size = nums.size();
id = new int[size];
sz = new int[size];
for (int i = 0; i < size; ++i) {
id[i] = i;
sz[i] = 1;
}
unordered_map<int, int> m;
for (int i = 0; i < size; i++) {
if (m.find(nums[i]) != m.end()) continue; // in case of duplicate
// instore the position of current key
m[nums[i]] = i;
if (m.find(nums[i]+1) != m.end()) {
union_(i, m[nums[i]+1]);
}
if (m.find(nums[i]-1) != m.end()) {
union_(i, m[nums[i]-1]);
}
}
return maxSz();
}
};