37. Sudoku Solver

backtracking

/*

    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;
    }
}

T: O(9!^9), ๆฏๅˆ—ๆœ‰ 9! ็š„ๆ”พๅ…ฅๅฏ่ƒฝ, 9 ๅˆ—, ๆ‰€ไปฅๆ˜ฏ O(9!^9)

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

ๆ›ดๅฅฝๆ‡‚็š„ๅฏซๆณ•

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
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)

*/
```

Last updated