Taro Logo

Decompress Run-Length Encoded List

Easy
Asked by:
Profile picture
Profile picture
Profile picture
49 views
Topics:
Arrays

We are given a list nums of integers representing a list compressed with run-length encoding.

Consider each adjacent pair of elements [freq, val] = [nums[2*i], nums[2*i+1]] (with i >= 0).  For each such pair, there are freq elements with value val concatenated in a sublist. Concatenate all the sublists from left to right to generate the decompressed list.

Return the decompressed list.

Example 1:

Input: nums = [1,2,3,4]
Output: [2,4,4,4]
Explanation: The first pair [1,2] means we have freq = 1 and val = 2 so we generate the array [2].
The second pair [3,4] means we have freq = 3 and val = 4 so we generate [4,4,4].
At the end the concatenation [2] + [4,4,4] is [2,4,4,4].

Example 2:

Input: nums = [1,1,2,3]
Output: [1,3,3]

Constraints:

  • 2 <= nums.length <= 100
  • nums.length % 2 == 0
  • 1 <= nums[i] <= 100

Solution


Clarifying Questions

When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:

  1. What is the maximum size of the input `nums` array? What is the maximum value for `val` in `[freq, val]`?
  2. Can `freq` ever be zero or negative? If so, what should the output be?
  3. Is the input array `nums` guaranteed to always have an even number of elements, ensuring pairs of `freq` and `val` exist?
  4. Should the output array maintain the same data type as the `val` elements in the input array?
  5. Are there any memory constraints I should be aware of, given the potential expansion of the array?

Brute Force Solution

Approach

We are given a compressed list, where pairs of numbers tell us how many times to repeat a value. The brute force method simply expands the list by taking each pair and repeating the value the specified number of times.

Here's how the algorithm would work step-by-step:

  1. Look at the first pair of numbers.
  2. The first number in the pair tells you how many times to repeat the second number.
  3. For instance, if the pair is (3, 5), write down the number 5 three times: 5, 5, 5.
  4. Move to the next pair of numbers and repeat the same process.
  5. Keep doing this for every pair in the original list.
  6. Combine all the repeated values together to form the final expanded list.

Code Implementation

def decompress_run_length_encoded_list(encoded_list):
    decompressed_list = []

    # Iterate through the encoded list in pairs.
    for i in range(0, len(encoded_list), 2):

        frequency = encoded_list[i]
        value = encoded_list[i + 1]

        # Expand the list based on the frequency.
        for _ in range(frequency):
            decompressed_list.append(value)

    return decompressed_list

Big(O) Analysis

Time Complexity
O(n)The input list has n elements. We iterate through this list processing pairs of numbers. For each pair (frequency, value), we repeat the value 'frequency' times. The total number of repetitions across all pairs determines the size of the output list. In the worst case, the sum of all frequencies could be proportional to n, meaning we are essentially iterating up to 'n' times to build the output list. Therefore, the time complexity is O(n).
Space Complexity
O(N)The space complexity is determined by the size of the expanded list we build. The plain English explanation describes repeating values and combining them into a final list. In the worst case, we might need to store nearly all elements of the expanded list before returning it. Therefore, the auxiliary space required grows linearly with the size of the final expanded list, where N is the total number of elements in the decompressed list.

Optimal Solution

Approach

The core idea is to construct the decompressed list directly by repeating values based on the given frequency-value pairs. We avoid creating intermediate structures and build the final list in a single pass, optimizing memory and time.

Here's how the algorithm would work step-by-step:

  1. Examine the encoded list in pairs: the first number in each pair tells you how many times to repeat the second number.
  2. For each pair, take the 'frequency' number and the 'value' number.
  3. Repeat the 'value' that many times ('frequency' times) and add all the repeated instances of that value to a new list.
  4. Continue this process of pairing, repeating, and adding until you have gone through the entire encoded list.
  5. The new list you created is the decompressed list, which is your final answer.

Code Implementation

def decompress_run_length_encoded_list(encoded_list):
    decompressed_list = []

    # Iterate through the encoded list in pairs.
    for i in range(0, len(encoded_list), 2):

        frequency = encoded_list[i]
        value = encoded_list[i + 1]

        # Repeat the value based on the frequency.
        for _ in range(frequency):
            decompressed_list.append(value)

    return decompressed_list

Big(O) Analysis

Time Complexity
O(n)The algorithm iterates through the input list nums once, processing it in pairs. For each pair, it repeats a value a certain number of times. The crucial point is that the total number of repetitions across all pairs is directly proportional to the size of the output list, which can be at most proportional to the input size, n. Thus, the time complexity is linearly proportional to the number of elements in the final decompressed list, and therefore O(n).
Space Complexity
O(N)The algorithm constructs a new list to store the decompressed output. The size of this decompressed list depends on the input 'encoded list' and is determined by the sum of the 'frequency' values. In the worst-case scenario, where N represents the number of elements in the final decompressed list, the algorithm requires an auxiliary list of size N to store the result. Therefore, the space complexity is O(N).

Edge Cases

Empty input array
How to Handle:
Return an empty list since there are no pairs to process.
Input array with an odd number of elements
How to Handle:
Ignore the last element since run-length encoding requires pairs, and process up to the second to last element.
Input array contains zero frequency
How to Handle:
Skip this pair of frequency, value since frequency should always be positive.
Large frequency values leading to memory exhaustion
How to Handle:
Consider using an iterative approach to append elements gradually, or check the size of output before creation to prevent excessive memory allocation.
Input array with large number of repeating values
How to Handle:
The solution should handle this efficiently as it directly appends the value multiple times based on the frequency.
Integer overflow during frequency * value calculation (if applicable)
How to Handle:
Check for potential overflow during calculation if the product becomes significantly larger than the maximum integer value, possibly clipping the value or using a larger data type.
Negative numbers in frequency
How to Handle:
Frequencies should be non-negative, so treat a negative frequency as an invalid input and return an error or skip the pair.
Frequency is extremely large causing memory allocation errors
How to Handle:
Before expanding a frequency-value pair, check if the projected output size would exceed available memory and throw an exception or limit the expansion.