搞定leetcode面试经典150题之二叉树

系列博客目录



基础知识

在 Java 中,二叉树(Binary Tree)是一种常见的树形数据结构,它由一个节点组成,节点具有最多两个子节点,通常称为左子节点和右子节点。二叉树在计算机科学中广泛用于表示数据、优化搜索操作、实现排序算法等。

以下是二叉树的相关理论内容:

1. 二叉树的基本定义

  • 节点:二叉树中的基本元素,每个节点包含:

    • 一个值(或数据)
    • 一个指向左子节点的引用
    • 一个指向右子节点的引用
  • 根节点:二叉树的第一个节点,也就是最上层的节点。每棵树只有一个根节点。

  • 子树:树中的任意节点及其所有后代节点称为该节点的子树。每个节点的左子树和右子树本身也是二叉树。

  • 叶子节点:没有子节点的节点称为叶子节点。叶子节点是二叉树的终端节点。

  • 深度(Depth):节点的深度是指该节点从根节点开始的路径长度。根节点的深度为 0。

  • 高度(Height):树的高度是根节点的深度。一个节点的高度是指从该节点到其所有子节点的最大深度。

2. 二叉树的性质

  • 每个节点最多有两个子节点:每个节点最多有一个左子节点和一个右子节点。
  • 最多有 2 d 2^d 2d 个节点:如果二叉树的高度为 d,那么在最坏情况下(即完全二叉树),二叉树的节点数最多为 2 d − 1 2^d-1 2d1
  • 二叉树的节点总数与高度的关系
    • 对于一个完全二叉树,如果有 n 个节点,树的高度大约是 log₂n

3. 二叉树的类型

  • 满二叉树:一棵二叉树如果每个非叶子节点都有左右两个子节点,并且所有叶子节点都在同一层上,那么这棵树是满二叉树。

  • 完全二叉树:一棵二叉树如果除了最后一层外,其他层都已经完全填满,且最后一层的叶子节点都靠左排列,那么它是完全二叉树。

  • 平衡二叉树(AVL树):一棵二叉树如果它的左右子树高度差的绝对值不超过 1,那么它是平衡二叉树。

  • 二叉搜索树(BST,Binary Search Tree):一种特殊的二叉树,具有以下特点:

    • 左子树的所有节点的值小于根节点的值。
    • 右子树的所有节点的值大于根节点的值。
    • 每个节点的左子树和右子树也是二叉搜索树。
  • 红黑树:一种自平衡的二叉搜索树,其中每个节点都包含一个颜色属性(红色或黑色),通过一定的规则来保持树的平衡。

4. 二叉树的遍历

遍历是指访问二叉树的所有节点,通常有以下几种方式:

  • 前序遍历(Preorder Traversal):访问根节点 -> 遍历左子树 -> 遍历右子树。

    • 递归实现:
      void preorder(TreeNode root) {
             
             
          if (root == null) return;
          System.out.print(root.val + " ");
          preorder(root.left);
          preorder(root.right);
      }
      
  • 中序遍历(Inorder Traversal):遍历左子树 -> 访问根节点 -> 遍历右子树。对于二叉搜索树,中序遍历的结果是有序的。

    • 递归实现:
      void inorder(TreeNode root) {
             
             
          if (root == null) return;
          inorder(root.left);
          System.out.print(root.val + " ");
          inorder(root.right);
      }
      
    • 迭代实现:
      class Solution {
             
             
      public List<Integer> inorderTraversal(TreeNode root) {
             
             
          List<Integer> res = new ArrayList<>();
          Deque<TreeNode> treeNodes = new LinkedList<>();
          while(root!=null || !treeNodes.isEmpty()){
             
             
              while(root!=null){
             
             
                  treeNodes.push(root);
                  root = root.left;
              }
              final TreeNode pop = treeNodes.poll();
              res.add(pop.val);
              root = pop.right;
          }
          return res;
      	 }
      }
      
  • 后序遍历(Postorder Traversal):遍历左子树 -> 遍历右子树 -> 访问根节点。

    • 递归实现:
      void postorder(TreeNode root) {
             
             
          if (root == null) return;
          postorder(root.left);
          postorder(root.right);
          System.out.print(root.val + " ");
      }
      
  • 层序遍历(Level-order Traversal):按照从上到下、从左到右的顺序逐层访问树的节点。通常使用队列(Queue)实现。

    • 队列实现:
      void levelOrder(TreeNode root) {
             
             
          if (root == null) return;
          Queue<TreeNode> queue = new LinkedList<>();
          queue.offer(root);
          while (!queue.isEmpty()) {
             
             
              TreeNode node = queue.poll();
              System.out.print(node.val + " ");
              if (node.left != null) queue.offer(node.left);
              if (node.right != null) queue.offer(node.right);
          }
      }
      

5. 二叉树的实现

二叉树通常使用节点类(TreeNode)来实现,节点类包括值、左子节点和右子节点的引用。以下是一个简单的二叉树节点类:

class TreeNode {
   
   
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode(int val) {
   
   
        this.val = val;
        this.left = null;
        this.right = null;
    }
}

6. 常见的二叉树算法

  • 查找最大深度(高度):递归计算树的最大深度。

    int maxDepth(TreeNode root) {
         
         
        if (root == null) return 0;
        int leftDepth = maxDepth(root.left);
        int rightDepth = maxDepth(root.right);
        return Math.max(leftDepth, rightDepth) + 1;
    }
    
  • 查找最小深度:与最大深度类似,但返回的是树中最短的路径。

    int minDepth(TreeNode root) {
         
         
        if (root == null) return 0;
        if (root.left == null) return minDepth(root.right) + 1;
        if (root.right == null) return minDepth(root.left) + 1;
        return Math.min(minDepth(root.left), minDepth(root.right)) + 1;
    }
    
  • 判断二叉树是否对称:检查二叉树是否是镜像对称的(即左右子树镜像)。

    boolean isSymmetric(TreeNode root) {
         
         
        if (root == null) return true;
        return isMirror(root.left, root.right);
    }
    
    boolean isMirror(TreeNode t1, TreeNode t2) {
         
         
        if (t1 == null && t2 == null) return true;
        if (t1 == null || t2 == null) return false;
        return (t1.val == t2.val) &&
               isMirror(t1.left, t2.right) &&
               isMirror(t1.right, t2.left);
    }
    
  • 判断二叉搜索树:检查二叉树是否满足二叉搜索树的条件(左子树的值小于根,右子树的值大于根)。

    boolean isValidBST(TreeNode root) {
         
         
        return isValidBSTHelper(root, Long.MIN_VALUE, Long.MAX_VALUE);
    }
    
    boolean isValidBSTHelper(TreeNode node, long min, long max) {
         
         
        if (node == null) return true;
        if (node.val <= min || node.val >= max) return false;
        return isValidBSTHelper(node.left, min, node.val) &&
               isValidBSTHelper(node.right, node.val, max);
    }
    

7. 二叉树的应用

  • (Heap):一种完全二叉树,用于实现优先队列。最小堆和最大堆都是基于二叉树的结构。
  • 前缀表达式和后缀表达式:二叉树可用于解析和计算前缀或后缀表达式。
  • 最短路径和最小生成树:二叉树的变种,如哈夫曼树,可用于数据压缩。

总结

二叉树是一种非常重要的数据结构,具有许多不同的变种和应用。它可以通过递归方法非常方便地进行遍历和操作,并且广泛用于解决各种算法问题,如查找、排序、路径查找等。

例题

class TreeNode {
   
   
    int val;
    TreeNode left;
    TreeNode right;
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值