给出一个未排序的整数数组,找出最长的连续元素序列的长度。
如:
给出[100, 4, 200, 1, 3, 2],
最长的连续元素序列是[1, 2, 3, 4]。返回它的长度:4。
你的算法必须有O(n)的时间复杂度。
初始思路
要找连续的元素,第一反应一般是先把数组排序。但悲剧的是题目中明确要求了O(n)的时间复杂度,要做一次排序,是不能达到的。不过我们还是先来看看排序的方案要怎么实现。
简单来说,排序后我们只要遍历数组,检查当前值减1是否等于上一个值,如果等,增加当前连续序列的计数;如果不等,将当前计数与当前最大值比较,如果更优替换最大值, 并重置计数为1。具体到细节上,我们还要考虑几个问题:
- 第一个数
处理第一个数时是没有上一个值的。有人可能觉得可以给存储上一个值的变量赋一个特别的初始值来表示处理的是第一个数。但是由于数组内元素的取值范围是所有的整数,不可能找出一个特别的值。所以代码中需要对第一个数做特殊的判断
- 重复的数
数组中可能会有重复的数,所以我们不能光判断当前值减1等于或不等于上一个值。还需要加上一个等不等与上一个值的判断,如果等,说明是一个重复的数字,直接不做任何处理跳到数组中的下一个数。
- 最后一组连续序列
由于我们只在遍历中发现当前值减1不等于上一个值时才尝试更新序列长度最大值。如果有一个连续序列一直持续到数组中的最后一个元素,这个序列的长度是没有得到处理的。因此我们需要在遍历完数组后再尝试更新依稀最大值。
加入了这些细节考虑后,代码就呼之欲出了:
1 class SolutionSort 2 { 3 public: 4 int longestConsecutive(std::vector<int> &num) 5 { 6 std::sort(num.begin(), num.end()); 7 8 int maxLen = 0; 9 int currentLen = 0; 10 int previous = 0; 11 12 for(auto iter = num.begin(); iter != num.end(); ++iter) 13 { 14 if(iter == num.begin())//第一个数的特殊情况 15 { 16 ++currentLen; 17 } 18 else 19 { 20 if(*iter == previous)//重复数的情况 21 { 22 continue; 23 } 24 else if(*iter - 1 == previous) 25 { 26 ++currentLen; 27 } 28 else 29 { 30 if(currentLen > maxLen) 31 { 32 maxLen = currentLen; 33 } 34 currentLen = 1; 35 } 36 } 37 previous = *iter; 38 } 39 40 //有一个连续序列持续到数组最后一个元素的情况 41 if(currentLen > maxLen) 42 { 43 maxLen = currentLen; 44 } 45 46 return maxLen; 47 } 48 };