当前位置: 首页 > news >正文

【LeetCode】力扣刷题热题100道(31-35题)附源码 搜索二维矩阵 岛屿数量 腐烂的橙子 课程表 实现 Trie (前缀树)(C++)

一、搜索二维矩阵

编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:

  • 每行的元素从左到右升序排列。
  • 每列的元素从上到下升序排列。

可以使用 从右上角开始搜索 的方法来有效地找到目标值。

  1. 选择起始位置: 从矩阵的右上角开始。假设我们当前的位置是 matrix[0][n-1],其中 n 是列数。
  2. 逐步搜索:
    • 如果当前元素等于目标值,返回 true
    • 如果当前元素大于目标值,说明目标值可能出现在当前元素的左边,因此我们向左移动一列。
    • 如果当前元素小于目标值,说明目标值可能出现在当前元素的下方,因此我们向下移动一行。
  3. 结束条件: 如果超出了矩阵的边界,说明没有找到目标值,返回 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
    • 否则,返回所需的分钟数。

四、课程表

你这个学期必须选修 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
    • 如果遍历结束并且当前节点的 isWordtrue,说明找到了该单词,返回 true
  • startsWith(prefix)

    • 从根节点开始,逐个字符遍历 prefix
    • 如果在某个字符位置找不到对应的子节点,则返回 false
    • 如果能够遍历完前缀的所有字符,说明存在以该前缀为开始的单词,返回 true

相关文章:

【LeetCode】力扣刷题热题100道(31-35题)附源码 搜索二维矩阵 岛屿数量 腐烂的橙子 课程表 实现 Trie (前缀树)(C++)

一、搜索二维矩阵 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。每列的元素从上到下升序排列。 可以使用 从右上角开始搜索 的方法来有效地找到目标值。 选择起始位置&#xff1a; 从矩…...

react使用react-redux状态管理

1、安装 npm install react-redux2、创建store.js import { createStore } from redux;// 定义初始状态 const initialState {counter: 888 };// 定义 reducer 函数&#xff0c;根据 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 . (.不能少)出现&#xff1a; [] Building xxx(10/17) > [internal] load build definition from Dockerfile > > transferring dockerfile: … > > transferring context …...

LDN的蓝牙双模键盘帮助文档

文档索引 已支持的PCB列表(仅列出少部分)&#xff1a;键盘特性硬件软件键盘以及驱动蓝牙模式USB模式 驱动功能介绍主界面键盘列表页面键盘配置&#xff08;使用双模键盘的请务必细看本说明&#xff09;功能层配置(改键)触发层配置(改FN键等触发功能)功能选择&#xff08;重要&a…...

搭建一个基于Spring Boot的驾校管理系统

搭建一个基于Spring Boot的驾校管理系统可以涵盖多个功能模块&#xff0c;例如学员管理、教练管理、课程管理、考试管理、车辆管理等。以下是一个简化的步骤指南&#xff0c;帮助你快速搭建一个基础的系统。 1. 项目初始化 使用 Spring Initializr 生成一个Spring Boot项目&am…...

运动相机拍视频过程中摔了,导致录视频打不开怎么办

3-11 在使用运动相机拍摄激烈运动的时候&#xff0c;极大的震动会有一定概率使得保存在存储卡中的视频出现打不开的情况&#xff0c;原因是存储卡和相机在极端情况下&#xff0c;可能会出现接触不良的问题&#xff0c;如果遇到这种问题&#xff0c;就不得不进行视频修复了。 本…...

MongoDB vs Redis:相似与区别

前言 在当今的数据库领域&#xff0c;MongoDB 和 Redis 都是备受关注的非关系型数据库&#xff08;NoSQL&#xff09;&#xff0c;它们各自具有独特的优势和适用场景。本文将深入探讨 MongoDB 和 Redis 的特点&#xff0c;并详细对比它们之间的相似之处和区别&#xff0c;帮助…...

数字图像处理:实验二

任务一&#xff1a; 将不同像素&#xff08;32、64和256&#xff09;的原图像放大为像素大 小为1024*1024的图像&#xff08;图像自选&#xff09; 要求&#xff1a;1&#xff09;输出一幅图&#xff0c;该图包含六幅子图&#xff0c;第一排是原图&#xff0c;第 二排是对应放大…...

基于海思soc的智能产品开发(高、中、低soc、以及和fpga的搭配)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 市场上关于图像、音频的soc其实非常多&#xff0c;这里面有高、中、低档&#xff0c;开发方式也不相同。之所以会这样&#xff0c;有价格的因素&am…...

SSM旅游信息管理系统

&#x1f345;点赞收藏关注 → 添加文档最下方联系方式可咨询本源代码、数据库&#x1f345; 本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目希望你能有所收获&#xff0c;少走一些弯路。&#x1f345;关注我不迷路&#x1f345; 项目视频 …...

FastADMIN实现网站启动时执行程序的方法

FastAdmin基于ThinkPHP框架&#xff1a;ThinkPHP框架中与 Application_Start 类似的功能可以在应用初始化钩子&#xff08;Hook&#xff09;中实现。在FastAdmin项目中&#xff0c;一般在应用的 common.php 文件中定义行为&#xff08;Behavior&#xff09;来实现类似功能。 定…...

【威联通】FTP服务提示:服务器回应不可路由的地址。被动模式失败。

FTP服务器提示&#xff1a;服务器回应不可路由的地址。被动模式失败。 问题原因网络结构安全管理配置服务器配置网关![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/1500d9c0801247ec8c89db7a44907e4f.png) 问题 FTP服务器提示&#xff1a;服务器回应不可路由的地址…...

nginx常用配置 (含负载均衡、反向代理、限流、Gzip压缩、图片防盗链 等示例)

nginx的配置文件通常在 /etc/nginx/nginx.conf , /etc/nginx/conf.d/*.conf 中&#xff0c; 一般直接 改 conf.d目录下的 default.conf文件&#xff0c; 然后 先检测配置文件是否有错误 nginx -t 再重新加载配置文件 或 重启nginx&#xff0c;命令如下 nginx -s reload 或…...

21.1、网络设备安全概述

目录 网络设备安全概况——交换机、路由器安全威胁 网络设备安全概况——交换机、路由器安全威胁 第一个是MAC地址泛洪&#xff0c;MAC地址表记录着交换机拥有的MAC地址跟端口的对应关系 MAC地址表主要是三个字段&#xff0c;MAC地址对应的端口号&#xff0c;也就表示主机是连…...

通过idea创建的springmvc工程需要的配置

在创建的spring mvc工程中&#xff0c;使用idea开发之前需要配置文件包括porm.xml、web.xml、springmvc.xml 1、porm.xml 工程以来的spring库&#xff0c;主要包括spring-aop、spring-web、spring-webmvc&#xff0c;示例配置如下&#xff1a; <project xmlns"http:/…...

Redis 持久化机制:RDB 和 AOF

Redis 持久化机制&#xff1a;RDB 和 AOF Redis 主要提供了两种持久化方式&#xff1a;**RDB&#xff08;Redis Database&#xff09;**和 AOF&#xff08;Append-Only File&#xff09;。它们各自的实现原理、优缺点以及适用场景如下。 1. RDB&#xff08;Redis Database&…...

【博客之星评选】2024年度前端学习总结

故事的开端...始于2024年第一篇前端技术博客 那故事的终末...也该结束于陪伴了我一整年的前端知识了 踏入 2025 年&#xff0c;满心激动与自豪&#xff0c;我成功闯进了《2024 年度 CSDN 博客之星总评选》的 TOP300。作为一名刚接触技术写作不久的萌新&#xff0c;这次能走到这…...

将IDLE里面python环境pyqt5配置的vscode

首先安装pyqt5全套&#xff1a;pip install pyqt5-tools 打开Vscode&#xff1a; 安装第三方扩展&#xff1a;PYQT Integration 成功配置designer.exe的路径【个人安装pyqt5的执行路径】&#xff0c;便可直接打开UI文件&#xff0c;进行编辑。 配置pyuic,如果下图填写方法使用…...

【专题三:穷举vs暴搜vs深搜vs回溯vs剪枝】46. 全排列

1.题目解析 2.讲解算法原理 1.首先画出决策树&#xff0c;越详细越好 2.设计代码 全局变量 List<List<Integer>> retList<Integer> pathboolean[] check dfs函数 仅关心某一节点在干什么 细节问题回溯 干掉path最后一个元素修改check权限 剪枝 check中为…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

pam_env.so模块配置解析

在PAM&#xff08;Pluggable Authentication Modules&#xff09;配置中&#xff0c; /etc/pam.d/su 文件相关配置含义如下&#xff1a; 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块&#xff0c;负责验证用户身份&am…...

蓝桥杯 2024 15届国赛 A组 儿童节快乐

P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡&#xff0c;轻快的音乐在耳边持续回荡&#xff0c;小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下&#xff0c;六一来了。 今天是六一儿童节&#xff0c;小蓝老师为了让大家在节…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

【Go语言基础【13】】函数、闭包、方法

文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数&#xff08;函数作为参数、返回值&#xff09; 三、匿名函数与闭包1. 匿名函数&#xff08;Lambda函…...

嵌入式学习笔记DAY33(网络编程——TCP)

一、网络架构 C/S &#xff08;client/server 客户端/服务器&#xff09;&#xff1a;由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序&#xff0c;负责提供用户界面和交互逻辑 &#xff0c;接收用户输入&#xff0c;向服务器发送请求&#xff0c;并展示服务…...