返回

LeetCode 经典二叉树算法剖析,通俗易懂,小白也能读懂!

后端

征服二叉树:掌握 LeetCode 经典算法

作为程序员,理解二叉树的基本操作和算法至关重要。LeetCode,程序员面试的必备神器,自然少不了对二叉树算法的考察。让我们踏上一段旅程,深入剖析 LeetCode 中的经典二叉树算法,让小白程序员也能轻松掌握二叉树的精髓。

判断平衡二叉树

什么是平衡二叉树?

想象一棵二叉树像一棵树,左右两侧的树枝高度相差不大。这就是平衡二叉树。它的高度差在左右子树之间最多为 1。

算法步骤:

我们通过以下步骤来判断一棵二叉树是否平衡:

  1. 检查空树: 如果二叉树为空,它是平衡的。
  2. 获取左右子树高度: 计算二叉树的左子树和右子树的高度。
  3. 计算高度差: 计算左右子树高度差的绝对值。
  4. 递归检查: 如果高度差小于等于 1,并且左右子树也都是平衡的,则二叉树是平衡的。

代码示例:

public boolean isBalanced(TreeNode root) {
    // 判断空树
    if (root == null) {
        return true;
    }

    // 获取左右子树高度
    int leftHeight = getHeight(root.left);
    int rightHeight = getHeight(root.right);

    // 计算高度差
    int heightDiff = Math.abs(leftHeight - rightHeight);

    // 递归检查
    return heightDiff <= 1 && isBalanced(root.left) && isBalanced(root.right);
}

private int getHeight(TreeNode root) {
    // 判断空树
    if (root == null) {
        return 0;
    }

    // 计算最大深度
    return Math.max(getHeight(root.left), getHeight(root.right)) + 1;
}

二叉树的层序遍历

什么是层序遍历?

想像你从上方俯瞰一棵二叉树,你会看到它一层一层地排列。层序遍历就是按照这些层级顺序访问二叉树中的节点。

算法步骤:

  1. 使用队列: 创建一个队列来存储当前层级的节点。
  2. 遍历层级: 当队列不为空时,访问队列中的所有节点,并将它们的子节点放入队列中。
  3. 移动到下一层: 访问完当前层级的所有节点后,进入队列中的下一层级。

代码示例:

public List<List<Integer>> levelOrder(TreeNode root) {
    List<List<Integer>> result = new ArrayList<>();
    Queue<TreeNode> queue = new LinkedList<>();

    // 加入根节点
    if (root != null) {
        queue.offer(root);
    }

    // 遍历层级
    while (!queue.isEmpty()) {
        int size = queue.size();
        List<Integer> level = new ArrayList<>();

        // 访问当前层级节点
        for (int i = 0; i < size; i++) {
            TreeNode node = queue.poll();
            level.add(node.val);

            // 加入子节点
            if (node.left != null) {
                queue.offer(node.left);
            }
            if (node.right != null) {
                queue.offer(node.right);
            }
        }

        // 加入结果
        result.add(level);
    }

    return result;
}

二叉树的最近公共祖先

什么是最近公共祖先?

在二叉树中,两个节点的最近公共祖先是它们最近的共有祖先节点。

算法步骤:

  1. 特殊情况: 如果其中一个节点是另一个节点的祖先,则该节点是最近公共祖先。
  2. 递归: 否则,分别在左子树和右子树中查找节点,如果左右子树都找到了节点,则该节点是最近公共祖先。
  3. 继续递归: 如果只在一个子树中找到节点,则继续在该子树中递归查找。

代码示例:

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
    // 特殊情况
    if (root == null || root == p || root == q) {
        return root;
    }

    // 递归查找
    TreeNode left = lowestCommonAncestor(root.left, p, q);
    TreeNode right = lowestCommonAncestor(root.right, p, q);

    // 判断结果
    if (left != null && right != null) {
        return root;
    } else if (left != null) {
        return left;
    } else {
        return right;
    }
}

根据二叉树创建字符串

将二叉树转换成字符串

有时候我们需要将二叉树转换成字符串,比如进行序列化或输出。

算法步骤:

  1. 递归: 使用先序遍历来递归遍历二叉树。
  2. 拼接: 在遍历每个节点时,将其值添加到字符串中。
  3. 处理子树: 如果节点有子树,则将其放在括号内,并继续递归。

代码示例:

public String tree2str(TreeNode root) {
    // 判断空树
    if (root == null) {
        return "";
    }

    // 拼接根节点
    StringBuilder sb = new StringBuilder();
    sb.append(root.val);

    // 处理左子树
    if (root.left != null) {
        sb.append("(").append(tree2str(root.left)).append(")");
    }

    // 处理右子树
    if (root.right != null) {
        if (root.left == null) {
            sb.append("()");
        }
        sb.append("(").append(tree2str(root.right)).append(")");
    }

    return sb.toString();
}

结语

通过剖析这些经典算法,我们深入了解了二叉树的基本操作和算法思想。这些算法是解决二叉树问题的基石,掌握它们对于提升编程能力和面试表现至关重要。希望本文能够帮助小白程序员快速入门二叉树,成为算法界的明日之星!

常见问题解答

  1. 什么是二叉树的高度? 二叉树的高度是从根节点到最远叶节点的最长路径长度。
  2. 二叉搜索树和普通二叉树有什么区别? 二叉搜索树是一个特殊的二叉树,其中每个节点的值都比其左子树的所有值大,比其右子树的所有值小。
  3. 如何在二叉树中查找节点? 可以使用深度优先搜索(DFS)或广度优先搜索(BFS)算法来查找二叉树中的节点。
  4. 如何插入节点到二叉搜索树中? 在二叉搜索树中插入节点需要遵循二叉搜索树的性质,将新节点插入到正确的位置。
  5. 二叉树遍历有哪些常见的类型? 除了层序遍历之外,还有先序遍历、中序遍历和后序遍历等常见的二叉树遍历类型。