DFS:深搜+回溯+剪枝实战解决OJ问题

✨✨✨学习的道路很枯燥,希望我们能并肩走下来!

文章目录

目录

文章目录

前言

一  排列、子集问题

1.1  全排列I

1.2  子集I 

 1.3  找出所有子集的异或总和

1.4  全排列II

1.5  字母大小写全排列

1.6  优美的排列

二  组合问题 

2.1  电话号码的数字组合

 2.2  括号生成

2.3  组合 

2.4  目标和

2.5  组合总和

三  矩阵搜索问题

3.1  N皇后 

3.2  有效的数独

3.3  解数独 

3.4  单词搜素

3.5  黄金矿工

3.6  不同路径III

总结


前言

本篇详细介绍了进一步介绍DFS,让使用者对DFS有更加深刻的认知,而不是仅仅停留在表面,更好的模拟,为了更好的使用. 文章可能出现错误,如有请在评论区指正,让我们一起交流,共同进步!


我们在做DFS的题目时,首先要把决策树(通过策略把结果不重不漏的枚举得到)画下,缕清思路,设计代码自然水到渠成

一  排列、子集问题

1.1  全排列I

46. 全排列 - 力扣(LeetCode)

 

class Solution {vector<vector<int>> ret;vector<int> path;bool check[7];
public:vector<vector<int>> permute(vector<int>& nums) {dfs(nums);return ret;}void dfs(vector<int>& nums){if(path.size() == nums.size()){ret.push_back(path);return;}for(int i = 0;i<nums.size();i++){if(check[i] == false){path.push_back(nums[i]);check[i] = true;dfs(nums);//回溯-> 恢复现场path.pop_back();check[i] = false;}}}
};

1.2  子集I 

78. 子集 - 力扣(LeetCode)

解法一:

class Solution {vector<vector<int>> ret;vector<int> path;
public:vector<vector<int>> subsets(vector<int>& nums) {dfs(nums,0);return ret;}void dfs(vector<int>& nums,int n){if(n == nums.size()){ret.push_back(path);return;}//选path.push_back(nums[n]);dfs(nums,n+1);path.pop_back();//不选dfs(nums,n+1);}
};

解法二:

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

 1.3  找出所有子集的异或总和

1863. 找出所有子集的异或总和再求和 - 力扣(LeetCode)

 

class Solution {int sum;int path;
public:int subsetXORSum(vector<int>& nums) {dfs(nums,0);return sum;}void dfs(vector<int>& nums,int pos){sum += path;for(int i = pos;i<nums.size();i++){path^=nums[i];dfs(nums,i+1);path^=nums[i];       }}
};

1.4  全排列II

47. 全排列 II - 力扣(LeetCode)

 

class Solution {vector<vector<int>> ret;vector<int> path;bool check[9];
public:vector<vector<int>> permuteUnique(vector<int>& nums) {sort(nums.begin(),nums.end());dfs(nums);return ret;}void dfs(vector<int>& nums){if(path.size() == nums.size()){ret.push_back(path);return;}for(int i = 0;i<nums.size();i++){if(check[i] == false && (i==0 || nums[i] != nums[i-1] ||check[i-1] == true)){path.push_back(nums[i]);check[i] = true;dfs(nums);path.pop_back();check[i] = false;}}}
};

1.5  字母大小写全排列

784. 字母大小写全排列 - 力扣(LeetCode)

class Solution {vector<string> ret;string path;
public:vector<string> letterCasePermutation(string s) {dfs(s,0);return ret;}void dfs(string s,int pos){if(pos == s.size()){ret.push_back(path);return;}char ch = s[pos];//不改变path += ch;dfs(s,pos+1);path.pop_back();//改变if(ch<'0' || ch>'9'){char tmp = change(ch);path += tmp;dfs(s,pos+1);path.pop_back();}}char change(char ch){if(ch>='a'&&ch<='z')    ch-=32;else    ch+=32;return ch;}
};

1.6  优美的排列

526. 优美的排列 - 力扣(LeetCode)

class Solution {bool check[16];int ret;
public:int countArrangement(int n) {dfs(n,1);return ret;}void dfs(int n, int pos){if(pos == n+1){ret++;return;}for(int i = 1; i<=n;i++){if(check[i] == false&&(i % pos == 0 || pos % i == 0)){check[i] = true;dfs(n,pos+1);check[i] = false;}}}
};

二  组合问题 

2.1  电话号码的数字组合

17. 电话号码的字母组合 - 力扣(LeetCode)

 

class Solution {string path;vector<string> ret;vector<string> hash = {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
public:vector<string> letterCombinations(string digits) {if(digits.size() == 0)    return ret;dfs(digits,0);return ret;}void dfs(string digits,int pos){if(pos == digits.size()){ret.push_back(path);return;}for(auto& ch : hash[digits[pos] - '0']){path.push_back(ch);dfs(digits,pos+1);path.pop_back();}}
};

 2.2  括号生成

22. 括号生成 - 力扣(LeetCode)

class Solution {vector<string> ret;string path;int count; //记录有效括号的对数
public:vector<string> generateParenthesis(int n) {count = n;dfs(0,0);return ret;}void dfs(int left,int right){if(path.size() == 2*count){ret.push_back(path);return;}if(left<count){path.push_back('(');dfs(left+1,right);path.pop_back();}if(right<left){path.push_back(')');dfs(left,right+1);path.pop_back();}}
};

2.3  组合 

77. 组合 - 力扣(LeetCode)

 

class Solution {vector<vector<int>> ret;vector<int> path;int n, k;
public:vector<vector<int>> combine(int _n, int _k) {n = _n;k = _k;dfs(1);return ret;}void dfs(int pos){if(path.size() == k){ret.push_back(path);return;}for(int i = pos; i<=n; ++i){path.push_back(i);dfs(i+1);path.pop_back();}}
};

2.4  目标和

494. 目标和 - 力扣(LeetCode)

class Solution {int ret;int target;
public:int findTargetSumWays(vector<int>& nums, int _target) {target = _target;dfs(nums,0,0);return ret;}void dfs(vector<int>& nums, int pos, int prev){if(pos == nums.size()){if(prev == target)ret++;return;}dfs(nums,pos+1,prev+nums[pos]);dfs(nums,pos+1,prev-nums[pos]);}
};

2.5  组合总和

39. 组合总和 - 力扣(LeetCode)

解法一:

class Solution {vector<vector<int>> ret;vector<int> path;int target;
public:vector<vector<int>> combinationSum(vector<int>& candidates, int _target) {target = _target;dfs(candidates,0,0);return ret;}void dfs(vector<int>& candidates,int sum, int pos){if(sum>target)  return;if(sum == target){ret.push_back(path);return;}for(int i = pos;i<candidates.size();i++){path.push_back(candidates[i]);dfs(candidates,sum+candidates[i],i);path.pop_back();}}
};

 解法二:

class Solution {vector<vector<int>> ret;vector<int> path;int target;
public:vector<vector<int>> combinationSum(vector<int>& candidates, int _target) {target = _target;dfs(candidates,0,0);return ret;}void dfs(vector<int>& candidates,int sum, int pos){if(sum == target){ret.push_back(path);return;}if(sum>target || pos == candidates.size())  return;for(int k = 0;k*candidates[pos]+sum<=target;k++){if(k)   path.push_back(candidates[pos]);dfs(candidates,sum+k*candidates[pos],pos+1);}for(int k = 1;k*candidates[pos]+sum<=target;k++){path.pop_back();}}
};

三  矩阵搜索问题

3.1  N皇后 

51. N 皇后 - 力扣(LeetCode)

 

class Solution {bool checkCol[10], checkDig1[20], checkDig2[20];vector<vector<string>> ret;vector<string> path;
public:vector<vector<string>> solveNQueens(int n) {path.resize(n);for(int i = 0;i<n;i++)path[i].append(n,'.');dfs(n,0);return ret;}void dfs(int n, int row){if(row == n){ret.push_back(path);return;}for(int col = 0;col<n;col++){if(!checkCol[col]&&!checkDig1[row-col+n]&&!checkDig2[row+col]){path[row][col] = 'Q';checkCol[col] = checkDig1[row-col+n] = checkDig2[row+col] = true;dfs(n,row+1);path[row][col] = '.';checkCol[col] = checkDig1[row-col+n] = checkDig2[row+col] = false;}}}
};

3.2  有效的数独

36. 有效的数独 - 力扣(LeetCode)

class Solution {bool row[9][10];bool col[9][10];bool grid[3][3][10];
public:bool isValidSudoku(vector<vector<char>>& board) {for(int i = 0;i<9;i++){for(int j = 0;j<9;j++){if(board[i][j] != '.'){int num = board[i][j] -'0';if(row[i][num] || col[j][num] || grid[i/3][j/3][num])return false;row[i][num] = col[j][num] = grid[i/3][j/3][num] = true;}}}return true;}
};

3.3  解数独 

37. 解数独 - 力扣(LeetCode)

 

class Solution {bool row[9][10];bool col[9][10];bool grid[3][3][10];
public:void solveSudoku(vector<vector<char>>& board) {for(int i = 0;i<9;i++){for(int j = 0;j<9;j++){if(board[i][j] != '.'){int num = board[i][j] -'0';row[i][num] = col[j][num] = grid[i/3][j/3][num] = true;}}}dfs(board);}bool dfs(vector<vector<char>>& board){for(int i = 0;i<9;i++){for(int j = 0;j<9;j++){if(board[i][j] == '.'){for(int num = 1; num<=9; num++){if(!row[i][num]&&!col[j][num]&&!grid[i/3][j/3][num]){board[i][j] = num + '0';row[i][num] = col[j][num] = grid[i/3][j/3][num] = true;if(dfs(board) == true)  return true;  //判断当前所填的数是否有效board[i][j] = '.';row[i][num] = col[j][num] = grid[i/3][j/3][num] = false;}}return false;  //无法填数时,则说明之前的填的数错误,返回错误}}}return true;}
};

3.4  单词搜素

79. 单词搜索 - 力扣(LeetCode)

 

class Solution {bool vis[7][7];int dx[4] = {0,0,1,-1};int dy[4] = {1,-1,0,0};int m,n;
public:bool exist(vector<vector<char>>& board, string word) {m = board.size(),n = board[0].size();for(int i = 0;i<m;i++){for(int j = 0;j<n;j++){if(board[i][j] == word[0]){vis[i][j] = true;if(dfs(board,word,i,j,1))   return true;vis[i][j] = false;}}}return false;}bool dfs(vector<vector<char>>& board, string word,int i,int j,int pos){if(pos == word.size())  return true;for(int k = 0;k<4;k++){int x = i + dx[k],y = j + dy[k];if(x >=0 && x < m && y >= 0 && y < n && !vis[x][y] && board[x][y] == word[pos]){vis[x][y] = true;if(dfs(board,word,x,y,pos+1))   return true;vis[x][y] = false;}}return false;}
};

3.5  黄金矿工

1219. 黄金矿工 - 力扣(LeetCode)

 本题的算法原理和单词搜索同,只不过多了一两个变量

class Solution {bool vis[16][16];int dx [4] = {0,0,1,-1};int dy [4] = {1,-1,0,0};int m,n,path,ret;
public:int getMaximumGold(vector<vector<int>>& grid) {m = grid.size(),n = grid[0].size();for(int i = 0;i<m;i++){for(int j = 0;j<n;j++){if(grid[i][j] != 0){vis[i][j] = true;dfs(grid,i,j,grid[i][j]);vis[i][j] = false;}}}return ret;}void dfs(vector<vector<int>>& grid,int i,int j,int path){ret = max(ret,path);for(int k = 0; k < 4; k++){int x = i + dx[k], y = j + dy[k];if(x >=0 && x < m && y >= 0 && y < n && !vis[x][y] && grid[x][y] != 0){vis[x][y] = true;dfs(grid,x,y,path+grid[x][y]);vis[x][y] = false;}}}
};

3.6  不同路径III

980. 不同路径 III - 力扣(LeetCode)

 

class Solution {bool vis[21][21];int dx[4] = {0,0,1,-1};int dy[4] = {1,-1,0,0};int m,n,step;int ret;
public:int uniquePathsIII(vector<vector<int>>& grid) {int bx,by;m = grid.size(),n = grid[0].size();for(int i = 0;i<m;i++){for(int j = 0; j < n;j++){if(grid[i][j] == 0)     step++;else if(grid[i][j] == 1){bx = i;by = j;}}}step += 2;vis[bx][by] = true;dfs(grid,bx,by,1);return ret;}void dfs(vector<vector<int>>& grid,int i,int j,int count){if(grid[i][j] == 2){if(count == step) //判断是否合法ret++;return;}for(int k = 0;k < 4;k++){int x = i + dx[k],y = j + dy[k];if(x >=0 && x < m && y >= 0 && y < n && !vis[x][y] && grid[x][y] != -1){vis[x][y] = true;dfs(grid,x,y,count + 1);vis[x][y] = false;}}}
};


总结

✨✨✨各位读友,本篇分享到内容是否更好的让你理解DFS,如果对你有帮助给个👍赞鼓励一下吧!!
🎉🎉🎉世上没有绝望的处境,只有对处境绝望的人。
感谢每一位一起走到这的伙伴,我们可以一起交流进步!!!一起加油吧!!

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

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

相关文章

三菱模拟量入门接线与编程详解

当我们学会完基础后。下面就需要学习模拟量,希望小编的文章对读者有所帮助! 什么是模拟量? 模拟量是指一些连续变化的物理量(简单来说就是连续变化的量),在PLC中通常电压信号为0~10V,电流信号为4~20mA。 为什么要使用模拟量? 当我们需要检测如电压、电流、压力、速度、…

【计网】从零开始使用TCP进行socket编程 --- 客户端与服务端的通信实现

阵雨后放晴的天空中&#xff0c; 出现的彩虹很快便会消失。 而人心中的彩虹却永不会消失。 --- 太宰治 《斜阳》--- 从零开始使用TCP进行socket编程 1 TCP与UDP2 TCP服务器类2.1 TCP基础知识2.2 整体框架设计2.3 初始化接口2.4 循环接收接口与服务接口 3 服务端与客户端测试…

JS落叶动画代码分析

秋天到了&#xff0c;秋高气爽的季节。我们来做一个落叶动画吧&#xff01;来迎接秋天的到来 文字可以更换。 1.目录如下 在线演示&#xff1a;点击我在线演示 images两张照片&#xff0c;首先&#xff0c;你得要准备一个vscode编辑器。和一个chorme浏览器或edge浏览器。 …

PyTorch 激活函数及非线性变换详解

激活函数是深度学习模型的重要组成部分&#xff0c;它们引入非线性&#xff0c;从而使模型能够更好地拟合复杂的数据模式。本文将详细介绍激活函数的作用、常见类型、经典应用示例&#xff0c;并比较它们的优缺点。 激活函数的作用 激活函数的主要作用是引入非线性变换&#…

理解高并发

文章目录 1、如何理解高并发2、高并发的关键指标3、高并发系统设计的目标是什么&#xff1f;1_宏观目标2_微观目标1.性能指标2.可用性指标3.可扩展性指标 4、高并发的实践方案有哪些&#xff1f;1_通用的设计方法1.纵向扩展&#xff08;scale-up&#xff09;2.横向扩展&#xf…

ROS组合导航笔记2:使用外部定位系统

在上一单元中&#xff0c;我们了解了如何合并不同传感器的数据以生成机器人的姿势估计。因此&#xff0c;基本上&#xff0c;我们介绍了图表的以下部分&#xff0c;其中向 robot_localization 节点提供了不同的传感器&#xff0c;以便通过卡尔曼滤波器进行合并。 但是...图表的…

背包问题 总结详解

就是感觉之前 dp 的 blog 太乱了整理一下。 0-1 背包 例题:P1048 朴素算法 思路 对于一个物品&#xff0c;我们可以选&#xff0c;也可以不选。 我们用表示第 i 件物品的重量&#xff0c;表示第 i 件物品的价值。 考虑表示前 i 件物品放入容量为j的背包中的最大价值。 如…

【图像匹配】基于Harris算法的图像匹配,matlab实现

博主简介&#xff1a;matlab图像代码项目合作&#xff08;扣扣&#xff1a;3249726188&#xff09; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 本次案例是基于基于Harris算法的图像匹配&#xff0c;用matlab实现。 一、案例背景和算法介绍 …

Observability:日志管理的最佳实践 - 利用日志更快地解决问题

作者&#xff1a;来自 Elastic Luca Wintergerst•David Hope•Bahubali Shetti 在当今快速发展的软件开发环境中&#xff0c;高效的日志管理对于维护系统可靠性和性能至关重要。随着基础架构和应用程序组件的不断扩展和复杂化&#xff0c;运营和开发团队的职责也不断增加且越来…

yolov8区域入侵检测警报系统-pyside6可视化界面

yolov8区域入侵检测警报系统&#xff0c;是微智启软件工作室基于yolov8目标追踪和pyside6开发&#xff0c;在window的pycharm或者vscode里运行&#xff0c;可以应用于多个领域&#xff0c;检测统计物体个数以及入侵语音警报。 功能介绍 可以应用于 江河流域危险区域禁止游泳警…

利用AI技术提升ISP处理:图像质量的四大关键模块

随着智能手机和数码相机的飞速发展&#xff0c;图像质量成为了影响用户体验的关键因素之一。图像信号处理&#xff08;ISP&#xff0c;Image Signal Processing&#xff09;管道是将图像传感器捕捉到的原始数据转化为高质量输出的核心技术。然而&#xff0c;传统的ISP处理方法在…

螺丝、螺母、垫片等紧固件常用类型详细介绍

螺钉、螺母、垫片等紧固件介绍 螺钉 杯头内六角 首先介绍一下杯头内六角&#xff0c;杯头内六角是我们用的最常见的一种螺钉&#xff0c;如果你对选择螺钉没有什么想法&#xff0c;可以直接无脑选杯头内六角去使用。 比如说我们有一个零件加工了通孔&#xff0c;另一个零件加…

vmware,centos8(虚拟机) 的安装

安装vmware 点击下方网址 虚拟机安装地址https://www1.msc23.cn/vm/?bd_vid8829610582362807097选择VMware17 打开文件所在地&#xff0c;双击安装 同意条款 选择安装位置 不将VMware配置到环境变量path 不检查更新,不加入客户体验 创建桌面快捷方式 开始安装 安装完成…

CSP-J/S 考试介绍

CSP-J/S是由中国计算机学会&#xff08;CCF&#xff09;主办的非专业级别的软件能力认证考试。 CSP-J/S全称为CCF CSP-J/S&#xff0c;是CCF计算机软件能力认证&#xff08;简称CCFCSP认证&#xff09;中的一个部分&#xff0c;重点考察软件开发者实际编程能力。该项认证由CCF…

MTC完成右臂抓取放置任务\\放置姿态设置

#include "mtc_tutorial/mtc_glass_bottle.hpp" static const rclcpp::Logger LOGGER rclcpp::get_logger("mtc_glass_right"); // 获取节点基础接口的实现 rclcpp::node_interfaces::NodeBaseInterface::SharedPtr MTCTaskNode_Right::getNodeBaseInterf…

棋盘格角点检测-libcbdetect

libcbdetect libcbdetect 是一个用于自动子像素级别的棋盘格&#xff08;checkerboard&#xff09;、棋盘&#xff08;chessboard&#xff09;以及 Deltille 图案检测的库。它主要由 C 编写&#xff0c;旨在提供高精度、高鲁棒性的角点检测和图案组合功能&#xff0c;是一种基…

使用HTML和CSS制作网页的全面指南

目录 引言 一、理解HTML 1. 什么是HTML&#xff1f; 2. HTML文档的基本结构 3. 常用的HTML标签 4. 示例&#xff1a;创建一个简单的HTML页面 二、理解CSS 1. 什么是CSS&#xff1f; 2. CSS的使用方式 3. CSS选择器和属性 4. 常用的CSS属性 三、创建网页的步骤 1. 规…

【Java数据结构】二叉树

目录 树树的特征树的概念 二叉树两种特殊的二叉树二叉树的性质二叉树的基本操作4 种遍历二叉树的方式判断一棵树是不是完全二叉树获取二叉树总共的节点个数获取叶子节点的个数获取第 k 层的节点个数获取二叉树的高度检测值为 value 的元素是否存在 二叉树基本操作完整代码 树 …

VS code 安装使用配置 Continue

Continue 插件介绍 Continue 是一款高效的 VS Code 插件&#xff0c;提供类似 GitHub Copilot 的功能&#xff0c;旨在提升开发者的编程效率。其配置简单&#xff0c;使用体验流畅&#xff0c;深受开发者喜爱。 主要功能特点 智能代码补全 Continue 能够基于当前代码上下文生…

年化60.7%,最大回撤-16.5%,RSRS标准分择时效果差不多

原创内容第653篇&#xff0c;专注量化投资、个人成长与财富自由。 中秋节&#xff0c;祝大家中秋快乐&#xff01; 人有悲欢离合&#xff0c;月有阴晴圆缺&#xff0c;此事古难全。但愿人长久&#xff0c;千里共婵娟。 今天引入RSRS来择时&#xff0c;看下策略效果。 年化60.7…