From 5dd35539a59e5917a9c01de253199376cef4883c Mon Sep 17 00:00:00 2001 From: Matej Focko Date: Fri, 5 Aug 2022 16:51:33 +0200 Subject: [PATCH] problems: add flatten nested list iterator Signed-off-by: Matej Focko --- problems/flatten-nested-list-iterator.java | 118 +++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 problems/flatten-nested-list-iterator.java diff --git a/problems/flatten-nested-list-iterator.java b/problems/flatten-nested-list-iterator.java new file mode 100644 index 0000000..67c406a --- /dev/null +++ b/problems/flatten-nested-list-iterator.java @@ -0,0 +1,118 @@ +import java.util.ArrayDeque; +import java.util.Iterator; +import java.util.List; + +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 empty list if this NestedInteger holds a single integer + public List getList(); +} + +/** + * // 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 empty list if this NestedInteger holds a single integer + * public List getList(); + * } + */ +class NestedIterator implements Iterator { + + private class DFSEntry { + private List it; + private int i = 0; + + public DFSEntry(List it) { + this.it = it; + } + + private int size() { + return it.size(); + } + + public boolean isEmpty() { + return i >= size(); + } + + public NestedInteger at() { + return it.get(i); + } + + public void advance() { + i++; + } + } + + ArrayDeque stack = new ArrayDeque<>(); + + public NestedIterator(List nestedList) { + stack.addLast(new DFSEntry(nestedList)); + findNext(); + } + + private DFSEntry top() { + return stack.peekLast(); + } + + // Performs one „iteration“ of the DFS algorithm + private void findNext() { + while (!stack.isEmpty()) { + // We ran out of successors + if (top().isEmpty()) { + stack.removeLast(); + + // Advance the parent of the removed list + if (top() != null) { + top().advance(); + } + + continue; + } + + // Base: we have found an integer + if (top().at().isInteger()) { + return; + } + + stack.addLast(new DFSEntry(top().at().getList())); + } + } + + @Override + public Integer next() { + DFSEntry top = stack.getLast(); + Integer e = top.at().getInteger(); + + // Find next integer in the nested list + top.advance(); + findNext(); + + // Return the popped element + return e; + } + + @Override + public boolean hasNext() { + return !stack.isEmpty(); + } +} + +/** + * Your NestedIterator object will be instantiated and called as such: + * NestedIterator i = new NestedIterator(nestedList); + * while (i.hasNext()) v[f()] = i.next(); + */