【每日算法】扁平化嵌套列表迭代器

113 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情

扁平化嵌套列表迭代器

给你一个嵌套的整数列表 nestedList 。每个元素要么是一个整数,要么是一个列表;该列表的元素也可能是整数或者是其他列表。请你实现一个迭代器将其扁平化,使之能够遍历这个列表中的所有整数。

实现扁平迭代器类 NestedIterator :

  • NestedIterator(List nestedList) 用嵌套列表 nestedList 初始化迭代器。
  • int next() 返回嵌套列表的下一个整数。
  • boolean hasNext() 如果仍然存在待迭代的整数,返回 true ;否则,返回 false 。

你的代码将会用下述伪代码检测:

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

如果 res 与预期的扁平化列表匹配,那么你的代码将会被判为正确。

方案1:栈

  • 让原始数组倒序入栈:[1,2,3,[4,5],6] => [6, [4, 5], 3, 2, 1]

  • 每次出栈,判断是否是单个元素

    • 如果是单个元素则直接出栈

    • 否则其就是一个数组,将其出栈后拆开,再对拆开的元素依次倒序入栈

    • 假设目前已经出了 1,2,3 三个元素,正在出 [4, 5]

      • 当前栈:[6, [4, 5]]
      • 弹出栈顶元素后,当前栈:[6],弹出的元素 [4, 5]
      • 发现弹出的元素是一个数组,则将其依次倒序入栈后,当前栈:[6, 5, 4]
      • 继续出栈操作,知道栈为空
 function reverseInsert(result, list) { // 逆序插入元素
   result.push(...list.reverse())
 }
 /**
  * @constructor
  * @param {NestedInteger[]} nestedList
  */
 var NestedIterator = function(nestedList) {
   // 注意,题目说明了传入的是一个 NestedInteger 的数组,NestedInteger是一个实例,上面有 isInteger 、 getInteger 和 getList 三个方法
   this.stack = []
   reverseInsert(this.stack, nestedList)
 }
 NestedIterator.prototype.stackTop2Integer = function() {
   while(this.stack.length > 0) { // 持续循环到栈为空,或者栈顶元素不是数组
     const top = this.stack[this.stack.length - 1] // 获取栈顶元素
     if(top.isInteger()) return // 如果栈顶元素是 Integer 类型,则结束循环
     // 走到这里,说明栈顶元素是一个数组
     this.stack.pop() // 删除栈顶元素
     const list = top.getList() // 如果 NestedInteger 是一个嵌套数组,则 getList 返回这个链表数组
     reverseInsert(this.stack, list) // 将其倒序插入栈中
   }
 }
 NestedIterator.prototype.next = function() {
   this.stackTop2Integer() // 调整栈顶元素,调整过后栈顶元素一定是单值,或者为空
   const top = this.stack.pop()
   return top.getInteger()
 }
 NestedIterator.prototype.hasNext = function() {
   this.stackTop2Integer()
   return this.stack.length > 0
 }

方法2:递归

在栈的解法中,我们是等到每次调用 next 才调整一次栈顶

换个思路的话,在初始化的时候直接用递归构建好展平后的数组,等待 next 来取

 var NestedIterator = function (nestedList) {
   this.nums = []
   this.index = 0
   for(let nestedInterger of nestedList) {
     this.nums.push(...dfs(nestedInterger))
   }
 };
 function dfs(nestedInterger) {
   const res = []
   if(nestedInterger.isInteger()) {
     res.push(nestedInterger.getInteger())
   } else {
     for(let child of nestedInterger.getList()) {
       res.push(...dfs(child))
     }
   }
   return res
 }
 NestedIterator.prototype.hasNext = function () {
     return this.index < this.nums.length;
 };
 ​
 NestedIterator.prototype.next = function () {
     return this.nums[this.index++];
 };

\