题目描述[原题链接][https://leetcode-cn.com/problems/sudoku-solver/]
编写一个程序,通过已填充的空格来解决数独问题。
一个数独的解法需遵循如下规则:
数字 1-9
在每一行只能出现一次。
数字 1-9
在每一列只能出现一次。
数字 1-9
在每一个以粗实线分隔的 3x3
宫内只能出现一次。
空白格用 '.'
表示。
一个数独。
答案被标成红色。
Note:
给定的数独序列只包含数字 1-9
和字符 '.'
。
你可以假设给定的数独只有唯一解。
给定数独永远是 9 x 9
形式的。
算法描述
使用的概念
了解两个编程概念会对接下来的分析有帮助。
第一个叫做 约束编程。
基本的意思是在放置每个数字时都设置约束。在数独上放置一个数字后立即
排除当前 行, 列 和 子方块 对该数字的使用。这会传播 约束条件 并有利于减少需要考虑组合的个数。
第二个叫做 回溯。
让我们想象一下已经成功放置了几个数字
在数独上。
但是该组合不是最优的并且不能继续放置数字了。该怎么办? 回溯。
意思是回退,来改变之前放置的数字并且继续尝试。如果还是不行,再次 回溯。
如何枚举子方块
一种枚举子方块的提示是:
使用 方块索引= (行 / 3) * 3 + 列 / 3
其中 /
表示整数除法。
算法
现在准备好写回溯函数了backtrack(row = 0, col = 0)
。
从最左上角的方格开始
row = 0, col = 0
。直到到达一个空方格。从
1
到9
迭代循环数组,尝试放置数字d
进入(row, col)
的格子。如果数字
d
还没有出现在当前行,列和子方块中:将
d
放入(row, col)
格子中。记录下
d
已经出现在当前行,列和子方块中。如果这是最后一个格子
row == 8, col == 8:
- 意味着已经找出了数独的解。
否则
- 放置接下来的数字。
如果数独的解还没找到:
将最后的数从
(row, col)
移除。
C++代码
1 | class Solution { |
Java代码
1 | class Solution { |