数独的暴力解法

刚才刷leetcode,碰到一个问题,验证一个数独的正确性(36. Valid Sudoku),意思是只要满足以下规则就行:
1、每一行只能出现1~9这九个数字,并且不能重复。
2、每一列只能出现1~9这九个数字,并且不能重复。
3、每一个子九宫格里面只能出现1~9这九个数字,不能重复。

数独问题

这道题目的解法也不难,直接暴力就可以,n方的复杂度。
精彩的部分来了,大家注意(敲黑板)。
下面一题是,给你一个数独,写通用程序去解这个数独(37. Sudoku Solver)。
我觉得这存粹是一个数学题目了,求几十个方程组的解嘛,可能用到线性代数矩阵啥的,早忘了。于是果断放弃,去看题目后面的讨论。
首先看到了新加坡总理李显龙的解法,总理写代码谁也挡不住啊,深深地感受到智商被压制了。可以参考下面两个链接。
https://arstechnica.com/information-technology/2015/05/prime-minister-of-singapore-shares-his-c-code-for-sudoku-solver/
https://leetcode.com/problems/sudoku-solver/discuss/15796/Singapore-prime-minister-Lee-Hsien-Loong's-Sudoku-Solver-code-runs-in-1ms
然后我看到下面这种暴力解决方法:

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

    public 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++){//trial. Try 1 through 9
                        if(isValid(board, i, j, c)){
                            board[i][j] = c; //Put c for this cell

                            if(solve(board))
                                return true; //If it's the solution return true
                            else
                                board[i][j] = '.'; //Otherwise go back
                        }
                    }

                    return false;
                }
            }
        }
        return true;
    }

    private boolean isValid(char[][] board, int row, int col, char c){
        for(int i = 0; i < 9; i++) {
            if(board[i][col] != '.' && board[i][col] == c) return false; //check row
            if(board[row][i] != '.' && board[row][i] == c) return false; //check column
            if(board[3 * (row / 3) + i / 3][ 3 * (col / 3) + i % 3] != '.' && 
board[3 * (row / 3) + i / 3][3 * (col / 3) + i % 3] == c) return false; //check 3*3 block
        }
        return true;
    }
}

没有耐心看代码的同学我简单说一下原理,这个方法就是把1到9这个数字逐一放到数独中去,然后验证是否是合法数独(调用上面一题的代码的部分逻辑),如果是合法的将数字放入数独中去,对新的数独做递归,直到填满整个数独。

我表示,这种方法与李显龙的方法比起来,不仅仅是暴力了,还有一种江湖气息。砍瓜切菜,一个一个试过去,就是递归到底!

推荐阅读更多精彩内容