Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Move from brute-force thinking to an efficient approach using array strategy.
We can use run-length encoding (i.e., RLE) to encode a sequence of integers. In a run-length encoded array of even length encoding (0-indexed), for all even i, encoding[i] tells us the number of times that the non-negative integer value encoding[i + 1] is repeated in the sequence.
arr = [8,8,8,5,5] can be encoded to be encoding = [3,8,2,5]. encoding = [3,8,0,9,2,5] and encoding = [2,8,1,8,2,5] are also valid RLE of arr.Given a run-length encoded array, design an iterator that iterates through it.
Implement the RLEIterator class:
RLEIterator(int[] encoded) Initializes the object with the encoded array encoded.int next(int n) Exhausts the next n elements and returns the last element exhausted in this way. If there is no element left to exhaust, return -1 instead.Example 1:
Input ["RLEIterator", "next", "next", "next", "next"] [[[3, 8, 0, 9, 2, 5]], [2], [1], [1], [2]] Output [null, 8, 8, 5, -1] Explanation RLEIterator rLEIterator = new RLEIterator([3, 8, 0, 9, 2, 5]); // This maps to the sequence [8,8,8,5,5]. rLEIterator.next(2); // exhausts 2 terms of the sequence, returning 8. The remaining sequence is now [8, 5, 5]. rLEIterator.next(1); // exhausts 1 term of the sequence, returning 8. The remaining sequence is now [5, 5]. rLEIterator.next(1); // exhausts 1 term of the sequence, returning 5. The remaining sequence is now [5]. rLEIterator.next(2); // exhausts 2 terms, returning -1. This is because the first term exhausted was 5, but the second term did not exist. Since the last term exhausted does not exist, we return -1.
Constraints:
2 <= encoding.length <= 1000encoding.length is even.0 <= encoding[i] <= 1091 <= n <= 1091000 calls will be made to next.Problem summary: We can use run-length encoding (i.e., RLE) to encode a sequence of integers. In a run-length encoded array of even length encoding (0-indexed), for all even i, encoding[i] tells us the number of times that the non-negative integer value encoding[i + 1] is repeated in the sequence. For example, the sequence arr = [8,8,8,5,5] can be encoded to be encoding = [3,8,2,5]. encoding = [3,8,0,9,2,5] and encoding = [2,8,1,8,2,5] are also valid RLE of arr. Given a run-length encoded array, design an iterator that iterates through it. Implement the RLEIterator class: RLEIterator(int[] encoded) Initializes the object with the encoded array encoded. int next(int n) Exhausts the next n elements and returns the last element exhausted in this way. If there is no element left to exhaust, return -1 instead.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array · Design
["RLEIterator","next","next","next","next"] [[[3,8,0,9,2,5]],[2],[1],[1],[2]]
Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #900: RLE Iterator
class RLEIterator {
private int[] encoding;
private int i;
private int j;
public RLEIterator(int[] encoding) {
this.encoding = encoding;
}
public int next(int n) {
while (i < encoding.length) {
if (encoding[i] - j < n) {
n -= (encoding[i] - j);
i += 2;
j = 0;
} else {
j += n;
return encoding[i + 1];
}
}
return -1;
}
}
/**
* Your RLEIterator object will be instantiated and called as such:
* RLEIterator obj = new RLEIterator(encoding);
* int param_1 = obj.next(n);
*/
// Accepted solution for LeetCode #900: RLE Iterator
type RLEIterator struct {
encoding []int
i, j int
}
func Constructor(encoding []int) RLEIterator {
return RLEIterator{encoding, 0, 0}
}
func (this *RLEIterator) Next(n int) int {
for this.i < len(this.encoding) {
if this.encoding[this.i]-this.j < n {
n -= (this.encoding[this.i] - this.j)
this.i += 2
this.j = 0
} else {
this.j += n
return this.encoding[this.i+1]
}
}
return -1
}
/**
* Your RLEIterator object will be instantiated and called as such:
* obj := Constructor(encoding);
* param_1 := obj.Next(n);
*/
# Accepted solution for LeetCode #900: RLE Iterator
class RLEIterator:
def __init__(self, encoding: List[int]):
self.encoding = encoding
self.i = 0
self.j = 0
def next(self, n: int) -> int:
while self.i < len(self.encoding):
if self.encoding[self.i] - self.j < n:
n -= self.encoding[self.i] - self.j
self.i += 2
self.j = 0
else:
self.j += n
return self.encoding[self.i + 1]
return -1
# Your RLEIterator object will be instantiated and called as such:
# obj = RLEIterator(encoding)
# param_1 = obj.next(n)
// Accepted solution for LeetCode #900: RLE Iterator
struct RLEIterator {
prefix: Vec<usize>,
values: Vec<i32>,
index: usize,
size: usize,
}
impl RLEIterator {
fn new(a: Vec<i32>) -> Self {
let mut prefix = vec![];
let mut values = vec![];
let n = a.len();
let index = 0;
let mut prev = 0;
for i in 0..n / 2 {
let time = a[i * 2] as usize;
if time != 0 {
prev += time;
prefix.push(prev);
values.push(a[i * 2 + 1]);
}
}
let size = values.len();
RLEIterator {
prefix,
values,
index,
size,
}
}
fn next(&mut self, n: i32) -> i32 {
self.index += n as usize;
match self.prefix.binary_search(&self.index) {
Ok(i) => self.values[i],
Err(i) => {
if i < self.size {
self.values[i]
} else {
-1
}
}
}
}
}
#[test]
fn test() {
let mut obj = RLEIterator::new(vec![3, 8, 0, 9, 2, 5]);
assert_eq!(obj.next(2), 8);
assert_eq!(obj.next(1), 8);
assert_eq!(obj.next(1), 5);
assert_eq!(obj.next(2), -1);
}
// Accepted solution for LeetCode #900: RLE Iterator
class RLEIterator {
private encoding: number[];
private i: number;
private j: number;
constructor(encoding: number[]) {
this.encoding = encoding;
this.i = 0;
this.j = 0;
}
next(n: number): number {
while (this.i < this.encoding.length) {
if (this.encoding[this.i] - this.j < n) {
n -= this.encoding[this.i] - this.j;
this.i += 2;
this.j = 0;
} else {
this.j += n;
return this.encoding[this.i + 1];
}
}
return -1;
}
}
/**
* Your RLEIterator object will be instantiated and called as such:
* var obj = new RLEIterator(encoding)
* var param_1 = obj.next(n)
*/
Use this to step through a reusable interview workflow for this problem.
Use a simple list or array for storage. Each operation (get, put, remove) requires a linear scan to find the target element — O(n) per operation. Space is O(n) to store the data. The linear search makes this impractical for frequent operations.
Design problems target O(1) amortized per operation by combining data structures (hash map + doubly-linked list for LRU, stack + min-tracking for MinStack). Space is always at least O(n) to store the data. The challenge is achieving constant-time operations through clever structure composition.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.