dfs专题四:综合练习
key:画出决策树(就是找个简单例子模拟一下的树状决策图)
dfs传参 or 全局变量:
- int, double等常量/比较小的变量,可以dfs参数传递
- vector等线性O(N)变量,要用全局变量 + 回溯, 降低时间&空间复杂度
dfs主要用途:
- 全排列
- 求子集
- 路径枚举
1.找出所有子集的异或综合再求和
link:1863. 找出所有子集的异或总和再求和 - 力扣(LeetCode)
就是求子集
code
class Solution {
public:int ret = 0;int cur = 0;int subsetXORSum(vector<int>& nums) {dfs(nums, 0);return ret;}void dfs(vector<int>& nums, int idx)//对idx下标选择取舍{// 出口if(idx >= nums.size()){printf("ret = %d\n", ret);ret += cur;return;}// 主题// 不要dfs(nums, idx + 1);// 要cur ^= nums[idx];dfs(nums, idx + 1);cur ^= nums[idx]; // 回溯}
};
2.全排列II
link:47. 全排列 II - 力扣(LeetCode)
不重复全排列
code
class Solution {
public:vector<vector<int>> ans;vector<int> cur;vector<bool> used;vector<vector<int>> permuteUnique(vector<int>& nums) {sort(nums.begin(), nums.end());used = vector<bool>(nums.size(), false);dfs(nums, 0);return ans;}void dfs(vector<int>& nums, int idx)// 选择第idx下标元素{// 出口if(idx >= nums.size()) {ans.push_back(cur);return;}// 主体for(int i = 0; i < nums.size(); i++){if(!used[i] && (i == 0 || !used[i-1] || nums[i] != nums[i-1])){cur.push_back(nums[i]);used[i] = true;dfs(nums, idx + 1);used[i] = false;cur.pop_back(); // 回溯}}}
};
3.电话号码的字母组合
link:17. 电话号码的字母组合 - 力扣(LeetCode)
组合
code
class Solution {
public:vector<string> ans;string cur; // 全局变量unordered_map<char, string> map = {{'2', "abc"}, {'3', "def"},{'4', "ghi"},{'5', "jkl"},{'6', "mno"}, {'7', "pqrs"},{'8', "tuv"},{'9', "wxyz"}};vector<string> letterCombinations(string digits) {if(!digits.size()) return {};dfs(digits, 0);return ans;}void dfs(string& digits, int idx){// 出口if(idx >= digits.size()){ans.push_back(cur);return;}for(char ch:map[digits[idx]]){cur += ch;dfs(digits, idx + 1);cur.pop_back();// 回溯}}
};
4.括号生成
link:22. 括号生成 - 力扣(LeetCode)
有条件全排列
code
class Solution {
public:vector<string> ans = {};string path = "";// 全局变量int sum = 0;// 全局变量int n;vector<string> generateParenthesis(int _n) {// key: '(' = 1, ')' = -1, 令sum属于[0, 3]即可n = _n;dfs(0);return ans;}void dfs(int idx){// 出口if(sum < 0 || sum > n) return;// 剪枝if(idx >= 2 * n){if(sum != 0) return;ans.push_back(path);return;}// 主体// (path += '(';sum += 1;dfs(idx + 1);sum -= 1; // 回溯path.pop_back();// )path += ')';sum += -1;dfs(idx + 1);sum -= -1;path.pop_back(); // 回溯}
};
5.组合
link:77. 组合 - 力扣(LeetCode)
组合
code
class Solution {
public:int n, k;vector<vector<int>> ans;vector<int> path;vector<bool> used;vector<vector<int>> combine(int _n, int _k) {n = _n;k = _k;used = vector<bool>(n, false);dfs();return ans;}void dfs(){// 出口if(path.size() >= k) {ans.push_back(path);return;}// 主体for(int i = 1; i <= n; i++){if(used[i] ) return;// 剪枝 不用continue 保证path有序(倒序path.push_back(i);used[i] = true;dfs();used[i] = false;path.pop_back(); // 回溯}}
};
6.目标和
link:494. 目标和 - 力扣(LeetCode)
满足条件的子集
暴力枚举
code
class Solution {
public:int ans = 0;int path = 0;vector<int> nums;int target;int findTargetSumWays(vector<int>& _nums, int _target) {nums = _nums;target = _target;// 类似子集问题, key为每个元素取舍(+/-)dfs(0);return ans;}void dfs(int idx){// 出口if(idx >= nums.size()){if(path == target) ans++;return;}// body// +path += nums[idx];dfs(idx + 1);path -= nums[idx];// -path += -nums[idx];dfs(idx + 1);path -= -nums[idx];}
};
7.组合总数
link:39. 组合总和 - 力扣(LeetCode)
code
class Solution {
public:vector<vector<int>> ans;vector<int> path;int sum = 0;int target;vector<int> candidates;vector<vector<int>> combinationSum(vector<int>& _candidates, int _target) {candidates = _candidates;target = _target;sort(candidates.begin(), candidates.end());dfs(0);return ans;}void dfs(int bgn)// 只能从[bgn:]中选择下一个, 保证path升序{// 出口if(sum >= target){if(sum == target) ans.push_back(path);return;//剪枝}// bodyfor(int i = bgn; i < candidates.size(); i++){sum += candidates[i];path.push_back(candidates[i]);dfs(i);path.pop_back();sum -= candidates[i];// 回溯}}
};
8.字母大小写全排列
link:784. 字母大小写全排列 - 力扣(LeetCode)
code
class Solution {
public:vector<string> ans;string path;vector<string> letterCasePermutation(string _s) {path = _s;dfs(0);return ans;}void dfs(int idx){// 出口if(idx >= path.size()){ans.push_back(path);return;}// bodychar cp = path[idx];// 大小写转换if(isalpha(path[idx])){path[idx] = toupper(path[idx]);dfs(idx + 1);path[idx] = tolower(path[idx]);dfs(idx + 1);}else dfs(idx + 1);path[idx] = cp;// 回溯}
};
9.优美的排列
link:526. 优美的排列 - 力扣(LeetCode)
求满足条件的全排列的个数,及时剪枝即可
求满足条件的全排列 + 及时剪枝
code
class Solution {
public:int ans = 0;vector<bool> used;int countArrangement(int n) {// 虽然是dfs暴力枚举,但只要及时剪枝, 复杂度就并不高used = vector<bool>(n + 1, false);dfs(1, n);return ans;}void dfs(int idx, int n){// 出口if(idx > n){ans++;return;}// bodyfor(int i = 1; i <= n; i++){if(used[i] || (i % idx != 0 && idx % i != 0)) continue;//剪枝used[i] = true;dfs(idx + 1, n);used[i] = false;// 回溯}}
};
10.N皇后
link:51. N 皇后 - 力扣(LeetCode)
全排列 + 剪枝
code
class Solution {
public:vector<vector<string>> ans;vector<string> path;vector<bool> used;unordered_set<int> set1, set2;vector<vector<string>> solveNQueens(int n) {path = vector<string>(n, string(n, '.'));used = vector<bool>(n, false);dfs(0);return ans;}void dfs(int col){// 出口if(col >= path.size()){ans.push_back(path);return;}// bodyfor(int i = 0; i < path.size(); i++){if(used[i] || !check(col, i)) continue;// 剪枝set(col, i);path[col][i] = 'Q';dfs(col + 1);path[col][i] = '.';reset(col, i);// 回溯}}void set(int col, int row){used[row] = true;set1.insert(col+row);set2.insert(col-row);}void reset(int col, int row){used[row] = false;set1.erase(col+row);set2.erase(col-row);}bool check(int col, int row){return (!set1.count(col + row)) && (!set2.count(col - row));}
};
11.有效的数独
link:36. 有效的数独 - 力扣(LeetCode)
和dfs没什么关系, 就是模拟题, 为下题做铺垫
code
class Solution {
public:bool isValidSudoku(vector<vector<char>>& board) {// rows检查for(vector<char> vc:board){if(repeat(vc)) return false;}// cols检查for(int col = 0; col < 9; col++){vector<char> tmp = {};for(int row = 0; row < 9; row++){tmp.push_back(board[row][col]);}if(repeat(tmp)) return false;}// 方块检查for(int row = 0; row < 9; row+=3)for(int col = 0; col < 9; col+=3){vector<char> tmp = {};for(int r = 0; r < 3; r++)for(int c = 0; c < 3; c++){tmp.push_back(board[row+r][col+c]);}if(repeat(tmp)) return false;}return true;}bool repeat(vector<char>& nums){vector<bool> used(10, false);for(char ch:nums){if(ch == '.') continue;if(used[ch-'0']) return true;used[ch-'0'] = true;}return false;}
};
12.解数独
Link:37. 解数独 - 力扣(LeetCode)
全排列 + 剪枝
code
class Solution {
public:vector<vector<char>> board;bool row[9][10];bool col[9][10];bool grid[3][3][10];void set(int r, int c, int num){row[r][num] = true;col[c][num] = true;grid[r / 3][c / 3][num] = true;}void reset(int r, int c, int num){row[r][num] = false;col[c][num] = false;grid[r / 3][c / 3][num] = false;}bool check(int r, int c, int num){return (!row[r][num]) && (!col[c][num]) && (!grid[r / 3][c / 3][num]);}void solveSudoku(vector<vector<char>>& _board) {memset(row, false, sizeof row);memset(col, false, sizeof col);memset(grid, false, sizeof grid);// 录入已有信息board = _board;for(int i = 0; i < 9; i++)for(int j = 0; j < 9; j++){if(board[i][j] == '.') continue;set(i, j, board[i][j] - '0');}if(!dfs()) printf("error!! 未找到\n");_board = board;}bool dfs(){for(int i = 0; i < 9; i++)for(int j = 0; j < 9; j++){if(board[i][j] != '.') continue;for(int num = 1; num <= 9; num++){if(check(i, j, num))// 剪枝{set(i, j, num);board[i][j] = num + '0';if(dfs()) return true;// 及时返回board[i][j] = '.';reset(i, j, num);// 回溯}}return false;// 剪枝}return true;}};
13.单词搜索
link:79. 单词搜索 - 力扣(LeetCode)
dfs枚举 + 剪枝
注意dfs(i, j, idx)作用:再board[i][j]旁边找word[idx]
每次使用dfs前后都要set/reset
code
class Solution {
public:vector<vector<char>> board; string word;vector<vector<bool>> used;vector<pair<int, int>> add = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};bool exist(vector<vector<char>>& _board, string _word) {board = _board;word = _word;used = vector<vector<bool>> (board.size(), vector<bool>(board[0].size(), false));for(int i = 0; i <board.size(); i++){for(int j = 0; j < board[0].size(); j++){if(board[i][j] != word[0]) continue;used[i][j] = true;if(dfs(i, j, 1)) return true;used[i][j] = false;}}return false;}bool dfs(int row, int col, int idx){// 出口if(idx == word.size()) return true;// bodyfor(auto[addx, addy] : add){auto[x, y] =make_pair(row + addx, col + addy);if(x < 0 || x >= board.size() || y < 0 || y >= board[0].size() || used[x][y] || board[x][y] != word[idx]) continue;used[x][y] = true;if(dfs(x, y, idx + 1)) return true;// 及时上传trueused[x][y] = false;// 回溯}return false;}
};
14.黄金矿工
link:1219. 黄金矿工 - 力扣(LeetCode)
dfs枚举
code
class Solution {
public:int ans = 0;int path = 0;int getMaximumGold(vector<vector<int>>& grid) {for(int i = 0; i < grid.size(); i++)for(int j = 0; j < grid[0].size(); j++){if(grid[i][j] == 0) continue;int cp = grid[i][j];path += cp;grid[i][j] = 0;dfs(i, j, grid);grid[i][j] = cp;path -= cp;}return ans;}vector<int> dx = {0, 0, 1, -1};vector<int> dy = {1, -1, 0, 0};void dfs(int row, int col, vector<vector<int>>& grid){ ans = max(ans, path);// 每次更新// bodyfor(int i = 0; i < 4; i++){int x = row + dx[i], y = col + dy[i];if(x < 0 || x >= grid.size() || y < 0 || y >= grid[0].size() ||grid[x][y] == 0) continue;// 及时判断int cp = grid[x][y];grid[x][y] = 0;path += cp;dfs(x, y, grid);path -= cp;grid[x][y] = cp; // 回溯}}
};
15.不同路径III
link:980. 不同路径 III - 力扣(LeetCode)
dfs枚举
code
class Solution {
public:int ans = 0;int path = 0;// 已经走过的格子数int m, n;int cnt = 0;// -1个数vector<vector<bool>> used;int uniquePathsIII(vector<vector<int>>& grid) {m = grid.size();n = grid[0].size();used = vector<vector<bool>>(m, vector<bool>(n, false));int x = 0, y = 0;for(int i = 0; i < m; i++)for(int j = 0; j < n; j++){cnt += (grid[i][j] == -1);if(grid[i][j] == 1){x = i;y = j;}}used[x][y] = true;path += 1;dfs(x, y, grid);path -= 1;used[x][y] = false;return ans;}vector<int> dx = {0, 0, 1, -1};vector<int> dy = {1, -1, 0, 0};void dfs(int row, int col, vector<vector<int>>& grid){// 出口if(grid[row][col] == 2){if(path == m * n - cnt) ans++;return;}// bodyfor(int i = 0; i < 4; i++){int x = row + dx[i], y = col + dy[i];if(x < 0 || x >= m || y < 0 || y >= n || used[x][y] || grid[x][y] == -1) continue;// 剪枝used[x][y] = true;path += 1;dfs(x, y, grid);path -= 1;used[x][y] = false;// 回溯}}
};
相关文章:
dfs专题四:综合练习
key:画出决策树(就是找个简单例子模拟一下的树状决策图) dfs传参 or 全局变量: int, double等常量/比较小的变量,可以dfs参数传递vector等线性O(N)变量,要用全局变量 回溯&#x…...

【线性代数】列主元法求矩阵的逆
列主元方法是一种用于求解矩阵逆的数值方法,特别适用于在计算机上实现。其基本思想是通过高斯消元法将矩阵转换为上三角矩阵,然后通过回代求解矩阵的逆。以下是列主元方法求解矩阵 A A A 的逆的步骤: [精确算法] 列主元高斯消元法 步骤 1&am…...
大写——蓝桥杯
1.题目描述 给定一个只包含大写字母和小写字母的字符串,请将其中所有的小写字母转换成大写字母后将字符串输出。 输入描述 输入一行包含一个字符串。 输出描述 输出转换成大写后的字符串。 输入输出样例 示例 输入 LanQiao输出 LANQIAO评测用例规模与约定 对…...
HTML `<head>` 元素详解
在 HTML 文档中,<head> 元素是一个非常重要的部分,它包含了文档的元数据(metadata)和其他与文档相关的信息。虽然 <head> 中的内容不会直接显示在网页上,但它对网页的行为、样式和搜索引擎优化(…...

一文速通stack和queue的理解与使用
CSTL之stack和queue 1.stack1.1.stack的基本概念1.2.stack的接口 2.queue2.1.queue的基本概念2.2.queue的接口 3.priority_queue3.1.priority_queue的基本概念3.2.priority_queue的接口3.3.仿函数 4.容器适配器5.deque5.1.deque的简单了解5.2.deque的优缺点 🌟&…...

Antd React Form使用Radio嵌套多个Select和Input的处理
使用Antd React Form使用Radio会遇到嵌套多个Select和Input的处理,需要多层嵌套和处理默认事件和冒泡,具体实现过程直接上代码。 实现效果布局如下图 代码 <Formname"basic"form{form}labelWrap{...formItemLayoutSpan(5, 19)}onFinish{on…...
Vue - toRefs() 和 toRef() 的使用
一、toRefs() 在 Vue 3 中,toRefs()可以将响应式对象的属性转换为可响应的 refs。主要用于在解构响应式对象时,保持属性的响应性。 1. 导入 toRefs 函数 import { toRefs } from vue;2. 将响应式对象的属性转换为 ref const state reactive({count: 0,message:…...

Python3 OS模块中的文件/目录方法说明九
一. 简介 前面文章简单学习了 Python3 中 OS模块中的文件/目录的部分函数。 本文继续来学习 OS 模块中文件、目录的操作方法:os.pipe() 方法、os.popen() 方法。 二. Python3 OS模块中的文件/目录方法 1. os.pipe() 方法 os.pipe() 方法用于创建一个管道, 返回…...

OpenCV文字绘制支持中文显示
OpenCV版本:4.4 IDE:VS2019 功能描述 OpenCV绘制文本的函数putText()不支持中文的显示,网上很多方法推荐的都是使用FreeType来支持,FreeType是什么呢?FreeType的官网上有介绍 FreeType官网 https://www.freetype.or…...

opengrok_windows_多工程环境搭建
目录 多工程的目录 工程代码下载和log配置 工程的索引 工程部署 工程测试 参考列表 多工程的目录 工程代码下载和log配置 工程代码下载 在每个工程的src目录下,下载工程代码,以下载pulseaudio的代码为例。 git clone gitgithub.com…...

基于ollama,langchain,springboot从零搭建知识库三【解析文档并存储到向量数据库】
安装环境 安装pgvector,先设置docker镜像源: vim /etc/docker/daemon.json {"registry-mirrors": ["https://05f073ad3c0010ea0f4bc00b7105ec20.mirror.swr.myhuaweicloud.com","https://mirror.ccs.tencentyun.com",&…...

Elasticsearch 和arkime 安装
安装一定要注意版本号,不然使用不了 这里Ubuntu使用ubuntu-20.04.6-desktop-amd64.iso elasticsearch这里使用Elasticsearch 7.17.5 | Elastic arkime这里使用wget https://s3.amazonaws.com/files.molo.ch/builds/ubuntu-20.04/arkime_3.4.2-1_amd64.deb 大家想…...
git回退
git回退 1、未使用 git add 缓存代码时 git checkout –- filepathname 放弃单个文件的修改 git checkout . 放弃所有的文件修改 此命令用来放弃掉所有还没有加入到缓存区(就是 git add 命令)的修改:内容修改与整个文件删除。但是此命令不…...

pytest+playwright落地实战大纲
前言 很久没有更新博客,是因为在梳理制作Playwright测试框架实战相关的课程内容。现在课程已经完结,开个帖子介绍下这门课程(硬广, o(〃^▽^〃)o) 课程放在CSDN学习频道, 欢迎关注~ PyTestPl…...

01-硬件入门学习/嵌入式教程-CH340C使用教程
前言 CH340C广泛应用于DIY项目和嵌入式开发中,用于USB数据转换和串口通信。本文将详细介绍CH340C的基本功能、引脚接线及使用方法。 CH340C简介 CH340C是一款USB转TTL电平转换器,可以将电脑的USB数据转换成串口数据,方便与单片机ÿ…...

小试牛刀调整Prompt,优化Token消耗
在上一篇文章 荒腔走板Mac电脑本地部署 LLM 中介绍过本地部署大模型之后,可以通过定制 prompt 来实现 domain 提取等各种各样的需求。 但是实际上,部署本地大模型 这种方式对于个人开发者来说实在是不太友好。一方面需要投入大量资金确保设备的算力足够支…...

snippets router pinia axios mock
文章目录 补充VS Code 代码片段注册自定义组件vue routerpinia删除vite创建项目时默认的文件axiosmock3.0.x版本的 viteMockServe 补充 为文章做补充:https://blog.csdn.net/yavlgloss/article/details/140063387 VS Code 代码片段 为当前项目创建 Snippets {&quo…...

Visual Studio2019调试DLL
1、编写好DLL代码之后,对DLL项目的属性进行设置,选择待注入的DLL,如下图所示 2、生成DLL文件 3、将DLL设置为启动项目之后,按F5启动调试。弹出选择注入的exe的界面之后,使用代码注入器注入步骤2中生成的dll࿰…...

深入解析:Docker 容器如何实现文件系统与资源的多维隔离?
目录 一、RootFs1. Docker 镜像与文件系统层2. RootFs 与容器隔离的意义 二、Linux Namespace1. 进程命名空间1.1 lsns 命令说明1.2 查看“祖先进程”命名空间1.3 查看当前用户进程命名空间 2. 容器进程命名空间2.1 查看容器进程命名空间列表2.2 容器进程命名空间的具体体现 三…...
vue项目中打包后的地址加载不出图片【五种解决方案】
在 Vue 项目中打包后,加载图片路径可能会出现问题,主要是因为打包后的路径与开发时的路径不同。为了确保图片可以正确加载,你可以考虑以下几种方法: 1. 使用 require 或 import 动态加载图片 如果你在 Vue 的模板或者脚本中引用…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...

【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...

Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...