Given an array of integers nums, return the length of the longest consecutive sequence of elements that can be formed.
A 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.
Example 1:
Input: nums = [2,20,4,10,3,4,5]
Output: 4Explanation: The longest consecutive sequence is [2, 3, 4, 5].
Example 2:
Input: nums = [0,3,2,5,4,6,1,1]
Output: 7Constraints:
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.
A brute force solution would be to consider every element from the array as the start of the sequence and count the length of the sequence formed with that starting element. This would be an O(n^2) solution. Can you think of a better way?
Is there any way to identify the start of a sequence? For example, in [1, 2, 3, 10, 11, 12], only 1 and 10 are the beginning of a sequence. Instead of trying to form a sequence for every number, we should only consider numbers like 1 and 10.
We can consider a number num as the start of a sequence if and only if num - 1 does not exist in the given array. We iterate through the array and only start building the sequence if it is the start of a sequence. This avoids repeated work. We can use a hash set for O(1) lookups by converting the array to a hash set.
A consecutive sequence grows by checking whether the next number (num + 1, num + 2, …) exists in the set.
The brute-force approach simply starts from every number in the list and tries to extend a consecutive streak as far as possible.
For each number, we repeatedly check if the next number exists, increasing the streak length until the sequence breaks.
Even though this method works, it does unnecessary repeated work because many sequences get recomputed multiple times.
res to store the maximum streak length.num in the original list:curr = num.curr exists in the set:curr += 1).res with the longest streak found so far.res after checking all numbers.class Solution:
def longestConsecutive(self, nums: List[int]) -> int:
res = 0
store = set(nums)
for num in nums:
streak, curr = 0, num
while curr in store:
streak += 1
curr += 1
res = max(res, streak)
return resIf we sort the numbers first, then all consecutive values will appear next to each other.
This makes it easy to walk through the sorted list and count how long each consecutive sequence is.
We simply move forward while the current number matches the expected next value in the sequence.
Duplicates don’t affect the result—they are just skipped—while gaps reset the streak count.
This approach is simpler and more organized than the brute force method because sorting places all potential sequences in order.
0.res to track the longest streak,curr as the first number,streak as 0,i = 0.i is within bounds:nums[i] does not match curr, reset:curr = nums[i]streak = 0curr by advancing i while nums[i] == curr.streak by 1 since we found the expected number.curr by 1 to expect the next number in the sequence.res with the maximum streak found so far.res after scanning the entire list.class Solution:
def longestConsecutive(self, nums: List[int]) -> int:
if not nums:
return 0
res = 0
nums.sort()
curr, streak = nums[0], 0
i = 0
while i < len(nums):
if curr != nums[i]:
curr = nums[i]
streak = 0
while i < len(nums) and nums[i] == curr:
i += 1
streak += 1
curr += 1
res = max(res, streak)
return resTo avoid repeatedly recounting the same sequences, we only want to start counting when we find the beginning of a consecutive sequence.
A number is the start of a sequence if num - 1 is not in the set.
This guarantees that each consecutive sequence is counted exactly once.
Once we identify such a starting number, we simply keep checking if num + 1, num + 2, … exist in the set and extend the streak as far as possible.
This makes the solution efficient and clean because each number contributes to the sequence only one time.
numSet for O(1) lookups.longest to track the length of the longest consecutive sequence.num in numSet:num - 1 is not in the set:num is the start of a sequence.length = 1.num + length exists in the set, increase length.longest with the maximum length found.longest after scanning all numbers.class Solution:
def longestConsecutive(self, nums: List[int]) -> int:
numSet = set(nums)
longest = 0
for num in numSet:
if (num - 1) not in numSet:
length = 1
while (num + length) in numSet:
length += 1
longest = max(length, longest)
return longestWhen we place a new number into the map, it may connect two existing sequences or extend one of them.
Instead of scanning forward or backward, we only look at the lengths stored at the neighbors:
mp[num - 1] gives the length of the sequence ending right before nummp[num + 1] gives the length of the sequence starting right after numBy adding these together and including the current number, we know the total length of the new merged sequence.
We then update the left boundary and right boundary of this sequence so the correct length can be retrieved later.
This keeps the whole operation very efficient and avoids repeated work.
mp that stores sequence lengths at boundary positions.res = 0 to store the longest sequence found.num in the input:num is already in mp, skip it.length = mp[num - 1] + mp[num + 1] + 1num.mp[num - mp[num - 1]] = lengthmp[num + mp[num + 1]] = lengthres to keep track of the longest sequence.res after processing all numbers.class Solution:
def longestConsecutive(self, nums: List[int]) -> int:
mp = defaultdict(int)
res = 0
for num in nums:
if not mp[num]:
mp[num] = mp[num - 1] + mp[num + 1] + 1
mp[num - mp[num - 1]] = mp[num]
mp[num + mp[num + 1]] = mp[num]
res = max(res, mp[num])
return res