CSDN每日一题学习训练——Java版(二叉搜索树迭代器、二叉树中的最大路径和、按要求补齐数组)

news2024/11/26 10:39:15

版本说明

当前版本号[20231115]。

版本修改说明
20231115初版

目录

文章目录

  • 版本说明
  • 目录
  • 二叉搜索树迭代器
    • 题目
    • 解题思路
    • 代码思路
    • 参考代码
  • 二叉树中的最大路径和
    • 题目
    • 解题思路
    • 代码思路
    • 参考代码
  • 按要求补齐数组
    • 题目
    • 解题思路
    • 代码思路
    • 参考代码

二叉搜索树迭代器

题目

实现一个二叉搜索树迭代器类BSTIterator ,表示一个按中序遍历二叉搜索树(BST)的迭代器:

BSTIterator(TreeNode root) 初始化 BSTIterator 类的一个对象。BST 的根节点 root 会作为构造函数的一部分给出。指针应初始化为一个不存在于 BST 中的数字,且该数字小于 BST 中的任何元素。
boolean hasNext() 如果向指针右侧遍历存在数字,则返回 true ;否则返回 false 。
int next()将指针向右移动,然后返回指针处的数字。

注意,指针初始化为一个不存在于 BST 中的数字,所以对 next() 的首次调用将返回 BST 中的最小元素。

你可以假设 next() 调用总是有效的,也就是说,当调用 next() 时,BST 的中序遍历中至少存在一个下一个数字。

示例:

image-20231115220727677

输入
[“BSTIterator”, “next”, “next”, “hasNext”, “next”, “hasNext”, “next”, “hasNext”, “next”, “hasNext”]
[[[7, 3, 15, null, null, 9, 20]], [], [], [], [], [], [], [], [], []]
输出
[null, 3, 7, true, 9, true, 15, true, 20, false]

解释
BSTIterator bSTIterator = new BSTIterator([7, 3, 15, null, null, 9, 20]);
bSTIterator.next(); // 返回 3
bSTIterator.next(); // 返回 7
bSTIterator.hasNext(); // 返回 True
bSTIterator.next(); // 返回 9
bSTIterator.hasNext(); // 返回 True
bSTIterator.next(); // 返回 15
bSTIterator.hasNext(); // 返回 True
bSTIterator.next(); // 返回 20
bSTIterator.hasNext(); // 返回 False

提示:

树中节点的数目在范围 [1, 105] 内
0 <= Node.val <= 106
最多调用 105 次 hasNext 和 next 操作

进阶:

你可以设计一个满足下述条件的解决方案吗?next() 和 hasNext() 操作均摊时间复杂度为 O(1) ,并使用 O(h) 内存。其中 h 是树的高度。

解题思路

  1. 初始化一个空栈,用于存储中序遍历过程中的节点。
  2. 从根节点开始,将所有左子节点依次入栈,直到遇到没有左子节点的节点。
  3. 当栈不为空时,弹出栈顶元素,将其值返回,并将其右子节点依次入栈,直到遇到没有右子节点的节点。
  4. 重复步骤2和3,直到栈为空。

代码思路

  1. 这段代码实现了一个二叉搜索树的迭代器。

  2. 首先定义了一个TreeNode类,表示二叉树的节点,包含一个整数值val和左右子节点left、right。

    // 定义一个二叉树节点类
    public class TreeNode {
        int val; // 节点值
        TreeNode left; // 左子节点
        TreeNode right; // 右子节点
        // 构造函数,初始化节点值
        TreeNode(int x) {
            val = x;
        }
    }
    
  3. 然后定义了一个BSTIterator类,用于实现二叉搜索树的迭代器。这个迭代器使用了一个LinkedList来存储遍历过程中的节点。

    // 定义一个二叉搜索树迭代器类
    class BSTIterator {
        LinkedList<TreeNode> stack = new LinkedList<>(); // 使用链表存储遍历过程中的节点
    
  4. 在构造函数中,将根节点root及其左子树的所有节点依次入栈。这样,栈顶元素就是当前最小的节点。

      // 构造函数,接收根节点作为参数,将根节点及其左子树的所有节点依次入栈
        public BSTIterator(TreeNode root) {
            TreeNode cur = root;
            while (cur != null) {
                stack.push(cur);
                cur = cur.left;
            }
        }
    
  5. next()方法用于获取下一个节点的值。首先弹出栈顶元素,然后将该节点的右子树及其左子树的所有节点依次入栈。这样,下一次调用next()方法时,栈顶元素就是当前最小的节点。

     // next() 方法,返回下一个节点的值
        public int next() {
            TreeNode n = stack.pop(); // 弹出栈顶元素
            TreeNode cur = n.right; // 获取弹出节点的右子节点
            while (cur != null) {
                stack.push(cur); // 将右子节点及其左子树的所有节点依次入栈
                cur = cur.left;
            }
            return n.val; // 返回弹出节点的值
        }
    
  6. hasNext()方法用于判断是否还有下一个节点。只要栈不为空,就说明还有下一个节点。

     // hasNext() 方法,判断是否还有下一个节点
        public boolean hasNext() {
            return !stack.isEmpty(); // 如果栈不为空,则说明还有下一个节点
        }
    

参考代码

public class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) {
        val = x;
    }
}
class BSTIterator {
    LinkedList<TreeNode> stack = new LinkedList<>();
    public BSTIterator(TreeNode root) {
        TreeNode cur = root;
        while (cur != null) {
            stack.push(cur);
            cur = cur.left;
        }
    }
    public int next() {
        TreeNode n = stack.pop();
        TreeNode cur = n.right;
        while (cur != null) {
            stack.push(cur);
            cur = cur.left;
        }
        return n.val;
    }
    public boolean hasNext() {
        return !stack.isEmpty();
    }
}
/**
 * Your BSTIterator object will be instantiated and called as such:
 * BSTIterator obj = new BSTIterator(root);
 * int param_1 = obj.next();
 * boolean param_2 = obj.hasNext();
 */

二叉树中的最大路径和

题目

路径 被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个节点,且不一定经过根节点。

路径和 是路径中各节点值的总和。

给你一个二叉树的根节点 root ,返回其 最大路径和 。

示例 1:

image-20231115224820246

输入:root = [1,2,3]
输出:6
解释:最优路径是 2 -> 1 -> 3 ,路径和为 2 + 1 + 3 = 6

示例 2:

image-20231115224846284

输入:root = [-10,9,20,null,null,15,7]
输出:42
解释:最优路径是 15 -> 20 -> 7 ,路径和为 15 + 20 + 7 = 42

提示:

树中节点数目范围是 [1, 3 * 104]
-1000 <= Node.val <= 1000

解题思路

  1. 初始化一个全局变量 maxSum,用于存储最大路径和,初始值为 Integer.MIN_VALUE。
  2. 定义一个递归函数 maxGain,输入参数为 TreeNode 类型的节点 node。
  3. 如果节点为空,返回 0。
  4. 计算左子树的最大增益 leftGain,如果小于等于 0,则取 0。
  5. 计算右子树的最大增益 rightGain,如果小于等于 0,则取 0。
  6. 计算新路径的价格 priceNewpath,即当前节点的值加上左右子树的最大增益。
  7. 更新 maxSum,将其设置为 maxSum 和 priceNewpath 中的较大值。
  8. 返回当前节点的值加上左右子树中增益较大的那个值。
  9. 在 maxPathSum 函数中调用 maxGain 函数,并返回 maxSum。

代码思路

  1. 首先定义了一个名为Solution的类,其中包含一个名为maxSum的整数变量,用于存储最大路径和。

    // 定义一个名为Solution的类
    class Solution {
        // 初始化最大路径和为整数最小值
        int maxSum = Integer.MIN_VALUE;
        // 定义一个名为maxPathSum的方法,接收一个TreeNode类型的参数root,返回一个整数值
    
  2. maxPathSum(TreeNode root):这是主方法,它接受一个二叉树的根节点作为参数,并返回最大路径和。在这个方法中,首先调用maxGain方法来计算最大路径和,然后返回maxSum变量的值。

     public int maxPathSum(TreeNode root) {
            // 调用maxGain方法计算最大路径和
            maxGain(root);
            // 返回最大路径和
            return maxSum;
        }
    
  3. maxGain(TreeNode node):这是一个辅助方法,用于递归地计算以给定节点为起点的最大路径和。它首先检查节点是否为空,如果为空则返回0。

        // 定义一个名为maxGain的方法,接收一个TreeNode类型的参数node,返回一个整数值
        public int maxGain(TreeNode node) {
            // 如果节点为空,返回0
            if (node == null) {
                return 0;
            }
    
  4. 然后,它分别计算左子树和右子树的最大增益(即不选择该子树的情况下的最大路径和),并将它们与当前节点的值相加得到新路径的价格。

       // 计算左子树的最大增益,如果小于0则取0
            int leftGain = Math.max(maxGain(node.left), 0);
            // 计算右子树的最大增益,如果小于0则取0
            int rightGain = Math.max(maxGain(node.right), 0);
            // 计算新路径的价格
            int priceNewpath = node.val + leftGain + rightGain;
    
  5. 接着,它将新路径的价格与当前的最大路径和进行比较,更新maxSum变量的值。最后,它返回当前节点的值加上左右子树中增益较大的那个值,作为以当前节点为起点的最大路径和。

       // 更新最大路径和
            maxSum = Math.max(maxSum, priceNewpath);
    
  6. 通过递归地遍历整个二叉树,该方法可以找到从根节点到任意叶子节点的最大路径和,并将其存储在maxSum变量中。最终,maxPathSum方法将返回这个最大路径和。

     // 返回当前节点的值加上左右子树中增益较大的那个值
            return node.val + Math.max(leftGain, rightGain);
    

参考代码

这段代码是二叉树路径和的最大值问题。

class Solution {
    int maxSum = Integer.MIN_VALUE;
    public int maxPathSum(TreeNode root) {
        maxGain(root);
        return maxSum;
    }
    public int maxGain(TreeNode node) {
        if (node == null) {
            return 0;
        }
        int leftGain = Math.max(maxGain(node.left), 0);
        int rightGain = Math.max(maxGain(node.right), 0);
        int priceNewpath = node.val + leftGain + rightGain;
        maxSum = Math.max(maxSum, priceNewpath);
        return node.val + Math.max(leftGain, rightGain);
    }
}

按要求补齐数组

题目

给定一个已排序的正整数数组 nums,和一个正整数 n 。从 [1, n] 区间内选取任意个数字补充到 nums 中,使得 [1, n] 区间内的任何数字都可以用 nums 中某几个数字的和来表示。请输出满足上述要求的最少需要补充的数字个数。

示例 1:

输入: nums =
[1,3]
, n =
6

输出: 1
解释:
根据 nums 里现有的组合
[1], [3], [1,3]
,可以得出
1, 3, 4

现在如果我们将
2
添加到 nums 中, 组合变为:
[1], [2], [3], [1,3], [2,3], [1,2,3]

其和可以表示数字
1, 2, 3, 4, 5, 6
,能够覆盖
[1, 6]
区间里所有的数。
所以我们最少需要添加一个数字。

image-20231115230203186

示例 2:

输入: nums =
[1,5,10]
, n =
20

输出: 2
解释: 我们需要添加
[2, 4]

示例 3:

输入: nums =
[1,2,2]
, n =
5

输出: 0

image-20231115230223208

解题思路

  1. 初始化 patches 为 0,表示需要补充的数字个数;i 为 0,表示当前处理的 nums 数组中的索引;miss 为 1,表示当前未覆盖的数字范围的最小值。
  2. 当 miss <= n 时,执行循环: a. 如果 i < nums.length 且 nums[i] <= miss,说明可以用 nums[i] 来表示 miss,将 miss 加上 nums[i],并将 i 向右移动一位。 b. 否则,说明需要补充一个数字,使得 miss 可以表示为两个数的和,即 miss = miss + miss。将 miss 加上 miss,并将 patches 加 1。
  3. 返回 patches。

代码思路

  1. 初始化变量patches为0,表示已经使用的补丁数量;变量i为0,表示当前处理的nums数组中的索引;变量miss为1,表示当前未覆盖的数字范围的最小值。

       // 初始化变量patches为0,i为0,miss为1
            int patches = 0, i = 0;
            long miss = 1;
    
  2. miss小于等于n时,执行循环。这是因为我们需要确保覆盖从1到n的所有数字。

  3. 在循环中,首先检查i是否小于nums的长度且nums[i]小于等于miss。如果是,则说明我们可以使用nums[i]来扩展当前的覆盖范围,因此将miss加上nums[i]并将i加1。

     // 当miss小于等于n时,执行循环
            while (miss <= n) {
                // 如果i小于nums的长度且nums[i]小于等于miss,则将miss加上nums[i]并将i加1
                if (i < nums.length && nums[i] <= miss)
                    miss += nums[i++];
    
  4. 如果上述条件不满足,说明我们需要增加一个新的补丁来扩展当前的覆盖范围。此时,将miss加上miss(即当前未覆盖的数字范围的最小值),并将patches加1。

     // 否则,将miss加上miss,并将patches加1
                else {
                    miss += miss;
                    patches++;
                }
    
  5. 循环结束后,返回patches的值,即所需的最少补丁数量。

        // 返回patches的值
        return patches;

参考代码

这段代码是计算将1到n之间的所有数字都覆盖所需要的最少的补丁数量。

class Solution {
    public int minPatches(int[] nums, int n) {
        int patches = 0, i = 0;
        long miss = 1;
        while (miss <= n) {
            if (i < nums.length && nums[i] <= miss)
                miss += nums[i++];
            else {
                miss += miss;
                patches++;
            }
        }
        return patches;
    }
}

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

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

相关文章

DevExpress WinForms HeatMap组件,一个高度可自定义热图控件!

通过DevExpress WinForms可以为Windows Forms桌面平台提供的高度可定制的热图UI组件&#xff0c;体验DevExpress的不同之处。 DevExpress WinForms有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。同时能完美构建流畅、美观且易于使用的应用程…

系列三、双亲委派机制

一、概述 当一个类收到了类加载的请求&#xff0c;它首先不会尝试自己去加载这个类&#xff0c;而是把这个请求委派给父类去完成&#xff0c;每一层的类加载器都是如此&#xff0c;因此所有的请求都应该传送到启动类加载器中&#xff0c;只有当父类加载器反馈自己无法完成这个…

人工智能赋能职业教育:技术融合引领教育变革

人工智能赋能职业教育&#xff1a;技术融合引领教育变革 摘要&#xff1a;本文探讨了人工智能技术在职业教育领域的应用及其带来的变革。通过分析人工智能在个性化教学、智能评估和教学资源优化等方面的技术优势&#xff0c;结合职业教育的现状和发展需求&#xff0c;提出了人…

计算机网络之网络体系结构

计算机网络体系结构 一、常见的计算机体系结构 1.1 OSI标准以及TCP/IP体系结构 OSI标准失败的原因&#xff1a; OSI的专家们缺乏实际经验&#xff0c;他们在完成OSI标准时没有商业驱动力OSI的协议实现起来过分复杂&#xff0c;而且运行效率很低OSI标准的制定周期太长&#x…

【ArcGIS Pro二次开发】(76):面积平差工具

之前做过一个【三调土地利用现状分类面积汇总】的工具&#xff0c;在流程中使用了面积平差的方法。 考虑了在其它场合可能也需要进行面积平差&#xff0c;因此单独提取出来作为一个工具。 平差实现的方法如下图&#xff1a; 主要的计算过程如上图所示&#xff0c;算出总面积差…

队列的实现---超详细

队列的实现—超详细 文章目录 队列的实现---超详细一、队列的模型二、代码实现以及测试用例①队列初始化②入队③出队④输出队头⑤输出队尾⑥判断队列是否为空⑦队列的长度⑧队列的销毁⑨测试用例 一、队列的模型 队列&#xff1a;只允许在一端进行插入数据操作&#xff0c;在…

从零搭建微服务架构:Spring Boot与Nacos完美整合

&#x1f38f;&#xff1a;你只管努力&#xff0c;剩下的交给时间 &#x1f3e0; &#xff1a;小破站 从零搭建微服务架构&#xff1a;Spring Boot与Nacos完美整合 前言第一&#xff1a;服务注册与发现第二&#xff1a;配置中心第三&#xff1a;报错问题解决第四&#xff1a;什…

深度学习+opencv+python实现车道线检测 - 自动驾驶 计算机竞赛

文章目录 0 前言1 课题背景2 实现效果3 卷积神经网络3.1卷积层3.2 池化层3.3 激活函数&#xff1a;3.4 全连接层3.5 使用tensorflow中keras模块实现卷积神经网络 4 YOLOV56 数据集处理7 模型训练8 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &am…

【数据结构】单链表基本操作的实现

【单链表的头插和尾插】//无头结点 #include<stdio.h> #include<stdlib.h> typedef struct LNode {int date;struct LNode *next; }LNode,*LinkList; LinkList great_LinkList(LinkList L)//头部插入 {LinkList s;int x,j1;scanf("%d",&x);while(x…

OPPO Watch纯手机开启远程ADB调试

Wear OS手表中&#xff0c;我们可以直接在开发者设置中打开WiFi调试。但是这在OPPO等魔改Android系统中不再奏效。 需要什么&#xff1f;&#xff1f; 手表一台手机一个OTG转接头一个手表充电器一个 演示设备 手机&#xff1a; OPPO Find X手表&#xff1a; OPPO Watch 1代 …

第十九章绘图

Java绘图类 Graphics 类 Grapics 类是所有图形上下文的抽象基类&#xff0c;它允许应用程序在组件以及闭屏图像上进行绘制。Graphics 类封装了Java 支持的基本绘图操作所需的状态信息&#xff0c;主要包括颜色、字体、画笔、文本、图像等。 Graphics 类提供了绘图常用的…

Oracle OCP / MySQL OCP认证容易通过吗

诸多学员在首次考OCP时&#xff0c;不清楚要如何选择。在本文中&#xff0c;我会为大家进行讲解&#xff01; 选择OCP认证时需要考虑的几大项目&#xff1a; 授课老师师资经验 课程大纲 试听课程 考试通过率 业界口碑 服务质量 郭一军老师的OCP培训在业界培训的学员中已…

SystemVerilog学习 (6)——验证平台

一、概述 测试平台&#xff08;Testbench&#xff09;是整个验证系统的总称。它包含了验证系统的各个组件、组件之间的互联关系&#xff0c;测试平台的配置与控制等&#xff0c; 从更系统的意义来讲&#xff0c;它还包括编译仿真的流程、结果分析报告和覆盖率检查等。 从狭义上…

【Phoenix】请求的生命周期

本文的目的是讨论Phoenix请求的生命周期。我们实战添加两个新的页面&#xff0c;并讨论整个过程是如何串起来的。 让我们从添加第一个新页面开始。 添加一个新页面 web应用通常通过将HTTP方法和路径映射到应用的某个函数来处理请求。Phoenix通过路由器来实现这个匹配。例如将…

蒙HarmonyOS从零实现类微信app效果第二篇,我的+发现页面实现

本着不拖更的原则&#xff0c;今天上新了&#xff0c;今天实现了类微信app的发现页和我的页面。先看效果。 效果是不是看着还不错。其实这两个页面功能实现还是比较简单的&#xff0c;接下来还是老规矩&#xff0c;先进行页面的拆分和代码实现&#xff0c;然后进行相关我认为比…

嵌入式linux--sysfs文件系统以及操作GPIO

sysfs文件系统 在Linux系统中&#xff0c;/sys路径是一个特殊的虚拟文件系统&#xff08;Virtual File System&#xff09;&#xff0c;用于提供对内核和设备的运行时信息的访问。它是sysfs文件系统的挂载点&#xff0c;提供了一种以文件和目录形式表示系统设备、总线、驱动程…

【Web开发】基于 Jekyll 中的 Chirpy 模板搭建博客网站(一):成功经验篇

基于 Jekyll 中的 Chirpy 模板搭建博客网站&#xff08;一&#xff09;&#xff1a;成功经验篇 1.Jekyll 介绍2.Chirpy 介绍3.安装步骤3.1 Prerequisites3.2 Installation3.2.1 Creating a New Site3.2.2 Installing Dependencies 3.3 Usage3.3.1 Configuration3.3.2 Running L…

使用C#插件Quartz.Net定时执行CMD任务工具2

目录 创建简易控制台定时任务步骤完整程序 创建简易控制台定时任务 创建winform的可以看&#xff1a;https://blog.csdn.net/wayhb/article/details/134279205 步骤 创建控制台程序 使用vs2019新建项目&#xff0c;控制台程序&#xff0c;使用.net4.7.2项目右键&#xff08…

ubuntu下C++调用matplotlibcpp进行画图(超详细)

目录 一、换源 二、安装必要的软件 三、下载matplotlibcpp 四、下载anaconda 1.anaconda下载 2.使用anaconda配置环境 五、下载CLion 1.下载解压CLion 2.替换jbr文件夹 3.安装CLion 4.激活CLion 5.CLion汉化 6.Clion配置 六、使用CLion运行 七、总结 我的环…

posix定时器的使用

POSIX定时器是基于POSIX标准定义的一组函数&#xff0c;用于实现在Linux系统中创建和管理定时器。POSIX定时器提供了一种相对较高的精度&#xff0c;可用于实现毫秒级别的定时功能。 POSIX定时器的主要函数包括&#xff1a; timer_create()&#xff1a;用于创建一个定时器对象…