练习题(2024/5/7)

news2024/11/23 8:10:43

1验证二叉搜索树

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

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

  • 节点的左

    子树

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

示例 1:

输入:root = [2,1,3]
输出:true

示例 2:

输入:root = [5,1,4,null,null,3,6]
输出:false
解释:根节点的值是 5 ,但是右子节点的值是 4 。

提示:

  • 树中节点数目范围在[1, 104] 内
  • -231 <= Node.val <= 231 - 1

思路1:

中序遍历下,输出的二叉搜索树节点的数值是有序序列。

有了这个特性,验证二叉搜索树,就相当于变成了判断一个序列是不是递增的了 我们把二叉树转变为数组来判断,是最直观的

通过中序遍历将二叉搜索树转换为有序数组,然后检查该数组是否严格递增。中序遍历保证了二叉搜索树的节点按照从小到大的顺序被访问,因此如果数组中存在相邻元素相等或逆序,则说明不满足二叉搜索树的性质

代码:

class Solution {
private:
    vector<int> vec;
    void traversal(TreeNode* root) {
        if (root == NULL) return;
        traversal(root->left);
        vec.push_back(root->val); // 将二叉搜索树转换为有序数组
        traversal(root->right);
    }
public:
    bool isValidBST(TreeNode* root) {
        vec.clear(); // 清空数组
        traversal(root);
        for (int i = 1; i < vec.size(); i++) {
            // 判断是否是二叉搜索树的条件
            if (vec[i] <= vec[i - 1]) return false;
        }
        return true;
    }
};

思路2:

不用转变成数组,可以在递归遍历的过程中直接判断是否有序。

利用递归来检查二叉搜索树的有效性。首先,通过递归遍历左子树,确保左子树是一个有效的二叉搜索树;然后,检查当前节点是否大于前一个节点(中序遍历时前一个节点的值),如果不是则返回 false;最后,递归遍历右子树,确保右子树也是一个有效的二叉搜索树。整体思路是基于二叉搜索树的性质,即左子树的所有节点小于根节点,右子树的所有节点大于根节点。

代码:

class Solution {
public:
    TreeNode* pre = NULL; // 用来记录前一个节点

    // 检查是否为有效的二叉搜索树
    bool isValidBST(TreeNode* root) {
        if (root == NULL) return true;
        bool left = isValidBST(root->left); // 检查左子树

        // 如果前一个节点不为空且大于等于当前节点的值,则不是二叉搜索树
        if (pre != NULL && pre->val >= root->val) return false;
        pre = root; // 记录前一个节点

        bool right = isValidBST(root->right); // 检查右子树
        return left && right;
    }
};

思路3:

迭代法解题思路是基于中序遍历二叉搜索树的特性。首先,我们使用一个栈来模拟中序遍历过程。从根节点开始,将所有左子节点依次入栈,直到最左的叶子节点。然后,开始出栈操作,每次出栈一个节点,判断其值是否大于前一个访问的节点值(如果有的话)。如果不是,则说明不满足二叉搜索树的定义,直接返回 false。如果满足,则更新前一个访问的节点,并将当前节点的右子节点入栈。这样,通过迭代遍历整个树,如果全部节点都满足二叉搜索树的定义,则返回 true

代码:

class Solution {
public:
    // 判断是否为有效的二叉搜索树
    bool isValidBST(TreeNode* root) {
        stack<TreeNode*> st; // 创建一个栈
        TreeNode* cur = root; // 当前节点指针
        TreeNode* pre = NULL; // 记录前一个节点
        while (cur != NULL || !st.empty()) {
            if (cur != NULL) {
                st.push(cur);
                cur = cur->left; // 遍历左子树
            } else {
                cur = st.top(); // 中序遍历当前节点
                st.pop();
                // 如果当前节点值小于等于前一个节点值,则不是二叉搜索树
                if (pre != NULL && cur->val <= pre->val)
                    return false;
                pre = cur; // 保存前一个访问的结点

                cur = cur->right; // 遍历右子树
            }
        }
        return true;
    }
};

2二叉搜索树的最小绝对差

给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。

差值是一个正数,其数值等于两值之差的绝对值。

示例 1:

输入:root = [4,2,6,1,3]
输出:1

示例 2:

输入:root = [1,0,48,null,null,12,49]
输出:1

提示:

  • 树中节点的数目范围是 [2, 104]
  • 0 <= Node.val <= 105

思路:

首先,通过中序遍历二叉搜索树,将节点值按照从小到大的顺序存储在一个数组中。这样,得到的数组就是一个有序数组。然后,遍历这个有序数组,计算相邻两个节点值的差值,找出其中的最小值,即为任意两节点的最小差值。整体思路是利用中序遍历得到有序数组的特性,然后在有序数组上进行差值计算,从而求得最小差值。

代码:

class Solution {
private:
    vector<int> vec; // 存储中序遍历后的有序数组
    // 中序遍历二叉树,将节点值存入有序数组中
    void traversal(TreeNode* root) {
        if (root == NULL) return;
        traversal(root->left);
        vec.push_back(root->val); // 将二叉搜索树转换为有序数组
        traversal(root->right);
    }

public:
    // 计算二叉搜索树任意两节点的最小差值
    int getMinimumDifference(TreeNode* root) {
        vec.clear(); // 清空有序数组
        traversal(root); // 中序遍历,得到有序数组
        if (vec.size() < 2) return 0; // 如果节点数量小于2,直接返回0
        int result = INT_MAX; // 初始化结果为最大值
        // 遍历有序数组,计算相邻节点的差值,找出最小的差值
        for (int i = 1; i < vec.size(); i++) {
            result = min(result, vec[i] - vec[i-1]);
        }
        return result; // 返回最小差值
    }
}; 

思路2:

在中序遍历的过程中,每次比较当前节点和前一个节点的差值,更新最小差值的结果。首先初始化一个最大值作为结果变量,一个空指针pre用于保存前一个节点的指针。然后进行中序遍历,遍历左子树,比较当前节点和前一个节点的值,更新结果。每次遍历完成后,更新pre指针,继续遍历右子树。最终返回计算得到的最小差值。整体思路是通过中序遍历一次得到有序数组,但是在计算最小差值的过程中,不需要保存整个数组,只需要保存前一个节点指针进行比较即可。

代码:

class Solution{
private:
      int result=INT_MAX; // 存储节点值最小差值的结果
      TreeNode* pre=NULL; // 前一个访问的节点指针,用于计算相邻节点的差值
      void traversal(TreeNode *cur){
        if(cur == nullptr) return; // 递归终止条件
        traversal(cur->left); // 左子树递归遍历
        if(pre != nullptr){
            result = min(result, cur->val-pre->val); // 更新最小差值
        }
        pre = cur; // 更新前一个访问的节点
        traversal(cur->right); // 右子树递归遍历
      }
public:
     int getMinimumDifference(TreeNode* root){
        traversal(root); // 递归遍历整个二叉搜索树
        return result; // 返回最小差值结果
   }
}; // 加中文注释

3二叉搜索树中的众数

给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。

如果树中有不止一个众数,可以按 任意顺序 返回。

假定 BST 满足如下定义:

  • 结点左子树中所含节点的值 小于等于 当前节点的值
  • 结点右子树中所含节点的值 大于等于 当前节点的值
  • 左子树和右子树都是二叉搜索树

示例 1:

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

示例 2:

输入:root = [0]
输出:[0]

提示:

  • 树中节点的数目在范围 [1, 104] 内
  • -105 <= Node.val <= 105

思路:

既然是搜索树,它中序遍历就是有序的

在中序遍历的过程中,通过比较当前节点和前一个节点的值来统计当前节点出现的次数,同时更新最大出现次数和众数结果。首先初始化计数变量count和最大出现次数变量maxCount,以及存储结果的vector。然后进行中序遍历,遍历左子树,比较当前节点和前一个节点的值,更新计数。如果当前节点的值与前一个节点相同,则增加计数;否则重新设置计数为1。更新前一个访问的节点指针pre,并根据计数更新结果和最大出现次数。最终返回存储众数结果的vector。整体思路是在中序遍历的过程中,通过比较当前节点和前一个节点的值来统计出现次数,同时更新最大出现次数和众数结果,最终返回找到的众数值。

代码:

class Solution{
private:
   int count=0; // 统计当前节点出现的次数
   int maxCount =0; // 统计最大出现次数
   vector<int> result; // 存储众数的结果
   TreeNode* pre =nullptr; // 前一个访问的节点指针
   void searchBST(TreeNode* cur){
    if(cur ==nullptr) return; // 递归终止条件
    searchBST(cur->left); // 左子树递归遍历
    if(pre ==nullptr) {
        count=1; // 初始情况下设置当前节点出现次数为1
    } else if(pre->val== cur->val){
        count++; // 当前节点值与前一个节点相同,增加计数
    } else {
        count=1; // 当前节点值与前一个节点不同,重新设置计数为1
    } 
    pre =cur; // 更新前一个访问的节点
    if(count ==maxCount){
        result.push_back(cur->val); // 结果中添加当前众数
    }
    if(count>maxCount){
        maxCount=count; // 更新最大出现次数
        result.clear();
        result.push_back(cur->val); // 清空结果,加入当前节点值
    }
    searchBST(cur->right); // 右子树递归遍历
    return;
   }
    
public:
     vector<int> findMode(TreeNode* root){
        count=0; // 初始化变量
        maxCount =0;
        pre=nullptr;
        result.clear();
        searchBST(root); // 开始搜索二叉搜索树
        return result; // 返回众数结果
     }
};

4查找拥有有效邮箱的用户

表: Users

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| user_id       | int     |
| name          | varchar |
| mail          | varchar |
+---------------+---------+
user_id 是该表的主键(具有唯一值的列)。
该表包含了网站已注册用户的信息。有一些电子邮件是无效的。

编写一个解决方案,以查找具有有效电子邮件的用户。

一个有效的电子邮件具有前缀名称和域,其中:

  1.  前缀 名称是一个字符串,可以包含字母(大写或小写),数字,下划线 '_' ,点 '.' 和/或破折号 '-' 。前缀名称 必须 以字母开头。
  2.  为 '@leetcode.com' 。

以任何顺序返回结果表。

结果的格式如以下示例所示:

示例 1:

输入:
Users 表:
+---------+-----------+-------------------------+
| user_id | name      | mail                    |
+---------+-----------+-------------------------+
| 1       | Winston   | winston@leetcode.com    |
| 2       | Jonathan  | jonathanisgreat         |
| 3       | Annabelle | bella-@leetcode.com     |
| 4       | Sally     | sally.come@leetcode.com |
| 5       | Marwan    | quarz#2020@leetcode.com |
| 6       | David     | david69@gmail.com       |
| 7       | Shapiro   | .shapo@leetcode.com     |
+---------+-----------+-------------------------+
输出:
+---------+-----------+-------------------------+
| user_id | name      | mail                    |
+---------+-----------+-------------------------+
| 1       | Winston   | winston@leetcode.com    |
| 3       | Annabelle | bella-@leetcode.com     |
| 4       | Sally     | sally.come@leetcode.com |
+---------+-----------+-------------------------+
解释:
用户 2 的电子邮件没有域。 
用户 5 的电子邮件带有不允许的 '#' 符号。
用户 6 的电子邮件没有 leetcode 域。 
用户 7 的电子邮件以点开头

思路:

从名为Users的表中选择user_idnamemail这三个字段,并使用正则表达式来筛选出以字母开头,后面跟着字母、数字、下划线、点或连字符的字符串,最后以@leetcode.com结尾的邮箱地址

代码:

select  user_id, name, mail
from Users
-- 转义了`@`字符,因为它在某些正则表达式中具有特殊意义
where mail regexp '^[a-zA-Z][a-zA-Z0-9_.-]*\\@leetcode\\.com$'; -- 匹配以字母开头,后面跟着字母、数字、下划线、点或连字符的字符串,最后以`@leetcode.com`结尾的邮箱地址

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

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

相关文章

[HUBUCTF 2022 新生赛]checkin

数组反序列化弱比较 <?php $info array(username>true,password>true); echo serialize($info); ?> //?infoa:2:{s:8:"username";b:1;s:8:"password";b:1;}1.构造不能用类&#xff0c;因为$data_unserialize只是一个变量&#xff0c;不能…

绘唐ai工具怎么获取

这款产品的最大亮点在于其高度精准的语音克隆能力&#xff0c;利用先进的模型&#xff0c;能够捕捉到用户独特的音调、音高和调制方式&#xff0c;使用户能够以前所未有的方式复制和利用自己的声音。仅需10秒钟的录制时间&#xff0c;即可实现声音的克隆&#xff0c;相当便捷。…

GORM的常见命令

文章目录 一、什么是GORM&#xff1f;二、GORM连接mysql以及AutoMigrate创建表三、查询1、检索此对象是否存在于数据库&#xff08;First,Take,Last方法&#xff09;2、Find()方法检索3、根据指定字段查询 四、更新1、Save() 保存多个字段2、更新单个字段 五、删除 一、什么是G…

CSDN我的创作纪念日128天||不忘初心|努力上进|勇往直前

机缘 Hello&#xff0c;大家好&#xff0c;我是景天&#xff0c;其实很早之前我就加入到了CSND的大军&#xff0c;彼时我还是个刚毕业的小白白&#xff0c;时常过来CSND汲取养料&#xff0c;就这样&#xff0c;慢慢的来提升自己&#xff0c;强大自己。工作锻炼了我&#xff0c…

Qt---day2-信号与槽

1、思维导图 2、 拖拽式 源文件 #include "mywidget.h" #include "ui_mywidget.h" MyWidget::MyWidget(QWidget *parent) : QWidget(parent) , ui(new Ui::MyWidget) { ui->setupUi(this); //按钮2 this->btn2new QPushButton("按钮2",th…

52. 【Android教程】网页视图:WebView

在前面的章节我们所围绕的全部都是纯客户端开发&#xff0c;我们叫 Native 开发。这样的好处就是体验和性能会非常好&#xff0c;但是在实际的使用中我们会发现存在大量的 H5 页面。这样就可以结合 Native / H5 双端的优势完成一个混合开发&#xff0c;而在这种开发模式中首当其…

C语言 函数的定义与调用

上文 C语言 函数概述 我们对函数进行了概述 本文 我们来说函数的定义和调用 C语言规定 使用函数之前&#xff0c;首先要对函数进行定义。 根据模块化程序设计思想&#xff0c;C语言的函数定义是互相平行、独立的&#xff0c;即函数定义不能嵌套 C语言函数定义 分为三种 有参函…

快速排序找出第K大的元素

有序数组里第 K 大的元素就是index 为 array.length - k 的元素。 快速排序的思路主要就是选一个基准值p&#xff0c;然后将小于p的值放在p的左右&#xff0c;大于p的值放在p的右边&#xff0c;然后对左右数组进行递归。 利用这个思路&#xff0c;当我们找到这个基准值对应的 i…

SQL查询语句(一)简单查询和简单条件查询

MySQL的所有语句中&#xff0c;我们日常用的最多的其实就是查询语句。因此这篇文章主要介绍查询语句中的一些基础语法。 目录 简单查询 简单条件查询 简单查询 最简单的查询语句的语法如下所示&#xff1a; SELECT * FROM student; 它的语法解析如下&#xff1a; SELECT关…

【软测学习笔记】Python入门Day02

&#x1f31f;博主主页&#xff1a;我是一只海绵派大星 &#x1f4da;专栏分类&#xff1a;软件测试笔记 &#x1f4da;参考教程&#xff1a;黑马教程❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ python安装 1、进入Python的官方下载页面&#xff1a; Download Python | Py…

如何在已经安装好的PostgreSQL14中安装uuid 扩展

当前环境 PG14.8 LINUX 8.8 存在问题&#xff1a; 开发人员问&#xff0c;PG中&#xff0c;支持 生成UUID吗&#xff0c;具体是什么&#xff0c;答&#xff0c;类似这个函数 uuid_generate_v4() 看了一下&#xff0c; select uuid_generate_v4();会报错&#xff0…

“视频号小店”和“抖音小店”新手做电商选择哪个更好?

哈喽~我是电商月月 做电商的老商家和&#xff0c;准备做电商的新手朋友都知道现在最大的电商平台就是“抖音小店” 但抖店小店毕竟发展了四年&#xff0c;流量多&#xff0c;商家也多&#xff0c;最近又崛起了一个新黑马“视频号小店” 那到底去哪个平台发展才有前景呢&…

QX-mini51学习---(2)点亮LED

目录 1什么是ed 2led工作参数 3本节相关原理图分析 4本节相关c 5实践 1什么是ed 半导体发光二极管&#xff0c;将电能转化为光能&#xff0c;耗电低&#xff0c;寿命长&#xff0c;抗震动 长正短负&#xff0c;贴片是绿点处是负极 2led工作参数 3本节相关原理图分析 当…

一文读懂Python的`__init__`,`__init__`方法的终极指南

大家好&#xff0c;今天给大家介绍一个Python中一个特殊的函数__init__。 在Python中&#xff0c;__init__方法是一个特殊的函数&#xff0c;它在创建类的新实例时自动调用。它的作用类似于其他编程语言中的构造函数&#xff0c;用于初始化对象的状态。这篇文章将带你深入了解…

LeetCode刷题记(五):121~150题

121. 买卖股票的最佳时机 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。 返回你可以从…

用PowerPoint创建毛笔字书写动画

先看看下面这个毛笔字书写动画&#xff1a; 这个动画是用PowerPoint创建的。下面介绍创建过程。 1、在任何一款矢量图片编辑软件中创建一个图片&#xff0c;用文字工具输入文字内容。我用的是InkScape。排好版后将图片保存为.svg格式的矢量图片文件。 2、打开PowerPoint&…

强一致性的皇冠:分布式事务模型的至高法则揭秘

关注微信公众号 “程序员小胖” 每日技术干货&#xff0c;第一时间送达&#xff01; 引言 分布式事务模型是分布式系统设计的核心&#xff0c;关键在于保证数据一致性和事务完整性&#xff0c;尤其强调强一致性。诸如2PC、3PC、Saga、TCC等模型与协议&#xff0c;应运而生以解…

elementui+vue通过下拉框多选字段进行搜索模糊匹配

从字典中选择的值为["01","03"],在最开始的时候进行的处理是类似于表单提交的时候将json对象转换成了String类型 nature:["01","03"] this.queryParams.nature JSON.stringify(this.queryParams.nature); mapper层 <if test&quo…

keystone学习小结

1 keystone middleware 1.1 工作流程 middleware在客户端和服务端之间&#xff0c;会拦截客户端请求并判断请求身份是否是正确合法的&#xff0c;若是&#xff0c;则继续将请求发给其他middleware或app 具体看&#xff0c;干了这些事 1将请求里的auth header去除&#xff0c…

【FL常用插件#1】Ozone11臭氧的安装和使用

本文内容收集自互联网&#xff0c;仅供个人学习参考使用&#xff0c;不允许用于商业用途&#xff0c;造成的侵权行为与本文作者无关 安装 VST2、VST3、AAX和NKS是音频技术界常见的几种插件格式&#xff0c;它们在功能和兼容性上有所不同&#xff1a; VST2 (Virtual Studio Tec…