力扣日记1.13-【二叉树篇】669. 修剪二叉搜索树

2024-01-13 12:36

本文主要是介绍力扣日记1.13-【二叉树篇】669. 修剪二叉搜索树,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

力扣日记:【二叉树篇】669. 修剪二叉搜索树

日期:2023.1.13
参考:代码随想录、力扣

669. 修剪二叉搜索树

题目描述

难度:中等

给你二叉搜索树的根节点 root ,同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树,使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即,如果没有被移除,原有的父代子代关系都应当保留)。 可以证明,存在 唯一的答案 。

所以结果应当返回修剪好的二叉搜索树的新的根节点。注意,根节点可能会根据给定的边界发生改变。

示例 1:
在这里插入图片描述

输入:root = [1,0,2], low = 1, high = 2
输出:[1,null,2]

示例 2:
在这里插入图片描述

输入:root = [3,0,4,null,2,null,null,1], low = 1, high = 3
输出:[3,2,null,1]

提示:

  • 树中节点数在范围 [1, 10^4] 内
  • 0 <= Node.val <= 10^4
  • 树中每个节点的值都是 唯一 的
  • 题目数据保证输入是一棵有效的二叉搜索树
  • 0 <= low <= high <= 10^4

题解

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:// 递归的返回值:当前root树经过修剪后的新根节点TreeNode* trimBST(TreeNode* root, int low, int high) {// 终止条件:遇到空节点就返回空if (root == nullptr)    return root;// 如果root的值小于low,此时root以及root的左子树一定是要删除的// 但是root的右子树(大于root)可能存在满足条件的,所以要对root的右子树进行修剪,并将修剪后的右子树根节点返回给root的上一层来接收(因为这里的root是要被删除的,所以是返回给root的上一层)if (root->val < low) {return trimBST(root->right, low, high); // 对root的右子树进行修剪,并将新的右子树根节点返回给上一层} // 大于high的情况也是同理,此时对root的左子树进行修剪,并返回新的左子树根节点给上一层else if (root->val > high) {return trimBST(root->left, low, high);}// 如果当前root满足条件,但其左右子树可能存在不满足条件的// 则对其左右子树分别进行修剪root->left = trimBST(root->left, low, high);    // 左子树修剪后作为root的左节点(这里当前层可能就会接收来自root的左节点的下一层的根节点)root->right = trimBST(root->right, low, high);  // 右子树同理// 返回当前rootreturn root;}
};

复杂度

时间复杂度:
空间复杂度:

思路总结

  • 本题相比于前两道的插入和删除,还是复杂了许多,且不同于以往的递归,本题在不符合处理(如这里的删除)条件时需要递归,在符合处理(删除)条件时也要递归!!!(以前一般都是只需要在不符合类似于中节点的处理条件的时候进行递归)
  • 这里要明确理解递归函数的意义:即对传入的root树进行修剪,并返回修剪后的树的新根节点
  • 且读题要准确,是节点值不在[low, high]范围的要剔除
  • 因此,删除时要分别对小于low和大于high的情况进行处理:
    • 对于root的值小于low的情况,:
      • 此时root以及root的左子树一定是要删除的
      • 但是root的右子树(大于root)可能存在在范围内的节点,所以要对root的右子树进行修剪,并将修剪后的右子树根节点返回给root的上一层来接收(因为这里的root是要被删除的,所以是返回给root的上一层)
      • 这里要理解“返回给上一层”的含义:即return后,是由root的上一层去接收的
        在这里插入图片描述
        对应于代码中就是
        当前层(这里的0):
        if (root->val < low) {return trimBST(root->right, low, high); // 对root的右子树进行修剪,并将新的右子树根节点返回给上一层
        } 
        
        而return后回到上一层(即3),会接收来自0的右子树的根节点
        root->left = trimBST(root->left, low, high);    // 左子树修剪后作为root的左节点(这里当前层可能就会接收来自root的左节点的下一层的根节点)
        
    • 对于root的值大于high的情况处理是同理的。
  • 在写代码时,就按注释时的思路:
    • 终止条件:遇到空节点就返回空
    • 如果root的值小于low
      • 此时对root的右子树进行修剪,并将修剪后的右子树根节点返回给root的上一层来接收
    • 如果root的值大于high
      • 此时对root的左子树进行修剪,并返回新的左子树根节点给上一层
    • 如果root的是符合条件的(但其左右子树可能存在不满足条件需要修剪的)
      • 则对其左右子树分别进行修剪 ,此时要用root的左右节点去接收,即:
      • 左子树修剪后作为root的左节点
      • 右子树同理
    • 最后返回root

这篇关于力扣日记1.13-【二叉树篇】669. 修剪二叉搜索树的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/601480

相关文章

Python使用DeepSeek进行联网搜索功能详解

《Python使用DeepSeek进行联网搜索功能详解》Python作为一种非常流行的编程语言,结合DeepSeek这一高性能的深度学习工具包,可以方便地处理各种深度学习任务,本文将介绍一下如何使用P... 目录一、环境准备与依赖安装二、DeepSeek简介三、联网搜索与数据集准备四、实践示例:图像分类1.

C# ComboBox下拉框实现搜索方式

《C#ComboBox下拉框实现搜索方式》文章介绍了如何在加载窗口时实现一个功能,并在ComboBox下拉框中添加键盘事件以实现搜索功能,由于数据不方便公开,作者表示理解并希望得到大家的指教... 目录C# ComboBox下拉框实现搜索步骤一步骤二步骤三总结C# ComboBox下拉框实现搜索步骤一这

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

hdu1240、hdu1253(三维搜索题)

1、从后往前输入,(x,y,z); 2、从下往上输入,(y , z, x); 3、从左往右输入,(z,x,y); hdu1240代码如下: #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#inc

hdu 4517 floyd+记忆化搜索

题意: 有n(100)个景点,m(1000)条路,时间限制为t(300),起点s,终点e。 访问每个景点需要时间cost_i,每个景点的访问价值为value_i。 点与点之间行走需要花费的时间为g[ i ] [ j ] 。注意点间可能有多条边。 走到一个点时可以选择访问或者不访问,并且当前点的访问价值应该严格大于前一个访问的点。 现在求,从起点出发,到达终点,在时间限制内,能得到的最大

AI基础 L9 Local Search II 局部搜索

Local Beam search 对于当前的所有k个状态,生成它们的所有可能后继状态。 检查生成的后继状态中是否有任何状态是解决方案。 如果所有后继状态都不是解决方案,则从所有后继状态中选择k个最佳状态。 当达到预设的迭代次数或满足某个终止条件时,算法停止。 — Choose k successors randomly, biased towards good ones — Close

hdu4277搜索

给你n个有长度的线段,问如果用上所有的线段来拼1个三角形,最多能拼出多少种不同的? import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;

leetcode105 从前序与中序遍历序列构造二叉树

根据一棵树的前序遍历与中序遍历构造二叉树。 注意: 你可以假设树中没有重复的元素。 例如,给出 前序遍历 preorder = [3,9,20,15,7]中序遍历 inorder = [9,3,15,20,7] 返回如下的二叉树: 3/ \9 20/ \15 7   class Solution {public TreeNode buildTree(int[] pr

两数之和--力扣1

两数之和 题目思路C++代码 题目 思路 根据题目要求,元素不能重复且不需要排序,我们这里使用哈希表unordered_map。注意题目说了只对应一种答案。 所以我们在循环中,使用目标值减去当前循环的nums[i],得到差值,如果我们在map中能够找到这个差值,就说明存在两个整数的和为目标值。 如果没有找到,就将当前循环的nums[i]以及下标i放入map中,以便后续查

PHP实现二叉树遍历(非递归方式,栈模拟实现)

二叉树定义是这样的:一棵非空的二叉树由根结点及左、右子树这三个基本部分组成,根据节点的访问位置不同有三种遍历方式: ① NLR:前序遍历(PreorderTraversal亦称(先序遍历)) ——访问结点的操作发生在遍历其左右子树之前。 ② LNR:中序遍历(InorderTraversal) ——访问结点的操作发生在遍历其左右子树之中(间)。 ③ LRN:后序遍历(PostorderT