哎,这题又不会做,想了好久,还是想不出来,最长连续的数的长度,首先想到的肯定是排序,O(nlogn),不过题目要求是O(n),
于是又想到用hash的思想,类似数组记数的方式,不过即便不考虑存的空间的话,因为给定的数的大小并不在一定的范围之内,
所以最后的时间复杂度会是O(max - min),max是最大的数,min是最小的数,还是不满足题目的要求。
其实思考一下题目,所谓连续的数,只需要记录一段连续的数的最小的数和最大的数即可,当时也想到了这个,不过下意识的想法是用数组来存每个数所在的连续段,
这样每个数还是都要往回查找是否可以扩展前面某个连续段,感觉复杂度是O(n2)了,所以放弃了这个想法。
做不出来,无奈只好看别人的方法了,参考了peking2的解法(),很巧妙的利用了set,
不过感觉也不能完全算是O(n)的呀,因为set的插入、删除操作并不是O(1),而是O(logn),实际复杂度应该是O(log(n!))呀,实际具体和O(n)的差距是多少,还很难评估!
1 class Solution { 2 public: 3 set store; 4 int consecute(int n, bool direct) { 5 int count = 0; 6 while (store.count(n)) { 7 ++count; 8 store.erase(n); 9 if (direct) 10 n--;11 else 12 n++;13 }14 return count;15 }16 int longestConsecutive(vector &num) {17 // Start typing your C/C++ solution below18 // DO NOT write int main() function19 int res = 0;20 if (num.size() == 0) {21 return res;22 }23 store.clear();24 for (int i = 0; i < num.size(); i++) {25 store.insert(num[i]);26 }27 for (int i = 0; i < num.size(); i++) {28 if (store.count(num[i])) {29 res = max(res, (consecute(num[i], true) + consecute(num[i] + 1, false)));30 }31 }32 return res;33 }34 };
其实用记录每个数所在的连续段的范围(最小值,最大值)也是可以的,可以利用map<int, pair<int, int> >来每个数的对应范围。
然后遇到可以扩展区间的数时更新区间范围即可。同样也参考了peking2的代码(),
不过他的代码有个bug,遇到重复的数应该忽略。
1 class Solution { 2 public: 3 map> section; 4 int longestConsecutive(vector &num) { 5 // Start typing your C/C++ solution below 6 // DO NOT write int main() function 7 section.clear(); 8 int start = 0; 9 int end = 0;10 for (int i = 0; i < num.size(); i++) {11 int k = num[i];12 map >::iterator it = section.find(k);13 if (it != section.end()) {14 continue;15 }16 else {17 section.insert(make_pair(k, pair (k, k)));18 }19 it = section.find(k - 1);20 if (it != section.end()) {21 section[k].first = (it->second).first;22 }23 it = section.find(k + 1);24 if (it != section.end()) {25 section[k].second = (it->second).second;26 }27 it = section.find(section[k].first);28 if (it != section.end()) {29 (it->second).second = section[k].second;30 }31 it = section.find(section[k].second);32 if (it != section.end()) {33 (it->second).first = section[k].first;34 }35 if (section[k].second - section[k].first > end - start) {36 start = section[k].first;37 end = section[k].second;38 }39 }40 return (end - start + 1);41 }42 };