算法题目总结-二叉树

news2025/1/21 19:43:16

文章目录

    • 1.二叉树的最大深度
        • 1.答案
        • 2.思路
    • 2.相同的树
        • 1.答案
        • 2.思路
    • 3.翻转二叉树
        • 1.答案
        • 2.思路
    • 4.对称二叉树
        • 1.答案
        • 2.思路
    • 5.填充每个节点的下一个右侧节点指针 II
        • 1.答案
        • 2.思路
    • 6.二叉树展开为链表
        • 1.答案
        • 2.思路
    • 7.路径总和
        • 1.答案
        • 2.思路
    • 8.求根节点到叶节点数字之和
        • 1.答案
        • 2.思路
    • 9.二叉树的最近公共祖先
        • 1.答案
        • 2.思路
    • 10.二叉树的层序遍历
        • 1.答案
        • 2.思路
    • 11.二叉搜索树的最小绝对差
        • 1.答案
        • 2.思路
    • 12.验证二叉搜索树
        • 1.答案
        • 2.思路

1.二叉树的最大深度

1.答案
package com.sunxiansheng.arithmetic.day7;

import com.sunxiansheng.arithmetic.util.TreeNode;

/**
 * Description: 104. 二叉树的最大深度
 *
 * @Author sun
 * @Create 2025/1/9 10:16
 * @Version 1.0
 */
public class t104 {

    public int maxDepth(TreeNode root) {
        if (root == null) {
            // 如果当前节点为空,那么最大深度就是0
            return 0;
        } else {
            // 可以获取到左右子树的最大深度
            int left = maxDepth(root.left);
            int right = maxDepth(root.right);
            // 取左右子树中深度最大的加一就是当前子树的最大深度
            return Math.max(left, right) + 1;
        }
    }
}
2.思路

取左右子树中深度最大的加一就是当前子树的最大深度

2.相同的树

1.答案
package com.sunxiansheng.arithmetic.day7;

import com.sunxiansheng.arithmetic.util.TreeNode;

/**
 * Description: 100. 相同的树
 *
 * @Author sun
 * @Create 2025/1/9 10:23
 * @Version 1.0
 */
public class t100 {

    public static boolean isSameTree(TreeNode left, TreeNode right) {
        if (left == null && right == null) {
            return true;
        } else if (left == null || right == null) {
            return false;
        } else {
            // 先比较当前两个节点的值
            if (left.val != right.val) {
                return false;
            }
            // 当前两个节点的值如果相同,就比较两个子树是否是相同的树
            boolean leftTree = isSameTree(left.left, right.left);
            boolean rightTree = isSameTree(left.right, right.right);
            return leftTree && rightTree;
        }
    }
}
2.思路
  1. 参数,传递状态
  2. 终止条件:两个节点都为空返回true,两个节点一个为空就返回false
  3. 如果两个节点都不为空,则先比较两个节点的值,然后当左右子树都相同时就返回true

3.翻转二叉树

1.答案
package com.sunxiansheng.arithmetic.day8;

import com.sunxiansheng.arithmetic.util.TreeNode;

/**
 * Description: 226. 翻转二叉树
 *
 * @Author sun
 * @Create 2025/1/11 09:59
 * @Version 1.0
 */
public class t226 {

    public TreeNode invertTree(TreeNode root) {
        if (root == null) {
            // 如果为空,直接返回即可,因为null就是翻转后的结果了
            return null;
        } else {
            TreeNode left = invertTree(root.left);
            TreeNode right = invertTree(root.right);
            // 翻转左右子树
            root.left = right;
            root.right = left;
            return root;
        }
    }
}
2.思路
  1. 参数传递状态
  2. 终止条件就是如果为null,就返回null,因为返回的就是翻转后的树了
  3. 然后在返回翻转后的左右子树之后,再将当前节点的左右子树翻转后返回即可

4.对称二叉树

1.答案
package com.sunxiansheng.arithmetic.day8;

import com.sunxiansheng.arithmetic.util.TreeNode;

/**
 * Description: 101. 对称二叉树
 *
 * @Author sun
 * @Create 2025/1/11 10:09
 * @Version 1.0
 */
public class t101 {

    public boolean isSymmetric(TreeNode root) {
        if (root == null) {
            return true;
        }
        // 检查左右子树是否对称
        return check(root.left, root.right);
    }

    /**
     * 检查左右子树是否轴对称
     *
     * @param left
     * @param right
     * @return
     */
    private boolean check(TreeNode left, TreeNode right) {
        if (left == null && right == null) {
            return true;
        } else if (left == null || right == null) {
            return false;
        } else {
            // 都不为空的情况,就先比较两个节点的值
            if (left.val != right.val) {
                return false;
            }
            // 到这里就是两个节点的值相同,则判断子树是否对称
            boolean leftTree = check(left.right, right.left);
            boolean rightTree = check(left.left, right.right);
            return leftTree && rightTree;
        }
    }
}
2.思路

就是相同的树,不过在传递状态的时候不同而已

5.填充每个节点的下一个右侧节点指针 II

1.答案
package com.sunxiansheng.arithmetic.day8;

import com.sunxiansheng.arithmetic.util.Node;

import java.util.LinkedList;
import java.util.Queue;

/**
 * Description: 117. 填充每个节点的下一个右侧节点指针 II
 *
 * @Author sun
 * @Create 2025/1/11 10:19
 * @Version 1.0
 */
public class t117 {

    public Node connect(Node root) {
        // 层序遍历
        if (root == null) {
            return null;
        }
        Queue<Node> queue = new LinkedList<>();
        queue.add(root);
        while (!queue.isEmpty()) {
            int size = queue.size();
            // 前一个节点的指针
            Node prev = null;
            for (int i = 0; i < size; i++) {
                Node node = queue.poll();
                // 只要前一个节点不是空,就指向当前节点
                if (prev != null) {
                    prev.next = node;
                }
                // 更新前一个节点的指针指向当前节点
                prev = node;
                if (node.left != null) {
                    queue.add(node.left);
                }
                if (node.right != null) {
                    queue.add(node.right);
                }
            }
        }
        return root;
    }
}
2.思路

使用层序遍历,并记录前一个指针的值,只要前一个指针不为null,就让他的next指向当前节

6.二叉树展开为链表

1.答案
package com.sunxiansheng.arithmetic.day8;

import com.sunxiansheng.arithmetic.util.TreeNode;

/**
 * Description: 114. 二叉树展开为链表
 *
 * @Author sun
 * @Create 2025/1/11 10:30
 * @Version 1.0
 */
public class t114 {

    TreeNode prev = null;

    public void flatten(TreeNode root) {
        if (root == null) {
            return;
        } else {
            flatten(root.right);
            flatten(root.left);
            // 将当前节点的左子树置空
            root.left = null;
            // 当前节点的right指向prev
            root.right = prev;
            // 更新prev为当前节点
            prev = root;
        }
    }
}
2.思路

反前序遍历,先将当前子树的左节点置空,右节点指向prev,然后更新prev指向当前节点

7.路径总和

1.答案
package com.sunxiansheng.arithmetic.day8;

import com.sunxiansheng.arithmetic.util.TreeNode;

/**
 * Description: 112. 路径总和
 *
 * @Author sun
 * @Create 2025/1/11 10:44
 * @Version 1.0
 */
public class t112 {

    public boolean hasPathSum(TreeNode root, int targetSum) {
        if (root == null) {
            return false;
        }
        boolean[] res = new boolean[1];
        backtrace(root, 0, res, targetSum);
        return res[0];
    }

    public static void backtrace(TreeNode root, int sum, boolean[] res, int targetSum) {
        // 累加结果
        sum += root.val;
        if (root.left == null && root.right == null) {
            if (sum == targetSum) {
                res[0] = true;
            }
            return;
        } else {
            if (root.left != null) {
                backtrace(root.left, sum, res, targetSum);
            }
            if (root.right != null) {
                backtrace(root.right, sum, res, targetSum);
            }
        }
    }
}
2.思路

对于每个节点,先计算当前节点的和,如果是叶子节点就直接与targetSum比较,如果不是叶子节点就传递状态

8.求根节点到叶节点数字之和

1.答案
package com.sunxiansheng.arithmetic.day8;

import com.sunxiansheng.arithmetic.util.TreeNode;

/**
 * Description: 129. 求根节点到叶节点数字之和
 *
 * @Author sun
 * @Create 2025/1/11 11:00
 * @Version 1.0
 */
public class t129 {

    public int sumNumbers(TreeNode root) {
        int[] res = new int[1];
        backtrace(root, new StringBuilder(), res);
        return res[0];
    }
    
    public static void backtrace(TreeNode root, StringBuilder sum, int[] res) {
        if (root.left == null && root.right == null) {
            // 计算和
            sum.append(root.val);
            // 累加和
            res[0] += Integer.valueOf(sum.toString());
            return;
        } else {
            // 计算和
            sum.append(root.val);
            if (root.left != null) {
                backtrace(root.left, sum, res);
                // 回溯
                sum.deleteCharAt(sum.length() - 1);
            }
            if (root.right != null) {
                backtrace(root.right, sum, res);
                // 回溯
                sum.deleteCharAt(sum.length() - 1);
            }
        }
    }
}
2.思路

这种路径问题,采用的遍历方式一定是root.left != null xxx root.right != null xxx 然后根节点使用的是root.left == null && root.right == null 这样就不会走到null节点了,然后再if和else都需要计算路径,回溯的话只有递归之后才回溯

9.二叉树的最近公共祖先

1.答案
package com.sunxiansheng.arithmetic.day9;

import com.sunxiansheng.arithmetic.util.TreeNode;

import java.util.Objects;

/**
 * Description: 236. 二叉树的最近公共祖先
 *
 * @Author sun
 * @Create 2025/1/13 09:33
 * @Version 1.0
 */
public class t236 {

    public static TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        // 如果目前的树为null或者是p或者q,那么公共祖先就是root
        if (root == null || root == p || root == q) {
            return root;
        } else {
            TreeNode left = lowestCommonAncestor(root.left, p, q);
            TreeNode right = lowestCommonAncestor(root.right, p, q);
            // 如果都找不到公共祖先,就说明子树中没有p,q
            if (Objects.isNull(left) && Objects.isNull(right)) {
                return null;
            }
            // 如果有一个找到了公共祖先,那么公共祖先就是那个节点
            if (Objects.isNull(left) || Objects.isNull(right)) {
                return left == null ? right : left;
            }
            // 如果都找到了公共祖先,则当前节点就是公共祖先
            return root;
        }
    }
}
2.思路

如果目前的树为null或者是p或者q,那么公共祖先就是root,其他情况则从左右子树寻找公共祖先,如果都找不到,就说明左右子树没有p,q,则公共祖先为null,如果有一个找到了公共祖先,则公共祖先就是那个节点,如果都找到了公共祖先,则当前节点就是公共祖先

10.二叉树的层序遍历

1.答案
package com.sunxiansheng.arithmetic.day9;

import com.sunxiansheng.arithmetic.util.TreeNode;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

/**
 * Description: 二叉树的层序遍历
 *
 * @Author sun
 * @Create 2025/1/13 09:57
 * @Version 1.0
 */
public class t102 {

    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        if (root == null) {
            return res;
        }
        // 队列
        Queue<TreeNode> queue = new LinkedList<>();
        // 根节点入队
        queue.add(root);
        while (!queue.isEmpty()) {
            // 当前层的节点数
            int size = queue.size();
            // 存当前层节点
            List<Integer> list = new ArrayList<>();
            // 遍历当前层节点
            for (int i = 0; i < size; i++) {
                // 取出一个节点
                TreeNode node = queue.poll();
                // 放入列表
                list.add(node.val);
                // 左右节点入队
                if (node.left != null) {
                    queue.add(node.left);
                }
                if (node.right != null) {
                    queue.add(node.right);
                }
            }
            // 将当前层的节点放到列表中
            res.add(list);
        }
        return res;
    }
}
2.思路

标准的二叉树层序遍历

11.二叉搜索树的最小绝对差

1.答案
package com.sunxiansheng.arithmetic.day9;

import com.sunxiansheng.arithmetic.util.TreeNode;

/**
 * Description: 530. 二叉搜索树的最小绝对差
 *
 * @Author sun
 * @Create 2025/1/13 10:07
 * @Version 1.0
 */
public class t530 {

    public int getMinimumDifference(TreeNode root) {
        int[] res = new int[2];
        res[0] = Integer.MAX_VALUE;
        // 前一个节点的值初始化为-1
        res[1] = - 1;
        midderOrder(root, res);
        return res[0];
    }

    public void midderOrder(TreeNode root, int[] res) {
        if (root == null) {
            return;
        } else {
            midderOrder(root.left, res);
            // 如果前一个节点的值不为-1,才求差值
            if (res[1] != -1) {
                // 跟前一个节点求差值
                int diff = Math.abs(root.val - res[1]);
                // 然后跟当前的最小差值比较
                res[0] = Math.min(res[0], diff);
            }
            // 更新前一个节点
            res[1] = root.val;
            midderOrder(root.right, res);
        }
    }
}
2.思路

这里需要注意的点是如果前一个节点的值不为-1,才求差值,也就是要跳过第一个根

12.验证二叉搜索树

1.答案
package com.sunxiansheng.arithmetic.day9;

import com.sunxiansheng.arithmetic.util.TreeNode;

/**
 * Description: 98. 验证二叉搜索树
 *
 * @Author sun
 * @Create 2025/1/13 10:41
 * @Version 1.0
 */
public class t98 {

    public boolean isValidBST(TreeNode root) {
        return middleOrder(root, Long.MIN_VALUE, Long.MAX_VALUE);
    }

    public boolean middleOrder(TreeNode root, long min, long max) {
        if (root == null) {
            return true;
        }
        if (root.val <= min || root.val >= max) {
            return false;
        }
        // 再判断左右子树的节点范围满不满足要求
        boolean left = middleOrder(root.left, min, root.val);
        boolean right = middleOrder(root.right, root.val, max);
        return left && right;
    }
}
2.思路

核心就是判断节点是否在从min到max的范围内

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2279987.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Comment(爆破+git泄漏+二次注入)

通过爆破密码的后三位&#xff0c;获得账号为&#xff1a;zhangwei666 F12查看控制台 使用bugscanteam的githack工具&#xff0c;下载泄漏的源码&#xff0c;根据控制台的提示&#xff0c;完整源码还在历史的commit中 git log –reflog 查看历史记录 查看最新的提交记录&#…

C++otlv4连接sql serveer使用记录(注意点)

C使用otlv4在做插入时&#xff0c;有一些设计的坑需要注意 插入数据&#xff1a; 当要给表中插入单个字符时&#xff0c;数据库表设计使用varchar(1)是合理的&#xff0c;但是otlv4一直报错char。 后续查很久才知道&#xff0c;otlv4所写的绑定的字符数组的长度应该实际数组…

2024又是一年的CSDN之旅-总结过去展望未来

一、前言 一年就这样在忙忙碌碌的工作和生活中一晃而过&#xff0c;总结今年在CSDN上发表的博客&#xff0c;也有上百篇之多&#xff0c;首先感谢CSDN这个平台&#xff0c;能让我有一个地方记录工作中的点点滴滴&#xff0c;也在上面学到了不少知识&#xff0c;解决了工作中遇到…

JDK长期支持版本(LTS)

https://blogs.oracle.com/java/post/the-arrival-of-java-23 jdk长期支持版本&#xff08;LTS&#xff09;&#xff1a;JDK 8、11、17、21&#xff1a;

大数据学习(37)- Flink运行时架构

&&大数据学习&& &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 承认自己的无知&#xff0c;乃是开启智慧的大门 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4dd;支持一下博主哦&#x1f91…

“AI 大模型内容安全审核软件系统:守护网络世界的卫士

在如今这个信息爆炸的互联网时代&#xff0c;网络上的内容那是五花八门、层出不穷。这时候&#xff0c;咱就得靠 AI 大模型内容安全审核软件系统来给咱把把关了。 咱就说社交媒体平台吧&#xff0c;每天都有海量的用户在上面发布文字、图片、视频啥的。要是没有一个靠谱的审核系…

pyspark连接clickhouse数据库的方式(其它数据库同样适用)

目录 一、背景简记二、pyspark连接clickhouse方式记录三、结语参考学习博文 一、背景简记 实际工作中&#xff0c;大部分所用的数据存储地址都是在数据库中&#xff0c;如我司现在常用的数据库是clickhouse&#xff0c;相关数据的统计分析都在此上操作。如果想用pyspark连接cl…

C 语言雏启:擘画代码乾坤,谛观编程奥宇之初瞰

大家好啊&#xff0c;我是小象٩(๑ω๑)۶ 我的博客&#xff1a;Xiao Xiangζั͡ޓއއ 很高兴见到大家&#xff0c;希望能够和大家一起交流学习&#xff0c;共同进步。* 这一课主要是让大家初步了解C语言&#xff0c;了解我们的开发环境&#xff0c;main函数&#xff0c;库…

nacos2.3.0 接入pgsql或其他数据库

首先尝试使用官方插件进行扩展&#xff0c;各种报错后放弃&#xff0c;不如自己修改源码吧。 一、官方解决方案 1、nocos 文档地址&#xff1a;Nacos 配置中心简介, Nacos 是什么 | Nacos 官网 2、官方解答&#xff1a;nacos支持postgresql数据库吗 | Nacos 官网 3、源码下载地…

随遇随记篇

vue 函数 unref() 获取原始值 ref 定义的属性 需要 .value 才能拿到值&#xff0c;unref 直接返回原始值&#xff1b;若属性不是ref 定义的&#xff0c;也是直接返回原始值&#xff1b; /* description: 是否必填*/required?: boolean | Ref<boolean>.....let value …

网站HTTP改成HTTPS

您不仅需要知道如何将HTTP转换为HTTPS&#xff0c;还必须在不妨碍您的网站自成立以来建立的任何搜索排名权限的情况下进行切换。 为什么应该从HTTP转换为HTTPS&#xff1f; 与非安全HTTP于不同&#xff0c;安全域使用SSL&#xff08;安全套接字层&#xff09;服务器上的加密代…

微软Win10 RP 19045.5435(KB5050081)预览版发布!

系统之家1月20日最新报道&#xff0c;微软面向Release Preview频道的Windows Insider项目成员&#xff0c;发布了适用于Windows10 22H2版本的KB5050081更新&#xff0c;更新后系统版本号将升至19045.5435。本次更新增加了对GB18030-2022标准的支持&#xff0c;同时新版日历将为…

从提供的 package.json 文件可以看出,项目已经集成了 vue-cli-service lint --fix,并且配置了相关的工具和脚本

文章目录 1. 确认 vue-cli-service lint 已集成2. 确认 lintOnSave 是否启用示例&#xff1a;vue.config.js 3. 确认 ESLint 配置4. 确认 Git 钩子配置5. 如何实现保存时自动修复&#xff08;1&#xff09;启用 lintOnSave&#xff08;2&#xff09;配置编辑器的 ESLint 插件&a…

2024年博客之星主题创作|Android 开发:前沿技术、跨领域融合与就业技能展望

目录 引言 一、推动 Android 应用创新的核心力量 1.1 人工智能与机器学习的崛起 1.2 增强现实&#xff08;AR&#xff09;与虚拟现实&#xff08;VR&#xff09;的应用扩展 1.3 5G技术的推动 1.4 跨平台开发技术的成熟 1.4.1 React Native 1.4.2 Flutter 1.4.3 Taro …

mac 安装mongodb

本文分享2种mac本地安装mongodb的方法&#xff0c;一种是通过homebrew安装&#xff0c;一种是通过tar包安装 homebrew安装 brew tap mongodb/brew brew upate brew install mongodb-community8.0tar包安装 安装mongodb 1.下载mongodb社区版的tar包 mongdb tar包下载地址 2…

Nvidia Blackwell架构深度剖析:深入了解RTX 50系列GPU的升级

在CES 2025上&#xff0c;英伟达推出了基于Blackwell架构的GeForce RTX 50系列显卡&#xff0c;包括RTX 5090、RTX 5080、RTX 5070 Ti和RTX 5070。一段时间以来&#xff0c;我们已经知晓了该架构的各种细节&#xff0c;其中许多此前还只是传闻。不过&#xff0c;英伟达近日在20…

抽奖系统(4——活动模块)

1. 活动创建 需求回顾 创建的活动信息包含&#xff1a; 活动名称活动描述关联的一批奖品&#xff0c;关联时需要选择奖品等级&#xff08;一等奖、二等奖、三等奖&#xff09;&#xff0c;及奖品库存圈选一批人员参与抽奖 tip&#xff1a;什么时候设置奖品数量和奖品等级&am…

Oracle 深入学习 Part 14:Managing Password Security and Resources(管理密码安全性和资源)

Profiles Profile 是一个以名称标识的集合&#xff0c;用于管理 密码 和 资源限制。 每个用户都对应一个profiles&#xff0c;可以通过 CREATE USER 或 ALTER USER 命令分配给用户。 Profiles 可以启用或禁用。 Profiles 可以关联到默认的 DEFAULT Profile。 密码管理&…

Qt 5.14.2 学习记录 —— 십칠 窗口和菜单

文章目录 1、Qt窗口2、菜单栏设置快捷键添加子菜单添加分割线和菜单图标 3、工具栏 QToolBar4、状态栏 QStatusBar5、浮动窗口 QDockWidget 1、Qt窗口 QWidget&#xff0c;即控件&#xff0c;是窗口的一部分。在界面中创建控件组成界面时&#xff0c;Qt自动生成了窗口&#xf…

计算机视觉模型的未来:视觉语言模型

一、视觉语言模型 人工智能已经从识别数据中的简单模式跃升为理解复杂的多模态数据。该领域的发展之一是视觉语言模型 (VLM) 的兴起。这类模型将视觉和文本之间联系起来,改变了我们理解视觉数据并与之交互的方式。随着 VLM 的不断发展,它们正在为计算机视觉设定一个新的水平…