Longest Consecutive Sequence
You can arrange string anyways you need to return longest consecutive string,
Longest Consecutive Sequence
Problem
You are given an unsorted array of integers nums. Return the length of the longest consecutive sequence of numbers.
You must write an algorithm that runs in O(n) time.
A consecutive sequence is a group of numbers like 1, 2, 3, 4, where each number is exactly one more than the one before it. The numbers do not need to be next to each other in the array.
Examples
Example 1
Input: nums = [100,4,200,1,3,2]
Output: 4
- The longest consecutive sequence is
[1, 2, 3, 4]. - Its length is 4.
Example 2
Input: nums = [0,3,7,2,5,8,4,6,0,1]
Output: 9
- The sequence is
0, 1, 2, 3, 4, 5, 6, 7, 8.
Example 3
Input: nums = [1,0,1,2]
Output: 3
- The sequence is
0, 1, 2. - The duplicate
1is counted only once.
Constraints
0 <= nums.length <= 10^5-10^9 <= nums[i] <= 10^9
Main Idea
The values can be as large as 10^9, so we cannot make an array with one cell for each value. We need another way.
Sorting idea
- Sort the array. Then consecutive numbers sit next to each other.
- Walk through the sorted array and count the length of each run.
- Skip duplicates, because they do not make a sequence longer.
- This is simple, but sorting takes
O(n log n), so it does not meet theO(n)rule.
Set idea (optimal)
- Put all numbers in a Set. A Set checks "is this number here?" in
O(1)time. - A number is the start of a sequence if
num - 1is not in the set. - For each start, count upward:
num + 1,num + 2, ... while the numbers are in the set. - Numbers that are not a start are skipped. They will be counted when we count from their start.
Why is this
O(n)? The innerwhileloop runs only from a start. Each number is visited by thewhileloop at most once, because it belongs to only one sequence. So the total work isO(n), notO(n²).
Solution 1: Sorting
var longestConsecutive = function (nums) {
if (nums.length === 0) return 0;
nums.sort((a, b) => a - b);
let streak = 1;
let longestStreak = 1;
for (let i = 1; i < nums.length; i++) {
if (nums[i] === nums[i - 1]) {
// duplicate, skip it
continue;
} else if (nums[i] === nums[i - 1] + 1) {
// the run continues
streak++;
} else {
// the run is broken, start again
streak = 1;
}
longestStreak = Math.max(longestStreak, streak);
}
return longestStreak;
};
Note: I removed the
console.log(nums)line from your code. It prints the whole array and slows the code down.
How the Code Works
- If the array is empty, we return
0. sort((a, b) => a - b)sorts numbers by value. The default sort compares numbers as text, so we need(a, b) => a - b.streakis the length of the current run.longestStreakis the best run so far. Both start at1.- Duplicate: We use
continue, so the run stays the same. - Next number (
previous + 1): The run grows by1. - Gap: The run is broken, so
streakgoes back to1. - After each step, we keep the maximum.
Dry Run
Let us take nums = [1, 0, 1, 2]. After sorting: [0, 1, 1, 2].
i | nums[i] | Case | streak | longestStreak |
|---|---|---|---|---|
| start | - | - | 1 | 1 |
1 | 1 | 0 + 1, run continues | 2 | 2 |
2 | 1 | Duplicate, skip | 2 | 2 |
3 | 2 | 1 + 1, run continues | 3 | 3 |
The answer is 3.
Complexity
- Time Complexity:
O(n log n)- Sorting is the biggest cost. The loop takes
O(n).
- Sorting is the biggest cost. The loop takes
- Space Complexity:
O(1)extra, orO(n)depending on the sort.- The sort works in place, but the engine may use extra memory.
Important: This solution works, but it does not meet the
O(n)rule of the problem.
Solution 2: Set (Optimal)
function longestConsecutive(nums) {
if (nums.length === 0) return 0;
const set = new Set(nums);
let longest = 1;
for (let num of set) {
// check if num is the start of a sequence
if (!set.has(num - 1)) {
let currentNum = num;
let currentStreak = 1;
// count the length of the sequence
while (set.has(currentNum + 1)) {
currentNum += 1;
currentStreak += 1;
}
longest = Math.max(longest, currentStreak);
}
}
return longest;
}
How the Code Works
- Step 1:
new Set(nums)puts all numbers in a set. Duplicates are removed automatically. - Step 2: We loop over the numbers in the set.
- Step 3: If
num - 1is in the set,numis in the middle of a sequence. We skip it. - Step 4: If
num - 1is not in the set,numis a start. We count upward with thewhileloop, andcurrentStreakbecomes the length of the sequence. - Step 5: We keep the maximum in
longest.
Dry Run
Let us take nums = [100, 4, 200, 1, 3, 2].
The set is {100, 4, 200, 1, 3, 2}.
num | Is num - 1 in the set? | Start? | Sequence counted | longest |
|---|---|---|---|---|
100 | 99: No | Yes | 100 (length 1) | 1 |
4 | 3: Yes | No, skip | - | 1 |
200 | 199: No | Yes | 200 (length 1) | 1 |
1 | 0: No | Yes | 1, 2, 3, 4 (length 4) | 4 |
3 | 2: Yes | No, skip | - | 4 |
2 | 1: Yes | No, skip | - | 4 |
The answer is 4.
Complexity
- Time Complexity:
O(n)- Building the set takes
O(n). - The
whileloop runs only from a sequence start, so each number is visited at most once in total. - Each
hascheck takesO(1)on average.
- Building the set takes
- Space Complexity:
O(n)- The set holds up to
nnumbers.
- The set holds up to
Comparison
| Approach | Time Complexity | Space Complexity | Meets O(n)? |
|---|---|---|---|
| Sorting | O(n log n) | O(1) extra | No |
| Set | O(n) | O(n) | Yes |
Summary
- The values can be very large, so we cannot use an array indexed by value.
- Sorting works, but it takes
O(n log n)time, so it does not meet the problem rule. - The Set solution counts only from the start of each sequence, which is a number whose
num - 1is not in the set. - Because of this, each number is counted once, and the total time is
O(n). - The Set also removes duplicates for us.
- The Set solution runs in
O(n)time and usesO(n)space.