代码随想录-算法训练营day30(回溯算法06:重新安排行程,N皇后,数独,回溯算法总结)

第七章 回溯算法part06
 
● 332.重新安排行程 
● 51. N皇后 
● 37. 解数独 
● 总结 
 
详细布置 
 
今天这三道题都非常难,那么这么难的题,为啥一天做三道? 
 
因为 一刷 也不求大家能把这么难的问题解决,所以 大家一刷的时候,就了解一下题目的要求,了解一下解题思路,
不求能直接写出代码,先大概熟悉一下这些题,二刷的时候,随着对回溯算法的深入理解,再去解决如下三题。 
 
大家今天的任务,其实是 对回溯算法章节做一个总结就行。 
 
重点是看 回溯算法总结篇:
https://programmercarl.com/%E5%9B%9E%E6%BA%AF%E6%80%BB%E7%BB%93.html  
 
332.重新安排行程(可跳过) 
https://programmercarl.com/0332.%E9%87%8D%E6%96%B0%E5%AE%89%E6%8E%92%E8%A1%8C%E7%A8%8B.html  
 
51. N皇后(可跳过) 
https://programmercarl.com/0051.N%E7%9A%87%E5%90%8E.html   
视频讲解:https://www.bilibili.com/video/BV1Rd4y1c7Bq 
 
37. 解数独(可跳过) 
https://programmercarl.com/0037.%E8%A7%A3%E6%95%B0%E7%8B%AC.html   
视频讲解:https://www.bilibili.com/video/BV1TW4y1471V
 
总结 
https://programmercarl.com/%E5%9B%9E%E6%BA%AF%E6%80%BB%E7%BB%93.html 
 
往日任务
● day 1 任务以及具体安排:https://docs.qq.com/doc/DUG9UR2ZUc3BjRUdY  
● day 2 任务以及具体安排:https://docs.qq.com/doc/DUGRwWXNOVEpyaVpG  
● day 3 任务以及具体安排:https://docs.qq.com/doc/DUGdqYWNYeGhlaVR6 
● day 4 任务以及具体安排:https://docs.qq.com/doc/DUFNjYUxYRHRVWklp 
● day 5 周日休息
● day 6 任务以及具体安排:https://docs.qq.com/doc/DUEtFSGdreWRuR2p4 
● day 7 任务以及具体安排:https://docs.qq.com/doc/DUElCb1NyTVpXa0Jj 
● day 8 任务以及具体安排:https://docs.qq.com/doc/DUGdsY2JFaFhDRVZH 
● day 9 任务以及具体安排:https://docs.qq.com/doc/DUHVXSnZNaXpVUHN4 
● day 10 任务以及具体安排:https://docs.qq.com/doc/DUElqeHh3cndDbW1Q 
●day 11 任务以及具体安排:https://docs.qq.com/doc/DUHh6UE5hUUZOZUd0 
●day 12 周日休息 
●day 13 任务以及具体安排:https://docs.qq.com/doc/DUHNpa3F4b2dMUWJ3 
●day 14 任务以及具体安排:https://docs.qq.com/doc/DUHRtdXZZSWFkeGdE 
●day 15 任务以及具体安排:https://docs.qq.com/doc/DUHN0ZVJuRmVYeWNv 
●day 16 任务以及具体安排:https://docs.qq.com/doc/DUHBQRm1aSWR4T2NK 
●day 17 任务以及具体安排:https://docs.qq.com/doc/DUFpXY3hBZkpabWFY 
●day 18 任务以及具体安排:https://docs.qq.com/doc/DUFFiVHl3YVlReVlr 
●day 19 周日休息
●day 20 任务以及具体安排:https://docs.qq.com/doc/DUGFRU2V6Z1F4alBH  
●day 21 任务以及具体安排:https://docs.qq.com/doc/DUHl2SGNvZmxqZm1X 
●day 22 任务以及具体安排:https://docs.qq.com/doc/DUHplVUp5YnN1bnBL  
●day 23 任务以及具体安排:https://docs.qq.com/doc/DUFBUQmxpQU1pa29C 
●day 24 任务以及具体安排:https://docs.qq.com/doc/DUEhsb0pUUm1WT2NP  
●day 25 任务以及具体安排:https://docs.qq.com/doc/DUExTYXVzU1BiU2Zl 
●day 26 休息 
●day 27 任务以及具体安排:https://docs.qq.com/doc/DUElpbnNUR3hIbXlY 
●day 28 任务以及具体安排:https://docs.qq.com/doc/DUG1yVHdlWEdNYlhZ  
●day 29 任务以及具体安排:https://docs.qq.com/doc/DUHZYbWhwSHRCRmp3 

day29

重新安排行程

图论好像还学,先跳过啦


N皇后

 class Solution {
     List<List<String>> res = new ArrayList<>();
 ​
     public List<List<String>> solveNQueens(int n) {
         char[][] chessboard = new char[n][n];//初始化棋盘大小
         for (char[] c : chessboard) {
             Arrays.fill(c, '.');//Arrays.fill()方法填充棋盘;
         }
         backTrack(n, 0, chessboard);
         return res;
     }
     //row去判断深度停止
     public void backTrack(int n, int row, char[][] chessboard) {
         if (row == n) {//for也是用row去判断,最后会++变成n
             res.add(Array2List(chessboard));
             return;
         }
 ​
         for (int col = 0;col < n; col++) {
             if (isValid (row, col, n, chessboard)) {
                 chessboard[row][col] = 'Q';
                 row++;
                 backTrack(n, row, chessboard);
                 row--;
                 chessboard[row][col] = '.';
             }
         }
     }
 ​
     //chessboard转化为List<String>的方法
     public List Array2List(char[][] chessboard) {
         List<String> list = new ArrayList<>();
         for (char[] c : chessboard) {
             //list.add(String.copyValueOf(c));
             list.add(new String(c) );
         }
         return list;
     }
 ​
     //检查在row行col列的chessboard上放Q的合法性
     public boolean isValid(int row, int col, int n, char[][] chessboard) {
         // 检查列,行不用检查了,添加的时候就判断只会加一个了
         for (int i=0; i<row; ++i) { // 相当于剪枝
             if (chessboard[i][col] == 'Q') {
                 return false;
             }
         }
         // 检查45度对角线,只需要向上一行去检查,因为下一行的皇后还没往里面放呢
         for (int i=row-1, j=col-1; i>=0 && j>=0; i--, j--) {
             if (chessboard[i][j] == 'Q') {
                 return false;
             }
         }
         // 检查135度对角线,只需要向上检查
         for (int i=row-1, j=col+1; i>=0 && j<=n-1; i--, j++) {
             if (chessboard[i][j] == 'Q') {
                 return false;
             }
         }
         return true;
     }
 }

数独

 class Solution {
     public void solveSudoku(char[][] board) {
         solveSudokuHelper(board);
     }
 ​
     private boolean solveSudokuHelper(char[][] board){
         //一个for循环遍历棋盘的行,一个for循环遍历棋盘的列,
         //一行一列确定下来之后,递归遍历这个位置放9个数字的可能性
         //其实两个for也就是把数独棋盘拉直变成一位数组,一个一个格子去遍历1~9
         for (int i = 0; i < 9; i++){ // 遍历行
             for (int j = 0; j < 9; j++){ // 遍历列
                 if (board[i][j] != '.'){ // 跳过原始数字
                     continue;
                 }
                 for (char k = '1'; k <= '9'; k++){ // (i, j) 这个位置放k是否合适
                     if (isValidSudoku(i, j, k, board)){
                         board[i][j] = k;
                         if (solveSudokuHelper(board)){ // 如果找到合适一组立刻返回
                             return true;
                         }
                         board[i][j] = '.';//初始化回去,走for横向的另一个小分支,比如1不合适再添2
                     }
                 }
                 // 9个数都试完了,都不行,那么就返回false
                 return false;
                 // 因为如果一行一列确定下来了,这里尝试了9个数都不行,说明这个棋盘找不到解决数独问题的解!
                 // 那么会直接返回, 「这也就是为什么没有终止条件也不会永远填不满棋盘而无限递归下去!」
             }
         }
         // 遍历完没有返回false,说明找到了合适棋盘位置了
         return true;
     }
 ​
     /**
      * 判断棋盘是否合法有如下三个维度:
      *     同行是否重复
      *     同列是否重复
      *     9宫格里是否重复
      */
     private boolean isValidSudoku(int row, int col, char val, char[][] board){
         // 同行是否重复
         for (int i = 0; i < 9; i++){
             if (board[row][i] == val){
                 return false;
             }
         }
         // 同列是否重复
         for (int j = 0; j < 9; j++){
             if (board[j][col] == val){
                 return false;
             }
         }
         // 9宫格里是否重复
         //通过/3再*3去找到小九宫格的起点
         int startRow = (row / 3) * 3;
         int startCol = (col / 3) * 3;
         for (int i = startRow; i < startRow + 3; i++){
             for (int j = startCol; j < startCol + 3; j++){
                 if (board[i][j] == val){
                     return false;
                 }
             }
         }
         return true;
     }
 }

回溯算法总结:

代码随想录

感谢大佬分享:

代码随想录-算法训练营day30【回溯算法06:重新安排行程、N皇后、解数独、总结】-优快云博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值