日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

leetcode 37. 解数独 思考分析

發布時間:2023/12/1 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 leetcode 37. 解数独 思考分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

    • 題目
    • 核心思路的不斷細化
      • 1、核心框架
      • 2、考慮到每個位置的工作
      • 3、考慮到到達最后一列、該位置的數已經預置的情況
      • 4、判斷是否符合規則的函數
      • 5、確定遞歸終止條件+確定函數返回值
    • AC代碼

題目

編寫一個程序,通過填充空格來解決數獨問題。
一個數獨的解法需遵循如下規則:

1、數字 1-9 在每一行只能出現一次。
2、數字 1-9 在每一列只能出現一次。
3、數字 1-9 在每一個以粗實線分隔的 3x3 宮內只能出現一次。

空白格用 ‘.’ 表示。

一個數獨。 答案被標成紅色。
提示:

給定的數獨序列只包含數字 1-9 和字符 ‘.’ 。
你可以假設給定的數獨只有唯一解。
給定數獨永遠是 9x9 形式的。

核心思路的不斷細化

算法的核心思路就是對每一個空著的格子窮舉 1 到 9,如果遇到不合法的數字(在同一行或同一列或同一個 3×3 的區域中存在相同的數字)則跳過,如果找到一個合法的數字,則繼續窮舉下一個空格子。
寫出核心框架:

1、核心框架

void solveSudoku(vector<vector<char>>& board) {backtrack(board, 0, 0); }void backtrack(vector<vector<char>>& board, int hang, int lie) {// 就是對棋盤的每個位置進行窮舉for (int i = hang; i < 9; i++) {for (int j = lie; j < 9; j++) {// 做選擇backtrack(board, i, j);// 撤銷選擇}} }

2、考慮到每個位置的工作

對于每個位置有1~9的選擇,這樣就變成了3重嵌套循環。

void backtrack(vector<vector<char>>& board, int hang, int lie) {// 就是對每個位置進行窮舉for (int i = hang; i < 9; i++) {for (int j = lie; j < 9; j++) {for (char ch = '1'; ch <= '9'; ch++) {// 做選擇board[i][j] = ch;// 繼續窮舉下一列,backtrack(board, i, j + 1);// 撤銷選擇board[i][j] = '.';}}} }

3、考慮到到達最后一列、該位置的數已經預置的情況

1、當lie到達超過最后一個索引時,轉為增加hang開始窮舉下一行。
2、如果當前位置元素不為“.”,那么跳過即可。
3、窮舉的時候如果遇到符合規則的數字,填入,否則跳過。

void backtrack(vector<vector<char>>& board, int hang, int lie) {if(lie==9){backtrack(board, hang+1, 0);}// 就是對每個位置進行窮舉for (int i = hang; i < 9; i++) {for (int j = lie; j < 9; j++) {// 如果該位置是預設的數字,不用我們操心if (board[i][j] != '.') {backtrack(board, i, j + 1);return;} //如果不是預置的數字for (char ch = '1'; ch <= '9'; ch++) {// 如果遇到符合規則的數字,填入if (isValid(board, i, j, ch)){// 做選擇board[i][j] = ch;// 繼續窮舉下一列,backtrack(board, i, j + 1);// 撤銷選擇board[i][j] = '.';}}}} }

4、判斷是否符合規則的函數

規則如下:

1、數字 1-9 在每一行只能出現一次。
2、數字 1-9 在每一列只能出現一次。
3、數字 1-9 在每一個以粗實線分隔的 3x3 宮內只能出現一次。

翻譯成函數:
注意這里對第3個規則的描述:

// 判斷 board[i][j] 是否可以填入 n bool isValid(vector<vector<char>>& board, int hang, int lie, char n) {for (int i = 0; i < 9; i++) {// 判斷行是否存在重復if (board[hang][i] == n) return false;// 判斷列是否存在重復if (board[i][lie] == n) return false;// 判斷 3 x 3 方框是否存在重復if (board[(hang/3)*3 + i/3][(lie/3)*3 + i%3] == n)return false;}return true; }

下面是這個式子的含義,并且將i=0~8模擬了一下:

5、確定遞歸終止條件+確定函數返回值

如果遞歸完最后一行,那么我們就可以返回我們的結果了。
如果找到一個解我們的任務就結束了,本題并沒有要求找到所有解。
如果一個位置遍歷完所有數字,都不符合,這說明此路不通,應該及時返回false。
如果每個位置都遍歷過了,結果都沒有返回true,說明,這個數獨棋盤沒有解,返回false。
所以使用bool類型的值作為返回值:

if(hang == 9) return true;

完整的回溯函數代碼應該如下:

bool backtrack(vector<vector<char>>& board, int hang, int lie) {//遍歷完這一行最后一列,轉而遍歷下一行if(lie==9){return backtrack(board, hang+1, 0);}//找到一個解,返回if(hang == 9) return true;// 就是對每個位置進行窮舉for (int i = hang; i < 9; i++) {for (int j = lie; j < 9; j++) {// 如果該位置是預設的數字,不用我們操心if (board[i][j] != '.') {return backtrack(board, i, j + 1);} //如果不是預置的數字for (char ch = '1'; ch <= '9'; ch++) {// 如果遇到符合規則的數字,填入if (isValid(board, i, j, ch)){// 做選擇board[i][j] = ch;// 繼續窮舉下一列,如果找到了一個解,立即結束if(backtrack(board, i, j + 1) == true) return true;// 撤銷選擇board[i][j] = '.';}}// 窮舉完 1~9,依然沒有找到可行解,此路不通return false;}}return false; }

AC代碼

class Solution { public:// 判斷 board[i][j] 是否可以填入 nbool isValid(vector<vector<char>>& board, int hang, int lie, char n) {for (int i = 0; i < 9; i++) {// 判斷行是否存在重復if (board[hang][i] == n) return false;// 判斷列是否存在重復if (board[i][lie] == n) return false;// 判斷 3 x 3 方框是否存在重復if (board[(hang/3)*3 + i/3][(lie/3)*3 + i%3] == n)return false;}return true;}bool backtrack(vector<vector<char>>& board, int hang, int lie) {//遍歷完這一行最后一列,轉而遍歷下一行if(lie==9){return backtrack(board, hang+1, 0);}//找到一個解,返回if(hang == 9) return true;// 就是對每個位置進行窮舉for (int i = hang; i < 9; i++) {for (int j = lie; j < 9; j++) {// 如果該位置是預設的數字,不用我們操心if (board[i][j] != '.') {return backtrack(board, i, j + 1);} //如果不是預置的數字for (char ch = '1'; ch <= '9'; ch++) {// 如果遇到符合規則的數字,填入if (isValid(board, i, j, ch)){// 做選擇board[i][j] = ch;// 繼續窮舉下一列,如果找到了一個解,立即結束if(backtrack(board, i, j + 1) == true) return true;// 撤銷選擇board[i][j] = '.';}}// 窮舉完 1~9,依然沒有找到可行解,此路不通return false;}}return false;}void solveSudoku(vector<vector<char>>& board) {backtrack(board, 0, 0);return;} };

總結

以上是生活随笔為你收集整理的leetcode 37. 解数独 思考分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。