##原题如下:
(不想看的直接看下面的简单中文解释)
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 encoding of some sequence. More specifically, for all even 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.
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”.
中文意思:简单地说,就是给定一个序列,如A = [3,8,0,9,2,5],对于偶数i,A[i]表示A[i]出现的个数,比如这个A就表示3个8,0个9,2个5,那么序列A就是序列[8, 8, 8, 5, 5]的RLE(run-length encoding),我们要实现的是一个函数next(int n),表示删掉用RLE初始化的原序列的n个数字(从头开始按顺序删),并返回最后删除的那个元素的值;若数不够删,则返回-1。
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].
删除序列的两个元素,最后删除的是8,所以返回8;剩下的序列为[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:
0 <= A.length <= 1000
A.length
is an even integer.0 <= A[i] <= 10^9
1000
calls to RLEIterator.next(int n)
per test case.RLEIterator.next(int n)
will have 1 <= n <= 10^9
.##思路:
一开始天真地以为真的要按照RLE计算出原来的序列再进行操作,然后提交之后发现runtime error,原来给出的测试样例的数字会非常大,所以如果转换出原序列,需要的空间自然会非常大,导致资源浪费,甚至空间不够用。仔细一想,这样的RLE转换本来就是为了节省空间的,我又把它转换回去了,自然不是这道题的意思。所以就必须在RLE上面处理了,能想到这里其实就不复杂了。
首先对于RLE序列A,下标为偶数i的项A[i]为其后一项A[i+1]的数量,所以当要删掉其中的n项时,自然就需要跟A[i]比较大小,分三种情况:
(1) A[i] >= n 够减,则v[i] -= n;并返回v[i+1]的值;
(2) A[i] < n 不够减,则n -= v[i];v[i] = 0;并继续检测下一个i;
(3) 循环结束了还是不能找到A[i] >= n,表示数不够,返回-1。
##代码:
class RLEIterator {
public:
RLEIterator(vector<int> A) {
v = A;
}
int next(int n) {
// 遍历偶数项
for(int i = 0; i < v.size() - 1; i+=2){
if(v[i] >= n){
v[i] -= n;
return v[i+1];
}
else if (v[i] != 0){
n -= v[i];
v[i] = 0;
}
}
return -1;
}
private:
vector<int> v;
};
##改进
以上的方法每次都要从头开始,如果经过多次删除之后前面很多数的个数为0,这样就浪费了前面查询的时间,可以用一个head来跟踪第一个不是0的偶数位置,这样就不用每次都要从头开始,提高效率。代码如下:
class RLEIterator {
public:
RLEIterator(vector A) {
v = A;
head = 0;
}
int next(int n) {
int ret = -1;
for(; head < v.size(); head+=2){
if(v[head] >= n){
v[head] -= n;
ret = v[head+1];
break;
}
if(v[head] != 0){
n -= v[head];
v[head] = 0;
}
}
// 跳过个数为0的数
while(head < v.size() && v[head] == 0) head += 2;
return ret;
}
private:
vector v;
int head;
};