Description
Given two 1d vectors, implement an iterator to return their elements alternately.
Example:
Input:
v1 = [1,2]
v2 = [3,4,5,6]
Output: `[1,3,2,4,5,6]
Explanation:By calling next repeatedly until hasNext returns false
,
the order of elements returned by next should be: [1,3,2,4,5,6]
.
Follow up: What if you are given k
1d vectors? How well can your code be extended to such cases?
Clarification ****for the follow up question****:
The "Zigzag" order is not clearly defined and is ambiguous for k > 2
cases. If "Zigzag" does not look right to you, replace "Zigzag" with "Cyclic". For example:
Input:
[1,2,3]
[4,5,6,7]
[8,9]
Output: [1,4,8,2,5,9,3,6,7]
.
Iterator, O(n), S(1)
public class ZigzagIterator {
private Iterator<Integer>[] iters;
private int index;
private Integer next;
public ZigzagIterator(List<Integer> v1, List<Integer> v2) {
iters = new Iterator[] {v1.iterator(), v2.iterator()};
readNext();
}
private void readNext() {
if (next != null) {
return;
}
if (iters[index % 2].hasNext()) {
next = iters[index % 2].next();
++index;
} else {
if (iters[(index + 1) % 2].hasNext()) {
next = iters[(index + 1) % 2].next();
++index;
}
}
}
public int next() {
if (!hasNext()) {
return Integer.MIN_VALUE;
}
int tmp = next;
next = null;
return tmp;
}
public boolean hasNext() {
readNext();
return next != null;
}
}
/**
* Your ZigzagIterator object will be instantiated and called as such:
* ZigzagIterator i = new ZigzagIterator(v1, v2);
* while (i.hasNext()) v[f()] = i.next();
*/
Follow-up: K iterators, O(n), S(k)
像上面这么写是不是太麻烦了?其实没有必要提前读取next val,因为list iterator自己就帮我们封装好了hasNext和next。我们可以在hasNext()时将iterator pos移动到下一个可以读取的iterator上,然后在next中直接返回其next() val,并移动pos即可。看下面这个解法:
public class ZigzagIterator {
private Iterator<Integer>[] iters;
private int pos;
private int k;
public ZigzagIterator(List<Integer> v1, List<Integer> v2) {
iters = new Iterator[] {v1.iterator(), v2.iterator()};
k = iters.length;
}
public int next() {
if (!hasNext()) {
return Integer.MIN_VALUE;
}
int next = iters[pos].next(); // read from iterator that pos is at
pos = (pos + 1) % k; // move pos forward
return next;
}
public boolean hasNext() {
// if current iterator has next, return directly
if (iters[pos].hasNext()) {
return true;
}
// iterator through the circular arr to find a valid iterator
for (int i = (pos + 1) % k; i != pos; i = (i + 1) % k) {
if (iters[i].hasNext()) {
pos = i; // move pos to this iterator
return true;
}
}
return false;
}
}
/**
* Your ZigzagIterator object will be instantiated and called as such:
* ZigzagIterator i = new ZigzagIterator(v1, v2);
* while (i.hasNext()) v[f()] = i.next();
*/
更牛掰的还可以这样,用LinkedList保存若干个可用的iterators。每次读取next时,将头部的iterator取出,读取,如果该iter已经没有剩余了则抛弃掉,否则将它append到list的尾部。这样就能保证循环读取k个iterators!好妙啊!
public class ZigzagIterator {
private List<Iterator<Integer>> list;
public ZigzagIterator(List<Integer> v1, List<Integer> v2) {
list = new LinkedList<>(); // tricky
if (!v1.isEmpty()) {
list.add(v1.iterator());
}
if (!v2.isEmpty()) {
list.add(v2.iterator());
}
}
public int next() {
Iterator<Integer> head = list.remove(0); // remove head iterator
int next = head.next();
if (head.hasNext()) {
list.add(head); // append it to the tail
}
return next;
}
public boolean hasNext() {
return !list.isEmpty();
}
}
/**
* Your ZigzagIterator object will be instantiated and called as such:
* ZigzagIterator i = new ZigzagIterator(v1, v2);
* while (i.hasNext()) v[f()] = i.next();
*/