编写一个程序,通过已填充的空格来解决数独问题。
一个数独的解法需遵循如下规则:
数字 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一下,到底是你是否是有算法思路了还是只是看到题解才能想出。
原文:https://www.cnblogs.com/CherryTab/p/12219213.html