128. Longest Consecutive Sequence (M)

https://leetcode.com/problems/longest-consecutive-sequence/

Given an unsorted array of integers nums, return the length of the longest consecutive elements sequence.

You must write an algorithm that runs in O(n) time.

Example 1:

Input: nums = [100,4,200,1,3,2]
Output: 4
Explanation: The longest consecutive elements sequence is [1, 2, 3, 4]. Therefore its length is 4.

Example 2:

Input: nums = [0,3,7,2,5,8,4,6,0,1]
Output: 9

Constraints:

  • 0 <= nums.length <= 105

  • -109 <= nums[i] <= 109

Solution:

https://www.jiuzhang.com/problem/longest-consecutive-sequence/

Version 1:

既然要O(n)算法,排序显然不行,所以自然想到用hash table。将序列中的所有数存到一个unordered_set中。对于序列里任意一个数A[i],我们可以通过set马上能知道A[i]+1和A[i]-1是否也在序列中。如果在,继续找A[i]+2和A[i]-2,以此类推,直到将整个连续序列找到。为了避免在扫描到A[i]-1时再次重复搜索该序列,在从每次搜索的同时将搜索到的数从set中删除。直到set中为空时,所有连续序列搜索结束。

复杂度:由于每个数字只被插入set一次,并删除一次,所以算法是O(n)的。

public class Solution {
    /**
     * @param nums: A list of integers
     * @return an integer
     */
    public int longestConsecutive(int[] nums) {
        HashSet<Integer> set = new HashSet<>();
        for (int i = 0; i < nums.length; i++) {
            set.add(nums[i]);
        }
        
        int longest = 0;
        for (int i = 0; i < nums.length; i++) {
            int down = nums[i] - 1;
            while (set.contains(down)) {
                set.remove(down);
                down--;
            }
            
            int up = nums[i] + 1;
            while (set.contains(up)) {
                set.remove(up);
                up++;
            }
            
            longest = Math.max(longest, up - down - 1);
        }
        
        return longest;
    }
}

Version 2:

  • 相比标准答案,此解是one pass solution

  • 用一个HashMap来记录还有数字i的连续序列的长度,该长度等于左右连续序列长度的和加 - count(i) = count(i - 1) + count(i + 1) + 1

  • 需要注意的是,当加入一个数字i的时候,除了要利用上面公式更新该点的序列长度以外,还要把它左边和右边连续序列端点对应的长度改掉 举个例子:4(1)表示含有数字4的连续序列长度是1 4,5,3,1,2 => 4(1) => 4(2), 5(2) => 4(2), 5(3), 3(3) => 4(2), 5(3), 3(3), 1(1) => 4(2), 5(5), 3(3), 1(5), 2(5)

public class Solution {
    /**
     * @param num: A list of integers
     * @return: An integer
     */
    public int longestConsecutive(int[] num) {
        // write your code here
        if (num == null || num.length == 0) {
            return 0;
        }
        
        Map<Integer, Integer> streak = new HashMap<>();
        
        int max = 0;
        for (int n : num) {
            if (streak.containsKey(n)) {
                continue;
            }
            int leftCount = 0, rightCount = 0;
            if (streak.containsKey(n - 1)) {
                leftCount = streak.get(n - 1);    
            }
            if (streak.containsKey(n + 1)) {
                rightCount = streak.get(n + 1);
            }
            int count = leftCount + rightCount + 1;
            max = Math.max(max, count);
            streak.put(n, count);
            streak.put(n - leftCount, count);
            streak.put(n + rightCount, count);
        }
        
        return max;
    }
}

Version 3:

pq排了一下序, set去了一下重复, 剩下就没啥难度了, 应该算O(N)的吧

public class Solution {
    /**
     * @param num: A list of integers
     * @return: An integer
     */
    public int longestConsecutive(int[] num) {
        // write your code here
        if (num == null || num.length == 0) {
            return 0;
        } 
        
        PriorityQueue<Integer> pq = new PriorityQueue<Integer>();
        Set<Integer> set = new HashSet<>();
        for (int i = 0; i < num.length; i++) {
            if (!set.contains(num[i])) {
                set.add(num[i]);
                pq.offer(num[i]);
            }
        }
        
        int res = 1;
        int temp = 1;
        int start = pq.poll();
        while (!pq.isEmpty()) {
            int curr = pq.poll();
            if (curr == start + 1) {
                start = curr;
                temp++;
            } else {
                temp = 1;
                start = curr;
            }
            res = Math.max(res, temp);
        }
        
        return res;
    }
}

Last updated