Summary Ranges solution and explanation
9 more videos on this problem
Summary Ranges - Leetcode 228 - Arrays & Strings (Python)Greg Hogg · 5:57 · 31K views
Summary Ranges | Leetcode-228 | GOOGLE | Explanation ➕ Live CodingcodestorywithMIK · 13:04 · 10K views
Summary Ranges | summary ranges | summary ranges leetcode | leetcode 228 | linearNaresh Gupta · 6:22 · 10K views
Leetcode - Summary Ranges (Python)Timothy H Chang · 5:03 · 4K views
Summary Ranges | Leet code 228 | Theory explained + Python codeSai Anish Malla · 11:15 · 2K views
Summary Ranges | LeetCode 228 | Solution Walkthrough - PythonTech and Navid · 13:52 · 1K views
Summary Ranges - 228. LeetCode - JavaTeddy Smith · 10:30 · 1K views
Summary Ranges | LeetCode 228 | October LeetCode Challenge | Day 28Learn Code Repeat · 8:14 · 605 views
Leetcode 228 - Summary Ranges - Python SolutionData Engineering Studies · 8:36 · 413 views
LeetCode 228. [easy] Summary RangesFrancesco Manicardi · 5:05 · 352 views
The problem
You are given a sorted unique integer array nums.
A range [a,b] is the set of all integers from a to b (inclusive).
Return the smallest sorted list of ranges that cover all the numbers in the array exactly. That is, each element of nums is covered by exactly one of the ranges, and there is no integer x such that x is in one of the ranges but not in nums.
Each range [a,b] in the list should be output as:
"a->b"ifa != b"a"ifa == b
Example 1:
Input: nums = [0,1,2,4,5,7] Output: ["0->2","4->5","7"] Explanation: The ranges are: [0,2] --> "0->2" [4,5] --> "4->5" [7,7] --> "7"
Example 2:
Input: nums = [0,2,3,4,6,8,9] Output: ["0","2->4","6","8->9"] Explanation: The ranges are: [0,0] --> "0" [2,4] --> "2->4" [6,6] --> "6" [8,9] --> "8->9"
Constraints:
0 <= nums.length <= 20-231 <= nums[i] <= 231 - 1- All the values of
numsare unique. numsis sorted in ascending order.
Approach overview
Problem Overview: You receive a sorted array of unique integers. The goal is to compress consecutive numbers into range strings. A single number becomes "x", while a sequence like 1,2,3 becomes "1->3". The result is a list of ranges covering the entire array.
The key observation: because the array is sorted and contains no duplicates, consecutive numbers always appear next to each other. The problem reduces to detecting where a sequence starts and where it breaks.
Approach 1: Sequential Range Detection (O(n) time, O(1) space)
Iterate through the array while tracking the start of the current range. For each element, check whether the next number continues the sequence using nums[i] + 1 == nums[i+1]. When this condition fails, the range ends. If the start and end indices are the same, output a single value string; otherwise output start->end. Then reset the start pointer to the next element and continue scanning.
This approach works because every element belongs to exactly one range, so the array only needs a single pass. No additional data structures are required. It’s straightforward and highly readable, making it a common baseline implementation.
Approach 2: Optimal Pointer Movement (O(n) time, O(1) space)
This method uses a two‑pointer style scan. One pointer marks the beginning of a range, while the other pointer advances forward as long as numbers remain consecutive. When the sequence breaks, the interval between the two pointers forms a valid range. Format the result and move the start pointer to the next unexplored position.
The difference from the previous approach is that the forward pointer aggressively expands the range before producing output. Each element is still visited once, giving linear time complexity. Because only a few index variables are used, the space complexity remains constant.
This pattern appears often in problems involving sorted arrays and interval compression. Similar pointer movement techniques show up in problems involving array traversal and range grouping.
Recommended for interviews: Interviewers expect the linear scan solution. Either sequential detection or two‑pointer expansion demonstrates the same key insight: detect boundaries where consecutive numbers stop. A brute force or nested scan would signal missed optimization opportunities, while the O(n) approach shows you recognize sorted array structure and exploit it efficiently.
Approach 1: Sequential Range Detection
This approach involves detecting the start and end of each range by iterating through the array sequentially. You remember the start of a potential range and adjust the range's end as long as consecutive numbers are found. When a break in consecutiveness occurs, you fix the end of the current range and start a new one.
from typing import List
def summaryRanges(nums: List[int]) -> List[str]:
ranges = []
i = 0
while i < len(nums):
start = i
while i + 1 < len(nums) and nums[i] + 1 == nums[i + 1]:
i += 1
if start == i:
ranges.append(str(nums[start]))
else:
ranges.append(f"{nums[start]}->{nums[i]}")
i += 1
return ranges
import java.util.ArrayList;
import java.util.List;
public class Solution {
public List<String> summaryRanges(int[] nums) {
List<String> result = new ArrayList<>();
int i = 0;
while (i < nums.length) {
int start = i;
while (i + 1 < nums.length && nums[i] + 1 == nums[i + 1]) {
i++;
}
if (start == i) {
result.add(String.valueOf(nums[start]));
} else {
result.add(nums[start] + "->" + nums[i]);
}
i++;
}
return result;
}
}
#include <vector>
#include <string>
using namespace std;
vector<string> summaryRanges(vector<int>& nums) {
vector<string> result;
int n = nums.size();
int i = 0;
while (i < n) {
int start = i;
while (i + 1 < n && nums[i] + 1 == nums[i + 1]) {
i++;
}
if (start == i) {
result.push_back(to_string(nums[start]));
} else {
result.push_back(to_string(nums[start]) + "->" + to_string(nums[i]));
}
i++;
}
return result;
}
function summaryRanges(nums) {
const result = [];
let i = 0;
while (i < nums.length) {
let start = i;
while (i + 1 < nums.length && nums[i] + 1 === nums[i + 1]) {
i++;
}
if (start === i) {
result.push(`${nums[start]}`);
} else {
result.push(`${nums[start]}->${nums[i]}`);
}
i++;
}
return result;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char** summaryRanges(int* nums, int numsSize, int* returnSize) {
char **result = (char **)malloc(numsSize * sizeof(char *));
*returnSize = 0;
int i = 0;
while (i < numsSize) {
int start = i;
while (i + 1 < numsSize && nums[i] + 1 == nums[i + 1]) {
i++;
}
int end = i;
char *range = (char *)malloc(25 * sizeof(char));
if (start == end) {
sprintf(range, "%d", nums[start]);
} else {
sprintf(range, "%d->%d", nums[start], nums[end]);
}
result[(*returnSize)++] = range;
i++;
}
return result;
}
using System;
using System.Collections.Generic;
public class Solution {
public IList<string> SummaryRanges(int[] nums) {
List<string> result = new List<string>();
int i = 0;
while (i < nums.Length) {
int start = i;
while (i + 1 < nums.Length && nums[i] + 1 == nums[i + 1]) {
i++;
}
if (start == i) {
result.Add(nums[start].ToString());
} else {
result.Add(nums[start] + "->" + nums[i]);
}
i++;
}
return result;
}
}Python uses a straightforward looping structure to find ranges. It uses format strings to easily concatenate numbers for ranges needing a '->'. This solution appends directly to list using range or single-potential numbers.
Time Complexity: O(n)
Space Complexity: O(n)
Approach 2: Optimal Pointer Movement
This approach utilizes a two-pointer method where one pointer marks the beginning of a new range, and another pointer (or the loop index itself) expands the range as far as possible until the next number isn't consecutive. Once a sequence ends, if numbers are the same, it is a single-element range; otherwise, a range connecting two different numbers is formed.
from typing import List
def summaryRanges(nums: List[int]) -> List[str]:
ranges = []
i = 0
while i < len(nums):
start = i
j = i
while j + 1 < len(nums) and nums[j] + 1 == nums[j + 1]:
j += 1
if start == j:
ranges.append(str(nums[start]))
else:
ranges.append(f"{nums[start]}->{nums[j]}")
i = j + 1
return ranges
import java.util.ArrayList;
import java.util.List;
public class Solution {
public List<String> summaryRanges(int[] nums) {
List<String> result = new ArrayList<>();
int i = 0;
while (i < nums.length) {
int start = i;
int j = i;
while (j + 1 < nums.length && nums[j] + 1 == nums[j + 1]) {
j++;
}
if (start == j) {
result.add(String.valueOf(nums[start]));
} else {
result.add(nums[start] + "->" + nums[j]);
}
i = j + 1;
}
return result;
}
}
#include <vector>
#include <string>
using namespace std;
vector<string> summaryRanges(vector<int>& nums) {
vector<string> result;
int n = nums.size();
int i = 0;
while (i < n) {
int start = i;
int j = i;
while (j + 1 < n && nums[j] + 1 == nums[j + 1]) {
j++;
}
if (start == j) {
result.push_back(to_string(nums[start]));
} else {
result.push_back(to_string(nums[start]) + "->" + to_string(nums[j]));
}
i = j + 1;
}
return result;
}
function summaryRanges(nums) {
const result = [];
let i = 0;
while (i < nums.length) {
let start = i;
let j = i;
while (j + 1 < nums.length && nums[j] + 1 === nums[j + 1]) {
j++;
}
if (start === j) {
result.push(`${nums[start]}`);
} else {
result.push(`${nums[start]}->${nums[j]}`);
}
i = j + 1;
}
return result;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char** summaryRanges(int* nums, int numsSize, int* returnSize) {
char **result = (char **)malloc(numsSize * sizeof(char *));
*returnSize = 0;
int i = 0;
while (i < numsSize) {
int start = i;
while (i + 1 < numsSize && nums[i] + 1 == nums[i + 1]) {
i++;
}
int end = i;
char *range = (char *)malloc(25 * sizeof(char));
if (start == end) {
sprintf(range, "%d", nums[start]);
} else {
sprintf(range, "%d->%d", nums[start], nums[end]);
}
result[(*returnSize)++] = range;
i++;
}
return result;
}
using System;
using System.Collections.Generic;
public class Solution {
public IList<string> SummaryRanges(int[] nums) {
List<string> result = new List<string>();
int i = 0;
while (i < nums.Length) {
int start = i;
int j = i;
while (j + 1 < nums.Length && nums[j] + 1 == nums[j + 1]) {
j++;
}
if (start == j) {
result.Add(nums[start].ToString());
} else {
result.Add(nums[start] + "->" + nums[j]);
}
i = j + 1;
}
return result;
}
}Python uses nested loops to manage two pointers, 'i' and 'j', determining where ranges start and extend until consecutive integers break. Then, constructs string format to reflect the range.
Time Complexity: O(n)
Space Complexity: O(n)
Approach 3: Two Pointers
We can use two pointers i and j to find the left and right endpoints of each interval.
Traverse the array, when j + 1 < n and nums[j + 1] = nums[j] + 1, move j to the right, otherwise the interval [i, j] has been found, add it to the answer, then move i to the position of j + 1, and continue to find the next interval.
Time complexity O(n), where n is the length of the array. Space complexity O(1).
function summaryRanges(nums: number[]): string[] {
const f = (i: number, j: number): string => {
return i === j ? `${nums[i]}` : `${nums[i]}->${nums[j]}`;
};
const n = nums.length;
const ans: string[] = [];
for (let i = 0, j = 0; i < n; i = j + 1) {
j = i;
while (j + 1 < n && nums[j + 1] === nums[j] + 1) {
++j;
}
ans.push(f(i, j));
}
return ans;
}func summaryRanges(nums []int) (ans []string) {
f := func(i, j int) string {
if i == j {
return strconv.Itoa(nums[i])
}
return strconv.Itoa(nums[i]) + "->" + strconv.Itoa(nums[j])
}
for i, j, n := 0, 0, len(nums); i < n; i = j + 1 {
j = i
for j+1 < n && nums[j+1] == nums[j]+1 {
j++
}
ans = append(ans, f(i, j))
}
return
}impl Solution {
#[allow(dead_code)]
pub fn summary_ranges(nums: Vec<i32>) -> Vec<String> {
if nums.is_empty() {
return vec![];
}
let mut ret = Vec::new();
let mut start = nums[0];
let mut prev = nums[0];
let mut current = 0;
let n = nums.len();
for i in 1..n {
current = nums[i];
if current != prev + 1 {
if start == prev {
ret.push(start.to_string());
} else {
ret.push(start.to_string() + "->" + &prev.to_string());
}
start = current;
prev = current;
} else {
prev = current;
}
}
if start == prev {
ret.push(start.to_string());
} else {
ret.push(start.to_string() + "->" + &prev.to_string());
}
ret
}
}Complexity comparison
| Approach | Complexity |
|---|---|
| Sequential Range Detection | Time Complexity: O(n) |
| Optimal Pointer Movement | Time Complexity: O(n) |
| Two Pointers | – |
Complexity analysis
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Sequential Range Detection | O(n) | O(1) | Simple single-pass scan when array is already sorted and you want the most readable implementation |
| Optimal Pointer Movement | O(n) | O(1) | When using two-pointer range expansion patterns common in sorted array and interval problems |
Frequently asked questions
Is Summary Ranges easy or hard?
Summary Ranges is categorized as an Easy problem on LeetCode. The challenge mainly involves correctly detecting consecutive sequences and formatting the output ranges. Once you recognize that a single pass over the sorted array is sufficient, the implementation becomes straightforward.
How to solve Summary Ranges in O(n)?
Traverse the array while tracking the start of the current range. Continue moving forward while consecutive numbers satisfy nums[i] + 1 == nums[i+1]. When the sequence stops, output the range and reset the start pointer. Because every element is processed once, the algorithm runs in linear time.
What is the best approach for Summary Ranges?
The optimal approach is a linear scan that detects boundaries of consecutive numbers. Track the start of a range and continue advancing while numbers remain consecutive. Once the sequence breaks, format the range as either a single number or "start->end". This solution runs in O(n) time and O(1) space.
What data structure is used in Summary Ranges?
The problem primarily uses arrays and simple index variables. No advanced data structures such as hash maps or stacks are required. The logic relies on sequential traversal and detecting boundaries between consecutive values.
What is the time complexity of Summary Ranges?
The standard solution runs in O(n) time because each element in the sorted array is visited exactly once during the scan. No nested loops are required. Space complexity is O(1) excluding the output list since only a few index variables are maintained.
Summary Ranges Python or Java solution approach?
In Python or Java, the typical implementation iterates through the array while tracking the start index of a range. When the next value is not consecutive, the range is formatted and appended to the result list. The same O(n) time and O(1) extra space complexity applies across languages.
Is Summary Ranges asked at Google, Amazon, or Meta?
Summary Ranges is a classic array scanning problem commonly used in coding interviews to test iteration logic and handling of ranges. Variations of range compression and interval grouping appear in interviews at companies like Amazon and Meta, especially in early technical screens.
