Leetcode: Zigzag Iterator
Given two 1d vectors, implement an iterator to return their elements alternately. For example, given two 1d vectors: v1 = [1, 2] v2 = [3, 4, 5, 6] 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 - Update (2015-09-18): 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, given the following input: [1,2,3] [4,5,6,7] [8,9] It should return [1,4,8,2,5,9,3,6,7].
Best Solution: O(N) This solution also works for K vectors
Use a queue to store the iterators in different vectors. Every time we call next(), we pop an element from the list, and re-add it to the end to cycle through the lists if it is not empty
1 public class ZigzagIterator { 2 Queue<Iterator> list; 3 public ZigzagIterator(List<Integer> v1, List<Integer> v2) { 4 list = new LinkedList<Iterator>(); 5 if(!v1.isEmpty()) list.add(v1.iterator()); 6 if(!v2.isEmpty()) list.add(v2.iterator()); 7 } 8 9 public int next() { 10 Iterator poll = list.poll(); 11 int result = (Integer)poll.next(); 12 if(poll.hasNext()) list.add(poll); 13 return result; 14 } 15 16 public boolean hasNext() { 17 return !list.isEmpty(); 18 } 19 }
之前做法: 参考http://segmentfault.com/a/1190000003786218
Q:如果输入是k个列表呢?
A:使用一个迭代器的列表来管理这些迭代器。用turns变量和取模来判断我们该取列表中的第几个迭代器。不同点在于,一个迭代器用完后,我们要将其从列表中移出,这样我们下次就不用再找这个空的迭代器了。同样,由于每用完一个迭代器后都要移出一个,turns变量也要相应的更新为该迭代器下标的上一个下标。如果迭代器列表为空,说明没有下一个了。
1 public class ZigzagIterator implements Iterator<Integer> { 2 3 List<Iterator<Integer>> itlist; 4 int turns; 5 6 public ZigzagIterator(List<Iterator<Integer>> list) { 7 this.itlist = new LinkedList<Iterator<Integer>>(); 8 // 将非空迭代器加入列表 9 for(Iterator<Integer> it : list){ 10 if(it.hasNext()){ 11 itlist.add(it); 12 } 13 } 14 turns = 0; 15 } 16 17 public Integer next() { 18 if(!hasNext()){ 19 return 0; 20 } 21 Integer res = 0; 22 // 算出本次使用的迭代器的下标 23 int pos = turns % itlist.size(); 24 Iterator<Integer> curr = itlist.get(pos); 25 res = curr.next(); 26 // 如果这个迭代器用完,就将其从列表中移出 27 if(!curr.hasNext()){ 28 itlist.remove(pos); 29 // turns变量更新为上一个下标 30 turns = pos - 1; 31 } 32 turns++; 33 return res; 34 } 35 36 public boolean hasNext() { 37 return itlist.size() > 0; 38 } 39 }