Given an unsorted array of integers, find the length of the longest consecutive elements sequence.
Your algorithm should run in O(n) complexity.
Example:
Input: [100, 4, 200, 1, 3, 2]
Output: 4
Explanation: The longest consecutive elements sequence is [1, 2, 3, 4]. Therefore its length is 4.
思路:
如果能排序的话就比较简单,但是要求时间复杂度是O(n),而比较排序O(nlogn)
所以不用排序(虽然快速排序最佳是O(n))
注意最长连续子序列不包括重复元素,[4,4,5,5,6,6]的最长连续子序列长度是3, 而不是6
对每个元素,看它左边连续序列的长度和右边子序列长度
遍历每个元素,每个元素保存(key, value), 其中key是nums[i], value是在nums[i]处最长连续子序列的长度。
而nums[i]可能是以下几种情况
len代表当前元素nums[i]处最长连续子序列的长度
(1)nums[i]是最长连续子序列的右边界,如[1, 2]中的2
子序列的长度保存在左边界和右边界处,即key = nums[i] 和 nums[i - len_r] 处保存value = len, len_l指nums[i]左边的最长连续子序列长度,即看key=nums[i]-1处的value
(2)nums[i]是最长连续子序列的左边界,如[1, 2]中的1
子序列的长度保存在左边界和右边界处,即key = nums[i] 和 nums[i + len_r] 处保存value = len, len_r指nums[i]右边的最长连续子序列长度,即看key=nums[i]+1处的value
(3)nums[i]把左右子序列连接起来,如[1, 2] + 3 + [4, 5]
左边子序列的长度可以保存在2元素处,即看key=nums[i]-1处的value
右边子序列的长度可以保存在4元素处,即看key=nums[i]+1处的value
整体长度为len = len_r + len_r + 1
再更新nums[i], nums[i]-len_r, nums[i] + len_r,即更新元素本身(用来排除重复元素),左边界,右边界处的value到len
再更新整体最大值
由此可以看到需要一个HashMap保存元素和它对应的长度
对每个元素,仅需要根据它左右相邻的元素来得到左右子序列长度
每遍历一个元素,保存它自己和左右子序列边界处的元素对应的序列长度
public int longestConsecutive(int[] nums) {
HashMap<Integer, Integer> count = new HashMap<>();
int maxLen = 0;
for (int num : nums) {
if (count.containsKey(num)) {
continue;
}
int left = count.getOrDefault(num - 1, 0);
int right = count.getOrDefault(num + 1, 0);
int len = left + right + 1;
maxLen = Math.max(maxLen, len);
count.put(num, len);
count.put(num - left, len);
count.put(num + right, len);
}
return maxLen;
}