【LeetCode】力扣刷题热题100道(31-35题)附源码 搜索二维矩阵 岛屿数量 腐烂的橙子 课程表 实现 Trie (前缀树)(C++)
一、搜索二维矩阵
编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:
- 每行的元素从左到右升序排列。
- 每列的元素从上到下升序排列。


可以使用 从右上角开始搜索 的方法来有效地找到目标值。
- 选择起始位置: 从矩阵的右上角开始。假设我们当前的位置是
matrix[0][n-1],其中n是列数。 - 逐步搜索:
- 如果当前元素等于目标值,返回
true。 - 如果当前元素大于目标值,说明目标值可能出现在当前元素的左边,因此我们向左移动一列。
- 如果当前元素小于目标值,说明目标值可能出现在当前元素的下方,因此我们向下移动一行。
- 如果当前元素等于目标值,返回
- 结束条件: 如果超出了矩阵的边界,说明没有找到目标值,返回
false。
class Solution {
public:bool searchMatrix(vector<vector<int>>& matrix, int target) {if (matrix.empty() || matrix[0].empty()) return false;int m = matrix.size(); // 行数int n = matrix[0].size(); // 列数// 从右上角开始int row = 0;int col = n - 1;while (row < m && col >= 0) {if (matrix[row][col] == target) {return true; // 找到目标值} else if (matrix[row][col] > target) {col--; // 当前元素大于目标值,向左移动} else {row++; // 当前元素小于目标值,向下移动}}return false; // 没有找到目标值}
};
- 初始位置:从矩阵的右上角
matrix[0][n-1]开始。 - 移动规则:
- 如果当前元素等于目标值,则返回
true。 - 如果当前元素大于目标值,则移动到左边一列。
- 如果当前元素小于目标值,则移动到下方一行。
- 如果当前元素等于目标值,则返回
- 边界条件:当行数或列数超出范围时,结束搜索。
二、岛屿数量
给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。

-
DFS 遍历:从每个尚未访问的陆地单元格开始,使用 DFS 遍历其所有相邻的陆地单元格,将它们标记为已访问。每次发现一个新的未被访问的陆地,就说明发现了一个新的岛屿。
-
标记访问:为了避免重复计算同一个岛屿,需要在遍历过程中将已经访问过的陆地标记为水('0'),这样就不会再次访问到它。
-
岛屿计数:每当我们从一个未访问的陆地开始 DFS 时,岛屿数加一。
- 对于每一个格子,如果它是陆地 ('1') 且未被访问,则从该格子开始进行 DFS,将与之相连的所有陆地格子标记为已访问,并将岛屿数量加一。
- 遍历所有格子,最终得到岛屿的数量。
- 对于一个陆地格子('1'),递归地向上下左右四个方向扩展,找到与它相连的所有陆地并将其标记为水('0')。
- 这样做的目的是确保每个岛屿的陆地只被计数一次。
class Solution {
public:void dfs(vector<vector<char>>& grid, int i, int j) {// 边界条件:如果当前格子越界或已经是水('0'),则返回if (i < 0 || i >= grid.size() || j < 0 || j >= grid[0].size() || grid[i][j] == '0') {return;}// 将当前陆地格子标记为水,表示已访问grid[i][j] = '0';// 递归四个方向dfs(grid, i + 1, j); // 向下dfs(grid, i - 1, j); // 向上dfs(grid, i, j + 1); // 向右dfs(grid, i, j - 1); // 向左}int numIslands(vector<vector<char>>& grid) {if (grid.empty()) return 0;int numIslands = 0;// 遍历整个网格for (int i = 0; i < grid.size(); ++i) {for (int j = 0; j < grid[0].size(); ++j) {// 找到一个未访问的陆地,启动 DFSif (grid[i][j] == '1') {numIslands++; // 发现新的岛屿dfs(grid, i, j); // 使用 DFS 标记整个岛屿}}}return numIslands;}
};
-
DFS 函数:
dfs用来递归访问与当前格子相连的所有陆地格子,并将它们标记为水('0')。- 参数
i, j表示当前正在处理的格子坐标。 - 在函数内部,首先检查是否越界或是否已经是水('0'),如果是则直接返回。
- 然后标记当前格子为水,并递归检查四个方向(上下左右)。
- 参数
-
主函数:
numIslands遍历整个二维网格,发现每个未访问的陆地时,调用dfs来标记所有相连的陆地,从而确保每个岛屿只计算一次。 -
边界条件:如果网格为空,直接返回
0。
三、腐烂的橙子
在给定的 m x n 网格 grid 中,每个单元格可以有以下三个值之一:
- 值
0代表空单元格; - 值
1代表新鲜橘子; - 值
2代表腐烂的橘子。
每分钟,腐烂的橘子 周围 4 个方向上相邻 的新鲜橘子都会腐烂。
返回 直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回 -1 。

class Solution {
public:int orangesRotting(vector<vector<int>>& grid) {int m = grid.size();int n = grid[0].size();// 记录腐烂的橘子的位置queue<pair<int, int>> rotten;int freshCount = 0; // 记录新鲜橘子的数量// 初始化队列和新鲜橘子数量for (int i = 0; i < m; ++i) {for (int j = 0; j < n; ++j) {if (grid[i][j] == 2) {rotten.push({i, j});} else if (grid[i][j] == 1) {freshCount++;}}}// 如果没有新鲜橘子,直接返回 0if (freshCount == 0) return 0;// 四个方向vector<pair<int, int>> directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};int minutes = 0;// 开始 BFSwhile (!rotten.empty()) {int size = rotten.size();bool rottedThisRound = false; // 记录这一轮是否有橘子腐烂for (int i = 0; i < size; ++i) {auto [x, y] = rotten.front();rotten.pop();// 四个方向扩展for (auto& dir : directions) {int nx = x + dir.first;int ny = y + dir.second;// 如果新位置在网格内且是新鲜橘子if (nx >= 0 && nx < m && ny >= 0 && ny < n && grid[nx][ny] == 1) {grid[nx][ny] = 2; // 将新鲜橘子腐烂rotten.push({nx, ny}); // 加入队列freshCount--; // 减少新鲜橘子的数量rottedThisRound = true;}}}// 如果这一轮有橘子腐烂,时间增加if (rottedThisRound) {minutes++;}}// 如果还有新鲜橘子,返回 -1return freshCount == 0 ? minutes : -1;}
};
- 初始化:
- 我们先遍历网格,找到所有腐烂的橘子,并将其加入队列。同时,我们统计新鲜橘子的数量。
- BFS 过程:
- 我们从腐烂的橘子开始,逐层扩展,检查每个腐烂橘子周围的四个方向。
- 如果发现相邻位置是新鲜橘子(值为
1),我们就把它变成腐烂的橘子(值改为2),并将其加入队列,继续扩展。 - 每次扩展都意味着时间增加一分钟。
- 结束条件:
- 如果在 BFS 完成后还有新鲜橘子(
freshCount > 0),说明不能完全腐烂所有橘子,返回-1。 - 否则,返回所需的分钟数。
- 如果在 BFS 完成后还有新鲜橘子(
四、课程表
你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1 。
在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai 则 必须 先学习课程 bi 。
- 例如,先修课程对
[0, 1]表示:想要学习课程0,你需要先完成课程1。
请你判断是否可能完成所有课程的学习?如果可以,返回 true ;否则,返回 false 。

class Solution {
public:bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {vector<int> indegree(numCourses, 0); // 记录每个课程的入度vector<vector<int>> graph(numCourses); // 邻接表表示图// 构建图和入度数组for (const auto& prereq : prerequisites) {int course = prereq[0]; // 需要学习的课程int pre = prereq[1]; // 先修课程graph[pre].push_back(course); // 将 course 加入 pre 的邻接表indegree[course]++; // course 的入度加 1}// 使用队列存储入度为 0 的课程queue<int> q;for (int i = 0; i < numCourses; ++i) {if (indegree[i] == 0) {q.push(i); // 将入度为 0 的课程加入队列}}int count = 0; // 记录已修课程的数量while (!q.empty()) {int course = q.front();q.pop();count++;// 对当前课程的所有后续课程(即它的邻接课程)进行处理for (int nextCourse : graph[course]) {indegree[nextCourse]--; // 当前课程修完,减去下一个课程的入度if (indegree[nextCourse] == 0) {q.push(nextCourse); // 如果下一个课程的入度为 0,加入队列}}}// 如果修完的课程数量等于总课程数,则可以完成所有课程return count == numCourses;}
};
- 构建图和入度数组:
- 我们首先创建一个
graph数组来存储图的邻接表,并创建一个indegree数组来记录每个课程的入度(即每个课程有多少先修课程)。 - 然后,我们根据
prerequisites数组来构建图,并更新每个课程的入度。
- 我们首先创建一个
- 拓扑排序:
- 我们初始化一个队列
q,将所有入度为 0 的课程加入队列。 - 逐个从队列中取出课程,修完后,将它的邻接课程的入度减 1。如果某个邻接课程的入度变为 0,则将它加入队列。
- 我们初始化一个队列
- 判断是否完成所有课程:
- 最后,我们检查已修的课程数量
count是否等于总课程数numCourses。如果相等,说明没有环路,返回true;否则,返回false。
- 最后,我们检查已修的课程数量
五、实现 Trie (前缀树)
Trie(发音类似 "try")或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补全和拼写检查。
请你实现 Trie 类:
Trie()初始化前缀树对象。void insert(String word)向前缀树中插入字符串word。boolean search(String word)如果字符串word在前缀树中,返回true(即,在检索之前已经插入);否则,返回false。boolean startsWith(String prefix)如果之前已经插入的字符串word的前缀之一为prefix,返回true;否则,返回false。

class Trie {
private:struct TrieNode {unordered_map<char, TrieNode*> children;bool isWord;TrieNode() : isWord(false) {}};TrieNode* root;public:// 构造函数,初始化 Trie 树Trie() {root = new TrieNode();}// 向 Trie 插入一个字符串void insert(string word) {TrieNode* node = root;for (char c : word) {// 如果当前字符的子节点不存在,则创建一个新的节点if (node->children.find(c) == node->children.end()) {node->children[c] = new TrieNode();}node = node->children[c];}// 标记字符串结束的节点node->isWord = true;}// 查找字符串是否存在于 Trie 中bool search(string word) {TrieNode* node = root;for (char c : word) {if (node->children.find(c) == node->children.end()) {return false; // 如果有字符没有找到对应节点,返回 false}node = node->children[c];}// 如果到达字符串结尾并且是一个完整的单词,返回 truereturn node->isWord;}// 检查是否有任何单词以 prefix 为前缀bool startsWith(string prefix) {TrieNode* node = root;for (char c : prefix) {if (node->children.find(c) == node->children.end()) {return false; // 如果有字符没有找到对应节点,返回 false}node = node->children[c];}// 如果遍历完整个前缀,说明 Trie 中有以 prefix 为前缀的单词return true;}
};/*** Your Trie object will be instantiated and called as such:* Trie* obj = new Trie();* obj->insert(word);* bool param_2 = obj->search(word);* bool param_3 = obj->startsWith(prefix);*/
-
TrieNode 结构体:每个
TrieNode代表一个树节点,包含:children:一个哈希表,键是字符,值是指向子节点的指针。这个哈希表用于存储当前节点的所有子节点。isWord:一个布尔值,标记当前节点是否为一个单词的结束。
-
Trie 构造函数:创建一个空的根节点
root。 -
insert(word):
- 从根节点开始,逐个字符遍历
word。 - 如果某个字符的子节点不存在,则创建一个新的子节点。
- 最后,将最后一个字符的
isWord标记为true,表示这是一个完整的单词。
- 从根节点开始,逐个字符遍历
-
search(word):
- 从根节点开始,逐个字符遍历
word。 - 如果在任何字符位置找不到对应的子节点,则返回
false。 - 如果遍历结束并且当前节点的
isWord为true,说明找到了该单词,返回true。
- 从根节点开始,逐个字符遍历
-
startsWith(prefix):
- 从根节点开始,逐个字符遍历
prefix。 - 如果在某个字符位置找不到对应的子节点,则返回
false。 - 如果能够遍历完前缀的所有字符,说明存在以该前缀为开始的单词,返回
true。
- 从根节点开始,逐个字符遍历
相关文章:
【LeetCode】力扣刷题热题100道(31-35题)附源码 搜索二维矩阵 岛屿数量 腐烂的橙子 课程表 实现 Trie (前缀树)(C++)
一、搜索二维矩阵 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性: 每行的元素从左到右升序排列。每列的元素从上到下升序排列。 可以使用 从右上角开始搜索 的方法来有效地找到目标值。 选择起始位置: 从矩…...
react使用react-redux状态管理
1、安装 npm install react-redux2、创建store.js import { createStore } from redux;// 定义初始状态 const initialState {counter: 888 };// 定义 reducer 函数,根据 action 类型更新状态 function reducer(state initialState, action) {switch (action.ty…...
04_角色创建窗口
将上文的登录窗口隐藏 创建空节点 作为创建角色窗口 命名为CreateWnd 创建输入的名字的输入框 再创建一个按钮用来随机角色名字 创建开始游戏按钮 End....
Dockerfile -> Docker image -> Docker container
1. Dockfile -> Docker image docker build -t shuai_image -f xxx/xxx/Dockerfile . (.不能少)出现: [] Building xxx(10/17) > [internal] load build definition from Dockerfile > > transferring dockerfile: … > > transferring context …...
LDN的蓝牙双模键盘帮助文档
文档索引 已支持的PCB列表(仅列出少部分):键盘特性硬件软件键盘以及驱动蓝牙模式USB模式 驱动功能介绍主界面键盘列表页面键盘配置(使用双模键盘的请务必细看本说明)功能层配置(改键)触发层配置(改FN键等触发功能)功能选择(重要&a…...
搭建一个基于Spring Boot的驾校管理系统
搭建一个基于Spring Boot的驾校管理系统可以涵盖多个功能模块,例如学员管理、教练管理、课程管理、考试管理、车辆管理等。以下是一个简化的步骤指南,帮助你快速搭建一个基础的系统。 1. 项目初始化 使用 Spring Initializr 生成一个Spring Boot项目&am…...
运动相机拍视频过程中摔了,导致录视频打不开怎么办
3-11 在使用运动相机拍摄激烈运动的时候,极大的震动会有一定概率使得保存在存储卡中的视频出现打不开的情况,原因是存储卡和相机在极端情况下,可能会出现接触不良的问题,如果遇到这种问题,就不得不进行视频修复了。 本…...
MongoDB vs Redis:相似与区别
前言 在当今的数据库领域,MongoDB 和 Redis 都是备受关注的非关系型数据库(NoSQL),它们各自具有独特的优势和适用场景。本文将深入探讨 MongoDB 和 Redis 的特点,并详细对比它们之间的相似之处和区别,帮助…...
数字图像处理:实验二
任务一: 将不同像素(32、64和256)的原图像放大为像素大 小为1024*1024的图像(图像自选) 要求:1)输出一幅图,该图包含六幅子图,第一排是原图,第 二排是对应放大…...
基于海思soc的智能产品开发(高、中、低soc、以及和fpga的搭配)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 市场上关于图像、音频的soc其实非常多,这里面有高、中、低档,开发方式也不相同。之所以会这样,有价格的因素&am…...
SSM旅游信息管理系统
🍅点赞收藏关注 → 添加文档最下方联系方式可咨询本源代码、数据库🍅 本人在Java毕业设计领域有多年的经验,陆续会更新更多优质的Java实战项目希望你能有所收获,少走一些弯路。🍅关注我不迷路🍅 项目视频 …...
FastADMIN实现网站启动时执行程序的方法
FastAdmin基于ThinkPHP框架:ThinkPHP框架中与 Application_Start 类似的功能可以在应用初始化钩子(Hook)中实现。在FastAdmin项目中,一般在应用的 common.php 文件中定义行为(Behavior)来实现类似功能。 定…...
【威联通】FTP服务提示:服务器回应不可路由的地址。被动模式失败。
FTP服务器提示:服务器回应不可路由的地址。被动模式失败。 问题原因网络结构安全管理配置服务器配置网关 问题 FTP服务器提示:服务器回应不可路由的地址…...
nginx常用配置 (含负载均衡、反向代理、限流、Gzip压缩、图片防盗链 等示例)
nginx的配置文件通常在 /etc/nginx/nginx.conf , /etc/nginx/conf.d/*.conf 中, 一般直接 改 conf.d目录下的 default.conf文件, 然后 先检测配置文件是否有错误 nginx -t 再重新加载配置文件 或 重启nginx,命令如下 nginx -s reload 或…...
21.1、网络设备安全概述
目录 网络设备安全概况——交换机、路由器安全威胁 网络设备安全概况——交换机、路由器安全威胁 第一个是MAC地址泛洪,MAC地址表记录着交换机拥有的MAC地址跟端口的对应关系 MAC地址表主要是三个字段,MAC地址对应的端口号,也就表示主机是连…...
通过idea创建的springmvc工程需要的配置
在创建的spring mvc工程中,使用idea开发之前需要配置文件包括porm.xml、web.xml、springmvc.xml 1、porm.xml 工程以来的spring库,主要包括spring-aop、spring-web、spring-webmvc,示例配置如下: <project xmlns"http:/…...
Redis 持久化机制:RDB 和 AOF
Redis 持久化机制:RDB 和 AOF Redis 主要提供了两种持久化方式:**RDB(Redis Database)**和 AOF(Append-Only File)。它们各自的实现原理、优缺点以及适用场景如下。 1. RDB(Redis Database&…...
【博客之星评选】2024年度前端学习总结
故事的开端...始于2024年第一篇前端技术博客 那故事的终末...也该结束于陪伴了我一整年的前端知识了 踏入 2025 年,满心激动与自豪,我成功闯进了《2024 年度 CSDN 博客之星总评选》的 TOP300。作为一名刚接触技术写作不久的萌新,这次能走到这…...
将IDLE里面python环境pyqt5配置的vscode
首先安装pyqt5全套:pip install pyqt5-tools 打开Vscode: 安装第三方扩展:PYQT Integration 成功配置designer.exe的路径【个人安装pyqt5的执行路径】,便可直接打开UI文件,进行编辑。 配置pyuic,如果下图填写方法使用…...
【专题三:穷举vs暴搜vs深搜vs回溯vs剪枝】46. 全排列
1.题目解析 2.讲解算法原理 1.首先画出决策树,越详细越好 2.设计代码 全局变量 List<List<Integer>> retList<Integer> pathboolean[] check dfs函数 仅关心某一节点在干什么 细节问题回溯 干掉path最后一个元素修改check权限 剪枝 check中为…...
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...
