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

[Algorithm][回溯][字母大小写全排列][优美的排列][N皇后]详细讲解

目录

  • 1.字母大小写全排列
    • 1.题目链接
    • 2.算法原理详解
    • 3.代码实现
  • 2.优美的排列
    • 1.题目链接
    • 2.算法原理详解
    • 3.代码实现
  • 3.N 皇后
    • 1.题目链接
    • 2.算法原理详解
    • 3.代码实现


1.字母大小写全排列

1.题目链接

  • 字母大小写全排列

2.算法原理详解

  • 本题逻辑与子集大致相同
    • 思路一:每次盯着一个字符,变或是不变
      • 全局变量
        • string path
        • vector<string> ret
      • DFS()设计
        • 函数头void DFS(string, pos)
          • pos:下一层递归要选的元素
        • 函数体
          • 字母可能变/不变,数字一定不需要变
        • 递归出口pos == nums.size()
      • 回溯:变完函数返回时需要回溯
        请添加图片描述

3.代码实现

class Solution 
{string path;vector<string> ret;
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'){ch = Change(ch);path += ch;DFS(s, pos + 1);path.pop_back(); // 回溯,恢复现场}}char Change(char ch){if(ch >= 'a' && ch <= 'z'){ch -= 32;}else{ch += 32;}return ch;}
};

2.优美的排列

1.题目链接

  • 优美的排列

2.算法原理详解

  • 思路:对每个位置挨个尝试填入数字
    • 全局变量
      • int ret
      • vector<bool> check -> 剪枝
    • DFS()设计void DFS(pos, n)
    • 剪枝
      • 之前用过的数字不再使用
      • 不符合情况的不填入
    • 回溯:每层递归返回时回溯
      请添加图片描述

3.代码实现

class Solution 
{int ret = 0;vector<bool> check;
public:int countArrangement(int n) {check.resize(n + 1, false);DFS(1, n);return ret;}void DFS(int pos, int n){if(pos == n + 1){ret++;return;}for(int i = 1; i <= n; i++){if(!check[i] && (i % pos == 0 || pos % i == 0)){check[i] = true;DFS(pos + 1, n);check[i] = false; // 回溯,恢复现场}}}
};

3.N 皇后

1.题目链接

  • N 皇后

2.算法原理详解

  • 本题可以学习二维数组判断行列、主副对角线是否放有数据

  • 思路:在每一行找合适的列放置皇后,即每次枚举都是枚举一行
    - DFS()设计:void DFS(row)

    • 决策树
      请添加图片描述
  • 如何剪枝?-> 当前这个位置,能否放上皇后?

    • 无脑四个循环判断行列、主副对角线 -> ×
    • 类似哈希表的策略,需要一定数学理解
      • 不需要剪枝,收递归限制
      • bool checkCol[n] -> 判断
        • 对应下标表示每列是否放置过皇后
      • bool checkDig1[2 * n] -> 主对角线
        • y = x + b -> y - x = b -> b可以唯一标识一个对角线
        • y - x + n = b + n -> 两边加上一个固有偏移量防止下标出现负数
      • bool checkDig2[2 * n] -> 副对角线
        • y = -x + b -> y + x = b -> b可以唯一标识一个对角线
        • 副对角线不需要固定偏移量,因为副对角线的纵截距都大于0
          请添加图片描述

3.代码实现

class Solution 
{int _n = 0;vector<bool> checkCol;vector<bool> checkDig1;vector<bool> checkDig2;vector<vector<string>> ret;vector<string> path;
public:vector<vector<string>> solveNQueens(int n) {_n = n;checkCol.resize(n, false);checkDig1.resize(2 * n, false);checkDig2.resize(2 * n, false);path.resize(n, string(n, '.'));DFS(0);return ret;}void DFS(int row){// 递归出口if(row == _n){ret.push_back(path);return;}// 对于每一行,枚举每一列for(int i = 0; i < _n; i++){// 剪枝if(!checkCol[i] && !checkDig1[row - i + _n] && !checkDig2[row + i]){checkCol[i] = checkDig1[row - i + _n] = checkDig2[row + i] = true;path[row][i] = 'Q';DFS(row + 1);checkCol[i] = checkDig1[row - i + _n] = checkDig2[row + i] = false; // 回溯path[row][i] = '.';}}}
};
http://www.lryc.cn/news/350326.html

相关文章:

  • .NET_NLog
  • Linux查看进程命令ps和top
  • 深入解析Wireshark1:从捕获到分析,一网打尽数据包之旅
  • C++语法|指向类成员(成员变量和成员方法)的指针及其相关应用场景
  • 【C语言】通讯录系统实现
  • (delphi11最新学习资料) Object Pascal 学习笔记---第12章第1节 ( 类静态方法与Windows API回调)
  • 第一个Rust程序
  • 【LInux】<基础IO> 文件操作 | 文件描述符 | 重定向
  • MySQL--增、删、改、查,
  • 5.12学习总结
  • ansible利用playbook 部署lamp架构
  • SPI通信(使用SPI读写W25Q64)
  • <sa8650>QCX Usecase 使用详解—拓扑图 XML 定义
  • 使用C++11实现Golang的defer功能
  • 前端之电力系统SVG图低代码
  • 括号生成[中等]
  • 配置ubuntu的VNC时遇到报错_XSERVTransmkdir: Mode of /tmp/.X11-unix should be set to 1777
  • openstack部署nova中出现的问题:
  • 【OpenCV 基础知识 3】边缘检测
  • 拓宽知识储备量(指数级成长)
  • x264 帧类型代价计算原理:slicetype_mb_cost 函数分析
  • 战网国际服加速器哪个好用 暴雪战网免费加速器分享
  • Java入门基础学习笔记26——break,continue
  • HNU-算法设计与分析-作业6
  • 2D Chests Assets - Mega Pack
  • 一种基于电场连续性的高压MOSFET紧凑模型,用于精确表征电容特性
  • vue阶段性测试题,内容丰富,案例典型,题目配有答案
  • 如何查看PC电脑已经已经连接上的网络WiFi密码?
  • Java 语言的特点分析及应用
  • Golang | Leetcode Golang题解之第84题柱状图中最大的矩形