第七章 回溯算法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; } }
回溯算法总结:
感谢大佬分享: