美文网首页
2020-05-03 37. Sudoku Solver Ha

2020-05-03 37. Sudoku Solver Ha

作者: _伦_ | 来源:发表于2020-05-03 10:20 被阅读0次

题目在后面,先记录点心得:

这个hard的题目还是有点难的,我卡住了好像一个钟左右(这两天做其他medium提都是几分钟到几十分钟),快要放弃想要看别人答案的时候摸索出来几个门路,还是解出来了(因为这题还是想自己做出来,毕竟代码都写得差不多了,而且不觉得自己有什么大错误):

1、也是回溯方法,注意的细节是找下一个空格的时候,如果当前行不是起始行,y要从0开始,否则就直接跳过没有判断的格子了:

for (int j = (i == x ? y : 0); j < board[0].length; j++)

2、还有就是对于结束的判断,正确的判断条件为,找不到'.'符号,就是正确了(因为每一步填各自都验证了正确性,所以能够填满就是正确)

3、另外就是这个程序开始觉得很难排查问题,因为本身解数独就比较困难,需要看很多格子,慢慢数出来。这里我是借了题目的便利,因为题目给了一个正确答案,所以我把每次遍历的board打印出来,然后看看我的程序解到哪一步出错了(也就是把一行正确答案拷贝出来,然后黏贴到控制台输出去搜索,看看程序有没有解对)。就是用这个方法,我才发现了程序其实都解对了,就是结束条件不对。所以有时候排查问题的能力也很重要,需要想些新思路检查自己到底是哪里不对。

题目:

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

A sudoku solution must satisfyall of the following rules:

Each of the digits1-9 must occur exactly once in each row.

Each of the digits1-9must occur exactly once in each column.

Each of the the digits1-9 must occur exactly once in each of the 9 3x3 sub-boxes of the grid.

Empty cells are indicated by the character '.'.

(图片挂了传不了,想看图可以去原网页看https://leetcode.com/problems/sudoku-solver/

A sudoku puzzle...

(同上)

...and its solution numbers marked in red.

Note:

The given board contain only digits 1-9 and the character '.'.

You may assume that the given Sudoku puzzle will have a single unique solution.

The given board size is always 9x9.

代码:

class Solution {

    public void solveSudoku(char[][] board) {

        findNextEmptyCellAndSolve(board, 0, 0);

    }

    private boolean findNextEmptyCellAndSolve(char[][] board, int x, int y) {

        for (int i = x; i < board.length; i++) {

            for (int j = (i == x ? y : 0); j < board[0].length; j++) {

                char c = board[i][j];

                if (c == '.') {

                    if (doSolve(board, i, j)) return true;

                    return false;

                }

            }

        }

        return true;

    }

    private boolean doSolve(char[][] board, int i, int j) {

        int curCell = board[i][j];

        for (char candidate = '1'; candidate <= '9'; candidate++) {

            boolean invalid = false;

            for (int d = 0; d < 9; d++) {

                if (board[i][d] == candidate || board[d][j] == candidate) { invalid = true; break; }

            }

            if (invalid) continue;

            for (int a = i / 3 * 3; a < i / 3 * 3 + 3; a++) {

                for (int b = j / 3 * 3; b < j / 3 * 3 + 3; b++) {

                    if (board[a][b] == candidate) { invalid = true; break; }

                }

                if (invalid) break;

            }

            if (invalid) continue;

            board[i][j] = candidate;

            if (findNextEmptyCellAndSolve(board, i, j + 1)) return true;

            board[i][j] = '.';

        }

        return false;

    }

}

第二种方法:

上面的方法还不是很快,看了些排名前面的代码,发现原来可以用几个数组直接辅助判断,就不需要每次都循环,而且空间复杂度也是固定的

    private boolean row[][] = new boolean[N][N];

    private boolean col[][] = new boolean[N][N];

    private boolean adj[][][] = new boolean[n][n][N];

完整代码:

class Solution {

    private static final int n = 3;

    private static final int N = n * n;

    private boolean row[][] = new boolean[N][N];

    private boolean col[][] = new boolean[N][N];

    private boolean adj[][][] = new boolean[n][n][N];

    public void solveSudoku(char[][] board) {

        for (int i = 0; i < N; i++) {

            for (int j = 0; j < N; j++) {

                if (board[i][j] != '.') {

                    row[i][board[i][j] - '1'] = true;

                    col[j][board[i][j] - '1'] = true;

                    adj[i / 3][j / 3][board[i][j] - '1'] = true;

                }

            }

        }

        findNextEmptyCellAndSolve(board, 0, 0);

    }

    private boolean findNextEmptyCellAndSolve(char[][] board, int x, int y) {

        for (int i = x; i < board.length; i++) {

            for (int j = (i == x ? y : 0); j < board[0].length; j++) {

                char c = board[i][j];

                if (c == '.') {

                    if (doSolve(board, i, j)) return true;

                    return false;

                }

            }

        }

        return true;

    }

    private boolean doSolve(char[][] board, int i, int j) {

        int curCell = board[i][j];

        for (char candidate = '1'; candidate <= '9'; candidate++) {

            if (row[i][candidate - '1'] || col[j][candidate - '1'] || adj[i / 3][j / 3][candidate - '1']) continue;

            row[i][candidate - '1'] = col[j][candidate - '1'] = adj[i / 3][j / 3][candidate - '1'] = true;

            board[i][j] = candidate;

            if (findNextEmptyCellAndSolve(board, i, j + 1)) return true;

            row[i][candidate - '1'] = col[j][candidate - '1'] = adj[i / 3][j / 3][candidate - '1'] = false;

            board[i][j] = '.';

        }

        return false;

    }

}

相关文章

  • 2020-05-03 37. Sudoku Solver Ha

    题目在后面,先记录点心得: 这个hard的题目还是有点难的,我卡住了好像一个钟左右(这两天做其他medium提都是...

  • 37. Sudoku Solver

    明明是一样的代码,但是。。。我的为什么有bug,算了,没空调,先贴上别人的吧:

  • 37. Sudoku Solver

    Write a program to solve a Sudoku puzzle by filling the e...

  • 37. Sudoku Solver

    题目 Write a program to solve a Sudoku puzzle by filling th...

  • 37. Sudoku Solver

    这道题。。真是有点难。 首先,这题的套路我懂,是N皇后那种全排列DFS问题。有几个难以理解的点,第一,为什么这题的...

  • 37. Sudoku Solver

    问题 Write a program to solve a Sudoku puzzle by filling th...

  • 37. Sudoku Solver

    Solution: https://leetcode.com/problems/sudoku-solver/dis...

  • 37. Sudoku Solver

    key tips 回溯法 notes 对于回溯法解决的问题,如果可行解只有一个,则可以在最后一层递归中,返回tru...

  • Leetcode 37. Sudoku Solver

    题目 Write a program to solve a Sudoku puzzle by filling th...

  • LeetCode 37. Sudoku Solver

    Write a program to solve a Sudoku puzzle by filling the e...

网友评论

      本文标题:2020-05-03 37. Sudoku Solver Ha

      本文链接:https://www.haomeiwen.com/subject/oyxdghtx.html