Find the length of the longest run of consecutive integers in an unsorted array — in O(n)time by using a hash set to skip anything that isn't the first number of its run.
Given an unsorted array of integers, return the length of the longest consecutive sequence (e.g. 4, 5, 6, 7has length 4). Duplicates don't extend a run. For [100, 4, 200, 1, 3, 2] the answer is 4 — the sequence 1, 2, 3, 4.
v is the start of a consecutive run iff v - 1 is not in the set. Skip every other value. Then walk v, v+1, v+2, … with O(1) set lookups until the chain breaks. Each value is visited at most once total, giving O(n) — no sorting needed.new Set(nums) takes O(n) and gives O(1) lookups. Duplicates collapse — that's fine.v in the set, check if v - 1 is present.set.has(v - 1), v is a middle/end value — skip it entirely. This is the key savings.cur while set.has(cur + 1), counting the length.best = Math.max(best, run) after each run ends.while loop even begins.The while loop looks like it could walk O(n) per start. But we only enter a walk from a sequence start. Each element belongs to exactly one run and is visited at most once across all walks. Total work is O(n).
Set from [100, 4, 200, 1, 3, 2]. O(1) membership checks let us avoid sorting entirely.1function longestConsecutive(nums: number[]): number {2▶ const set = new Set<number>(nums);3▶ let best = 0;45 for (const v of set) {6 // Only begin a walk from sequence STARTS (no left neighbour).7 if (set.has(v - 1)) continue;89 let cur = v;10 let run = 1;11 while (set.has(cur + 1)) {12 cur++;13 run++;14 }1516 best = Math.max(best, run);17 }1819 return best;20}
function longestConsecutive(nums: number[]): number {
const set = new Set<number>(nums);
let best = 0;
for (const v of set) {
// Only begin a walk from sequence STARTS (no left neighbour).
if (set.has(v - 1)) continue;
let cur = v;
let run = 1;
while (set.has(cur + 1)) {
cur++;
run++;
}
best = Math.max(best, run);
}
return best;
}Set<number>costs O(n) and enables O(1) membership checks everywhere below. Duplicates are silently deduplicated — they can't extend a consecutive run.set (not nums) to avoid processing duplicate values twice. if (set.has(v - 1)) continueskips any value that has a left neighbour — it's provably not the start of its run. This single line is responsible for the O(n) guarantee.cur while the next integer exists in the set. Each step costs O(1). The total steps across all runs equal exactly the number of distinct values, so the total across all iterations is O(n).Math.max is O(1). Return best when done.while looks quadratic but the start-check ensures total iterations across all walks equal n.bestStart alongside best; after the loop reconstruct with Array.from({length: best}, (_, i) => bestStart + i).nums.includes(v + k)scan for k = 1, 2, …. That's O(n²) or O(n³) depending on inner loop implementation.function longestConsecutive(nums: number[]): number {
const set = new Set<number>(nums);
let best = 0;
for (const v of set) {
// Only begin a walk from sequence STARTS (no left neighbour).
if (set.has(v - 1)) continue;
let cur = v;
let run = 1;
while (set.has(cur + 1)) {
cur++;
run++;
}
best = Math.max(best, run);
}
return best;
}while looks quadratic but the start-check ensures total iterations across all walks equal n.Sort the numbers, then sweep once counting the length of each run of consecutive integers, skipping duplicates and resetting whenever the gap breaks.
function longestConsecutive(nums: number[]): number {
if (nums.length === 0) return 0;
const sorted = [...nums].sort((a, b) => a - b);
let best = 1;
let cur = 1;
for (let i = 1; i < sorted.length; i++) {
if (sorted[i] === sorted[i - 1]) continue; // duplicate — ignore
if (sorted[i] === sorted[i - 1] + 1) cur++; // extends the run
else cur = 1; // gap — restart
best = Math.max(best, cur);
}
return best;
}O(n log n). Dropping everything into a hash set and only starting a count at run-heads (values with no x − 1 present) reaches O(n).| "longest consecutive" or "consecutive run" | hash set + start-only walk |
| unsorted array, O(n) required | Set for O(1) membership, skip non-starts |
| temptation to sort first | ask: can a set skip the redundant work? |
| "how many distinct runs / components" | start-check + walk per component |
function longestConsecutive(nums: number[]): number {
const set = new Set<number>(nums);
let best = 0;
for (const v of set) {
if (set.has(v - 1)) continue; // skip: not a start
let cur = v, run = 1;
while (set.has(cur + 1)) { cur++; run++; }
best = Math.max(best, run);
}
return best;
}Set<number> from the input array — enables O(1) lookups and collapses duplicates.nums = [100, 4, 200, 1, 3, 2], which values are sequence starts?