(From LeetCode #900 “RLE Iterator”)
Write an iterator that iterates through a run-length encoded sequence.
The iterator is initialized by RLEIterator(int[] A)
, where A
is a run-length encoded array of even length. Specifically, for all even indices i
, A[i]
tells us the number of times that the non-negative integer value A[i + 1]
is repeated in the sequence.
The iterator supports one function: next(int n)
, which exhausts the next n
elements (n
>= 1) and returns the last element exhausted in this way. If there is no element left to exhaust, next
returns -1
instead.
In other words, next
(n)`` returns the last element
of the next n
elements.
Note that n
is guaranteed to be a positive integer.
Example:
Input: ["RLEIterator","next","next","next","next"],
[[[3,8,0,9,2,5]], [2], [1], [1], [2]]
Output: [null,8,8,5,-1]
Explanation:
RLEIterator rle = new RLEIterator([3,8,0,9,2,5]);
rle.next(2); // exhausts 2 terms of the sequence, returns 8.
rle.next(1); // exhausts the next 1 term of the sequence, returns 8.
rle.next(1); // exhausts the next 1 term of the sequence, returns 5.
rle.next(2); // pass returns -1 because there are only 1 term left in the sequence.
What constraints are placed on the size of the array A
and the values it contains?
A
is guaranteed to be even, representing pairs of [frequency, value].A[i]
) and the integers (A[i + 1]
) are non-negative.Can the frequency of elements be zero?
__init__
method)
A
and setting an index pointer to track the current position in A
.next
method)
A
based on the frequency.-1
if there are not enough elements left in the sequence.class RLEIterator:
def __init__(self, A):
self.data = A
self.index = 0 # This will keep track of the current position in the encoded array
def next(self, n):
while self.index < len(self.data):
if self.data[self.index] >= n: # sufficient elements in the current run
self.data[self.index] -= n
return self.data[self.index + 1]
else:
n -= self.data[self.index] # exhaust all elements in the current run
self.index += 2 # move to the next pair
return -1
# Example usage:
rle = RLEIterator([3,8,0,9,2,5])
print(rle.next(2)) # returns 8
print(rle.next(1)) # returns 8
print(rle.next(1)) # returns 5
print(rle.next(2)) # returns -1
Initialization (__init__
): O(1) – Simply setting up the initial state, which takes constant time.
Next method (next
): O(n) – In the worst-case, we might need to scan through each element in the array if n
is large and there are many runs with zero or small counts. Here n
refers to the number of elements to pick, not the size of the input array.
The approach ensures that each call to next
efficiently manages the run-length encoded sequence by leveraging the inherent structure of the data (frequency-value pairs).
Got blindsided by a question you didn’t expect?
Spend too much time studying?
Or simply don’t have the time to go over all 3000 questions?