37. 解数独

编写一个程序,通过已填充的空格来解决数独问题。

一个数独的解法需遵循如下规则:

  1. 数字 1-9 在每一行只能出现一次。
  2. 数字 1-9 在每一列只能出现一次。
  3. 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
  4. 空白格用 ‘.’ 表示。

Note:

  1. 给定的数独序列只包含数字 1-9 和字符 ‘.’ 。
  2. 你可以假设给定的数独只有唯一解。
  3. 给定数独永远是 9x9 形式的。

解答

递归+回溯,按列遍历,一行的所有列遍历完后遍历下一行:

class Solution {
     
public:
    vector<char> numbers = {
     '1', '2', '3', '4', '5', '6', '7', '8', '9'};
    void solveSudoku(vector<vector<char>>& board) {
     
          helper(board, 0, 0);
    }
    bool helper(vector<vector<char>>& board, int row, int col){
      
        if(col==9){
     
            return helper(board, row+1, 0);
        }
        if(row==9){
     
            return true;
        }
        if(board[row][col]!='.'){
     
            return helper(board, row, col+1);
        }
        for(char c : numbers){
     
            if(check(board, row, col, c)){
     
                board[row][col] = c;
                if(helper(board, row, col+1)){
     
                    return true;
                }
                board[row][col] = '.';
            }
        }
        return false;

    }
    bool check(vector<vector<char>>& board, int row, int col, char c){
     
        for(int i=0;i<9;i++){
     
            // 判断行列是否有相对元素
            if(board[row][i] == c || board[i][col] == c)
                return false;
            // 判断格子内是否有相同元素
            if(board[row/3*3+i/3][col/3*3+i%3] == c)
                return false;
        }
        return true;
    }
};

上面的代码主要耗时在check()函数上,因此可以使用额外的变量记录是否有重复数字:

class Solution {
     
public:
    vector<char> numbers = {
     '1', '2', '3', '4', '5', '6', '7', '8', '9'};
    vector<vector<int>> row_used = vector<vector<int>>(9, vector<int>(9, 0));
    vector<vector<int>> col_used = vector<vector<int>>(9, vector<int>(9, 0));
    vector<vector<vector<int>>> cell_used = vector<vector<vector<int>>>(3, vector<vector<int>>(3, vector<int>(9, 0)));
    void solveSudoku(vector<vector<char>>& board) {
     
        for(int i=0;i<9;i++){
     
            for(int j=0;j<9;j++){
     
                if(board[i][j]=='.')
                    continue;
                int temp = board[i][j]-'1';
                row_used[i][temp] = 1;
                col_used[j][temp] = 1;
                cell_used[i/3][j/3][temp] = 1;
            }
        }
          helper(board, 0, 0);
    }
    bool helper(vector<vector<char>>& board, int row, int col){
      
        if(col==9){
     
            return helper(board, row+1, 0);
        }
        if(row==9){
     
            return true;
        }
        if(board[row][col]!='.'){
     
            return helper(board, row, col+1);
        }
        for(char c : numbers){
     
            int temp = c - '1';
            if(row_used[row][temp] || col_used[col][temp] || cell_used[row/3][col/3][temp]){
     
                continue;
            }
            else{
     
                board[row][col] = c;
                row_used[row][temp] = col_used[col][temp] = cell_used[row/3][col/3][temp] = 1;
                if(helper(board, row, col+1)){
     
                    return true;
                }
                board[row][col] = '.';
                row_used[row][temp] = col_used[col][temp] = cell_used[row/3][col/3][temp] = 0;
            }
        }
        return false;
    }
};

你可能感兴趣的:(每日一题,LeetCode)