package com.freetymekiyan.algorithms.level.medium; import java.util.ArrayDeque; import java.util.Deque; import java.util.Iterator; import java.util.List; /** * Given a nested list of integers, implement an iterator to flatten it. * <p> * Each element is either an integer, or a list -- whose elements may also be integers or other lists. * <p> * Example 1: * Given the list [[1,1],2,[1,1]], * <p> * By calling next repeatedly until hasNext returns false, the order of elements returned by next should be: * [1,1,2,1,1]. * <p> * Example 2: * Given the list [1,[4,[6]]], * <p> * By calling next repeatedly until hasNext returns false, the order of elements returned by next should be: [1,4,6]. * <p> * Company Tags: Google, Facebook, Twitter * Tags: Stack, Design * Similar Problems: (M) Flatten 2D Vector, (M) Zigzag Iterator, (M) Mini Parser */ public class FlattenNestedListIterator { /** * This is the interface that allows for creating nested lists. * You should not implement it, or speculate about its implementation */ public interface NestedInteger { // @return true if this NestedInteger holds a single integer, rather than a nested list. public boolean isInteger(); // @return the single integer that this NestedInteger holds, if it holds a single integer // Return null if this NestedInteger holds a nested list public Integer getInteger(); // @return the nested list that this NestedInteger holds, if it holds a nested list // Return null if this NestedInteger holds a single integer public List<NestedInteger> getList(); } /** * Stack. * Flatten by pushing a list of nested lists onto stack in reverse order. * So that we can get them in original order. * For hasNext(), first check if stack is empty. * If it is empty, return false. * If it is not, check whether the top is an integer. * If it is an integer, return true. * If it is a list, pop the list and add all elements to stack from back to front. * <p> * If the nested integer wraps an empty list, hasNext() should return false. * So we must unwrap nested integer in hasNext() to make sure. */ public class NestedIterator implements Iterator<Integer> { private Deque<NestedInteger> stack; public NestedIterator(List<NestedInteger> nestedList) { stack = new ArrayDeque<>(); flatten(nestedList); } @Override public Integer next() { return hasNext() ? stack.pop().getInteger() : null; } @Override public boolean hasNext() { while (!stack.isEmpty()) { // Must put in hasNext(), otherwise cannot pass "[[]]". if (stack.peek().isInteger()) { return true; } flatten(stack.pop().getList()); } return false; } /** * Push list of nested integers to stack in REVERSE order. * So that when popping out of stack, it's the correct order. */ private void flatten(List<NestedInteger> list) { for (int i = list.size() - 1; i >= 0; i--) { stack.push(list.get(i)); } } } /** * Your NestedIterator object will be instantiated and called as such: * NestedIterator i = new NestedIterator(nestedList); * while (i.hasNext()) v[f()] = i.next(); */ }