练习题(2024/4/8)

1 括号生成

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

示例 1:

输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]

示例 2:

输入:n = 1
输出:["()"]

思路:

一个合法的括号组合需要满足以下两个条件:

  1. 左括号和右括号的数量相等;
  2. 在任何一个位置,左括号的数量都不少于右括号的数量。

基于以上思路,可以采用回溯法或深度优先搜索(DFS)来生成所有有效的括号组合。

回溯法的实现思路是在每一步中都尝试添加左括号和右括号,并检查是否满足上述两个条件。如果满足条件,则继续向下递归生成;如果不满足条件,则进行回溯,尝试其他可能的选择。

深度优先搜索的实现思路是从当前括号组合开始,尝试向下递归生成所有可能的括号组合。在递归的过程中,需要记录当前左括号和右括号的数量,并根据条件决定是否继续添加左括号或右括号。

总体来说,无论是回溯法还是深度优先搜索,核心思想都是通过递归生成所有可能的括号组合,并在生成过程中保证每一步的合法性。这样,最终可以得到所有有效的括号组合。

代码:

#include <vector>
#include <string>
using namespace std;

class Solution {
    vector<string> ans; // 存储生成的所有有效括号组合
    
public:
    // 生成所有有效的括号组合
    vector<string> generateParenthesis(int n) {
        dfs(0, 0, n, ""); // 调用深度优先搜索函数
        return ans; // 返回结果集
    }
    
    // 深度优先搜索函数,生成所有有效的括号组合
    void dfs(int left, int right, int n, string seq) {
        // 当左右括号数量均达到n时,生成了一个有效括号组合
        if (left == n && right == n) {
            ans.push_back(seq); // 将当前字符串加入结果集
            return; // 结束当前递归
        }
        
        // 向下递归生成括号组合
        if (left < n) 
            dfs(left + 1, right, n, seq + "("); // 向当前字符串追加左括号,继续递归
        if (right < left) 
            dfs(left, right + 1, n, seq + ")"); // 向当前字符串追加右括号,继续递归
    }
};

2合并 K 个升序链表

给你一个链表数组,每个链表都已经按升序排列。

请你将所有链表合并到一个升序链表中,返回合并后的链表。

示例 1:

输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
  1->4->5,
  1->3->4,
  2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6

示例 2:

输入:lists = []
输出:[]

示例 3:

输入:lists = [[]]
输出:[]
思路:
1最小堆法

最小堆是一种数据结构,它保证了堆顶元素是堆中最小的元素。我们可以利用最小堆来维护当前K个链表中最小的元素。具体步骤如下:

  1. 创建一个最小堆,并定义一个比较函数,使得堆中的节点按照节点值的大小进行排序,以确保堆顶元素是当前K个链表中最小的节点。

  2. 遍历K个链表的头节点,并将它们依次加入到最小堆中。

  3. 创建一个哨兵节点(dummy),作为合并后链表的头节点的前一个节点。

  4. 循环直到最小堆为空:

    • 取出最小堆的堆顶节点(当前K个链表中最小的节点)。
    • 如果这个最小节点有下一个节点,则将其下一个节点加入到最小堆中。
    • 将这个最小节点接入到合并后的链表中。
  5. 返回哨兵节点的下一个节点,即合并后链表的头节点。

代码:

class Solution {
public:
    ListNode *mergeKLists(vector<ListNode *> &lists) {
        // 定义比较函数用于最小堆排序
        auto cmp = [](const ListNode *a, const ListNode *b) {
            return a->val > b->val; // 最小堆
        };
        // 定义优先队列(最小堆),使用自定义的比较函数
        priority_queue<ListNode*, vector<ListNode*>, decltype(cmp)> pq(cmp);
        // 将每个链表的头结点放入优先队列中
        for (auto head: lists)
            if (head) pq.push(head);

        // 哨兵节点,作为合并后链表头节点的前一个节点
        auto dummy = new ListNode(-1);
        auto cur = dummy;
        // 循环直到堆为空
        while (!pq.empty()) {
            // 取出堆顶节点,即剩余节点中的最小节点
            auto node = pq.top();
            pq.pop();
            // 如果最小节点有下一个节点,则将下一个节点加入堆中
            if (node->next)
                pq.push(node->next);
            // 将当前最小节点接入新链表中
            cur->next = node;
            cur = cur->next;
        }
        // 返回哨兵节点的下一个节点,即新链表的头节点
        return dummy->next;
    }
};

// 创建链表函数
ListNode* createLinkedList(vector<int>& arr) {
    ListNode* dummy = new ListNode(-1);
    ListNode* current = dummy;
    for (int val : arr) {
        current->next = new ListNode(val);
        current = current->next;
    }
    return dummy->next;
}

 2 分治法

分治法的基本思路是将原问题分解成若干个规模较小的子问题,然后递归地解决这些子问题,最后将子问题的解合并起来,得到原问题的解。对于合并K个升序链表的问题,我们可以采用以下步骤:

  1. 分解:将K个链表划分为两个大致相等的子组。对于每个子组,递归地调用合并函数 mergeTwoLists,将两个链表合并成一个有序链表。

  2. 合并:递归地将子组的合并结果再次合并,直到最终将所有链表合并成一个有序链表。

代码:

class Solution {
    // 21. 合并两个有序链表
    // 输入两个有序链表,返回合并后的有序链表
    ListNode *mergeTwoLists(ListNode *list1, ListNode *list2) {
        auto dummy = new ListNode(); // 使用哨兵节点简化代码
        auto cur = dummy; // cur 指向新链表的末尾
        while (list1 && list2) {
            if (list1->val < list2->val) {
                cur->next = list1; // 将 list1 加入新链表
                list1 = list1->next; // 移动 list1 指针
            } else { // 注意:当节点值相等时,可选任意一个加入新链表
                cur->next = list2; // 将 list2 加入新链表
                list2 = list2->next; // 移动 list2 指针
            }
            cur = cur->next; // 移动新链表的指针
        }
        // 将剩余部分链接到新链表
        cur->next = list1 ? list1 : list2;
        return dummy->next; // 返回合并后的链表头节点
    }

    // 合并 lists[i] 到 lists[j-1] 的链表
    // 递归实现分治法合并链表
    ListNode *mergeKLists(vector<ListNode *> &lists, int i, int j) {
        int m = j - i;
        if (m == 0) return nullptr; // 若链表为空,则返回空指针
        if (m == 1) return lists[i]; // 若只有一个链表,则直接返回该链表
        auto left = mergeKLists(lists, i, i + m / 2); // 合并左半部分链表
        auto right = mergeKLists(lists, i + m / 2, j); // 合并右半部分链表
        return mergeTwoLists(left, right); // 最终合并左右两部分链表
    }

public:
    // 合并 K 个升序链表
    ListNode *mergeKLists(vector<ListNode *> &lists) {
        return mergeKLists(lists, 0, lists.size());
    }
};

3. 两两交换链表中的节点

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

示例 1:

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

示例 2:

输入:head = []
输出:[]

示例 3:

输入:head = [1]
输出:[1]

提示:

  • 链表中节点的数目在范围 [0, 100] 内
  • 0 <= Node.val <= 100

思路:

  1. 创建一个虚拟头节点 dummy,并将其指向原链表的头部。
  2. 使用 prev 指针初始化为虚拟头节点,用于迭代遍历链表。
  3. 在循环中,每次交换两个相邻的节点,需要记住当前的第一个节点 first 和第二个节点 second
  4. 进行节点交换:将 prev->next 指向 secondfirst->next 指向 second->nextsecond->next 指向 first,完成交换。
  5. 将 prev 指针移动到下一组待交换的节点位置,即 first 的位置。
  6. 重复以上步骤,直到遍历完所有相邻的节点。
  7. 终止条件是在循环中,当 prev->next 或 prev->next->next 为空时,即链表中不足两个节点可供交换时,循环停止。这是因为两两交换节点需要至少有两个节点才能进行交换,所以当没有足够的节点时,就不需要再进行交换操作,循环可以结束。

代码:

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        // 创建一个虚拟头结点,简化边界情况处理
        ListNode* dummyHead = new ListNode(0);
        dummyHead->next = head; // 将虚拟头结点指向head,方便后面做删除操作
        ListNode* prev = dummyHead; // 初始化前一个节点指针

        // 循环遍历链表,直到链表末尾或者仅剩一个节点
        while (prev->next != nullptr && prev->next->next != nullptr) {
            // 记录当前两个相邻节点
            ListNode* first = prev->next;
            ListNode* second = prev->next->next;

            // 交换节点
            prev->next = second; // 前一个节点指向第二个节点
            first->next = second->next; // 第一个节点指向第二个节点的下一个节点
            second->next = first; // 第二个节点指向第一个节点

            // 移动prev指针到下一组待交换的位置
            prev = first; // 前一个节点移动两位,准备下一轮交换
        }

        // 虚拟头结点指向链表的新头部
        ListNode* result = dummyHead->next;

        // 删除虚拟头结点,避免内存泄漏
        delete dummyHead;

        // 返回交换后的链表头部
        return result;
    }
};

4员工奖金  

表:Employee 

+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| empId       | int     |
| name        | varchar |
| supervisor  | int     |
| salary      | int     |
+-------------+---------+
empId 是该表中具有唯一值的列。
该表的每一行都表示员工的姓名和 id,以及他们的工资和经理的 id。

表:Bonus

+-------------+------+
| Column Name | Type |
+-------------+------+
| empId       | int  |
| bonus       | int  |
+-------------+------+
empId 是该表具有唯一值的列。
empId 是 Employee 表中 empId 的外键(reference 列)。
该表的每一行都包含一个员工的 id 和他们各自的奖金。

编写解决方案,报告每个奖金 少于 1000 的员工的姓名和奖金数额。

以 任意顺序 返回结果表。

结果格式如下所示。

示例 1:

输入:
Employee table:
+-------+--------+------------+--------+
| empId | name   | supervisor | salary |
+-------+--------+------------+--------+
| 3     | Brad   | null       | 4000   |
| 1     | John   | 3          | 1000   |
| 2     | Dan    | 3          | 2000   |
| 4     | Thomas | 3          | 4000   |
+-------+--------+------------+--------+
Bonus table:
+-------+-------+
| empId | bonus |
+-------+-------+
| 2     | 500   |
| 4     | 2000  |
+-------+-------+
输出:
+------+-------+
| name | bonus |
+------+-------+
| Brad | null  |
| John | null  |
| Dan  | 500   |
+------+-------+

思路:

首先需要知道每个员工的奖金数量,因此需要首先将 Employee 表与 Bonus 表连接。注意需要使用外连接,以处理员工没有出现在 Bonus 表上的情况。这里因为不存在员工只出现在 Bonus 表中的情况,所以只需要使用左外连接(left join 或 left outer join)

其中 Brad 和 John 的 bonus 值为空,空值在数据库中的表示为 null。我们使用 bonus is null(而不是 bonus = null)判断奖金是否为 null。随后即可用 where 子句筛选奖金小于 1000 或者为空的员工。

代码:

#选择员工的姓名和奖金
select name, bonus
#从 Employee 表和 Bonus 表进行左连接
from Employee left join Bonus
on Employee.EmpId = Bonus.EmpId
 #筛选出奖金为空或者奖金小于 1000 的员工
where bonus is null or bonus < 1000

 5大的国家

World 表:

+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| name        | varchar |
| continent   | varchar |
| area        | int     |
| population  | int     |
| gdp         | bigint  |
+-------------+---------+
name 是该表的主键(具有唯一值的列)。
这张表的每一行提供:国家名称、所属大陆、面积、人口和 GDP 值。

如果一个国家满足下述两个条件之一,则认为该国是 大国 :

  • 面积至少为 300 万平方公里(即,3000000 km2),或者
  • 人口至少为 2500 万(即 25000000

编写解决方案找出 大国 的国家名称、人口和面积。

按 任意顺序 返回结果表。

返回结果格式如下例所示。

示例:

输入:
World 表:
+-------------+-----------+---------+------------+--------------+
| name        | continent | area    | population | gdp          |
+-------------+-----------+---------+------------+--------------+
| Afghanistan | Asia      | 652230  | 25500100   | 20343000000  |
| Albania     | Europe    | 28748   | 2831741    | 12960000000  |
| Algeria     | Africa    | 2381741 | 37100000   | 188681000000 |
| Andorra     | Europe    | 468     | 78115      | 3712000000   |
| Angola      | Africa    | 1246700 | 20609294   | 100990000000 |
+-------------+-----------+---------+------------+--------------+
输出:
+-------------+------------+---------+
| name        | population | area    |
+-------------+------------+---------+
| Afghanistan | 25500100   | 652230  |
| Algeria     | 37100000   | 2381741 |
+-------------+------------+---------+

思路:我们需要从 World 表中选择符合大国条件的国家,并返回它们的名称、人口和面积。

这个查询会选择满足以下条件之一的国家:

  1. 面积大于等于 300 万平方公里;
  2. 人口大于等于 2500 万。

代码:

select name  ,population,area   
from World
where 
    area >= 3000000 
    or population >= 25000000

6超过5名学生的课

表: Courses

+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| student     | varchar |
| class       | varchar |
+-------------+---------+
在 SQL 中,(student, class)是该表的主键列。
该表的每一行表示学生的名字和他们注册的班级。

查询 至少有5个学生 的所有班级。

以 任意顺序 返回结果表。

查询结果格式如下所示。

示例 1:

输入: 
Courses table:
+---------+----------+
| student | class    |
+---------+----------+
| A       | Math     |
| B       | English  |
| C       | Math     |
| D       | Biology  |
| E       | Math     |
| F       | Computer |
| G       | Math     |
| H       | Math     |
| I       | Math     |
+---------+----------+
输出: 
+---------+ 
| class   | 
+---------+ 
| Math    | 
+---------+
解释: 
-数学课有6个学生,所以我们包括它。
-英语课有1名学生,所以我们不包括它。
-生物课有1名学生,所以我们不包括它。
-计算机课有1个学生,所以我们不包括它。

思路:我们需要找出至少有5个学生的所有班级。要做到这一点,我们可以使用SQL的聚合功能,具体来说,我们会按班级进行分组,并统计每个班级中的学生数量。然后,我们将筛选出学生数量至少为5的班级。这样,我们就可以得到满足条件的班级列表。

代码:

-- 选择至少有5个学生的所有班级
select class
-- 从 Courses 表中进行查询
from Courses
-- 根据班级进行分组,并筛选出学生数量至少为5的班级
group by class
having count(student) >= 5;

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

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

相关文章

GEE必须会教程—一文教会你GEE下载影像数据的方法

一、基本流程 A.平台进入&#xff1a;网站搜索&#xff1a;https://developers.google.com/earth-engine&#xff0c;进入Google Earth Engine 官网平台&#xff08;以下简称GEE平台&#xff09;&#xff0c;正常登录该平台需要利用邮箱进行申请&#xff0c;申请通过后可以正常…

图书馆自助借书机怎么借书

图书馆自助借书机借书流程如下&#xff1a; 1. 找到图书馆自助借书机&#xff0c;在机器上选择借书功能。 2. 输入自己的借书卡号或者身份证号码&#xff0c;如果是第一次借书&#xff0c;可能需要进行注册。 3. 输入图书的条形码号码&#xff0c;可以通过扫描条形码或者手动输…

LangChain-11 Code Writing FunctionCalling 大模型通过编写代码完成需求 大模型计算加法

背景简介 我们知道GPT模型对于内容的输出&#xff0c;是对下一个字符的预测&#xff0c;通过概率选出下一个文本。 而且我们也知道&#xff0c;训练样本是非常庞大的&#xff0c;对于GPT来说&#xff0c;也是有可能学习过1 1 2的。 当我们向GPT询问11 时&#xff0c;完全可以…

Verilog语法——按位取反“~“和位宽扩展的优先级

前言 先说结论&#xff0c;如下图所示&#xff0c;在Verilog中“~ ”按位取反的优先级是最高的&#xff0c;但是在等式计算时&#xff0c;有时候会遇到位宽扩展&#xff0c;此时需要注意的是位宽扩展的优先级高于“~”。 验证 仿真代码&#xff0c;下面代码验证的是“~”按位取…

腾讯云视频点播配置说明 | Modstart

开通云点播 开通云点播 云点播VOD_音视频点播_直播回看_音视频上传、存储转码AI处理方案-腾讯云 获取腾讯云 SecretId 和 SecretSecret 注册并且登录 腾讯云

【深度学习基础】

打基础日常记录 CNN基础知识1. 感知机2. DNN 深度神经网络&#xff08;全连接神经网络&#xff09;DNN 与感知机的区别DNN特点&#xff0c;全连接神经网络DNN前向传播和反向传播 3. CNN结构【提取特征分类】4. CNN应用于文本 RNN基础1. RNN的本质 词向量模型word2Vec1. 自然语言…

LC低通滤波

LC滤波器&#xff0c;是指将电感L与电容器 C进行组合设计构成的滤波电路&#xff0c;可去除或通过特定频率的无源器件。电容器具有隔直流通交流&#xff0c;且交流频率越高越容易通过的特性。而电感则具有隔交流通直流&#xff0c;且交流频率越高越不易通过的特性。因此&#x…

广州等级保护测评公司一览表2024

广州等级保护测评公司一览表2024 序号&#xff1a;1 名称&#xff1a;南方电网科学研究院有限责任公司 地址&#xff1a;广东省广州市萝岗区科学城科翔路11号J1栋3、4、5楼及J3栋3楼 序号&#xff1a;2 名称&#xff1a;广州竞远安全技术股份有限公司 地址&#xff1a;广…

提高网站安全性,漏洞扫描能带来什么帮助

随着互联网的蓬勃发展&#xff0c;网站已经成为人们获取信息、交流思想、开展业务的重要平台。然而&#xff0c;与之伴随的是日益严重的网络安全问题&#xff0c;包括恶意攻击、数据泄露、隐私侵犯等。 为了保障网站的安全性&#xff0c;提前做好网站的安全检测非常有必要&…

二维码门楼牌管理应用平台:实现精细化、智能化场所管理

文章目录 前言一、二维码门楼牌管理应用平台的构建二、场所任务的精细化管理三、消防检查与整改的智能化管理四、二手交易登记的便捷化管理五、未来展望 前言 随着城市管理的日益精细化&#xff0c;二维码门楼牌管理应用平台应运而生。通过这一平台&#xff0c;场所负责人可以…

在Ubuntu系统下连接远程Ubuntu服务器

本篇文章介绍&#xff0c;如何在Ubuntu系统下连接远程Ubuntu系统并传输文件。 一. 连接远程Ubuntu服务器。 1. 打开命令行&#xff0c;输入 : sudo apt-get update &#xff0c; 对系统进行更新。 2. 安装 OpenSSH Server&#xff0c;输入 &#xff1a; sudo apt-get insta…

Redis中的集群(一)

集群 概述 Redis集群是Redis提供的分布式数据库方案&#xff0c;集群通过分片(sharding)来进行数据共享&#xff0c;并提供复制和故障转移功能 节点 一个Redis集群通常由多个节点(node)组成&#xff0c;在刚开始的时候&#xff0c;每个节点都是相互独立的&#xff0c;它们都…

LLM是优秀的手语翻译者

LLM是优秀的手语翻译者 简介Related WorkMethodSignLLM Overviewector-Quantized Visual Sign ModuleCodebook Reconstruction and Alignment LLMs are Good Sign Language Translators 简介 基于观察&#xff0c;我们发现LLMs可以通过利用与之前学习过的语言的共有特性来有效…

【C++进阶】哈希的应用之位图和布隆过滤器

位图和布隆过滤器 一&#xff0c;位图1. 实现2. 位图的应用 二&#xff0c;布隆过滤器1. 使用场景2. 模拟实现 三&#xff0c;海量数据面试题哈希切分 四&#xff0c;总结 这一节我们来看哈希的应用 一&#xff0c;位图 先来看一个面试题 这里如果用unordered_set来解决&…

JS--demo2录入学生信息

实现学生信息录取。 效果图: <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><meta http-equiv"X-U…

SSL证书的作用是什么?

SSL证书让网站和用户之间安全传输信息&#xff0c;就像给网络对话加了一把密码锁。它主要做四件事&#xff1a; 1. 证明身份&#xff1a; - 像警察局一样&#xff0c;有个叫“证书颁发机构”的家伙负责检查网站是不是真的。网站要向它证明自己是谁&#xff08;比如&#xff0c;…

onedrive 清理文件历史版本 节省空间

onedrive 清理文件历史版本以节省空间的操作步骤 起因&#xff1a; 用的好好的onedrive高校教育版&#xff0c;突然在2024年4月2日晚上把空间从1T回收到100G&#xff0c;然后文件爆满&#xff0c;虽然没有把文件都给我删了&#xff0c;但是可能几个月窗口期过去就没文件了。而…

如何恢复被.locked勒索病毒加密的服务器和数据库?

.locked勒索病毒有什么特点&#xff1f; .locked勒索病毒的特点主要包括以下几个方面&#xff1a; 文件加密&#xff1a;.locked勒索病毒会对受感染设备上的所有文件进行加密&#xff0c;包括图片、文档、视频和其他各种类型的重要文件。一旦文件被加密&#xff0c;文件的扩展…

电商运营自动化新里程:取数宝引领数字化转型实践

随着电子商务行业的高速发展及复杂化&#xff0c;精细化运营已成为电商企业提升竞争力的关键所在。尤其是在海量数据处理与实时分析方面&#xff0c;自动化工具的引入对企业管理和决策带来了革命性变化。其中&#xff0c;“取数宝”作为一种先进的电商运营自动化解决方案&#…

20240325-2-K-means面试题

K-means面试题 1. 聚类算法&#xff08;clustering Algorithms&#xff09;介绍 聚类是一种无监督学习—对大量未知标注的数据集&#xff0c;按数据的内在相似性将数据集划分为多个类别&#xff0c;使类别内的数据相似度较大而类别间的数据相似度较小。 聚类算法可以分为原型…