算法训练营 day20 二叉树 最大二叉树 合并二叉树 二叉搜索树中的搜索 验证二叉树

news2024/12/27 17:48:51

算法训练营 day20 二叉树 最大二叉树 合并二叉树 二叉搜索树中的搜索 验证二叉树

最大二叉树

654. 最大二叉树 - 力扣(LeetCode)

给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建:

创建一个根节点,其值为 nums 中的最大值。
递归地在最大值 左边 的 子数组前缀上 构建左子树。
递归地在最大值 右边 的 子数组后缀上 构建右子树。
返回 nums 构建的 最大二叉树 。

最大二叉树的构建过程如下:

在这里插入图片描述

构造树一般采用的是前序遍历,因为先构造中间节点,然后递归构造左子树和右子树。

  • 确定递归函数的参数和返回值

参数传入的是存放元素的数组,返回该数组构造的二叉树的头结点。

  • 确定终止条件

题目中说了输入的数组大小一定是大于等于1的,所以我们不用考虑小于1的情况,那么当递归遍历的时候,如果传入的数组大小为1,说明遍历到了叶子节点了。

那么应该定义一个新的节点,并把这个数组的数值赋给新的节点,然后返回这个节点。 这表示一个数组大小是1的时候,构造了一个新的节点,并返回。

  • 确定单层递归的逻辑

这里有三步工作

  1. 先要找到数组中最大的值和对应的下标, 最大的值构造根节点,下标用来下一步分割数组。

  2. 最大值所在的下标左区间 构造左子树

  3. 最大值所在的下标右区间 构造右子树

class Solution {
    public TreeNode constructMaximumBinaryTree(int[] nums) {
        return construct(nums,0,nums.length);
    }

    private TreeNode construct(int[] nums, int leftindex, int rightindex) {
        if (rightindex - leftindex < 1) {// 没有元素了
            return null;
        }
        if (rightindex - leftindex == 1) {// 只有一个元素
            return new TreeNode(nums[leftindex]);
        }
        int maxvalue = -1;
        int maxindex = 0;
        for (int i = leftindex;i<rightindex; i++){
            if (nums[i]>maxvalue){
                maxvalue = nums[i];
                maxindex = i;
            }
        }
        TreeNode node = new TreeNode(maxvalue);

        node.left = construct(nums,leftindex,maxindex);
        node.right = construct(nums,maxindex+1,rightindex);

        return node;
    }
}

合并二叉树

617. 合并二叉树 - 力扣(LeetCode)

给你两棵二叉树: root1 和 root2 。

想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。

返回合并后的二叉树。

注意: 合并过程必须从两个树的根节点开始。

递归法

在这里插入图片描述

  1. 确定递归函数的参数和返回值:

首先要合入两个二叉树,那么参数至少是要传入两个二叉树的根节点,返回值就是合并之后二叉树的根节点。

  1. 确定终止条件:

因为是传入了两个树,那么就有两个树遍历的节点t1 和 t2,如果t1 == NULL 了,两个树合并就应该是 t2 了(如果t2也为NULL也无所谓,合并之后就是NULL)。

反过来如果t2 == NULL,那么两个数合并就是t1(如果t1也为NULL也无所谓,合并之后就是NULL)。

  1. 确定单层递归的逻辑:

单层递归的逻辑就比较好写了,这里我们重复利用一下t1这个树,t1就是合并之后树的根节点(就是修改了原来树的结构)。

那么单层递归中,就要把两棵树的元素加到一起。

    public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
        if (root1==null) return root2;
        if (root2==null) return root1;
        root1.val+=root2.val;
        root1.left = mergeTrees(root1.left,root2.left);
        root1.right = mergeTrees(root1.right,root2.right);
        return root1;
    }

迭代法

class Solution {
    public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
        if (root1 == null) return root2;
        if (root2 == null) return root1;

        Stack<TreeNode> st = new Stack<>();
        st.push(root2);
        st.push(root1);
        while (!st.isEmpty()) {
            TreeNode node1 = st.pop();
            TreeNode node2 = st.pop();
            // 此时两个节点一定不为空,val相加
            node1.val += node2.val;
            if (node1.left != null && node2.left != null) {// 如果两棵树左节点都不为空,加入队列
                st.push(node2.left);
                st.push(node1.left);
            } else if (node1.left == null) {//当t1的左节点 为空 t2左节点不为空,就赋值过去
                node1.left = node2.left;

            }
            if (node1.right != null && node2.right != null) {// 如果两棵树右节点都不为空,加入队列
                st.push(node2.right);
                st.push(node1.right);
            } else if (node1.right == null) { // 当t1的右节点 为空 t2右节点不为空,就赋值过去
                node1.right = node2.right;
            }
        }
        return root1;
    }
}

二叉搜索树中的搜索

700. 二叉搜索树中的搜索 - 力扣(LeetCode)

给定二叉搜索树(BST)的根节点 root 和一个整数值 val。

你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 null 。

递归法

class Solution {
    public TreeNode searchBST(TreeNode root, int val) {
        if (root == null) return null;
        if (root.val == val) return root;
        if (root.val < val) 
            return searchBST(root.right, val);
        else 
            return searchBST(root.left, val);
    }
}

迭代法

class Solution {
    public TreeNode searchBST(TreeNode root, int val) {
        Stack<TreeNode> st = new Stack<>();
        if (root == null || root.val == val) return root;
        st.push(root);
        while (!st.isEmpty()) {
            TreeNode node = st.pop();
            if (node.val == val) {
                return node;
            }
            if (node.right != null) {
                st.push(node.right);
            }
            if (node.left != null) {
                st.push(node.left);
            }
        }
        return null;
    }
}


//迭代法 二叉搜索树的性质
class Solution {
    public TreeNode searchBST(TreeNode root, int val) {
        while (root != null) {
            if (root.val < val) root = root.right;
            else if (root.val > val) root = root.left;
            else return root;
        }
        return null;
    }
}

验证二叉搜索树

98. 验证二叉搜索树 - 力扣(LeetCode)

给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。

有效 二叉搜索树定义如下:

节点的左子树只包含 小于 当前节点的数。
节点的右子树只包含 大于 当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。

这道题目比较容易陷入两个陷阱:

  • 陷阱1

不能单纯的比较左节点小于中间节点,右节点大于中间节点就完事了

我们要比较的是 左子树所有节点小于中间节点,右子树所有节点大于中间节点

在这里插入图片描述

节点10大于左节点5,小于右节点15,但右子树里出现了一个6 这就不符合了!

  • 陷阱2

样例中最小节点 可能是int的最小值,如果这样使用最小的int来比较也是不行的。

递归法

class Solution {
    TreeNode node;
    public boolean isValidBST(TreeNode root) {
        if (root == null) return true;
        boolean left = isValidBST(root.left);
        if (node != null && root.val <= node.val)
            return false;
        node = root;
        boolean right = isValidBST(root.right);
        return left && right;
    }
}

迭代法

class Solution {
    long maxValue = Long.MIN_VALUE;
    public boolean isValidBST(TreeNode root) {
        Stack<TreeNode> st = new Stack<>();
        st.push(root);
        while (!st.isEmpty()){
            TreeNode node = st.pop();
            if (node!=null){
                if (node.right!=null) st.push(node.right);
                st.push(node);
                st.push(null);
                if (node.left!=null) st.push(node.left);
            }else {
                node = st.pop();
                if (node.val>maxValue){
                    maxValue = node.val;
                }else 
                    return false;
            }
        }
        return true;
     }
}

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

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

相关文章

《Linux Shell脚本攻略》学习笔记-第十一章

11.1 简介 本章将会讲述如何获取相关网络分组。CPU占用率、磁盘使用情况以及东台调用的更多信息。 11.2 使用tcpdump跟踪分组 tcpdump需要以root身份运行。 关键字port可以只显示出发往或者来自特定端口的分组 src修饰符配合特定的“关键字-值”就可以指定源文件中的这类分组。…

Linux chown 命令

Linux chown&#xff08;英文全拼&#xff1a;change owner&#xff09;命令用于设置文件所有者和文件关联组的命令。Linux/Unix 是多人多工操作系统&#xff0c;所有的文件皆有拥有者。利用 chown 将指定文件的拥有者改为指定的用户或组&#xff0c;用户可以是用户名或者用户 …

基于机器学习 实现APT 检测(附完整代码)

项目环境概述以机器学习的方式&#xff0c;可以通过多种模型对 APT 组织所使用的恶意代码进行训练学习&#xff0c;同时由于训练的多样化&#xff0c;检测效果也会比家好。本项目采用的随机森林以及不同采样策略进行模型训练。详细设计见md文件。1.系统描述本系统主要是针对大量…

ElementUI中树形表格下拉卡死的问题解决

文章目录错误现象与描述&#xff1a;代码案例&#xff1a;错误现象与描述&#xff1a; 最近在修改一个前端的问题&#xff0c;发现后台返回给前端有数据&#xff0c;SQL查询也很快&#xff0c;但是就是前端的表格这里一直卡死&#xff0c;后来发现其他数据正常&#xff0c;其中…

【代码随想录】343. 整数拆分

343. 整数拆分 动态规划五部曲 1. 确定dp数组以及下标的含义 dp[i]&#xff1a;分拆数字i&#xff0c;可以得到的最大乘积为dp[i]。 2. 确定递推公式 其实可以从1遍历j&#xff0c;然后有两种渠道得到dp[i]. 一个是j * (i - j) 直接相乘。 一个是j * dp[i - j]&#xff0c;相…

文本向量化

1、one-hot 在one-hot里面每一个token用一个长度为N向量表示&#xff0c;N表示的是词典的数据量。&#xff08;不重复的词数量&#xff09; 缺点&#xff1a;维度太高&#xff0c;用稀疏向量表示文本。 2、word embedding 使用float的矩阵来表示token&#xff0c;根据词典的…

Qt环境生成dump文件解决程序异常崩溃以及生成日志文件

一、背景 1、在测试自己的项目代码过程 ① 程序的编译的时候没有报错&#xff0c;程序在Qt release模式下运行程序&#xff0c;程序运行五个小时后异常退出&#xff0c;The process was ended forcefully&#xff1b;② 以及在项目程序通过windeployqt 工具打包发布的程序&am…

用最简单的方式告诉你什么是集线器、交换机、路由器

欢迎来到东用知识小课堂&#xff01;某一天&#xff0c;你到你女友小芳(暂定这个名字吧)就读的学校去找她&#xff0c;那么你的做法是什么呢&#xff1a;一、集线器的工作方式&#xff1a;你站到学校中庭&#xff0c;大喊一声“小芳&#xff0c;我来你找你了!”(广播)如果这个时…

〖百宝书-思维锻炼①〗——思维进阶和升华

大家好&#xff0c;我是涵子&#xff0c;欢迎大家今天进入了新专题&#xff1a;百宝书-思维锻炼&#xff01; &#x1f4ac; 人生格言&#xff1a;Stay foolish, stay kind.&#x1f4ac; &#x1f4eb; 如果文章知识点有错误的地方&#xff0c;请指正&#xff01;和大家一起学…

SpringSecurity随笔(2)-OAuth2协议

短信登录 参考密码登录过程 1.编写短信登录过滤器&#xff0c;验证短信验证码 2.编写未认证得SmsAuthenticationToken 3.将未认证的SmsAuthenticationToken传递给AuthenticationManager 4.编写一个SmsAuthenticationProvider 5.调用UserDetialsService获取用户信息 OAuth协议…

【Linux杂篇】经常登录Linux,用户密码背后的知识了解一下

一&#xff0c;用户密码存放在哪里&#xff1f; 说到这个问题&#xff0c;绝大部分的同学肯定都知道/etc/passwd这个文件&#xff0c;不错&#xff0c;这个文件里存储的就是用户名&#xff0c;密码等信息。 每一行都是一个account&#xff0c;每一行有7个信息&#xff0c;分…

在农业银行做开发是什么样的体验?

本文已经收录到Github仓库&#xff0c;该仓库包含计算机基础、Java基础、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校招社招分享等核心知识点&#xff0c;欢迎star~ Github地址&#xff1a;https://github.com/…

MySQL环境搭建

文章目录1. MySQL的卸载步骤1&#xff1a;停止MySQL服务步骤2&#xff1a;软件卸载步骤3&#xff1a;残余文件的清理步骤4&#xff1a;清理注册表步骤5&#xff1a;删除环境变量配置2. MySQL的下载、安装、配置MySQL的4大版本软件的下载MySQL8.0 版本的安装配置MySQL8.0配置MyS…

超详解通讯录,保姆式教学 ,轻松学会实现通讯录的功能【c语言】

文章目录静态通讯录Contact.htest.c菜单的创建Contact.c初始化通讯录InitContact的实现增加联系人AddContact的实现查找指定联系人的信息SearchContact的实现删除指定联系人DelContact的实现修改指定联系人的信息ModifyContact的实现显示所有联系人的信息ShowContact的实现完整…

vite项目为什么可以直接使用NODE_ENV?

背景 我们知道&#xff0c;在process.env中并没有NODE_ENV这个变量&#xff0c;但是我们却可以在项目的代码中使用process.env.NODE_ENV这个值来判断当前是development环境还是production环境&#xff0c;然后进行后续的逻辑操作。 这说明&#xff0c;在vite内部&#xff0c;…

大数据面试题集锦-Hadoop面试题(二)-HDFS

你准备好面试了吗?这里有一些面试中可能会问到的问题以及相对应的答案。如果你需要更多的面试经验和面试题&#xff0c;关注一下"张飞的猪大数据分享"吧&#xff0c;公众号会不定时的分享相关的知识和资料。 1、 HDFS 中的 block 默认保存几份&#xff1f; 默认保存…

MacBook Pro外接显示器竖屏显示

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3;哈喽&#xff01;大家好&#xff0c;我是「奇点」&#xff0c;江湖人称 singularity。刚工作几年&#xff0c;想和大家一同进步&#x1f91d;&#x1f91d;一位上进心十足的【Java ToB端大厂领…

接口性能测试避坑 Django+Nginx+uwsgi接口性能调优postman Apifox ab

Django开发了个接口供外部调用&#xff0c;Django的并发性能弱早有所闻&#xff0c;所以采用DjangoNginxuwsgi架构来提高并发量。然后使用测试工具测试并发量。服务器配置&#xff1a;CPU 2&#xff0c;内存8G接口内容只有3句&#xff1a;request_data {"code":&quo…

MyBatis复习

本文章根据尚硅谷MyBatis教程整理而来 原视频地址&#xff1a;https://www.bilibili.com/video/BV1VP4y1c7j7 MyBatis简介 MyBatis历史 MyBatis最初是Apache的一个开源项目iBatis, 2010年6月这个项目由Apache Software Foundation迁 移到了Google Code。随着开发团队转投Goo…

力扣刷题记录——521. 最长特殊序列 Ⅰ、541. 反转字符串 II、557. 反转字符串中的单词 III

本专栏主要记录力扣的刷题记录&#xff0c;备战蓝桥杯&#xff0c;供复盘和优化算法使用&#xff0c;也希望给大家带来帮助&#xff0c;博主是算法小白&#xff0c;希望各位大佬不要见笑&#xff0c;今天要分享的是——《521. 最长特殊序列 Ⅰ、541. 反转字符串 II、557. 反转字…