1. 程式人生 > >leetcode|37. Sudoku Solver

leetcode|37. Sudoku Solver

Sudoku Solver

Write a program to solve a Sudoku puzzle by filling the empty cells.

Empty cells are indicated by the character ‘.’.

You may assume that there will be only one unique solution.

const static int ans=9;
   bool rows[ans][ans];
   bool cols[ans][ans];
   bool area[ans][ans];
   
   void initArray(vector<vector<char>>& board){
     memset(rows,false,sizeof(rows));
     memset(cols,false,sizeof(cols));
     memset(area,false,sizeof(area));
     isValidSudoku(board,0,0,0,false);
   }
   
   void solveSudoku(vector<vector<char>>& board){
       initArray(board);
       if(solveSudoku1(board)) return;
   }
    bool solveSudoku1(vector<vector<char>>& board) {
        for(int i=0;i<board.size();i++){
            for(int j=0;j<board[i].size();j++){
                if(board[i][j]=='.'){
                    for(int k=0;k<9;k++){
                        if(!isValidSudoku(board,i,j,k,true))
                              continue;
                        board[i][j]=k+'1';
                        rows[i][k]=cols[k][j]=area[k/3+(i/3)*3][k%3+(j/3)*3]=true;
                        if(solveSudoku1(board)){
                            return true;
                        }
                        board[i][j]='.';
                        rows[i][k]=cols[k][j]=area[k/3+(i/3)*3][k%3+(j/3)*3]=false;
                    }
                    return false;
                }
            }
        }
        return true;
    }<pre name="code" class="cpp">bool isValidSudoku(vector<vector<char>>& board,int r,int c,int k,bool mode) {//一直沒有傳進去k值
        if(board.size()!=9) return false;
        for(int i=0;i<0;i++){
            if(board[i].size()!=9) return false;
        }
        if(mode){
            int pos=k;
            //check area
            int ref_row=r/3;//對應0,1,2
            int ref_col=c/3;//對應0,1,2
            //對應9個area區域
            int area_i=pos/3+ref_row*3;
            int area_j=pos%3+ref_col*3;
            if(rows[r][pos]||cols[pos][c]||area[area_i][area_j])
                    return false;
            return true;
        }
        //下面用來初始化最初的棋盤
        for(int i=0;i<board.size();i++){
            for(int j=0;j<board[i].size();j++){
                if(board[i][j]=='.') continue;
                int pos=board[i][j]-'1';
                //check area
                int ref_row=i/3;//對應0,1,2
                int ref_col=j/3;//對應0,1,2
                //對應9個area區域
                int area_i=pos/3+ref_row*3;
                int area_j=pos%3+ref_col*3;
                rows[i][pos]=cols[pos][j]=area[area_i][area_j]=true;
            }
        }
    }

上種解法是藉助了三個矩陣輔助記錄。可以減小空間。

把空間複雜度降低為O(1)

bool solveSudoku(vector<vector<char> > &board) {
for (int i = 0; i < 9; ++i)
for (int j = 0; j < 9; ++j) {
if (board[i][j] == '.') {
for (int k = 0; k < 9; ++k) {
board[i][j] = '1' + k;
if (isValid(board, i, j) && solveSudoku(board))
return true;
board[i][j] = '.';
}
return false;
}
}
return true;
}

    // 檢查 (x, y) 是否合法
bool isValid(const vector<vector<char> > &board, int x, int y) {
int i, j;
for (i = 0; i < 9; i++) // 檢查 y 列
if (i != x && board[i][y] == board[x][y])
return false;
for (j = 0; j < 9; j++) // 檢查 x 行
if (j != y && board[x][j] == board[x][y])
return false;
for (i = 3 * (x / 3); i < 3 * (x / 3 + 1); i++)
for (j = 3 * (y / 3); j < 3 * (y / 3 + 1); j++)
if ((i != x || j != y) && board[i][j] == board[x][y])
return false;
return true;
}