乘风破浪:LeetCode真题_037_Sudoku Solver

 乘风破浪:LeetCode真题_037_Sudoku Solver

1、前言

   此次咱们对于上次的模型作一个扩展并求解。java

2、Sudoku Solver

2.1 问题

2.2 分析与解决

    这道题让咱们按照规则,填写数独表上的内容,而且已知假设答案是惟一的。这里咱们直到一个3*3的方格内的数字不能重复,所以需要填写完成,就须要全部的数字,所以咱们能够尝试使用图遍历中的深度优先和广度优先遍从来不断地试探,直到获得最后的结果。一样的递归也能达成上面的要求。算法

class Solution {
    int[][] hCounts;
    int[][] vCounts;
    int[][][] sqCounts;
    public void solveSudoku(char[][] board) {
        hCounts = new int[9][9];
        vCounts = new int[9][9];
        sqCounts = new int[3][3][9];
        for (int row=0;row<9;row++) {
            for (int col=0;col<9;col++) 
                if (board[row][col] != '.') 
                    set(board, row, col, board[row][col]);
        }
        solve(board, 0, 0);
    }
    private boolean solve(char[][] board, int row, int col) {
        if (row == board.length) 
            return true;
        if (col == board[0].length) 
            return solve(board, row+1, 0);
        if (board[row][col] != '.')
            return solve(board, row, col+1);
        
        for (int i=1;i<10;i++) {
            char n = (char)('0' + i);
            if (canAdd(row, col, n)) {
                set(board, row, col, n);
                if (solve(board, row, col+1)) 
                    return true;
                unset(board, row, col, n);
            }
        }
        return false;
    }
    private boolean canAdd(int row, int col, char c) {
        int n = c-'0'-1;
        return hCounts[row][n] == 0 && vCounts[col][n] == 0 && sqCounts[row/3][col/3][n] == 0;
    }
    private void set(char[][] board, int row, int col, char c) {
        board[row][col] = c;
        int n = c-'0'-1;
        hCounts[row][n]++;
        vCounts[col][n]++;
        sqCounts[row/3][col/3][n]++;
    }
    private void unset(char[][] board, int row, int col, char c) {
        board[row][col] = '.';
        int n = c-'0'-1;
        hCounts[row][n]--;
        vCounts[col][n]--;
        sqCounts[row/3][col/3][n]--;
    }
}

    这道题的算法能够说是很是经典的,进行了一些抽象,首先是初始化,经过三个数组来检验能不能添加元素进去。方法也很简单,若是存在过某个数值,就加一,而后再添加的时候须要判断一下是否是可以加入进去。数组

 1     private boolean canAdd(int row, int col, char c) {
 2         int n = c-'0'-1;
 3         return hCounts[row][n] == 0 && vCounts[col][n] == 0 && sqCounts[row/3][col/3][n] == 0;
 4     }
 5     private void set(char[][] board, int row, int col, char c) {
 6         board[row][col] = c;
 7         int n = c-'0'-1;
 8         hCounts[row][n]++;
 9         vCounts[col][n]++;
10         sqCounts[row/3][col/3][n]++;
11     }

    以后咱们从最开始的[0,0]按行遍历,经过递归算法,若是能将字符加入进去就加入,继续调用,不能的话就撤回,而后继续遍历,先对每一行的每一列的元素进行遍历,当完成以后遍历下一行,直至结束。spa

 1     private boolean solve(char[][] board, int row, int col) {
 2         if (row == board.length) //已经遍历到表外了,结束,成功。  3             return true;  4         if (col == board[0].length) //开始下一行  5             return solve(board, row+1, 0);  6         if (board[row][col] != '.') //不为.则继续下一列。  7             return solve(board, row, col+1);  8         
 9         for (int i=1;i<10;i++) {
10             char n = (char)('0' + i);
11             if (canAdd(row, col, n)) { 12  set(board, row, col, n); 13                 if (solve(board, row, col+1)) 14                     return true; 15  unset(board, row, col, n);//不成功,回退 16  } 17         }
18         return false; //最后都没成功,返回false 19     }

3、总结

    涉及到图的问题,让咱们想到了八皇后问题,一样的联想到这个题的解法。code

相关文章
相关标签/搜索