the set is empty
numSet on a number line sorted only for display · … marks a missing value · solid = current run · dashed = longest so far
public int longestConsecutive(int[] nums) { Set<Integer> numSet = new HashSet<>(); for (int n : nums) { numSet.add(n); } int longest = 0; for (int n : numSet) { if (!numSet.contains(n - 1)) { // n starts a run int length = 1; while (numSet.contains(n + length)) { length++; } longest = Math.max(length, longest); } } return longest;}
- n
- —
- contains(n − 1)
- —
- length
- —
- longest
- 0
- numSet
- —
Why it works
- Brute force counts up from every value: O(n²) set lookups, or O(n³) with a list. Sorting first and scanning for runs is O(n log n).
- Only start at a start. A value
nbegins a run exactly whenn − 1is missing. Every other value sits inside some run that its start will count, so it is skipped in O(1). - Why O(n): the inner
whileonly runs from starts, and each value is stepped over by at most one start's count. Total lookups: about 2 per value. The set costs O(n) space. - Pitfall: loop over the set, not over
nums. With many copies of a start value, looping overnumsrecounts the same run for each copy. - Order does not matter. A
HashSetis visited in whatever order it holds its values (the order is not guaranteed); a non-start can come before or after its start and the answer is the same.