Python 0228.py
class Solution:
def summaryRanges(self, nums: List[int]) -> List[str]:
if not nums:
return []
nums.append(2**100)
result = []
left = right = nums[0]
for i in range(1, len(nums)):
n = nums[i]
if n == right + 1:
right = n
else:
if left == right:
result.append(str(left))
else:
result.append(str(left) + "->" + str(right))
left = right = nums[i]
return result
Difficulty
and has an acceptance rate of about 55% (1+ million submissions).
Typical patterns to solve this problem:
- Array
AI Disclaimer
However, two years later I set up this website and used various AI tools to generate most of the walkthrough / explanations below.
See this dedicated page for more details.
Code Walkthrough
Overview
The provided implementation solves the “summary ranges” problem: given a sorted list of distinct integers, it produces a compact string representation of consecutive sequences. The algorithm walks through the input once, building ranges on-the-fly, and returns a list of formatted strings. It gracefully handles empty inputs and the termination of the final range by appending a sentinel value.
Core Logic
The function begins by checking for an empty list. If the input is empty, it immediately returns an empty list, covering the edge case where no processing is required.
if not nums:
return []
A sentinel value far beyond any realistic input (2**100) is appended to the original list. This sentinel guarantees that the last real range will be flushed when the loop encounters a gap, eliminating the need for a separate post-loop cleanup step.
nums.append(2**100)
Two variables, left and right, are initialized to the first element. They represent the start and end of the current consecutive range.
left = right = nums[0]
The main loop iterates from the second element to the end of the extended list. For each element n, the algorithm checks whether it continues the current range (n == right + 1). If it does, only the right bound is extended.
if n == right + 1:
right = n
When a gap is detected, the current range is finalized. If left equals right, the range consists of a single number and is added as that number’s string representation. Otherwise, the range is formatted as "start->end". After appending the formatted range to the result list, left and right are reset to start a new range from the current element.
if left == right:
result.append(str(left))
else:
result.append(str(left) + "->" + str(right))
left = right = nums[i]
Finally, the accumulated result list is returned.
return result
Edge Cases Handled
- Empty Input - The early return for an empty list prevents index errors and returns the correct empty result.
- Single-Element Input - With only one number, the loop still runs once (the sentinel forces a gap), and the code correctly formats the single value without the arrow.
- All Numbers Consecutive - The sentinel ensures the final range is emitted even when the entire list forms one continuous sequence.
- Non-Consecutive End - When the last numbers are not part of a longer range, the sentinel again forces the termination logic, producing the appropriate single-value entries.
Implicit Performance Optimizations
The algorithm processes the list in a single pass, updating only a few scalar variables (left, right, n) and appending to the result list when necessary. By appending a sentinel value, it avoids an extra conditional check after the loop, which reduces branching overhead. The use of direct string concatenation (str(left) + "->" + str(right)) avoids the overhead of more complex formatting functions. Overall, the approach minimizes memory allocations and keeps the runtime proportional to the length of the input.
ELI5 - Simplified Explanation
Imagine a long row of numbered tiles laid out on the floor. Some tiles are right next to each other, like one, two, and three. Other tiles have gaps between them, like jumping from three all the way to seven. The goal here is to group the neighboring numbers together so they can be bundled up like little families.
The computer starts by peeking at the first number and holding it in its hand. It looks at the next number to see if it is the very next one in line. If the number is just one step higher, the computer keeps holding onto the end of the group. If there is a gap, the computer knows the group is finished.
When a group is finished, it writes down a note. If the group is just one single number, it writes that number down on a piece of paper. If the group has several numbers in a row, it writes down the start of the group, a little arrow, and then the end of the group. Then it starts all over again with the next number it finds, making new groups until all the tiles are organized. A giant, secret, super large number is added to the end of the line just to make sure the computer checks the final group before it puts its pencil down.
Code Quality
Complexity Analysis
As a rule of thumb, the maximum input size for one second execution time is
- factorial: up to 10 elements
- exponential: up to 20 elements
- polynomial: a few thousand elements
- loglinear: up to 100,000 elements
- linear: a few million elements
- logarithmic: a billion elements
- constant: practically unlimited
Other Solutions
Obviously, I did that after I solved the problem myself.
In general, AlgoMonster and WalkCCC solutions are high-quality and always worth a look.
I haven't checked most of the other solutions, but they might be helpful as well.
And of course, the LeetCode forum is always a good place (or even the best) to look for alternative approaches.
(click on a column header to sort the table)
| author | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| author | solutions | ||||||||||
| www | AlgoMonster | C++ | Python | Java | TS | ||||||
| WalkCCC | C++ | Python | Java | ||||||||
| leetcode.ca | C++ | Python | Java | Rust | Go | C# | TS | ||||
| LeetcodeHelp | C++ | Python | Java | ||||||||
| MemoryLimitExceeded | C++ | Python | |||||||||
| Progiez | C++ | Python | Java | ||||||||
| github | aylei | Rust | |||||||||
| black-shadows | C++ | ||||||||||
| chandansgowda | Python | ||||||||||
| charles-wangkai | Java | ||||||||||
| chenyanzhe | C++ | ||||||||||
| Dijkstra-Edu | Java | ||||||||||
| everthis | JS | ||||||||||
| fartem | Ruby | ||||||||||
| fengvyi | C++ | ||||||||||
| fpdjsns | C++ | ||||||||||
| gaosq0604 | Python | ||||||||||
| halfrost | Go | ||||||||||
| haoel | C++ | ||||||||||
| JoshCrozier | JS | ||||||||||
| keineahnung2345 | C++ | ||||||||||
| lennylxx | C | ||||||||||
| linouk23 | C++ | ||||||||||
| lkwq007 | Python | ||||||||||
| muhammadfarhankt | Go | ||||||||||
| pruthvikp | Python | ||||||||||
| qiyuangong | Python | ||||||||||
| ruoru | Rust | ||||||||||
| shreymehul | C# | ||||||||||
| suxrobGM | C# | ||||||||||
| trung-hn | Python | ||||||||||
| varunu28 | Java | ||||||||||
| vli02 | C | ||||||||||
| YuriSpiridonov | Python | ||||||||||
| zfang399 | C++ | ||||||||||
| AlgoMonster | C++, Python, Java, TypeScript | ||||||||||
| WalkCCC | C++, Python, Java | ||||||||||
| leetcode.ca | C++, C#, Go, Java, Python, Rust, TypeScript | ||||||||||
| LeetcodeHelp | C++, Java, Python | ||||||||||
| MemoryLimitExceeded | Python, C++ | ||||||||||
| Progiez | C++, Java, Python | ||||||||||
| aylei | Rust | ||||||||||
| black-shadows | C++, C++ | ||||||||||
| chandansgowda | Python | ||||||||||
| charles-wangkai | Java | ||||||||||
| chenyanzhe | C++ | ||||||||||
| Dijkstra-Edu | Java | ||||||||||
| everthis | JavaScript | ||||||||||
| fartem | Ruby | ||||||||||
| fengvyi | C++ | ||||||||||
| fpdjsns | C++ | ||||||||||
| gaosq0604 | Python | ||||||||||
| halfrost | Go | ||||||||||
| haoel | C++ | ||||||||||
| JoshCrozier | JavaScript | ||||||||||
| keineahnung2345 | C++ | ||||||||||
| lennylxx | C | ||||||||||
| linouk23 | C++ | ||||||||||
| lkwq007 | Python | ||||||||||
| muhammadfarhankt | Go | ||||||||||
| pruthvikp | Python | ||||||||||
| qiyuangong | Python | ||||||||||
| ruoru | Rust | ||||||||||
| shreymehul | C# | ||||||||||
| suxrobGM | C# | ||||||||||
| trung-hn | Python | ||||||||||
| varunu28 | Java | ||||||||||
| vli02 | C | ||||||||||
| YuriSpiridonov | Python | ||||||||||
| zfang399 | C++ |
Videos
Similar Problems
- problem 352: Data Stream as Disjoint Intervals
Solved On The Same Day
- problem 110: Balanced Binary Tree
- problem 111: Minimum Depth of Binary Tree
- problem 118: Pascal's Triangle
- problem 119: Pascal's Triangle II
- problem 530: Minimum Absolute Difference in BST
- problem 82: Remove Duplicates from Sorted List II
- problem 102: Binary Tree Level Order Traversal
- problem 103: Binary Tree Zigzag Level Order Traversal
- problem 105: Construct Binary Tree from Preorder and Inorder Traversal
- problem 106: Construct Binary Tree from Inorder and Postorder Traversal
- problem 107: Binary Tree Level Order Traversal II
- problem 109: Convert Sorted List to Binary Search Tree
- problem 117: Populating Next Right Pointers in Each Node II
- problem 128: Longest Consecutive Sequence
- problem 138: Copy List with Random Pointer
- problem 150: Evaluate Reverse Polish Notation
- problem 155: Min Stack
- problem 209: Minimum Size Subarray Sum
- problem 274: H-Index
- problem 380: Insert Delete GetRandom O(1)
- problem 427: Construct Quad Tree
- problem 452: Minimum Number of Arrows to Burst Balloons
- problem 30: Substring with Concatenation of All Words
- problem 37: Sudoku Solver
- problem 44: Wildcard Matching
- problem 1326: Minimum Number of Taps to Open to Water a Garden
Extra
- Tech Stack - my development environment and tools
- AI - how AI helped me create this website (NOT solving the problems)
- Progress - progression over time
- Quality - code quality