Leetcode 37 解数独 --回溯法的返回值与分支选择问题

1. 方法一

**class Solution {


        boolean[][] usedRow;
        boolean[][] usedCol;
        boolean[][] usedBoxed;


        public Solution() {
            this.usedRow = new boolean[10][10];
            this.usedCol = new boolean[10][10];
            this.usedBoxed = new boolean[10][10];

        }


        public void solveSudoku(char[][] board) {
            initSudo(board);
            dfs(board, 0, 0);

        }

        private void initSudo(char[][] board) {
            for (int i = 0; i < board.length; i++) {
                for (int j = 0; j < board[0].length; j++) {
                    int num = board[i][j] - '0';
                    if (num > 0 && num <= 9) {
                        usedRow[i][num] = true;
                        usedCol[j][num] = true;
                        usedBoxed[(i / 3) * 3 + j / 3][num] = true;
                    }
                }

            }
        }

        private boolean dfs(char[][] board, int i, int j) {
            if (j == board[0].length) {
                j = 0;
                i++;
                if (i == board.length) {
                    return true;
                }
            }

            if (board[i][j] == '.') {
                for (int k = 1; k <= 9; k++) {
                    if (!usedRow[i][k] && !usedCol[j][k] && !usedBoxed[(i / 3) * 3 + j / 3][k]) {
                        usedRow[i][k] = true;
                        usedCol[j][k] = true;
                        usedBoxed[(i / 3) * 3 + j / 3][k] = true;
                        board[i][j] = (char) (k + '0');
                        if (dfs(board, i, j + 1)) {
                            return true;
                        }
                        usedRow[i][k] = false;
                        usedCol[j][k] = false;
                        usedBoxed[(i / 3) * 3 + j / 3][k] = false;
                        board[i][j] = '.';
                    }
                }
            } else {
                // 此处加与不加return的区别?
                // 如果加了,比如说之前第一个是数字,说明填过了,已经组成一张完整的棋盘
                // 如果不加,必然会遍历到最后一个格子,之前的没有联系到一起,即不是一张完整棋盘。
                return dfs(board, i, j + 1);
            }
            return false;
        }
    }**

注意点

回溯法的返回值问题

  1. 如果 需要找到某些解的时候,必然是带有返回值的。
  2. 注意else分支。在写的时候,经常会把else分支给忽略了。如果忽略了,就会枚举不全。

方法二

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


        }

        private boolean backTracking(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 k = '1'; k <= '9'; k++) {
                            if (validateNum(k, i, j, board)) {
                                board[i][j] = k;
                                if (backTracking(board)) {
                                    return true;
                                }
                                board[i][j] = '.';
                            }

                        }
                        return false;
                    }


                }

            }
            return true;
        }

        private boolean validateNum(int value, int row, int col, char[][] board) {

            for (int i = 0; i < 9; i++) {
                if (board[i][col] == value) {
                    return false;
                }
            }
            for (int i = 0; i < 9; i++) {
                if (board[row][i] == value) {
                    return false;
                }
            }
            int rowIndex = (row / 3) * 3;
            int colIndex = (col / 3) * 3;
            for (int i = rowIndex; i < rowIndex + 3; i++) {
                for (int j = colIndex; j < colIndex + 3; j++) {
                    if (board[i][j] == value) {
                        return false;
                    }
                }

            }
            return true;

        }

问题 为什么第一种方法,必须加上else,第二种方法不需要呢?区别在哪里?

第一种方法是逐行填的。 private boolean dfs(char[][] board, int i, int j)
第二种方法是尝试所有可能的数字。 private boolean backTracking(char[][] board)。
如果判断的对象是带有Index,逐个数字填的。需要考虑各种情况 。如果函数的对象是整整体,则不需要再次判断。
第一种方法是逐行。第2种方法相当于每次暴力搜索全部。因此不用单独判断每一行的状态。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值