图论回溯

news2025/6/2 20:13:00

图论

200.岛屿数量DFS

给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。此外,你可以假设该网格的四条边均被水包围。

深度优先遍历:用一个visited数组标记所有访问过的地方,遍历图,遇到第一个陆地且没被访问过,就用深搜遍历此岛屿的全部陆地。

class Solution {
private:
    int dir[4][2] = {0, 1, 1, 0, -1, 0, 0, -1};
    void dfs(vector<vector<bool>>& visit, vector<vector<char>>& grid, int x, int y){
        for(int i = 0; i < 4; i++) {
            int nextx = x + dir[i][0];
            int nexty = y + dir[i][1];
            if(nextx < 0 || nextx >= grid.size() || nexty < 0 || nexty >= grid[0].size()) continue;
            if(!visit[nextx][nexty] && grid[nextx][nexty] == '1') {
                visit[nextx][nexty] = true;
                dfs(visit, grid, nextx, nexty);
            }
        }
    }
public:
    int numIslands(vector<vector<char>>& grid) {
        int n = grid.size(), m = grid[0].size();
        vector<vector<bool>> visit = vector<vector<bool>>(n, vector<bool>(m, false));

        int result = 0;
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                if(!visit[i][j] && grid[i][j] == '1') {
                    result++;
                    visit[i][j] = true;
                    dfs(visit, grid, i, j);
                }
            }
        }
        return result;
    }
};

994.腐烂的橘子BFS

在给定的 m x n 网格 grid 中,每个单元格可以有以下三个值之一:
值 0 代表空单元格;
值 1 代表新鲜橘子;
值 2 代表腐烂的橘子。
每分钟,腐烂的橘子 周围 4 个方向上相邻 的新鲜橘子都会腐烂。
返回 直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回 -1 。

class Solution {
public:
    int orangesRotting(vector<vector<int>>& grid) {
        int n = grid.size(), m = grid[0].size();
        queue<pair<int, int>> q;
        int fresh = 0;
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                if(grid[i][j] == 2) {
                    q.push({i,j});
                }
                else if(grid[i][j] == 1) {
                    fresh++;
                }
            }
        }
        int time = 0;
        int dir[4][2] = {1, 0, 0, 1, -1, 0, 0, -1};
        while(!q.empty() && fresh > 0) {
            int size = q.size();
            while(size--) {
                auto [x, y] = q.front(); q.pop();
                for(int i = 0; i < 4;i++) {
                    int nx = x + dir[i][0];
                    int ny = y + dir[i][1];
                    if(nx < 0 || ny < 0 || nx >= grid.size() || ny >= grid[0].size() || grid[nx][ny] != 1) continue;
                    grid[nx][ny] = 2;
                    q.push({nx,ny});
                    fresh--;
                }

            }
            time++;
        }
        return fresh == 0 ? time : -1;
    }
};

207.课程表

你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1 。
在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai 则 必须 先学习课程 bi 。
例如,先修课程对 [0, 1] 表示:想要学习课程 0 ,你需要先完成课程 1 。
请你判断是否可能完成所有课程的学习?如果可以,返回 true ;否则,返回 false 。

本题可约化为: 课程安排图是否是 有向无环图(DAG)。
方法一:入度表(广度优先遍历)
算法流程:
统计课程安排图中每个节点的入度,生成 入度表 indegrees。
借助一个队列 queue,将所有入度为 0 的节点入队。
当 queue 非空时,依次将队首节点出队,在课程安排图中删除此节点 pre:
并不是真正从邻接表中删除此节点 pre,而是将此节点对应所有邻接节点 cur 的入度 −1,即 indegrees[cur] -= 1。
当入度 −1后邻接节点 cur 的入度为 0,说明 cur 所有的前驱节点已经被 “删除”,此时将 cur 入队。
在每次 pre 出队时,执行 numCourses–;
若整个课程安排图是有向无环图(即可以安排),则所有节点一定都入队并出队过,即完成拓扑排序。换个角度说,若课程安排图中存在环,一定有节点的入度始终不为 0。
因此,拓扑排序出队次数等于课程个数,返回 numCourses == 0 判断课程是否可以成功安排。

class Solution {
public:
    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
        vector<vector<int>> adjacency(numCourses);
        vector<int> indegrees(numCourses, 0);
        queue<int> q;
        for(const auto& pair : prerequisites) {
            int course = pair[0], pre = pair[1];
            indegrees[course]++;
            adjacency[pre].push_back(course);
        }
        for(int i = 0; i < indegrees.size(); i++) {
            if(indegrees[i] == 0) q.push(i);
        }
        while(!q.empty()){
            int pre = q.front(); q.pop();
            numCourses--;
            for(int i = 0; i < adjacency[pre].size(); i++) {
                if(--indegrees[adjacency[pre][i]] == 0)
                q.push(adjacency[pre][i]);
            }
        }
        return numCourses == 0;
    }
};

208.前缀树

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:
    bool isEnd;
    Trie* next[26];
public:
    Trie() {
        isEnd = false;
        memset(next, 0, sizeof(next));
    }
    
    void insert(string word) {
        Trie* node = this;
        for(char ch : word){
            if(node->next[ch - 'a'] == NULL) {
                node->next[ch - 'a'] = new Trie();
            }
            node = node->next[ch - 'a'];
        }
        node->isEnd = true;
    }
    
    bool search(string word) {
        Trie* node = this;
        for(char ch : word) {
            node = node->next[ch - 'a'];
            if(node == NULL) return false;
        }
        return node->isEnd;
    }
    
    bool startsWith(string prefix) {
        Trie* node = this;
        for(char ch : prefix) {
            node = node->next[ch - 'a'];
            if(node == NULL) return false;
        }
        return true;
    }
};

/**
 * Your Trie object will be instanti`ated and called as such:
 * Trie* obj = new Trie();
 * obj->insert(word);
 * bool param_2 = obj->search(word);
 * bool param_3 = obj->startsWith(prefix);
 */

全排列

46. 全排列

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
在这里插入图片描述

class Solution {
private:
    vector<int> path;
    vector<vector<int>> result;
    void backtracking(vector<int> & nums, vector<bool>& used){
        if(path.size() == nums.size()) {
            result.push_back(path);
            return;
        }
        for(int i = 0; i < nums.size(); i++){
            if(used[i] == true) continue;
            path.push_back(nums[i]);
            used[i] = true;
            backtracking(nums, used);
            used[i] = false;
            path.pop_back();
        }
    }
public:
    vector<vector<int>> permute(vector<int>& nums) {
        path.clear();
        result.clear();
        vector<bool> used(nums.size(), false);
        backtracking(nums,used);
        return result;
    }
};

78.子集

给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
在这里插入图片描述
子集问题、组合问题、分割问题可以抽象成树,组合和分割是收集树的叶子结点,而子集是找树的所有结点。

class Solution {
public:
    vector<int> path;
    vector<vector<int>> result;
    void backtracking(vector<int>& nums, int startIndex)  {
        result.push_back(path);
        for(int i = startIndex; i < nums.size(); i++) {
            path.push_back(nums[i]);
            backtracking(nums, i + 1);
            path.pop_back();
        }
    }
    vector<vector<int>> subsets(vector<int>& nums) {
        backtracking(nums, 0);
        return result;
    }
};

17. 电话号码的字母组合

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
在这里插入图片描述

class Solution {
private:
    const string letterMap[10] = {
        "",
        "",
        "abc",
        "def",
        "ghi",
        "jkl",
        "mno",
        "pqrs",
        "tuv",
        "wxyz"
    };
public:
    vector<string> result;
    string s;
    void backtracking(const string& digits, int index) {
        if(digits.size() == index) {
            result.push_back(s);
            return;
        }
        int digit = digits[index] - '0';
        string letter = letterMap[digit];
        for(int i = 0; i < letter.size(); i++){
            s.push_back(letter[i]);
            backtracking(digits, index + 1);
            s.pop_back();
        }
    }
    vector<string> letterCombinations(string digits) {
       s.clear();
       result.clear();
       if(digits.size() == 0)
        return result;
       backtracking(digits, 0);
       return result;
    }
};

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

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

相关文章

RFID测温芯片助力新能源产业安全与能效提升

在“双碳”目标驱动下&#xff0c;新能源产业正经历爆发式增长。无论是电动汽车、储能电站还是风光发电场&#xff0c;设备安全与能效提升始终是行业核心命题。而温度&#xff0c;这个看似普通的物理参数&#xff0c;却成为破解这一命题的关键密码。RFID测温芯片&#xff08;集…

S32K3 工具篇9:如何在无源码情况下灵活调试elf文件

S32K3 工具篇9&#xff1a;如何在无源码情况下灵活调试elf文件 一&#xff0c;文档简介二&#xff0c; 功能实现2.1 代码工具准备2.2 elf修改功能实现&#xff1a;Fun2功能跳过2.2.1 PC越过Fun22.2.2 Fun2替换为nop 2.3 elf修改功能实现&#xff1a;Fun4替换Fun2入口2.3.1 link…

Nacos 配置文件总结

Nacos 配置文件总结 文章目录 Nacos 配置文件总结1 、在 Nacos 服务端添加配置文件1. 启动Nacos Server。2. 新建配置文件。3. 发布配置集后&#xff0c;我们便可以在配置列表中查看相应的配置文件。4. 配置nacos数据库5. 运行 Nacos 容器6. 验证安装结果7. 配置验证 2 、在 Na…

ASP.NET Web Forms框架识别

ASP.NET 支持三种不同的开发模式&#xff1a; Web Pages&#xff08;Web 页面&#xff09;、MVC&#xff08;Model View Controller 模型-视图-控制器&#xff09;、Web Forms&#xff08;Web 窗体&#xff09;&#xff1a; Web Pages 单页面模式MVC 模型-视图-控制器Web Form…

哈工大计统大作业-程序人生

摘 要 本项目以“程序人生-Hellos P2P”为核心&#xff0c;通过编写、预处理、编译、汇编、链接及运行一个简单的Hello程序&#xff0c;系统探讨了计算机系统中程序从代码到进程的全生命周期。实验基于Ubuntu环境&#xff0c;使用GCC工具链完成代码转换&#xff0c;分析了预处…

设计模式——装饰器设计模式(结构型)

摘要 文中主要介绍了装饰器设计模式&#xff0c;它是一种结构型设计模式&#xff0c;可在不改变原有类代码的情况下&#xff0c;动态为对象添加额外功能。文中详细阐述了装饰器模式的角色、结构、实现方式、适合场景以及实战示例等内容&#xff0c;还探讨了其与其他设计模式的…

途景VR智拍APP:开启沉浸式VR拍摄体验

在数字化时代&#xff0c;VR技术以其沉浸式的体验逐渐走进了人们的日常生活。途景VR智拍APP作为一款集看图和拍照于一体的VR软件&#xff0c;为用户带来了全新的视觉体验和便捷的拍摄方式&#xff0c;无论是专业摄影师还是普通用户&#xff0c;都能轻松上手&#xff0c;拍出令人…

Linux环境搭建MCU开发环境

操作系统版本&#xff1a; ubuntu 22.04 文本编辑器&#xff1a; vscode 开发板&#xff1a; stm32f103c8t6 调试器&#xff1a; st-link 前言 步骤一&#xff1a; 安装交叉编译工具链 步骤二&#xff1a; 创建工程目录结构 步骤三&#xff1a; 调试…

【基础算法】高精度(加、减、乘、除)

文章目录 什么是高精度1. 高精度加法解题思路代码实现 2. 高精度减法解题思路代码实现 3. 高精度乘法解题思路代码实现 4. 高精度除法 (高精度 / 低精度)解题思路代码实现 什么是高精度 我们平时使用加减乘除的时候都是直接使用 - * / 这些符号&#xff0c;前提是进行运算的数…

Windows最快速打开各项系统设置大全

目录 一、应用背景 二、设置项打开方法 2.1 方法一界面查找&#xff08;最慢&#xff09; 2.2 方法二cmd命令&#xff08;慢&#xff09; 2.3 方法三快捷键&#xff08;快&#xff09; 2.4 方法四搜索栏&#xff08;快&#xff09; 2.5 方法五任务栏&#xff08;最快&am…

嵌入式编译工具链熟悉与游戏移植

在自己的虚拟机Ubuntu系统下&#xff0c;逐步编译 mininim源码(波斯王子重制开源版&#xff09; 指令流程 sudo apt-get remove liballegro5-dev liballegro-image5-dev \liballegro-audio5-dev liballegro-acodec5-dev liballegro-dialog5-dev sudo apt-get install automak…

DeepSeek-R1-0528,官方的端午节特别献礼

DeepSeek&#xff1a;端午安康&#xff01;刻在国人骨子里的浪漫 2025 年 05 月 28 日 | DeepSeek 端午特别献礼 当粽叶飘香时&#xff0c;DeepSeek 悄然带来一份节日惊喜 版本号 DeepSeek-R1-0528 正式上线 官方赋予它的灵魂是&#xff1a; 思考更深 推理更强 用户通过官网…

001 flutter学习的注意事项及前期准备

在学习flutter之前&#xff0c;还需要进行一些初始的配置&#xff0c;然后才可以学习flutter 1.安装flutter 国内官网&#xff1a;https://flutter.cn​​​​​​ 国际官网&#xff1a;https://flutter.dev 安装完成后&#xff0c;按照官网上面的操作步骤进行配置&#xf…

CS144 - Lecture 1 记录

CS144 - Lecture 1 由于没讲义&#xff0c;全看课了&#xff0c;系统性的总结有点难&#xff0c;记一些有趣的东西吧。 数据链路和网络层的传输 我们可以看见&#xff0c;对于发送方&#xff0c;我们的数据链路层为我们的网络层提供服务&#xff0c;在经过路由的时候&#xf…

【数据结构】——二叉树--链式结构

一、实现链式结构二叉树 二叉树的链式结构&#xff0c;那么从名字上我们就知道我们这个二叉树的底层是使用链表来实现的&#xff0c;前面我们的二叉树是通过数组来实现的&#xff0c;那么在其是完全二叉树的情况下&#xff0c;此时我们使用数组来实现就会使得其空间浪费较少&a…

充电便捷,新能源汽车移动充电服务如何预约充电

随着新能源汽车的普及&#xff0c;充电便捷性成为影响用户体验的关键因素之一。传统的固定充电桩受限于地理位置和数量&#xff0c;难以完全满足用户需求&#xff0c;而移动充电服务的出现&#xff0c;为车主提供了更加灵活的补能方式。通过手机APP、小程序或在线平台&#xff…

基于 Chrome 浏览器扩展的Chroma简易图形化界面

简介 ChromaDB Manager 是基于 Chrome 浏览器扩展的一款 ChromaDB&#xff08;一个流行的向量数据库&#xff09;的数据查询工具。提供了一个用户友好的界面&#xff0c;可以直接从浏览器连接到本地 ChromaDB 实例、查看集合信息和分片数据。本工具特别适合开发人员快速查看和…

IM系统的负载均衡

1.IM场景的负载均衡 2.方案总览 SDK层想要连接一个TCP网关或者WebSocket网关的方案 SDK单地址:在SDK中写死某个网关的IP或者域名,缺点是更换地址需要重新打包SDK SDK多地址:防止某一个地址嗝屁了写上多个地址用足保持高可用 暴露接口给客户端:SDK层访问接口动态获得地址 注…

使用 Zabbix 监控 MySQL 存储空间和性能指标的完整实践指南

目录 引言 一、最终目标支持功能 二、监控方案设计 2.1 技术选型 2.2 设计思路 三、实现步骤 3.1 准备工作 3.11 创建 MySQL 监控账号 3.12 配置 .my.cnf 文件 3.2 编写统一脚本 3.3 配置 Zabbix Agent UserParameter 3.4 Zabbix 前端配置建议 四、总结 引言 MySQL …

【技能拾遗】——家庭宽带单线复用布线与配置(移动2025版)

&#x1f4d6; 前言&#xff1a;在家庭网络拓扑中&#xff0c;客厅到弱电箱只预埋了一根网线&#xff0c;由于已将广电的有线电视取消并改用IPTV。现在需要解决在客厅布置路由器和观看IPTV问题&#xff0c;这里就用到单线复用技术。 目录 &#x1f552; 1. 拓扑规划&#x1f55…