1313. Decompress Run-Length Encoded List
Problem Description
You are given a list of integers called nums
that represents data compressed using run-length encoding.
The list is organized in pairs where every two consecutive elements form a pair: [frequency, value]
. Specifically:
nums[0]
is the frequency andnums[1]
is the value for the first pairnums[2]
is the frequency andnums[3]
is the value for the second pair- And so on...
For each pair [freq, val]
, you need to expand it by repeating the value val
exactly freq
times.
Your task is to decompress the list by:
- Taking each frequency-value pair from the compressed list
- Repeating each value according to its frequency
- Concatenating all the repeated values in order to form the decompressed list
For example, if nums = [1, 2, 3, 4]
:
- First pair: frequency = 1, value = 2 → generates
[2]
- Second pair: frequency = 3, value = 4 → generates
[4, 4, 4]
- Final decompressed list:
[2, 4, 4, 4]
The solution uses a list comprehension that iterates through the array in steps of 2 (to process pairs), and for each pair at index i
, it repeats nums[i+1]
(the value) exactly nums[i]
(the frequency) times.
Intuition
The problem is essentially asking us to reverse a compression technique. When we see run-length encoding, we're looking at a pattern where data is stored as (count, value)
pairs. The natural way to decompress this is to simply follow the encoding rules in reverse.
Since the input array alternates between frequencies and values, we need to process the array two elements at a time. Every even index (0, 2, 4, ...) contains a frequency, and every odd index (1, 3, 5, ...) contains the corresponding value to repeat.
The key insight is that we can iterate through the array with a step size of 2 to grab each pair. For indices i = 0, 2, 4, ...
, we have:
nums[i]
is the frequency (how many times to repeat)nums[i+1]
is the value to repeat
Python's list comprehension provides an elegant way to express this decompression in a single line. We can use a nested loop structure where:
- The outer loop moves through pairs:
for i in range(0, len(nums), 2)
- The inner loop repeats the value:
for _ in range(nums[i])
This directly translates the problem's requirement into code: for each frequency-value pair, generate frequency
copies of value
, and collect all results in order. The underscore _
in the inner loop indicates we don't actually use the loop variable - we just need to repeat the operation nums[i]
times.
Solution Approach
The solution follows a simulation approach where we directly implement the decompression process described in the problem.
The implementation uses a list comprehension with nested iteration:
return [nums[i + 1] for i in range(0, len(nums), 2) for _ in range(nums[i])]
Let's break down how this works:
-
Outer iteration:
for i in range(0, len(nums), 2)
- This iterates through the array with a step of 2, visiting indices 0, 2, 4, and so on
- Each
i
represents the starting index of a frequency-value pair
-
Inner iteration:
for _ in range(nums[i])
- For each pair, this loop runs
nums[i]
times (the frequency) - The underscore
_
indicates we don't use the loop variable itself
- For each pair, this loop runs
-
Value generation:
nums[i + 1]
- For each iteration of the inner loop, we add
nums[i + 1]
(the value) to our result list
- For each iteration of the inner loop, we add
The algorithm processes each pair sequentially from left to right:
- At index
i
, we read the frequency:freq = nums[i]
- At index
i+1
, we read the value:val = nums[i+1]
- We then add
val
to the result listfreq
times
For example, with nums = [2, 5, 1, 3]
:
- First pair (i=0): frequency = 2, value = 5 → adds
[5, 5]
- Second pair (i=2): frequency = 1, value = 3 → adds
[3]
- Final result:
[5, 5, 3]
The time complexity is O(n × m) where n is the length of the input array and m is the average frequency value, since we need to generate output elements based on the frequencies. The space complexity is O(k) where k is the total number of elements in the decompressed list.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through the solution with nums = [2, 3, 1, 5, 2, 4]
.
Step 1: Identify the frequency-value pairs
- Pair 1: frequency = 2 (index 0), value = 3 (index 1)
- Pair 2: frequency = 1 (index 2), value = 5 (index 3)
- Pair 3: frequency = 2 (index 4), value = 4 (index 5)
Step 2: Process each pair using our list comprehension
The outer loop for i in range(0, len(nums), 2)
gives us i = 0, 2, 4.
When i = 0:
nums[0]
= 2 (frequency)nums[1]
= 3 (value)- Inner loop runs 2 times, adding 3 each time
- Contributes: [3, 3]
When i = 2:
nums[2]
= 1 (frequency)nums[3]
= 5 (value)- Inner loop runs 1 time, adding 5
- Contributes: [5]
When i = 4:
nums[4]
= 2 (frequency)nums[5]
= 4 (value)- Inner loop runs 2 times, adding 4 each time
- Contributes: [4, 4]
Step 3: Concatenate all contributions The list comprehension automatically concatenates these in order: [3, 3] + [5] + [4, 4] = [3, 3, 5, 4, 4]
Final Result: [3, 3, 5, 4, 4]
This demonstrates how the solution efficiently decompresses the run-length encoded data by processing pairs and expanding each value according to its frequency.
Solution Implementation
1class Solution:
2 def decompressRLElist(self, nums: List[int]) -> List[int]:
3 """
4 Decompress a run-length encoded list.
5
6 The input list contains pairs [frequency, value] at even and odd indices.
7 For each pair, the value is repeated 'frequency' times in the output.
8
9 Args:
10 nums: Run-length encoded list where nums[2i] is frequency and nums[2i+1] is value
11
12 Returns:
13 Decompressed list with values repeated according to their frequencies
14 """
15 # Initialize result list
16 result = []
17
18 # Iterate through the list in steps of 2 to process each (frequency, value) pair
19 for i in range(0, len(nums), 2):
20 frequency = nums[i] # Extract frequency at even index
21 value = nums[i + 1] # Extract value at odd index
22
23 # Append the value 'frequency' times to the result
24 for _ in range(frequency):
25 result.append(value)
26
27 return result
28
1class Solution {
2 /**
3 * Decompresses a run-length encoded list.
4 * The input array represents pairs where:
5 * - nums[2i] = frequency (how many times to repeat)
6 * - nums[2i+1] = value (the value to repeat)
7 *
8 * @param nums The run-length encoded array
9 * @return The decompressed array
10 */
11 public int[] decompressRLElist(int[] nums) {
12 // List to store the decompressed values
13 List<Integer> decompressedList = new ArrayList<>();
14
15 // Process pairs of elements (frequency, value)
16 for (int i = 0; i < nums.length; i += 2) {
17 int frequency = nums[i];
18 int value = nums[i + 1];
19
20 // Add the value 'frequency' times to the result list
21 for (int j = 0; j < frequency; j++) {
22 decompressedList.add(value);
23 }
24 }
25
26 // Convert the list to an array and return
27 return decompressedList.stream()
28 .mapToInt(Integer::intValue)
29 .toArray();
30 }
31}
32
1class Solution {
2public:
3 vector<int> decompressRLElist(vector<int>& nums) {
4 vector<int> result;
5
6 // Process the RLE-encoded list in pairs (frequency, value)
7 for (int i = 0; i < nums.size(); i += 2) {
8 int frequency = nums[i]; // First element of pair: how many times to repeat
9 int value = nums[i + 1]; // Second element of pair: the value to repeat
10
11 // Add 'value' to result 'frequency' times
12 for (int j = 0; j < frequency; j++) {
13 result.push_back(value);
14 }
15 }
16
17 return result;
18 }
19};
20
1/**
2 * Decompresses a run-length encoded list.
3 * The input array contains pairs where nums[2i] is the frequency and nums[2i+1] is the value.
4 *
5 * @param nums - The run-length encoded array where pairs represent [frequency, value]
6 * @returns The decompressed array with values repeated according to their frequencies
7 */
8function decompressRLElist(nums: number[]): number[] {
9 const result: number[] = [];
10
11 // Process the array in pairs (frequency, value)
12 for (let i = 0; i < nums.length; i += 2) {
13 const frequency: number = nums[i];
14 const value: number = nums[i + 1];
15
16 // Add the value to result array 'frequency' times
17 for (let j = 0; j < frequency; j++) {
18 result.push(value);
19 }
20 }
21
22 return result;
23}
24
Time and Space Complexity
The time complexity is O(m)
, where m
is the total number of elements in the decompressed output. While we traverse the input array nums
of length n
once (iterating through pairs), for each frequency-value pair (nums[i], nums[i+1])
, we perform nums[i]
iterations in the inner loop to generate the output elements. The total work done is proportional to the sum of all frequencies, which equals the output size.
The space complexity is O(1)
if we exclude the space required for the output list. The list comprehension only uses a constant amount of extra space for loop variables i
and the implicit iterator. If we include the output space, the space complexity would be O(m)
, where m
is the total number of elements in the decompressed result.
Note: The reference answer states O(n)
for time complexity, which considers only the traversal of the input array. However, a more precise analysis should account for the total number of elements generated, as each frequency nums[i]
contributes nums[i]
iterations to the overall time complexity.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Index Out of Bounds Error
One common pitfall occurs when the input array has an odd number of elements. Since the algorithm expects pairs of [frequency, value], accessing nums[i+1]
when i
is the last index will cause an IndexError.
Problem Example:
nums = [2, 5, 3] # Odd number of elements - incomplete pair # When i=2, trying to access nums[3] causes IndexError
Solution: Add validation to ensure the input has an even number of elements:
def decompressRLElist(self, nums: List[int]) -> List[int]:
if len(nums) % 2 != 0:
raise ValueError("Input must contain complete frequency-value pairs")
result = []
for i in range(0, len(nums), 2):
frequency = nums[i]
value = nums[i + 1]
for _ in range(frequency):
result.append(value)
return result
2. Memory Overflow with Large Frequencies
If the frequency values are extremely large, the decompressed list could consume excessive memory, potentially causing memory errors.
Problem Example:
nums = [1000000000, 1, 1000000000, 2] # Would create 2 billion elements
Solution: Consider using a generator for memory-efficient processing or add a safety check:
def decompressRLElist(self, nums: List[int]) -> List[int]:
MAX_OUTPUT_SIZE = 10**6 # Set reasonable limit
total_size = sum(nums[i] for i in range(0, len(nums), 2))
if total_size > MAX_OUTPUT_SIZE:
raise ValueError(f"Output size {total_size} exceeds maximum allowed")
result = []
for i in range(0, len(nums), 2):
frequency = nums[i]
value = nums[i + 1]
result.extend([value] * frequency) # More efficient than loop
return result
3. Negative or Zero Frequencies
The algorithm doesn't explicitly handle negative frequencies, which could lead to unexpected behavior or silent errors.
Problem Example:
nums = [-1, 5, 0, 3, 2, 7] # Negative and zero frequencies
Solution: Add validation for non-negative frequencies:
def decompressRLElist(self, nums: List[int]) -> List[int]:
result = []
for i in range(0, len(nums), 2):
frequency = nums[i]
if frequency < 0:
raise ValueError(f"Frequency cannot be negative: {frequency}")
value = nums[i + 1]
result.extend([value] * frequency) # Zero frequency naturally produces no output
return result
4. Performance Inefficiency with Multiple Appends
Using repeated append()
calls in a loop can be less efficient than using list multiplication or extend()
.
Inefficient approach:
for _ in range(frequency):
result.append(value) # Multiple individual appends
Optimized approach:
result.extend([value] * frequency) # Single extend operation # OR use list comprehension as in the original solution
Which data structure is used to implement priority queue?
Recommended Readings
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!