# 37. Sudoku Solver

![](https://4272748102-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LekNH5IywF8mjBxFcnu%2F-Mhcl6nI9LEqdHSsIqo7%2F-MhcnP0tB91EGpZD1pbP%2Fimage.png?alt=media\&token=9d4f1855-6995-4686-a359-de75e8d1969e)

![](https://4272748102-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LekNH5IywF8mjBxFcnu%2F-Mhcl6nI9LEqdHSsIqo7%2F-MhcnSTRV3FA3Q41Kc-u%2Fimage.png?alt=media\&token=6c7532d7-3e9c-47e0-b43e-7b550e4dfaa3)

![](https://4272748102-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LekNH5IywF8mjBxFcnu%2F-Mhcl6nI9LEqdHSsIqo7%2F-MhcnVNiyjYYu__ERmki%2Fimage.png?alt=media\&token=b2e584f7-7e07-41e0-826d-79cf7c9b0ae3)

## backtracking

```java
/*

    time complexity: O(9^m), m represents the number of blanks to be filled in
    space complexity: O(1)

*/
class Solution {
    public void solveSudoku(char[][] board) {
        if (board == null || board.length == 0) return;
        solve(board);
    }

    private boolean solve(char[][] board) {
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {

                if (board[i][j] == '.') {
                    for (char c = '1'; c <= '9'; c++) { //每個位置一一放入去try
                        if (isValid(board, i, j, c)) {
                            board[i][j] = c; //set value

                            if (solve(board)) return true; // resursive, find unique solution, ealry stop

                            board[i][j] = '.'; // backtrack
                        }

                    }
                    return false;
                }
            }
        }
        return true;
    }

    
    private boolean isValid(char[][] board, int row, int col, char c) {
        for (int i = 0; i < 9; i++) { //判斷9個格子
            char rowVal = board[row][i];
            if (rowVal != '.' && rowVal == c) return false;

            char colVal = board[i][col];
            if (colVal != '.' && colVal == c) return false;

            // 因為沒有用set, 所以判斷式是這樣, 這裡再針對(i,j) 去判斷9宮格內是否有c了
            char boxVal = board[3*(row/3) + i/3][3*(col/3) + i%3];
            if (boxVal != '.' && boxVal == c) return false;
        }
        return true;
    }
}
```

![](https://4272748102-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LekNH5IywF8mjBxFcnu%2Fuploads%2Fm4ueEUzkbUXbBGefZ9LB%2F%E5%9C%96%E7%89%87.png?alt=media\&token=8ccec00f-54df-4d5a-b056-58fdc1aab504)

T: O(9!^9),  每列有 9! 的放入可能, 9 列, 所以是 O(9!^9)

S: O(9\*9) = O(81)

更好懂的寫法

```java
class Solution {
    public void solveSudoku(char[][] board) {
        dfs(board);
    }
    private boolean dfs(char[][] board) {
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                
                if (board[i][j] != '.') { // not empty, pass, do dfs from '.'
                    continue;
                }
                for (char c = '1'; c <= '9'; c++) {
                    if (isValid(board, i, j, c)) { // validate
                        board[i][j] = c; // try '1' to '9'
                        
                        if (dfs(board)) { // dfs
                            return true;
                        }
                        
                        board[i][j] = '.'; // backtracking
                    }
                }
                return false;
            }
        }
        return true;
    }
    
    private boolean isValid(char[][] board, int row, int col, char c) {
        for (int i = 0; i < 9; i++) {
            if (board[row][i] != '.' && board[row][i] == c) {
                return false;
            }
            if (board[i][col] != '.' && board[i][col] == c) {
                return false;
            }
        }
        
        int startRow = 3*(row/3);
        int startCol = 3*(col/3);
        for (int i = startRow; i < startRow+3; i++) {
            for (int j = startCol; j < startCol+3; j++) {
                if (board[i][j] != '.' && board[i][j] == c) {
                    return false;
                }
            }
        }
        return true;
    }
}

/*
最後用 startRow, startCol 來推 box 內 9 個座標
取的某點, ex 45, 3*(4/3), 3*(5/3) 取得起始座標=> 3,3

33.  3,4  35
43.  44.  45
53.  54.  55  => startRow, startCol = 3,3
ex 45, 3*(4/3), 3*(5/3) => 3,3

*/
```





````java
```java
class Solution {
    public void solveSudoku(char[][] board) {
        dfs(board, 0, 0);
    }
    private boolean dfs(char[][] board, int i, int j) {
        int m = board.length;
        int n = board[0].length;
        if (i == m) {
            return true;
        }
        if (j == n) { //col j reach n, so do next row, and col = 0
            return dfs(board, i+1, 0);
        }
        if (board[i][j] != '.') {
            return dfs(board, i, j+1);
        }
        for (char c = '1'; c <= '9'; c++) { // try to put each char into it
            if (isValid(board, i, j, c)) {
                board[i][j] = c;
                if (dfs(board, i, j+1)) {
                    return true;
                }
                board[i][j] = '.';
            }
        }
        return false;
    }
    private boolean isValid(char[][] board, int r, int c, char newChar) {
        for (int i = 0; i < 9; i++) {
            if (board[r][i] == newChar) {
                return false;
            }
            if (board[i][c] == newChar) {
                return false;
            }
        }
        int startR = r/3*3;
        int startC = c/3*3;
        for (int i = startR; i < startR+3; i++) {
            for (int j = startC; j < startC+3; j++) {
                if (board[i][j] == newChar) {
                    return false;
                }
            }
        }
        return true;
    }
}

/*
how to check it is valid?

if (board[r][i] == n) return false;
        // 判断列是否存在重复
        if (board[i][c] == n) return false;
        // 判断 3 x 3 方框是否存在重复
        if (board[(r/3)*3 + i/3][(c/3)*3 + i%3] == n)
            return false;


            3, 0

            3,0 4,0 5,0
            3,1.4,1 5,1  
            3,2 4,2.5,2



if j == n
dfs(i+1, 0)

not '.'
dfs(i, j+1)

if valid
dfs(i, j+1)

*/
```
````
