251. Flatten 2D Vector

题目:

Implement an iterator to flatten a 2d vector.

For example,
Given 2d vector =

[
  [1,2],
  [3],
  [4,5,6]
]

 

By calling next repeatedly until hasNext returns false, the order of elements returned by next should be: [1,2,3,4,5,6].

Hint:

  1. How many variables do you need to keep track?
  2. Two variables is all you need. Try with x and y.
  3. Beware of empty rows. It could be the first few rows.
  4. To write correct code, think about the invariant to maintain. What is it?
  5. The invariant is x and y must always point to a valid point in the 2d vector. Should you maintain your invariant ahead of time or right when you need it?
  6. Not sure? Think about how you would implement hasNext(). Which is more complex?
  7. Common logic in two different places should be refactored into a common method.

Follow up:
As an added challenge, try to code it using only iterators in C++ or iterators in Java.

链接: http://leetcode.com/problems/flatten-2d-vector/

题解:

构造一个2D的iterator。不太理解iterator的原理,第一想法是把vec2d里面的元素都读到Queue里 ,然后再逐个读取。这样的话初始化需要O(n), next和hasNext都为O(1),Space Complexity也是O(n),虽然能ac,但是当vec2d足够大的时候会出问题。

Time Complexity - constructor - O(n),  hasNext - O(1), next() - O(1), Space Complexity - O(n)。

public class Vector2D {
    private Queue<Integer> vec1d;
    
    public Vector2D(List<List<Integer>> vec2d) {
        vec1d = new LinkedList<>();
        for(List<Integer> list : vec2d) {
            for(int i : list) {
                vec1d.offer(i);
            }
        }
    }

    public int next() {
        if(hasNext())
            return vec1d.poll();
        else
            return Integer.MAX_VALUE;
    }

    public boolean hasNext() {
        return vec1d.size() > 0;
    }
}

/**
 * Your Vector2D object will be instantiated and called as such:
 * Vector2D i = new Vector2D(vec2d);
 * while (i.hasNext()) v[f()] = i.next();
 */

 

Update: 保存两个变量来遍历vec2d

public class Vector2D {
    private List<List<Integer>> list;
    private int listIndex;
    private int elemIndex;

    public Vector2D(List<List<Integer>> vec2d) {
        list = vec2d;
        listIndex = 0;
        elemIndex = 0;
    }

    public int next() {
        return list.get(listIndex).get(elemIndex++);
    }

    public boolean hasNext() {
        while(listIndex < list.size()) {
            if(elemIndex < list.get(listIndex).size()) {
                return true;
            } else {
                listIndex++;
                elemIndex = 0;
            }
        }
        
        return false;
    }
}

/**
 * Your Vector2D object will be instantiated and called as such:
 * Vector2D i = new Vector2D(vec2d);
 * while (i.hasNext()) v[f()] = i.next();
 */

 

二刷:

使用了ArrayList的iterator,这个算不算作弊...思路就是,一开始把vec2d里面每个list的iterator都加入到一个iters的ArrayList里。之后就可以很简单地写好hasNext()和next()两个方法了。

Java:

 

public class Vector2D implements Iterator<Integer> {
    private List<Iterator<Integer>> iters;
    private int curLine = 0;
    
    public Vector2D(List<List<Integer>> vec2d) {
        this.iters = new ArrayList<>();
        for (List<Integer> list : vec2d) {
            iters.add(list.iterator());
        }
    }

    @Override
    public Integer next() {
        return iters.get(curLine).next();
    }

    @Override
    public boolean hasNext() {
        while (curLine < iters.size()) {
            if (iters.get(curLine).hasNext()) return true;
            else curLine++;
        }
        return false;
    }
}

/**
 * Your Vector2D object will be instantiated and called as such:
 * Vector2D i = new Vector2D(vec2d);
 * while (i.hasNext()) v[f()] = i.next();
 */

 

Update:

还是使用两个元素来遍历

public class Vector2D implements Iterator<Integer> {
    private List<List<Integer>> list;
    private int curLine = 0;
    private int curElem = 0;
    
    public Vector2D(List<List<Integer>> vec2d) {
        this.list = vec2d;
    }

    @Override
    public Integer next() {
        return list.get(curLine).get(curElem++);
    }

    @Override
    public boolean hasNext() {
        while (curLine < list.size()) {
            if (curElem < list.get(curLine).size()) {
                return true;
            } else {
                curLine++;
                curElem = 0;
            }
        }
        return false;
    }
}

/**
 * Your Vector2D object will be instantiated and called as such:
 * Vector2D i = new Vector2D(vec2d);
 * while (i.hasNext()) v[f()] = i.next();
 */

 

 

Reference:

http://web.cse.ohio-state.edu/software/2231/web-sw2/extras/slides/17a.Iterators.pdf

http://docs.oracle.com/javase/7/docs/api/

http://stackoverflow.com/questions/21988341/how-to-iterate-through-two-dimensional-arraylist-using-iterator

http://www.cs.cornell.edu/courses/cs211/2005fa/Lectures/L15-Iterators%20&%20Inner%20Classes/L15cs211fa05.pdf

https://leetcode.com/discuss/50292/7-9-lines-added-java-and-c-o-1-space

https://leetcode.com/discuss/55199/pure-iterator-solution-additional-data-structure-list-get

https://leetcode.com/discuss/57984/simple-and-short-java-solution-with-iterator

https://leetcode.com/discuss/50356/my-concise-java-solution

https://leetcode.com/discuss/68860/java-o-1-space-solution

https://leetcode.com/discuss/71002/java-solution-beats-60-10%25

posted @ 2015-12-02 06:01  YRB  阅读(2001)  评论(0编辑  收藏  举报