Tags

  • AWS (7)
  • Apigee (3)
  • ArchLinux (5)
  • Array (6)
  • Backtracking (6)
  • BinarySearch (6)
  • C++ (19)
  • CI&CD (3)
  • Calculus (2)
  • DesignPattern (43)
  • DisasterRecovery (1)
  • Docker (8)
  • DynamicProgramming (20)
  • FileSystem (11)
  • Frontend (2)
  • FunctionalProgramming (1)
  • GCP (1)
  • Gentoo (6)
  • Git (15)
  • Golang (1)
  • Graph (10)
  • GraphQL (1)
  • Hardware (1)
  • Hash (1)
  • Kafka (1)
  • LinkedList (13)
  • Linux (27)
  • Lodash (2)
  • MacOS (3)
  • Makefile (1)
  • Map (5)
  • MathHistory (1)
  • MySQL (21)
  • Neovim (10)
  • Network (66)
  • Nginx (6)
  • Node.js (33)
  • OpenGL (6)
  • PriorityQueue (1)
  • ProgrammingLanguage (9)
  • Python (10)
  • RealAnalysis (20)
  • Recursion (3)
  • Redis (1)
  • RegularExpression (1)
  • Ruby (19)
  • SQLite (1)
  • Sentry (3)
  • Set (4)
  • Shell (3)
  • SoftwareEngineering (12)
  • Sorting (2)
  • Stack (4)
  • String (2)
  • SystemDesign (13)
  • Terraform (2)
  • Tree (24)
  • Trie (2)
  • TwoPointers (16)
  • TypeScript (3)
  • Ubuntu (4)
  • Home

    [LeetCode 341] Flatten Nested List Iterator

    Published May 29, 2022 [  Recursion  ]

    Problem

    You are given a nested list of integers nestedList. Each element is either an integer or a list whose elements may also be integers or other lists. Implement an iterator to flatten it.

    Implement the NestedIterator class:

    • NestedIterator(List<NestedInteger> nestedList) Initializes the iterator with the nested list nestedList.
    • int next() Returns the next integer in the nested list.
    • boolean hasNext() Returns true if there are still some integers in the nested list and false otherwise.

    Your code will be tested with the following pseudocode:

    initialize iterator with nestedList
    res = []
    while iterator.hasNext()
        append iterator.next() to the end of res
    return res
    

    If res matches the expected flattened list, then your code will be judged as correct.

    Example 1:

    Input: nestedList = [[1,1],2,[1,1]]
    Output: [1,1,2,1,1]
    Explanation: By calling next repeatedly until hasNext returns false, the order of elements returned by next should be: [1,1,2,1,1].
    

    Example 2:

    Input: nestedList = [1,[4,[6]]]
    Output: [1,4,6]
    Explanation: By calling next repeatedly until hasNext returns false, the order of elements returned by next should be: [1,4,6].
    

    Constraints:

    • 1 <= nestedList.length <= 500
    • The values of the integers in the nested list is in the range [-10^6, 10^6].

    Thoughts

    • Preprocessing: save all integers in an array
    • Postprocessing: use stack/queue to store the data, then process stack/queue on the fly
    • Generator: use generator to help

    TypeScript

    Preprocessing

    /**
     * // This is the interface that allows for creating nested lists.
     * // You should not implement it, or speculate about its implementation
     * class NestedInteger {
     *     If value is provided, then it holds a single integer
     *     Otherwise it holds an empty nested list
     *     constructor(value?: number) {
     *         ...
     *     };
     *
     *     Return true if this NestedInteger holds a single integer, rather than a nested list.
     *     isInteger(): boolean {
     *         ...
     *     };
     *
     *     Return the single integer that this NestedInteger holds, if it holds a single integer
     *     Return null if this NestedInteger holds a nested list
     *     getInteger(): number | null {
     *         ...
     *     };
     *
     *     Set this NestedInteger to hold a single integer equal to value.
     *     setInteger(value: number) {
     *         ...
     *     };
     *
     *     Set this NestedInteger to hold a nested list and adds a nested integer elem to it.
     *     add(elem: NestedInteger) {
     *         ...
     *     };
     *
     *     Return the nested list that this NestedInteger holds,
     *     or an empty list if this NestedInteger holds a single integer
     *     getList(): NestedInteger[] {
     *         ...
     *     };
     * };
     */
    
    class NestedIterator {
        queue: number[];
        
        constructor(nestedList: NestedInteger[]) {
    	const flatten = (lists: NestedInteger[]): number[] => {
               return lists.flatMap(list => list.isInteger() ? list.getInteger() : flatten(list.getList()))
            }
            this.queue = flatten(nestedList)
        }
    
        hasNext(): boolean {
    	return this.queue.length !== 0
        }
    
        next(): number {
    	return this.queue.shift()
        }
    }
    
    /**
     * Your ParkingSystem object will be instantiated and called as such:
     * var obj = new NestedIterator(nestedList)
     * var a: number[] = []
     * while (obj.hasNext()) a.push(obj.next());
     */
    

    Postprocessing

    /**
     * // This is the interface that allows for creating nested lists.
     * // You should not implement it, or speculate about its implementation
     * class NestedInteger {
     *     If value is provided, then it holds a single integer
     *     Otherwise it holds an empty nested list
     *     constructor(value?: number) {
     *         ...
     *     };
     *
     *     Return true if this NestedInteger holds a single integer, rather than a nested list.
     *     isInteger(): boolean {
     *         ...
     *     };
     *
     *     Return the single integer that this NestedInteger holds, if it holds a single integer
     *     Return null if this NestedInteger holds a nested list
     *     getInteger(): number | null {
     *         ...
     *     };
     *
     *     Set this NestedInteger to hold a single integer equal to value.
     *     setInteger(value: number) {
     *         ...
     *     };
     *
     *     Set this NestedInteger to hold a nested list and adds a nested integer elem to it.
     *     add(elem: NestedInteger) {
     *         ...
     *     };
     *
     *     Return the nested list that this NestedInteger holds,
     *     or an empty list if this NestedInteger holds a single integer
     *     getList(): NestedInteger[] {
     *         ...
     *     };
     * };
     */
    
    class NestedIterator {
        stack: NestedInteger[];
        
        constructor(nestedList: NestedInteger[]) {
    		this.stack = []
            this.addToStack(nestedList);
        }
    
        hasNext(): boolean {
    		while(this.stack.length !== 0){
                const top: NestedInteger = this.stack[this.stack.length - 1];
                if(top.isInteger()){
                    return true
                } else {
                    this.stack.pop();
                    this.addToStack(top.getList());
                }
            }
            
            return false
        }
    
    	next(): number {
    		return this.stack.pop().getInteger();
        }
    
        addToStack(nestedList: NestedInteger[]): void {
            for(let i = nestedList.length - 1; i >= 0; i--){
                this.stack.push(nestedList[i])
            }
        }
    }
    
    /**
     * Your ParkingSystem object will be instantiated and called as such:
     * var obj = new NestedIterator(nestedList)
     * var a: number[] = []
     * while (obj.hasNext()) a.push(obj.next());
     */
    

    Generator

    /**
     * // This is the interface that allows for creating nested lists.
     * // You should not implement it, or speculate about its implementation
     * class NestedInteger {
     *     If value is provided, then it holds a single integer
     *     Otherwise it holds an empty nested list
     *     constructor(value?: number) {
     *         ...
     *     };
     *
     *     Return true if this NestedInteger holds a single integer, rather than a nested list.
     *     isInteger(): boolean {
     *         ...
     *     };
     *
     *     Return the single integer that this NestedInteger holds, if it holds a single integer
     *     Return null if this NestedInteger holds a nested list
     *     getInteger(): number | null {
     *         ...
     *     };
     *
     *     Set this NestedInteger to hold a single integer equal to value.
     *     setInteger(value: number) {
     *         ...
     *     };
     *
     *     Set this NestedInteger to hold a nested list and adds a nested integer elem to it.
     *     add(elem: NestedInteger) {
     *         ...
     *     };
     *
     *     Return the nested list that this NestedInteger holds,
     *     or an empty list if this NestedInteger holds a single integer
     *     getList(): NestedInteger[] {
     *         ...
     *     };
     * };
     */
    
    class NestedIterator {
        listGenerator: Generator<number>;
        nextVal: IteratorResult<number>
        
        constructor(nestedList: NestedInteger[]) {
    		this.listGenerator = this.generator(nestedList)
            this.nextVal = this.listGenerator.next()
        }
    
        hasNext(): boolean {
    		return !this.nextVal.done;
        }
    
    	next(): number {
    		const res: number = this.nextVal.value;
            this.nextVal = this.listGenerator.next()
            return res;
        }
    
        *generator(lists: NestedInteger[]): Generator<number> {
            for(let list of lists){
                if(list.isInteger()){
                    yield list.getInteger()
                } else {
                    yield* this.generator(list.getList());
                }
            }
        }
    }
    
    /**
     * Your ParkingSystem object will be instantiated and called as such:
     * var obj = new NestedIterator(nestedList)
     * var a: number[] = []
     * while (obj.hasNext()) a.push(obj.next());
     */
    

    Reference