乐趣区

关于力扣:力扣-14494145102二叉树的遍历问题

DFS(Deep First Search)深度优先搜寻 与 BFS(Breath First Search)广度优先搜寻

DFS:用到了栈构造,先进后出,重点在于递归,适合寻找特定指标

BFS:用到了队列构造,先进先出,重点在于队列,适合大范畴搜查

二叉树的深度优先

二叉树的前序遍历

二叉树的中序遍历

二叉树的后序遍历

(上面解法以中序遍历为例)

1. 递归

工夫复杂度:O(n)
空间复杂度:O(n)

先判断根节点是否存在,再遍历左节点,最初遍历右节点

var inorderTraversal = function(root) {const res = [];
    const inorder = (root) => {if (!root) {return;}
        inorder(root.left);
        res.push(root.val);
        inorder(root.right);
    }
    inorder(root);
    return res;
};

2. 迭代

工夫复杂度:O(n)
空间复杂度:O(n)
与办法 1 相似,区别在于递归时隐式保护一个栈,而在迭代时须要显式地将这个栈模仿进去,其余的实现与细节都雷同

var inorderTraversal = function(root) {const res = [];
    const stk = [];
    while (root || stk.length) {while (root) {stk.push(root);
            root = root.left;
        }
        root = stk.pop();
        res.push(root.val);
        root = root.right;
    }
    return res;
};

3. Morris 遍历

工夫复杂度:O(n)
空间复杂度:O(1)

  1. 如果没有左节点,先将值退出答案数组,再拜访右节点,即 x = x.right
  2. 如果有左节点,则找到左节点上最右的节点(即左子树中序遍历的最初一个节点,在中序遍历中的前驱节点),记为 predecessor。依据 predecessor 的右节点是否为空,进行如下操作:
  • 如果 \textit{predecessor}predecessor 的右节点为空,则将其右节点指向 x,而后拜访左节点,即 x = x.left
  • 如果 predecessor 的右节点不为空,则此时其右节点指向 x,阐明曾经遍历完左子树,咱们将 predecessor 的右节点置空,将 x 的值退出答案数组,而后拜访 x 的右节点,即 x = x.right
  1. 反复上述操作,直至拜访完整棵树
var inorderTraversal = function(root) {const res = [];
    let predecessor = null;

    while (root) {if (root.left) {
            // predecessor 节点就是以后 root 节点向左走一步,而后始终向右走至无奈走为止
            predecessor = root.left;
            while (predecessor.right && predecessor.right !== root) {predecessor = predecessor.right;}

            // 让 predecessor 的右指针指向 root,持续遍历左子树
            if (!predecessor.right) {
                predecessor.right = root;
                root = root.left;
            }
            // 阐明左子树曾经拜访完了,咱们须要断开链接
            else {res.push(root.val);
                predecessor.right = null;
                root = root.right;
            }
        }
        // 如果没有左孩子,则间接拜访右孩子
        else {res.push(root.val);
            root = root.right;
        }
    }

    return res;
};

二叉树的广度遍历

二叉树的层序遍历

工夫复杂度:O(n)
空间复杂度:O(n)

var levelOrder = function(root) {const ret = [];
    if (!root) {return ret;}

    const q = [];
    q.push(root);
    while (q.length !== 0) {
        const currentLevelSize = q.length;
        ret.push([]);
        for (let i = 1; i <= currentLevelSize; ++i) {const node = q.shift();
            ret[ret.length - 1].push(node.val);
            if (node.left) q.push(node.left);
            if (node.right) q.push(node.right);
        }
    }
        
    return ret;
};
退出移动版