251.Flatten 2D Vector

Tags: [data_structure], [list], [nested_list], [queue], [iterator]

Com: {t}

Hard: [###]

Link: https://leetcode.com/problems/flatten-2d-vector/#/description

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

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


Better Solution: Iterator

public class Vector2D implements Iterator<Integer> {
    private Iterator<List<Integer>> iter;
    private Iterator<Integer> subIter;

    public Vector2D(List<List<Integer>> vec2d) {
        if (vec2d == null || vec2d.size() == 0) {
            return;
        }
        this.iter = vec2d.iterator();
        while (this.iter.hasNext() && this.subIter == null) {
            List<Integer> subList = iter.next();
            if (subList.size() > 0) {
                this.subIter = subList.iterator();
            }
        }
    }

    @Override
    public Integer next() {
        Integer val = subIter.next();

        while (iter.hasNext() && !subIter.hasNext()) {
            List<Integer> subList = iter.next();
            if (subList.size() > 0) {
                subIter = subList.iterator();
            }
        }

        return val;
    }

    @Override
    public boolean hasNext() {
        return subIter != null && subIter.hasNext();
    }
}

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

Revelation:

  • In Java, we should declare the type for iterator, such as Iterator<List<Integer>> iter = ....iterator();

Note:

  • Time complexity = O(n), n is the total integers in the given vec2d.
  • Space complexity = O(1).

Python Solution: Iterator

class Vector2D(object):

    def __init__(self, vec2d):
        """
        Initialize your data structure here.
        :type vec2d: List[List[int]]
        """
        self.main_iter = None
        self.main_next = None
        self.sub_iter = None
        self.sub_next = None

        if not vec2d:
            return

        self.main_iter = iter(vec2d)
        self.main_next = next(self.main_iter, None)

        while self.main_next is not None and not self.sub_iter:
            if len(self.main_next) > 0:
                self.sub_iter = iter(self.main_next)

            self.main_next = next(self.main_iter, None)

        if self.sub_iter:
            self.sub_next = next(self.sub_iter, None)

    def next(self):
        """
        :rtype: int
        """
        val = self.sub_next

        self.sub_next = next(self.sub_iter, None)
        if self.sub_next is None:
            while self.main_next is not None:
                if len(self.main_next) > 0:
                    self.sub_iter = iter(self.main_next)
                    break

                self.main_next = next(self.main_iter, None)

            self.main_next = next(self.main_iter, None)
            self.sub_next = next(self.sub_iter, None)

        return val

    def hasNext(self):
        """
        :rtype: bool
        """
        return self.sub_next is not None

# Your Vector2D object will be instantiated and called as such:
# i, v = Vector2D(vec2d), []
# while i.hasNext(): v.append(i.next())

Revelation:

  • In Python, iterator doesn't have 'has next' function, this is the reason why we need to maintain the 'self.main_next' and 'self.sub_next'.

Solution: Queue:

public class Vector2D implements Iterator<Integer> {
    private int index;
    private List<List<Integer>> vec2d;
    private Queue<Integer> queue;

    public Vector2D(List<List<Integer>> vec2d) {
        this.queue = new LinkedList<>();
        if (vec2d == null || vec2d.size() == 0) {
            return;
        }
        this.vec2d = vec2d;
        this.index = 0;

        while (index < vec2d.size() && queue.size() == 0) {
            List<Integer> subList = vec2d.get(index);
            if (subList.size() == 0) {
                index ++;
                continue;
            }

            for (Integer elem : subList) {
                queue.add(elem);
            }
            index ++;
        }
    }

    @Override
    public Integer next() {
        Integer val = queue.remove();
        while (index < vec2d.size() && queue.size() == 0) {
            List<Integer> subList = vec2d.get(index);
            if (subList.size() == 0) {
                index ++;
                continue;
            }

            for (Integer elem : subList) {
                queue.add(elem);
            }
            index ++;
        }

        return val;
    }

    @Override
    public boolean hasNext() {
        return queue.size() > 0;
    }
}

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

Solution: Flatten At Beginning

public class Vector2D implements Iterator<Integer> {

    private List<Integer> arr;
    private int index;

    public Vector2D(List<List<Integer>> vec2d) {
        this.arr = new ArrayList<>();
        this.index = 0;

        if (vec2d == null || vec2d.size() == 0) {
            return;
        }


        for (List<Integer> subList : vec2d) {
            for (Integer elem : subList) {
                arr.add(elem);
            }
        }
    }

    @Override
    public Integer next() {
        return arr.get(index ++);
    }

    @Override
    public boolean hasNext() {
        return index < arr.size();
    }
}

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

results matching ""

    No results matching ""