Longest Consecutive Sequence

Problem

Given an array of integers nums, return the length of the longest consecutive sequence of elements that can be formed.

consecutive sequence is a sequence of elements in which each element is exactly 1 greater than the previous element. The elements do not have to be consecutive in the original array.

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

Examples

Example 1:

Input: nums = [2,20,4,10,3,4,5]

Output: 4

Explanation: The longest consecutive sequence is [2, 3, 4, 5].

Example 2:

Input: nums = [0,3,2,5,4,6,1,1]

Output: 7

Constraints

  • 0 <= nums.length <= 1000
  • -10^9 <= nums[i] <= 10^9

You should aim for a solution as good or better than O(n) time and O(n) space, where n is the size of the input array.

Solution

For every number, we track what is the longest sequence it is a part of. For every number we read for the first time, we set its sequence length to the entry on the left + the entry on the right + 1. If those were empty, then its defaults to 0. We then need to update the endpoint of the new sequence we just made.

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        // Idea is to have a map track the current length the number is a part of
        //   If we add an unseen number, the length of the sequence its now is in the lengths 
        //   of the left-right side added plus itself (+1). We then need to update the endpoints,
        //   which we can find by walking left by the amount the left item thinks its length is, 
        //   and same with the right. Because we are only filling in unseen items, we can ignore 
        //   the fact that the items in the middle no longer have the correct length representation,
        //   because when an item is added, its always beside an existing endpoint(s).
        std::unordered_map<int, int> lengths;
        int result = 0;
        for (const auto &num : nums) {
            // We cant use contains here because accessing left/right will default insert 0,
            // what we really need to check is if the value is non-zero
            if (lengths[num] == 0) {
                const auto length = lengths[num-1] + lengths[num+1] + 1;
                lengths[num] = length;
                lengths[num - lengths[num-1]] = length;
                lengths[num + lengths[num+1]] = length;
                result = std::max(result, length);
            }
        }
        return result;
    }
};