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.
We will use HashMap. The key thing is to keep track of the sequence length and store that in the boundary points of the sequence. For example, as a result, for sequence {1, 2, 3, 4, 5}, map.get(1) and map.get(5) should both return 5.
Whenever a new element n is inserted into the map, do two things:
- See if n - 1 and n + 1 exist in the map, and if so, it means there is an existing sequence next to n. Variables left and right will be the length of those two sequences, while 0 means there is no sequence and n will be the boundary point later. Store (left + right + 1) as the associated value to key n into the map.
- Use left and right to locate the other end of the sequences to the left and right of n respectively, and replace the value with the new length.
Everything inside the for loop is O(1) so the total time is O(n).
package l128;
import java.util.HashMap;
import java.util.Map;
class Solution {
public int longestConsecutive(int[] nums) {
Map<Integer, Integer>m=new HashMap<Integer, Integer>();
for(int i:nums) {
if(m.containsKey(i)) continue;
int left=m.containsKey(i-1)?m.get(i-1):0;
int right=m.containsKey(i+1)?m.get(i+1):0;
/*
* Without it, the program may go wrong to handle duplicated num when there is only one neighbor number around it,
* or the consecutive area including it has changed longer on only one side, or both scenarios happen together.
*/
m.put(i, left+right+1);
m.put(i-left, left+right+1);
m.put(i+right, left+right+1);
}
int res=0;
for(int k:m.keySet()) res=Math.max(res, m.get(k));
return res;
}
public static void main(String[] args) {
Solution s=new Solution();
System.out.println(s.longestConsecutive(new int[]{100, 4, 200, 1, 3, 2}));
}
}
至于m.put(i, left+right+1); 这一行的作用:是让m记住有个i数值是存在的,因为后续可能还会用到
比如2把[-1,1] [3,4]连起来了,如果不把2记录下来,后面更长的[-10,1] [3,4]就合并不起来了
或者直接遍历所有以i开始的(因为最长的肯定是以数组中某个数开始的)
First turn the input into a set of numbers. That takes O(n) and then we can ask in O(1) whether we have a certain number.
Then go through the numbers. If the number x is the start of a streak (i.e., x-1 is not in the set), then test y = x+1, x+2, x+3, ... and stop at the first number y not in the set. The length of the streak is then simply y-x and we update our global best with that. Since we check each streak only once, this is overall O(n). This ran in 44 ms on the OJ, one of the fastest Python submissions.
def longestConsecutive(self, nums):
nums = set(nums)
best = 0
for x in nums:
if x - 1 not in nums:
y = x + 1
while y in nums:
y += 1
best = max(best, y - x)
return best