练习题(2024/5/7)

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.mfbz.cn/a/600162.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JSP企业快信系统的设计与实现参考论文(论文 + 源码)

【免费】JSP企业快信系统.zip资源-CSDN文库https://download.csdn.net/download/JW_559/89277688 JSP企业快信系统的设计与实现 摘 要 计算机网络的出现到现在已经经历了翻天覆地的重大改变。因特网也从最早的供科学家交流心得的简单的文本浏览器发展成为了商务和信息的中心…

深入理解Java虚拟机(JVM)

引言&#xff1a; Java虚拟机&#xff08;JVM&#xff09;是Java平台的核心组件&#xff0c;它负责将Java字节码转换成平台特定的机器指令&#xff0c;并在相应的硬件和操作系统上执行。JVM的引入使得Java语言具有“一次编写&#xff0c;到处运行”的跨平台特性。本文将深入探…

【练习2】

1.汽水瓶 ps:注意涉及多个输入&#xff0c;我就说怎么老不对&#xff0c;无语~ #include <cmath> #include <iostream> using namespace std;int main() {int n;int num,flag,kp,temp;while (cin>>n) {flag1;num0;temp0;kpn;while (flag1) {if(kp<2){if(…

初识C++ · 类和对象(下)

目录 1 再谈构造函数 2 类中的隐式类型转换 3 Static成员 4 友元和内部类 5 匿名对象 6 编译器的一些优化 1 再谈构造函数 先看一段代码&#xff1a; class Date { public :Date(int year, int month, int day){_year year;_month month;_day day;} private:int _ye…

Redis线程模型

文章目录 &#x1f496; Redis 单线程模型⭐ 单线程监听大量的客户端连接⭐ Redis 6.0 之前为什么不用多线程&#xff1f; &#x1f496; Redis多线程⭐ Redis 后台线程⭐ Redis 网络IO多线程 对于读写命令来说&#xff0c;Redis 一直是单线程模型。不过&#xff0c;在 Redis 4…

TinyXML-2介绍

1.简介 TinyXML-2 是一个简单、小巧的 C XML 解析库&#xff0c;它是 TinyXML 的一个改进版本&#xff0c;专注于易用性和性能。TinyXML-2 用于读取、修改和创建 XML 文档。它不依赖于外部库&#xff0c;并且可以很容易地集成到项目中。 tinyXML-2 的主要特点包括&#xff1a…

华为:三层交换机与路由器连通上网实验

三层交换机是一种网络交换机&#xff0c;可以实现基于IP地址的高效数据转发和路由功能&#xff0c;通常用于大型企业、数据中心和校园网络等场景。此外&#xff0c;三层交换机还支持多种路由协议&#xff08;如OSPF、BGP等&#xff09;&#xff0c;以实现更为复杂的网络拓扑结构…

automa警惕通过点击元素打开新的标签页,因为你可能会被他蒙蔽!

大家好&#xff0c;我是大胡子&#xff0c;专注于研究RPA实战与解决方案。 我们经常用到automa里面的【点击元素】组件&#xff0c;但要警惕通过点击元素打开新的标签页&#xff0c;例如下面这个场景&#xff0c;点击公众号的图文消息&#xff0c;之后&#xff0c;要自动输入标…

python环境下labelImg图片标注工具的使用

labelimg GitHub地址 python环境下labelImg图片标注工具的使用 1. 写在开头2. 如何使用2.1安装2.2 启动2.2.1 先启动后设置标注的目录2.2.2 指定标注的目录和预设置的标签 2.3 设置自动保存和显示类别。2.4 保存文件类型2.5 [快捷键](https://github.com/HumanSignal/labelImg…

【数据结构】C/C++ 带头双向循环链表保姆级教程(图例详解!!)

目录 一、前言 二、链表的分类 &#x1f95d;单链表 &#x1f95d;双链表 &#x1f95d;循环链表 &#x1f95d;带头双向循环链表 &#x1f34d;头节点&#xff08;哨兵位&#xff09;的作用 ✨定义&#xff1a; ✨作用&#xff1a; &#x1f347;总结 三、带头双向循环链表 …

技术速递|使用 .NET 为 Microsoft AI 构建可扩展网关

作者&#xff1a;Kara Saucerman 排版&#xff1a;Alan Wang Microsoft AI 团队构建了全面的内容、服务、平台和技术&#xff0c;以便消费者在任何设备上、任何地方获取他们想要的信息&#xff0c;并为企业改善客户和员工的体验。我们的团队支持多种体验&#xff0c;包括 Bing、…

通过氧气退火增强β-Ga₂O₃二极管.中国科技大学和河北半导体研究所的研究人员在这一特定领域取得了最新重大进展

上图所示&#xff1a;&#xff08;a&#xff09;增加台面有助于提高β-Ga2O3肖特基势垒二极管的阻断电压&#xff08;b&#xff09;。 氧气退火和自对准台面终端使β-Ga2O3二极管进一步走向商业化。 虽然β-Ga2O3电力电子技术已经取得了长足的进步&#xff0c;但仍然存在挑战&…

.双链表.

题目&#xff1a; 实现一个双链表&#xff0c;双链表初始为空&#xff0c;支持 55 种操作&#xff1a; 在最左侧插入一个数&#xff1b;在最右侧插入一个数&#xff1b;将第 k&#x1d458; 个插入的数删除&#xff1b;在第 k&#x1d458; 个插入的数左侧插入一个数&#xf…

Redis(Redis配置和订阅发布)

文章目录 1.Redis配置1.网络配置1.配置文件位置 /etc/redis.conf2.bind&#xff08;注销支持远程访问&#xff09;1.默认情况bind 127.0.0.1 只能接受本机的访问2.首先编辑配置文件3.进入命令模式输入/bind定位&#xff0c;输入n查找下一个&#xff0c;shift n查找上一个&…

书生·浦语大模型实战营之XTuner多模态训练与测试

书生浦语大模型实战营之XTuner多模态训练与测试 目录 XTuner多模态训练与测试给LLM装上电子眼&#xff1a;多模态LLM原理简介文本单模态文本图像多模态 电子眼&#xff1a;LLaVA方案简介LLaVA训练阶段示意图LLaVA测试阶段示意图 项目实践环境准备XTuner安装概述Pretrain阶段Fi…

NVIDIA_SMI has failed because it couldn’t communicate with the NVIDIA driver

参考&#xff1a;https://www.zhihu.com/question/474222642/answer/3127013936 https://blog.csdn.net/ZhouDevin/article/details/128265656 nvidia-smi查看报错&#xff0c;nvcc正常 1&#xff09;查看nvidia版本 ls /usr/src | grep nvidia nvidia-550.78 2&#xff09;…

无线通信基础

这里写目录标题 通信概述什么是无线通信无线通信电磁波 通信概述 什么是无线通信 无线通信 : 是指利用电磁波信号可以在自由空间中传播的特性进行信息交换的一种通信方式 无线通信的关键技术包括调制技术、解调技术、信道编码技术、信号处理技术、天线技术等。这些技术的不断…

【mobx-入门与思考】

介绍 mobx 是 nodejs生态中的框架&#xff0c; 主要用于做状态管理&#xff0c;可以监控变量状态的变化。 nodejs中除了mobx&#xff0c;还有个redux&#xff0c;也是做状态管理的&#xff0c;都是比较成熟的框架&#xff0c;二者的选择可以参考 【nodejs状态管理: Redux VS M…

太原理工大学Python数据分析原理与应用(课外考题:8~11章)

这部分大概只考10分&#xff0c;且大部分出在选择题&#xff0c;填空最多一两个 (仅供参考) 第十章 (理解概念为主&#xff0c;无需看推导过程) 第十一章

1-1ARM开发环境搭建(GD32)

1:安装MDK最好是5.27以及以上版本&#xff0c;避免后续学习中出现相关错误 2&#xff1a;安装芯片支持包 双击安装即可&#xff0c;也可以是默认路径&#xff0c;也可以自己更改路径 3&#xff1a;安装jlink下载器驱动&#xff08;下载调试器&#xff09; 具体安装步骤如下所示…
最新文章