码迷,mamicode.com
首页 > 其他好文 > 详细

力扣 - 37. 解数独

时间:2020-12-09 12:14:45      阅读:6      评论:0      收藏:0      [点我收藏+]

标签:toc   ade   题目   索引数组   targe   时间复杂度   lock   solution   i++   

题目

37. 解数独

思路(回溯+递归)

  • 用三个数组分别记录行、列、块是否已填入数字
  • 在用一个ArrayList数组来存储数组行、列下标
  • 从ArrayList的第一个元素开始尝试,如果符合条件,进入下一个数字的填写,如果不符合条件,那么就回溯,直到如果填道ArrayList的最后一个元素,那么就说明全部填完,将valid赋值为true,一路return即可

代码

class Solution {
    // 存储board的每一行
    boolean[][] row = new boolean[9][9];
    // 存储board的每一列
    boolean[][] col = new boolean[9][9];
    // 存储board的每一块
    boolean[][][] block = new boolean[3][3][9];
    // 刚开始将valid赋值为false,说明一个都还没开始填
    boolean valid = false;
    // 存储带填写位置的 行、列 索引
    List<int[]> spaces = new ArrayList<>();

    public void solveSudoku(char[][] board) {
        // 从头到尾,遍历board,如果填写就标记为true,否则将索引存储到spaces
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                if (board[i][j] == ‘.‘) {
                    spaces.add(new int[]{i, j});
                } else {
                    // num是用来标记该位置是否有数字的,减1是因为num是索引所以要减1
                    int num = board[i][j] - ‘0‘ - 1;
                    row[i][num] = true;
                    col[j][num] = true;
                    // 由于是3*3的块,所以i和j要除以3
                    block[i/3][j/3][num] = true;
                }
            }
        }
        // 递归回溯查找
        dfs(board, 0);
    }

    private void dfs(char[][] board, int pos) {
        // 如果遍历到spaces的末尾,说明全部匹配填写成功,然后一return,得到答案
        if (spaces.size() == pos) {
            // valid赋值为true
            valid = true;
            return;
        }

        // 选取在spaces中的pos位置的 i 和 j 索引
        int[] temp = spaces.get(pos);
        // 将获取的索引数组转换成 i 和 j 下标
        int i = temp[0];
        int j = temp[1];
        // 依次使用1-9填入回溯,!valid说明未找到答案
        for (int target = 0; target < 9 && !valid; target++) {
            // 该位置只有是未填写才可以
            if (!row[i][target] && !col[j][target] && !block[i/3][j/3][target]) {
                // 先将该位置改成true,说明填入了数字
                row[i][target] = true;
                col[j][target] = true;
                block[i/3][j/3][target] = true;
                board[i][j] = (char) (target + ‘0‘ + 1);
                // 然后递归进行下一个数字的填写
                dfs(board, pos+1);
                // 回溯,将刚刚填写过的撤销
                row[i][target] = false;
                col[j][target] = false;
                block[i/3][j/3][target] = false;
            }
        }
    }
}

复杂度分析

  • 时间复杂度:\(O(9^81)\)
  • 空间复杂度:\(O(3*3*9)\)

力扣 - 37. 解数独

标签:toc   ade   题目   索引数组   targe   时间复杂度   lock   solution   i++   

原文地址:https://www.cnblogs.com/linzedian/p/14088248.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!