二叉树高频题精讲 | 从入门到熟练掌握二叉树操作

本系列可作为JAVA学习系列的笔记,文中提到的一些练习的代码,小编会将代码复制下来,大家复制下来就可以练习了,方便大家学习。

点赞关注不迷路!您的点赞、关注和收藏是对小编最大的支持和鼓励!

系列文章目录

JAVA初阶---------已更完

JAVA数据结构 DAY1-集合和时空复杂度

JAVA数据结构 DAY2-包装类和泛型

JAVA数据结构 DAY3-List接口

JAVA数据结构 DAY4-ArrayList

JAVA数据结构 DAY5-LinkedList

JAVA数据结构 DAY6-栈和队列

JAVA数据结构 DAY7-二叉树


拓展目录

手把手教你用 ArrayList 实现杨辉三角:从逻辑推导到每行代码详解

链表高频 6 题精讲 | 从入门到熟练掌握链表操作

二叉树高频题精讲 | 从入门到熟练掌握二叉树操作


目录

目录

系列文章目录

拓展目录

目录

前言

1.二叉树的前序遍历(需要返回遍历完的节点)

法1:没有使用递归的返回值

法2:使用递归的返回值

2.完全二叉树的节点

[法1:遍历二叉树 只要root不为空 ++](#法1:遍历二叉树 只要root不为空 ++)

法2:子问题:整棵树有多少棵节点=左子树节点+右子树节点+1

3.整棵树的叶子节点

[法1:遍历二叉树 只要root不为空 ++](#法1:遍历二叉树 只要root不为空 ++)

法2:子问题:整棵树有多少棵叶子节点=左子树的叶子节点+右子树的叶子节点

4.求第K层的节点个数

[法1:遍历二叉树 只要root不为空 ++](#法1:遍历二叉树 只要root不为空 ++)

法2:子问题:整层的节点=左子树的叶子节点+右子树的叶子节点

5.求第K层的节点个数

6.值为value的元素是否存在

7.层序遍历

[核心原理(记住这 4 点)](#核心原理(记住这 4 点))

8.判断一棵树是否是完全二叉树

[8.1 什么是完全二叉树?](#8.1 什么是完全二叉树?)

[8.2 判断核心规则(层序遍历)](#8.2 判断核心规则(层序遍历))

总结


前言

小编作为新晋码农一枚,会定期整理一些写的比较好的代码,作为自己的学习笔记,会试着做一下批注和补充,如转载或者参考他人文献会标明出处,非商用,如有侵权会删改!欢迎大家斧正和讨论!

本节,我将分享一下二叉树的习题部分,以及思路详解,在力扣的运行环境,每一题将会附上练题链接,大家点击即可练习!

1.二叉树的前序遍历(需要返回遍历完的节点)

给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

https://leetcode.cn/problems/binary-tree-preorder-traversal

提示:

  • 树中节点数目在范围 [0, 100]
  • -100 <= Node.val <= 100

**进阶:**递归算法很简单,你可以通过迭代算法完成吗?

法1:没有使用递归的返回值

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    // 注意:变量名不要用List(大写L),和接口名重复了,改成小写list更规范
    List<Integer> list=new ArrayList<>();
    //在 Java 中,List 是一个定义了列表行为的接口,它只规定了 "列表应该能做什么"(比如 add()、get() 等方法),但并没有实现这些方法的具体逻辑。
    //接口本身不能被直接实例化(也就是不能写 new List<>()),因为它只是一个 "规范",没有具体的执行代码。
    //List 是接口,仅定义规范,不能直接实例化(不能 new List<>());
    //ArrayList 是 List 接口的一个具体实现类,它用数组的方式实现了 List 接口中所有的方法(比如 add() 是往数组里加元素,get() 是从数组里取元素)。
    //所以我们需要通过 new ArrayList<>() 来创建一个具体的、可使用的列表对象,然后把它赋值给 List 类型的变量(这是 Java 的多态特性)。
    public List<Integer> preorderTraversal(TreeNode root) {
        if(root==null){
            return list;
        }
        list.add(root.val);
        preorderTraversal(root.left);
        preorderTraversal(root.right);
        return list;
    }
}

法2:使用递归的返回值

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> list=new ArrayList<>();
        if(root==null){
            return list;
        }
        list.add(root.val);
        List<Integer> leftTree=preorderTraversal(root.left);
        list.addAll(leftTree);// 把左子树的遍历结果全部加入当前列表
        List<Integer> rightTree=preorderTraversal(root.right);
        list.addAll(rightTree);//// 把右子树的遍历结果全部加入当前列表

        return list;
    }
}

2.完全二叉树的节点

https://leetcode.cn/problems/count-complete-tree-nodes/

解法(其一):

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int countNodes(TreeNode root) {
        if(root==null){
            return 0;
        }
        return countNodes(root.left)+countNodes(root.right)+1;
    }
}

法1:遍历二叉树 只要root不为空 ++

java 复制代码
public static int nodeSize=0;
    public void size(TreeNode root){
        if(root==null){
            return;
        }
        nodeSize++;
        size(root.left);
        size(root.right);
        return;
    }

main函数中做测试

java 复制代码
public static void main(String[] args){
        //........
        binaryTree.size(root);
        System.out.println("节点的个数:"+BinaryTree.nodeSize);
}

法2:子问题:整棵树有多少棵节点=左子树节点+右子树节点+1

java 复制代码
 public int size2(TreeNode root){
        if(root==null){
            return 0;
        }
        return size2(root.left)+size2(root.right)+1;
    }

main函数中做测试

java 复制代码
System.out.println("节点的个数:"+binaryTree.size2(root));

3.整棵树的叶子节点

什么是叶子节点?

root.left==null&&root.right==null

整棵树的叶子节点=左子树的叶子+右子树的叶子

法1:遍历二叉树 只要root不为空 ++

java 复制代码
public static int leefSize=0;
    public void getLeefNode2(TreeNode root){
        if(root==null){
            return;
        }
        if(root.left==null&&root.right==null){
            leefSize++;
        }
        getLeefNode2(root.left);
        getLeefNode2(root.right);
    }

main中调用

java 复制代码
binaryTree.getLeefNode2(root);
System.out.println("叶子节点的个数:"+BinaryTree.leefSize);

法2:子问题:整棵树有多少棵叶子节点=左子树的叶子节点+右子树的叶子节点

java 复制代码
//寻找树的叶子结点

    public int getLeefNode(TreeNode root){
        if(root==null){
            return 0;
        }
        if(root.left==null&&root.right==null){
            return 1;
        }
        return getLeefNode(root.left)+getLeefNode(root.right);

    }

4.求第K层的节点个数

法1:遍历二叉树 只要root不为空 ++

java 复制代码
//获取第K层结点的个数
    //遍历二叉树
    public static int KLevelnodes=0;
    public int getKLevelNodeCount(TreeNode root,int k){
        if(root==null){
            return 0;
        }
        if(k==1){
            KLevelnodes++;
        }else{
            k=k-1;
            getKLevelNodeCount(root.left,k);
            getKLevelNodeCount(root.right,k);
        }
        return KLevelnodes;
    }

main中调用

java 复制代码
System.out.println("请输入层数:");
Scanner scan=new Scanner(System.in);
int k= scan.nextInt();
System.out.println("第"+k+"层的节点个数是:"+binaryTree.getKLevelNodeCount(root,k));

法2:子问题:整层的节点=左子树的叶子节点+右子树的叶子节点

java 复制代码
//左子树的节点+右子树的节点
    public int getKLevelnodes2(TreeNode root,int k){
        if(root==null){
            return 0;
        }
        if(k==1){
            return 1;
        }else{
            k=k-1;
            return getKLevelnodes2(root.left,k)+getKLevelnodes2(root.right,k);
        }
    }
java 复制代码
System.out.println("请输入层数:");
Scanner scan=new Scanner(System.in);
int k= scan.nextInt();
System.out.println("第"+k+"层的节点个数是:"+binaryTree.getKLevelnodes2(root,k));

5.求第K层的节点个数

  • 空树 = 0
  • 叶子节点 = max (0,0)+1 = 1
  • 非叶子 = 左右最高那个 + 1
java 复制代码
//获取二叉树的高度
    public int nodeHeight(TreeNode root){
        if(root==null){
            return 0;
        }
        int leftHeight=nodeHeight(root.left);
        int rightHeight=nodeHeight(root.right);
        return Math.max(leftHeight,rightHeight)+1;

    }

6.值为value的元素是否存在

  • 空节点返回 false
  • 找到返回 true
  • 否则返回 左子树查找 || 右子树查找
java 复制代码
//检测值为value的元素是否存在
    public boolean nodeFind(TreeNode root,char value){
        if(root==null){
            return false;
        }
        if(value==root.val){
            return true;
        }
        return nodeFind(root.left,value)||nodeFind(root.right,value);
    }

7.层序遍历

  • 队列放节点,出一个就进它左右孩子

  • 根节点先进队列

  • 取出节点 → 打印

  • 左孩子进队列 → 右孩子进队列

  • 直到队列为空

核心原理(记住这 4 点)

  1. 层序遍历 = 从上到下、从左到右,一层一层遍历
  2. 必须用队列(Queue) 辅助
  3. 先把根节点入队
  4. 循环:
    • 取出队首节点
    • 把它的左孩子、右孩子依次入队
java 复制代码
 public void levelOrder(TreeNode root){
        if(root==null){
            return;
        }
        // 1. 创建队列
        Queue<TreeNode> queue=new LinkedList<>();
        queue.offer(root);

        // 2. 循环遍历
        while(!queue.isEmpty()){
                // 取出队首节点
                TreeNode cur=queue.poll();
                System.out.print(cur.val+" ");
            // 左孩子不为空,入队
                if (cur.left != null) queue.offer(cur.left);
            // 右孩子不为空,入队
                if (cur.right != null) queue.offer(cur.right);

           
        }

    }

8.判断一棵树是否是完全二叉树

8.1 什么是完全二叉树?

一句话记住:除了最后一层,其他层都是满的; 最后一层的节点,都靠左排列。

8.2 判断核心规则(层序遍历)

  1. 用队列一层一层遍历节点
  2. 遇到第一个 null 之后不能再出现非 null 节点
  3. 如果满足 → 是完全二叉树不满足 → 不是
java 复制代码
//判断是否是完全二叉树
    //用队列一层一层遍历节点
    //遇到第一个 null 之后,不能再出现非 null 节点
    //如果满足 → 是完全二叉树不满足 → 不是
    public boolean isCompleteBinaryTree(TreeNode root){
        if(root==null){
            return true;
            //空树 = 完全二叉树
        }
        // 1. 创建队列
        Queue<TreeNode> queue=new LinkedList<>();
        queue.offer(root);
        boolean flag=false; // 标记:是否已经遇到过 null
        // 2. 循环遍历
        while(!queue.isEmpty()){

            // 取出队首节点
            TreeNode cur=queue.poll();
            if(cur==null){
                flag=true;//已经遇到了null
            }else{
                if(flag)
                //已经遇到了null 但又遇到了非空
                return false;

                // ✅ 关键:只有 cur 不是 null,才把左右孩子入队(包括 null)
                queue.offer(cur.left);
                queue.offer(cur.right);

                //1. 只要 cur == null
                //绝对不能访问 cur.left/cur.right
                //2. 入队必须写在 else 里面
                //只有 cur 不是 null,才把左右孩子丢进队列!
            }


        }
        return true;
    }

总结

以上就是今天要讲的内容,本文简单记录了java数据结构,仅作为一份简单的笔记使用,大家根据注释理解,您的点赞关注收藏就是对小编最大的鼓励!

相关推荐
kaikaile19951 小时前
基于PCNN和NSCT的图像融合MATLAB实现
开发语言·图像处理·算法·matlab
山栀shanzhi1 小时前
C++ 核心机制解析:#pragma once 与 extern 的具体职责与区别
开发语言·c++·面试
1231566801 小时前
PAT 1017 A除以B
c语言·数据结构·算法·pat考试
wuqingshun3141591 小时前
说说java中实现多线程有几种方法
java·开发语言·jvm
于眠牧北1 小时前
重写RedisTemplate后在lua脚本中传递参数不需要二次转换
java·junit·lua
深蓝轨迹2 小时前
SQL优化及实战分享
java·数据库·sql
voltina2 小时前
一致性哈希+虚拟节点
数据结构
hashiqimiya2 小时前
尝试其他项目使用本地仓库的jar包时报错没找到类的原因并下载到本地仓库
java·jar
常利兵2 小时前
Spring Boot + MyBatis,给数据穿上“隐形盔甲”
java·spring boot·mybatis