leetcode 128 是 longest consecutive sequence
[2, 9, 4,3] 如果是longest consecutive sequence 就是 [2, 4,3],而 longest consecutive subarray 是[4, 3]
1 longest consecutive sequence
思路1: 排序聚合,然后遍历只需要和前一个元素比较,O(nlgn)+O(n)
思路2: 类似无向图连通性问题,对于每个未被mark的值,分别左右探测,累计长度,并mark经过的值。
int longestConsecutive(vector<int> &num) {
unordered_map<int,bool> used;
for(auto &e :num) used[e]=false;
int maxLen =1;
for(auto &e : used) {
if(e.second) continue;
int len=1;
for(int x = e.first-1;used.find(x)!=used.end();--x){
len++;
used[x]=true;
}
for(int x = e.first+1;used.find(x)!=used.end();++x){
len++;
used[x]=true;
}
maxLen = max(maxLen,len);
}
return maxLen;
}
2 longest consecutive subarray
O(n^2)的方法:
枚举子答案子数组的右界i,维护一个当前连续的区间[start, end] 初始是[A[i], A[i]],j从i - 1往前扫,先加进set, 这个set的就是可以用来扩展边界的candidate集合,如果可以扩展(set 里有start - 1或者 end + 1)则更新边界,并且从set里移除,重复这个过程直到无法扩展,对于一个j,如果set为空,说明[j, i]之间的数都用上了,则[j, i]是一个合法的解,和最最优解比较、保存。
int longestConsecutiveSubArray(vector<int> &A) {
int maxLen = 0;
for (int i = 0; i < A.size(); ++i) {
unordered_set<int> s;
int start = A[i], end = A[i];
for (int j = i - 1; j >= 0; --j) {
s.insert(A[j]);
while (s.find(end + 1) != s.end()) {
++end;
s.erase(end);
}
while (s.find(start - 1) != s.end()) {
--start;
s.erase(start);
}
if (s.empty()) maxLen = max(maxLen, end - start + 1);
}
}
return maxLen;
}
update:又想出一个O(n)的
int longestConsecutiveSubArray(vector<int> &A) {
int maxLen = 0;
for (int i = 0; i < A.size(); ++i) {
unordered_set<int> s;
int start = A[i], end = A[i];
for (int j = i + 1; j < A.size(); ++j) {
s.insert(A[j]);
while (s.find(end + 1) != s.end()) {
++end;
s.erase(end);
}
while (s.find(start - 1) != s.end()) {
--start;
s.erase(start);
}
if (s.empty()) {
maxLen = max(maxLen, end - start + 1);
i = j;
}
}
}
return maxLen;
}