Longest Consecutive Sequence Solution
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.
Problem Statement
Given an unsorted array of integers nums, return the length of the longest consecutive elements sequence. For example, [1, 2, 3, 4] is a consecutive sequence of length 4. You must write an algorithm that runs in O(n) time.
Brute Force โ Sort O(n log n)
Sort the array, then scan for consecutive runs. Track the current streak length and update the maximum whenever the streak breaks.
After sorting, consecutive numbers are adjacent. A linear scan finds all consecutive runs by checking if nums[i] == nums[i-1] + 1.
num-1 is NOT in the set.
| Metric | Value |
|---|---|
| Time | O(n log n) โ dominated by sort |
| Space | O(1) โ or O(n) depending on sort implementation |
HashSet โ O(n)
Put all numbers in a HashSet. For each number, check if it's the start of a sequence (i.e., num-1 is NOT in the set). If it is, count consecutive numbers forward: num, num+1, num+2, ... Track the maximum length.
- Step 1: Add all elements to a HashSet (deduplicates automatically).
- Step 2: For each number in the set, check if
num - 1exists. If it does, skip โ this number is NOT a sequence head. - Step 3: If
num - 1is absent, this IS a head. Count forward:num, num+1, num+2, ...while each successor exists in the set. - Step 4: Update the maximum length. Return it after processing all elements.
- Any problem that asks for consecutive ranges in an unsorted collection โ think HashSet + sequence-head detection.
- The signal is "find longest run" or "count sequences" without sorting.
- The trick is to only start counting from heads to avoid redundant work.
- This pattern is specific to LC 128 but the "head detection" idea generalizes to union-find problems.
- The inner while-loop only runs for sequence heads, and each element is visited at most twice โ once in the outer loop and once as part of a forward count.
- Total work across all iterations is O(n), not O(nยฒ).
Visual Walkthrough
Trace through nums = [100, 4, 200, 1, 3, 2]:
- Elements 4, 3, 2 were skipped because they have predecessors in the set.
- Only sequence heads (1, 100, 200) trigger the counting loop. This prevents redundant work and keeps total time at O(n).
Code โ Java & Python
Complexity Analysis
| Approach | Time | Space | Trade-off |
|---|---|---|---|
| Sort + Scan | O(n log n) | O(1) | Violates O(n) requirement; modifies input |
| Brute Force (check each) | O(nยณ) | O(1) | For each element, search array for next consecutive |
| HashSet โ optimal | O(n) | O(n) | O(1) lookups; each element visited at most twice |
- Union-Find also achieves O(nยทฮฑ(n)) โ O(n) โ but it's more complex to implement for this specific problem.
- HashSet with head detection is cleaner, more intuitive, and strictly O(n) without the inverse-Ackermann constant.
- Use Union-Find when you need to merge dynamic ranges, not for static one-pass problems.
Edge Cases & Pitfalls
| Case | Input | Why It Matters |
|---|---|---|
| Empty array | [] | Return 0 โ no elements, no sequence. |
| Single element | [7] | One element is a sequence of length 1. |
| Duplicates | [1,2,2,3] | HashSet deduplicates automatically. Sequence is [1,2,3] โ length 3. |
| Negative numbers | [-3,-2,-1,0] | Negatives form valid sequences. Head is -3 (no -4 in set). |
| All same value | [5,5,5] | Set becomes {5}. 5 is a head (4 absent). Length 1. |
| Disjoint sequences | [1,3,5,7] | Four sequences of length 1. Each is its own head. |
nums and it has duplicates, you'll process the same head multiple times โ degrading performance. Always iterate over the set view to avoid redundant work.