每天一道LeetCode-----数独盘求解
Valid Sudoku
原題鏈接Valid Sudoku
判斷給定的數獨盤是否有效,數獨盤中可能有空位置。
簡述一下數獨的規則,參考連接Sudoku Puzzles - The Rules.
其實就是每個點只能存在1-9這九個數字中的一個,滿足每一行,每一列,每個3 * 3方格不能出現重復的數字
判斷一個數獨盤是否有效,只需要判斷是否滿足上述三個規則即可。另外,如果給出的數獨盤像圖片那樣有些地方沒有填充數字,也沒有關系。只需要判斷有數字的部分就好,比如說第一行只有5, 3, 7,那么可以判斷第一行沒有出現重復的數字,是滿足規則一的。
肯定需要全部遍歷一遍,每遍歷到一個位置,就判斷它所在的行,所在的列,所在的3 * 3方格是否已經存在同樣的數字了,如果存在,返回false,否則,將這個數字添加到行,列,3 * 3方格的記錄中。
所以需要分別記錄每一行,每一列,每一個3 * 3方格都有那些數字出現過,其實就是3個二維數組
對于3 * 3方格,這里用vector<vector<int>> boxes(9, vector<int>(10, 0));形式表示,意思是這個數獨盤是由9個3 * 3方格,編號從0到8。對于某個位置(row, column)而言,它所在的3 * 3方格編號為row / 3 * 3 + column / 3。
表示方法,假設當前位置為(i, j),數字為n
代碼如下
class Solution { public:bool isValidSudoku(vector<vector<char>>& board) {vector<vector<int>> rows(9, vector<int>(10, 0));vector<vector<int>> columns(9, vector<int>(10, 0));vector<vector<int>> boxes(9, vector<int>(10, 0));for(int i = 0; i < board.size(); ++i){for(int j = 0; j < board[i].size(); ++j){if(board[i][j] == '.')continue;int n = board[i][j] - '0';/* 如果之前有出現過(不為0),就說明數獨盤無效 */if(rows[i][n] || columns[j][n] || boxes[i / 3 * 3 + j / 3][n])return false;/* 否則,更新每一行,每一列,所在方格的內容 */elserows[i][n] = columns[j][n] = boxes[i / 3 * 3 + j / 3][n] = 1;}}return true;}};擴展
Sudoku Solver
原題鏈接Sudoku Solver
給定一個有效的數獨盤,解出結果。
解一個數獨盤就是要求把所有的空格都填上數字,要求仍然是滿足上述三個規則,即
對于某個空格,它所能填充的數字需要滿足
所以在上面的問題中,已經把每一行,每一列,每個3 * 3方格出現的數字都找出了,接下來就是深度優先(dfs)把每個空格填上數字即可,當然填充的數字需要滿足上面的要求。
如果填充到某個位置發現沒有可選的數字了,就說明之前的某個位置選擇錯了,就回退到之前的位置,選擇另一個滿足上述要求的數字
代碼如下
class Solution { public:void solveSudoku(vector<vector<char>>& board) {vector<vector<int>> rows(9, vector<int>(10, 0));vector<vector<int>> columns(9, vector<int>(10, 0));vector<vector<int>> boxes(9, vector<int>(10, 0));/* 計算每一行,每一列,每個3 * 3方格中每個數字是否出現 */for(int i = 0; i < board.size(); ++i){for(int j = 0; j < board[i].size(); ++j){if(board[i][j] == '.')continue;int n = board[i][j] - '0';rows[i][n] = columns[j][n] = boxes[i / 3 * 3 + j / 3][n] = 1;}}bool done = false;dfs(board, rows, columns, boxes, 0, 0, done); }private:void dfs(vector<vector<char>>& board, vector<vector<int>>& rows,vector<vector<int>>& columns, vector<vector<int>>& boxes,int row, int column, bool& done){/* 填充完成 */if(row >= board.size()){done = true;return;}/* 當前某一行的末尾,換到下一行 */else if(column >= board[row].size()){dfs(board, rows, columns, boxes, row + 1, 0, done);}/* 如果有數字,則不需要填充,繼續下一個 */else if(board[row][column] != '.'){dfs(board, rows, columns, boxes, row, column + 1, done);}else{for(int n = 1; n <= 9; ++n){/* 如果數字出現過,就不能填充到當前位置 */if(rows[row][n] || columns[column][n] || boxes[row / 3 * 3 + column / 3][n])continue;/* 將填充的數字記錄下來 */rows[row][n] = columns[column][n] = boxes[row / 3 * 3 + column / 3][n] = 1;board[row][column] = n + '0';/* 遞歸填充下一個空格 */dfs(board, rows, columns, boxes, row, column + 1, done);/* 如果完成,就退出 */if(done){return;}/* 否則,回到填充之前的狀態,重新找數字 */else{rows[row][n] = columns[column][n] = boxes[row / 3 * 3 + column / 3][n] = 0;board[row][column] = '.';}}}} };總結
以上是生活随笔為你收集整理的每天一道LeetCode-----数独盘求解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 每天一道LeetCode-----寻找地
- 下一篇: 每天一道LeetCode-----将字符