[路飞]_从层序遍历二叉树中理解递归与迭代

170 阅读2分钟

递归与迭代的区别

  • 递归(recursion):递归常被用来描述以自相似方法重复事物的过程,在数学和计算机科学中,指的是在函数定义中使用函数自身的方法。(A调用A)

  • 迭代(iteration):重复反馈过程的活动,每一次迭代的结果会作为下一次迭代的初始值。(A重复调用B)

算法题

理论上递归都可以用迭代实现

  • 遍历二叉树递归范式
    function recursion(root) {
        if(!root) return 
        // ...前序遍历在这里处理当前值root.val
        recursion(root.left) // 处理左边
        // ...中序遍历在这里处理当前值root.val
        recursion(root.right) // 处理右边
        // ...后序遍历在这里处理当前值root.val
    }
  • 层序遍历二叉树迭代范式
    var queue = [root] // 用双端队列处理
    while (queue.length) {
        var len = queue.length
        while (len--) {
            var top = queue.shift() // 取出当前需要处理的值
            // ...这里处理当前值top.val
            // 处理左右插入队列尾部,进入下一轮循环
            top.left && queue.push(top.left) 
            top.right && queue.push(top.right) 
        }
    }

102. 二叉树的层序遍历

图片.png

  • 递归
/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
var levelOrder = function (root) {
    var ans = []
    function recursion(root, k) {
        if(!root) return 
        if(!ans[k]) ans.push([])
        ans[k].push(root.val)
        recursion(root.left, k + 1)
        recursion(root.right, k + 1)
    }
    recursion(root, 0, ans)
    return ans
};
  • 迭代
/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
var levelOrder = function (root) {
    var ans = []
    if(!root) return ans
    var queue = [root]
    while (queue.length) {
        var len = queue.length
        var tmp = []
        while (len--) {
            var top = queue.shift()
            tmp.push(top.val)
            top.left && queue.push(top.left)
            top.right && queue.push(top.right)
        }
        ans.push(tmp)
    }
    return ans
};

107. 二叉树的层序遍历 II

图片.png

  • 递归
/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
 var levelOrderBottom = function (root) {
  var ans = []
  function recrusion(root, k) {
      if(!root) return
      if(!ans[ans.length - 1 - k]) ans.unshift([])
      ans[ans.length - 1 - k].push(root.val)
      recrusion(root.left, k + 1)
      recrusion(root.right, k + 1)
  }
  recrusion(root, 0)
  return ans
};
  • 迭代
/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
 var levelOrderBottom = function (root) {
  var ans = []
  if (!root) return ans
  var queue = [root]
  while (queue.length) {
      var len = queue.length
      var tmp = []
      while (len--) {
          var top = queue.shift()
          tmp.push(top.val)
          top.left && queue.push(top.left)
          top.right && queue.push(top.right)
      }
      ans.unshift(tmp)
  }
  return ans
};

103. 二叉树的锯齿形层序遍历

图片.png

  • 递归
/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
var zigzagLevelOrder = function(root) {
    var ans = []
    function recursion(root, k) {
        if(!root) return
        if(!ans[k]) ans.push([])
        if(k % 2 === 0) ans[k].push(root.val)
        else ans[k].unshift(root.val)
        recursion(root.left, k + 1)
        recursion(root.right, k + 1)
    }
    recursion(root, 0)
    return ans
};
  • 迭代
/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
var zigzagLevelOrder = function(root) {
    var ans = []
    if(!root) return ans
    var queue = [root]
    var flag = true
    while(queue.length) {
        var len = queue.length
        var tmp = []
        while(len--){
            var top = queue.shift()
            if(flag) tmp.push(top.val)
            else tmp.unshift(top.val)
            top.left && queue.push(top.left)
            top.right && queue.push(top.right)
        }
        ans.push(tmp)
        flag = !flag
    }
    return ans
};

589. N 叉树的前序遍历

图片.png

  • 递归
/**
 * @param {Node|null} root
 * @return {number[]}
 */
var preorder = function (root) {
    var ans = []
    function recursion(root) {
        if(!root) return
        ans.push(root.val)
        for(var i = 0; i < root.children.length; i++){
            recursion(root.children[i])
        }
    }
    recursion(root)
    return ans
};
  • 迭代
/**
 * @param {Node|null} root
 * @return {number[]}
 */
var preorder = function (root) {
    var ans = []
    if (!root) return ans
    var queue = [root]
    while (queue.length) {
        var top = queue.shift()
        ans.push(top.val)
        var children = top.children
        // 关键步骤,children反向添加到队列前
        for (var i = children.length - 1; i >= 0; i--) {
            queue.unshift(children[i])
        }
    }
    return ans
};