RLE Iterator LT900

Write an iterator that iterates through a run-length encoded sequence.this

The iterator is initialized by RLEIterator(int[] A), where A is a run-length encoding of some sequence.  More specifically, for all even iA[i] tells us the number of times that the non-negative integer value A[i+1] is repeated in the sequence.spa

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.code

For example, we start with A = [3,8,0,9,2,5], which is a run-length encoding of the sequence [8,8,8,5,5].  This is because the sequence can be read as "three eights, zero nines, two fives".blog

 Idea 1.a Bruteforce, using queue simulate the exhausting operationthree

 1 class RLEIterator {
 2     private Deque<Integer> buffer;
 3     public RLEIterator(int[] A) {
 4         buffer = new LinkedList<>();
 5         for(int i = 1; i < A.length; i+=2) {
 6             int cnt = A[i-1];
 7             int value = A[i];
 8             while(cnt > 0) {
 9                 buffer.offerLast(value);
10                 --cnt;
11             }
12         }
13     }
14     
15     public int next(int n) {
16         Integer value = null;
17         while(n > 0) {
18             value = buffer.pollFirst();
19             --n;
20         }
21         return value == null? -1: value;
22     }
23 }

Idea 1.b too much space and very slow to remove element one by one, the key is to find the index of last exhausted element, once we know the current index and remaining elements on the current index, we can get the resultci

A[currIndex+1] if remaining >= nelement

n -= remaining; remaining = A[currIndex + 2]; currIndex += 2, moving to the next elementrem

Time complexity: O(N + Q), N = A.length, Q = number of calls to next()get

Space complexity: O(N)input

 1 class RLEIterator {
 2     private int remaining;
 3     private int currIndex;
 4     private int[] A;
 5     public RLEIterator(int[] A) {
 6         remaining = A[0];
 7         currIndex = 0;
 8         this.A = A;
 9     }
10     
11     public int next(int n) {
12        while(currIndex < A.length) {
13            if(remaining < n) {
14                n -= remaining;
15                currIndex += 2;
16                if(currIndex < A.length) {
17                    remaining = A[currIndex];
18                }
19            }
20            else {
21                remaining -= n;
22                return A[currIndex+1];
23            }
24        }
25        
26        return -1;
27     }
28 }

Idea 1.c instead of storing the remaining elements, storing the exhausted elements which represents that exhausted elements of A[currIndex+1] are exhausted, hence the next exhausted = 0 for next element, saving checking index to get A[currIndex] for the next remaining

Time complexity: O(N + Q)

Space complexity: O(N)

 1 class RLEIterator {
 2     private int exhausted;
 3     private int currIndex;
 4     private int[] A;
 5     public RLEIterator(int[] A) {
 6         exhausted = 0;
 7         currIndex = 0;
 8         this.A = A;
 9     }
10     
11     public int next(int n) {
12        while(currIndex < A.length) {
13            if(A[currIndex] - exhausted < n) {
14                n -= A[currIndex] - exhausted;
15                currIndex += 2;
16                exhausted = 0;
17            }
18            else {
19                exhausted += n;
20                return A[currIndex+1];
21            }
22        }
23        
24        return -1;
25     }
26 }

Idea 1.d Modifying the Array

 1 class RLEIterator {
 2     private int currIndex;
 3     private int[] A;
 4     public RLEIterator(int[] A) {
 5         currIndex = 0;
 6         this.A = A;
 7     }
 8     
 9     public int next(int n) {
10        while(currIndex < A.length) {
11            if(A[currIndex] < n) {
12                n -= A[currIndex];
13                currIndex += 2;
14            }
15            else {
16                A[currIndex] -= n;
17                return A[currIndex+1];
18            }
19        }
20        
21        return -1;
22     }
23 }

which style would you prefer?

 1 class RLEIterator {
 2     private int currIndex;
 3     private int[] A;
 4     public RLEIterator(int[] A) {
 5         currIndex = 0;
 6         this.A = A;
 7     }
 8     
 9     public int next(int n) {
10        while(currIndex < A.length && A[currIndex] < n) {
11                n -= A[currIndex];
12                currIndex += 2;
13        }
14         
15        if(currIndex < A.length) {
16            A[currIndex] -= n;
17            return A[currIndex+1];
18        }
19        
20        return -1;
21     }
22 }

 

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 is initialized with RLEIterator([3,8,0,9,2,5]). This maps to the sequence [8,8,8,5,5]. RLEIterator.next is then called 4 times: .next(2) exhausts 2 terms of the sequence, returning 8. The remaining sequence is now [8, 5, 5]. .next(1) exhausts 1 term of the sequence, returning 8. The remaining sequence is now [5, 5]. .next(1) exhausts 1 term of the sequence, returning 5. The remaining sequence is now [5]. .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. 

Note:

  1. 0 <= A.length <= 1000
  2. A.length is an even integer.
  3. 0 <= A[i] <= 10^9
  4. There are at most 1000 calls to RLEIterator.next(int n) per test case.
  5. Each call to RLEIterator.next(int n) will have 1 <= n <= 10^9.
相關文章
相關標籤/搜索