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

回溯算法(3):番外篇

前言

我分别在回溯算法(1):子集问题以及回溯算法(2):全排列问题中讲解了使用回溯算法解决子集问题与全排列问题的基本思想。但是为了建立知识体系,我只选取了比较相关的方法,并将两者联系起来。
实际上这两种问题还有其他的方法解决,当然也是基于回溯算法的。为了不留下遗憾,我在这里给大家把剩下的几种方法补充一下。
注意:对于新手朋友,还是尽可能的看我前两篇文章,不然容易学得一个四不像。

子集问题的第二种解法

子集-力扣
这里我就不复述问题了,我们直接讲解思路:
对于vector<int> nums({1, 2, 3});我们不妨这样想:每个元素都有被选择与不被选择两种状态,因此我们可以构建一个完全二叉子集树如下图所示:
在这里插入图片描述
从头到尾遍历元素,每个元素对应有被选中(绿色)与没被选中(红色)两种状态。树的深度等于元素个数n+1。我们需要的子集就是二叉树的叶子节点。
实际上,这种方法比我在前面文章中讲的方法要更加容易理解,但之所以我没讲解这种方法主要是因为这种方法的无法应对那些比较复杂的情况,例如去重,或者是一些变形题目(可以应对但是特别困难)。此外这个方法无法与全排列建立联系,很难构建成体系。

完整代码:

class Solution {vector<vector<int>> res;vector<int> path;void fun(int indx, vector<int>& nums) {if(indx == nums.size()) {res.push_back(path);return;}// 第indx个元素没有被选中,对应左侧,不需要向path中push_backfun(indx + 1, nums);// 第indx个元素被选中,对应右侧,调用push_back向path中推入元素path.push_back(nums[indx]); fun(indx + 1, nums);path.pop_back();}
public:vector<vector<int>> subsets(vector<int>& nums) {fun(0, nums);return res;}
};

全排列问题的第二种解法

全排列-力扣
我之前讲过,想解决全排列问题有两个方法,时间复杂度与画出的树的结构都基本一致,分别为:
(1)元素交换法
(2)状态标注法
之前我讲的是状态标注法,进入我们要补充的就是元素交换法,直接看图:
在这里插入图片描述
每个节点上面的数组是继承自父节点的数组顺序,下面的数组是处理后的数组顺序,红色加粗的数字发生了位置互换。
indx = 1:第一个元素依次与自己以及后面的元素互换位置
indx = 2:第二个元素依次与自己以及后面的元素互换位置
。。。
可以看到两种方法得到的全排列树的结构基本一致,且都是取叶子节点作为结果。

完整代码:

class Solution {vector<vector<int>> res;// vector<int> path; 叫唤发不需要path,直接在nums上操作void fun(int indx, vector<int>& nums) {if(indx == nums.size()) {res.push_back(nums);}for(int i = indx; i<nums.size(); i++) {swap(nums[indx], nums[i]);fun(indx+1, nums);swap(nums[indx], nums[i]);}}
public:vector<vector<int>> permute(vector<int>& nums) {fun(0, nums);return res;}
};

数独

数独-力扣
如果大家能做出这道题,那么基本就出师了。

class Solution {bool valid(vector<vector<char>>& board, int x, int y, int v) {for(int i = 0; i<9; i++) {if(v == board[i][y] || v == board[x][i]) return false;}int areax = x/3;int areay = y/3;for(int i = 0; i < 9; i++) {int dx = i%3;int dy = i/3;if(v == board[dx+areax*3][dy+areay*3]) return false;}return true;}bool fun(int indx, vector<vector<char>>& board) {if(indx > 80) return true;int x = indx%9;int y = indx/9;if(board[x][y] == '.') {for(int v = 1; v <= 9; v++) {if(!valid(board, x, y, v + '0')) {continue;}board[x][y] = v + '0';if(fun(indx+1, board)) { return true; }board[x][y] = '.';}}else {return fun(indx+1, board);}return false;}
public:void solveSudoku(vector<vector<char>>& board) {fun(0, board);return;}
};

相关文章:

  • 【web服务_负载均衡Nginx】三、Nginx 实践应用与高级配置技巧
  • 上海市计算机学会竞赛平台2023年7月月赛丙组题目解题报告
  • Java中常见的锁synchronized、ReentrantLock、ReentrantReadWriteLock、StampedLock
  • 【机器学习】朴素贝叶斯算法:原理剖析与实战应用
  • 深度补全网络:如CSPN++填补稀疏点云的深度信息
  • 修改 <li> 元素小圆点的颜色
  • 不连续数据区间天数累计sql
  • 手机投屏到电视方法
  • MongoDB导出和导入数据
  • 【大疆dji】边缘计算模块在大疆机场中的位置
  • Datawhale AI春训营】AI + 新能源(发电功率预测)Task1
  • nohup的使用
  • 2025年第16届蓝桥杯嵌入式竞赛学习笔记(十四):RTC实时时钟
  • ESB —— 企业集成架构的基石:功能、架构与应用全解析
  • 详细解释浏览器是如何渲染页面的?
  • 国网B接口协议图像数据上报通知接口流程详解以及上报失败原因(电网B接口)
  • Docker 网络详解:从 docker0 网桥到网络命名空间
  • 深入Docker核心技术:从Namespace到容器逃逸防御
  • OpenCV 04.19 练习
  • Python带有else子句的循环语句
  • 海南医科大学继续开展部门正职竞聘上岗,致力营造“谁有本事谁来”
  • 孙颖莎4比1击败陈幸同,与蒯曼会师澳门世界杯女单决赛
  • 《王牌对王牌》确认回归,“奔跑吧”将有主题乐园
  • 马上评丨“化学麻将”创新值得点赞,但要慎言推广
  • 江西农商联合银行正式挂牌开业
  • 让观众从演唱会现场走到商场,上海虹口构建“票根经济”生态链