• leetcode-37


    编写一个程序,通过已填充的空格来解决数独问题。

    一个数独的解法需遵循如下规则:

    数字 1-9 在每一行只能出现一次。
    数字 1-9 在每一列只能出现一次。
    数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
    空白格用 '.' 表示。

    一个数独。

    答案被标成红色。

    Note:

    给定的数独序列只包含数字 1-9 和字符 '.' 。
    你可以假设给定的数独只有唯一解。
    给定数独永远是 9x9 形式的。

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/sudoku-solver
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    此题咋说呢,数独我大概十年前玩过,看到这道题自己想的第一个思路就是回溯,看完题解发现其中还有广度遍历的思维,考虑性能还需要剪枝,性能优化是这道题的关键。

    我们设置的几个数组,分别的row col idx为key,虽然我们设置的是二维数组,实际上我们是用两个二维rows cols来模拟一个map的,真正的二维数独数组是board

    class Solution {
        // box size
        int n = 3;
        // row size
        int N = n * n;
    
        int [][] rows = new int[N][N + 1];
        int [][] columns = new int[N][N + 1];
        int [][] boxes = new int[N][N + 1];
    
        char[][] board;
    
        boolean sudokuSolved = false;
    
        public boolean couldPlace(int d, int row, int col) {
        /*
        Check if one could place a number d in (row, col) cell
        */
            int idx = (row / n ) * n + col / n;
            return rows[row][d] + columns[col][d] + boxes[idx][d] == 0;
        }
    
        public void placeNumber(int d, int row, int col) {
        /*
        Place a number d in (row, col) cell
        */
            int idx = (row / n ) * n + col / n;
    
            rows[row][d]++;
            columns[col][d]++;
            boxes[idx][d]++;
            board[row][col] = (char)(d + '0');
        }
    
        public void removeNumber(int d, int row, int col) {
        /*
        Remove a number which didn't lead to a solution
        */
            int idx = (row / n ) * n + col / n;
            rows[row][d]--;
            columns[col][d]--;
            boxes[idx][d]--;
            board[row][col] = '.';
        }
    
        public void   placeNextNumbers(int row, int col) {
        /*
        Call backtrack function in recursion
        to continue to place numbers
        till the moment we have a solution
        */
            // if we're in the last cell
            // that means we have the solution
            if ((col == N - 1) && (row == N - 1)) {
                sudokuSolved = true;
            }
            // if not yet
            else {
                // if we're in the end of the row
                // go to the next row
                if (col == N - 1) backtrack(row + 1, 0);
                    // go to the next column
                else backtrack(row, col + 1);
            }
        }
    
        public void backtrack(int row, int col) {
        /*
        Backtracking
        */
            // if the cell is empty
            if (board[row][col] == '.') {
                // iterate over all numbers from 1 to 9
                for (int d = 1; d < 10; d++) {
                    if (couldPlace(d, row, col)) {
                        placeNumber(d, row, col);
                        placeNextNumbers(row, col);
                        // if sudoku is solved, there is no need to backtrack
                        // since the single unique solution is promised
                        if (!sudokuSolved) removeNumber(d, row, col);
                    }
                }
            }
            else placeNextNumbers(row, col);
        }
    
        public void solveSudoku(char[][] board) {
            this.board = board;
    
            // init rows, columns and boxes
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < N; j++) {
                    char num = board[i][j];
                    if (num != '.') {
                        int d = Character.getNumericValue(num);
                        placeNumber(d, i, j);
                    }
                }
            }
            backtrack(0, 0);
        }
    }

    end

    在这里推荐去YouTube搜索一些leetcode算法题解,如果你实在看不懂文字化和代码的解释,其实春节假期可以系统看一些renew一下,到底是你是否是有算法思路了还是只是看到题解才能想出。

    一个没有高级趣味的人。 email:hushui502@gmail.com
  • 相关阅读:
    H3C Comware V5、V7平台交换机分类
    如何从症状上区别风寒感冒与过敏性鼻炎
    rdp3389mstsc使用剪贴板重定向通过远程桌面服务或终端服务会话复制大于 2 GB 的文件 (复制) 会以静默方式失败
    小区光纤PON接入组网方式与案例
    Esxi6.7网络trunk端口设置和vlan端口设置访问
    安装VCenter 6.7的系统要求
    win10自定义时间服务器
    fabric基础设施管理-(四)多机-动态新增组织节点
    fabric基础设施管理-(三)单机-动态新增组织节点
    fabric基础设施管理-(二)基础网络搭建
  • 原文地址:https://www.cnblogs.com/CherryTab/p/12219213.html
Copyright © 2020-2023  润新知