class RLEIterator:
def __init__(self, encoding):
self.encoding = encoding
self.index = 0 # Points to the count in the encoding array
def next(self, n):
while self.index < len(self.encoding):
count = self.encoding[self.index]
value = self.encoding[self.index + 1]
if n > count:
n -= count
self.index += 2
else:
self.encoding[self.index] -= n
return value
return -1
class RLEIterator {
public:
vector<int> encoding;
int index;
RLEIterator(vector<int>& encoding) {
this->encoding = encoding;
index = 0;
}
int next(int n) {
while (index < encoding.size()) {
if (n > encoding[index]) {
n -= encoding[index];
index += 2;
} else {
encoding[index] -= n;
return encoding[index + 1];
}
}
return -1;
}
};
class RLEIterator {
private int[] encoding;
private int index;
public RLEIterator(int[] encoding) {
this.encoding = encoding;
this.index = 0;
}
public int next(int n) {
while (index < encoding.length) {
if (n > encoding[index]) {
n -= encoding[index];
index += 2;
} else {
encoding[index] -= n;
return encoding[index + 1];
}
}
return -1;
}
}
var RLEIterator = function(encoding) {
this.encoding = encoding;
this.index = 0;
};
RLEIterator.prototype.next = function(n) {
while (this.index < this.encoding.length) {
if (n > this.encoding[this.index]) {
n -= this.encoding[this.index];
this.index += 2;
} else {
this.encoding[this.index] -= n;
return this.encoding[this.index + 1];
}
}
return -1;
};
The RLE Iterator problem asks you to implement a class that can efficiently iterate through a run-length encoded sequence.
The input is an array encoding
where the even-indexed elements represent counts and the odd-indexed elements represent values.
For example, [3,8,0,9,2,5]
means "three 8s, zero 9s, two 5s" (i.e., the expanded sequence would be [8,8,8,5,5]
).
You must implement two methods:
__init__(encoding)
: Initialize the iterator with the run-length encoding array.next(n)
: Consume n
elements from the sequence and return the last element consumed. If there are not enough elements left, return -1
.next(n)
must consume elements in order and not reuse any element.
The first thing to notice is that expanding the entire sequence into a list would be inefficient, especially if some counts are very large.
For example, if the encoding is [1000000, 1]
, expanding this would take up a lot of memory and time.
Instead, we want a way to "skip" over large runs without generating all the elements. The iterator should efficiently move through the encoding array, keeping track of how many elements have been consumed from each run.
The brute-force solution would be to expand the encoded sequence into a full array and consume elements from it as needed. But this is not scalable for large inputs. The optimized approach is to process the encoding array directly, using pointers or indices to track our position and remaining counts.
To solve this problem efficiently, we avoid expanding the sequence and instead "walk" through the encoding as needed.
encoding
array and keep an index pointer (let's call it index
) at the start (position 0).
next(n)
:
n
is larger than the current count at encoding[index]
, subtract that count from n
and move the pointer forward by 2 (to the next run).n
is less than or equal to the current count, subtract n
from the count at encoding[index]
and return the value at encoding[index + 1]
.n
elements, return -1
.This approach is efficient because it only iterates through the encoding array as needed, without ever constructing the full sequence.
Let's use the input encoding = [3,8,0,9,2,5]
and several calls to next()
:
next(2)
next(1)
next(1)
next(2)
After each call, the encoding array's counts are updated to reflect what has already been consumed.
next
call.next
call, but in worst case O(k) where k is the number of runs (when skipping many exhausted runs).The optimized approach is far superior for large inputs, as it never constructs the full sequence and only traverses the encoding as needed.
The RLE Iterator problem demonstrates how to work efficiently with compressed data representations. By tracking your position and remaining counts within the encoding array, you avoid unnecessary computation and memory use. The key insight is to process the encoding in place, skipping over exhausted runs and updating counts as you go. This approach is both space- and time-efficient, making it ideal for large or highly compressed sequences.