Leetcode 笔记 36 - Sudoku Solver
2014-11-02 09:41
274 查看
题目链接:Sudoku Solver | LeetCode OJ
Write a program to solve a Sudoku puzzle by filling the empty cells.
Empty cells are indicated by the character '.'.
You may assume that there will be only one unique solution.
A sudoku puzzle...
...and its solution numbers marked in red.
Tags: Backtracking, Hash Table
如果出现所有可能的值都被试探过,而表格仍然不合法,则这个数独无解。
Leetcode 笔记系列的Python代码共享在https://github.com/wizcabbit/leetcode.solution
分析可知,每次对数独中的一个格子的值进行改变,只会影响其所在行、所在列、所在粗线宫的合法性,因此之前isValidSudoku函数每次遍历整张表格O(n^2)的复杂度就显得没有必要。优化后的isValidSudoku函数,只检查必须的检查项时间复杂度从O(n^2)降为O(n*3)。在数十万次执行后,总执行时间大大降低。
在调试、上传代码过程中,一定谨慎使用print等输出语句,即使只在isValidSudoku的首行加入一条输出语句也会被执行数十万次,导致实际执行时间严重超时,提交到OJ上基本都会TLE(Time Limit Exceeded)。
Write a program to solve a Sudoku puzzle by filling the empty cells.
Empty cells are indicated by the character '.'.
You may assume that there will be only one unique solution.
A sudoku puzzle...
...and its solution numbers marked in red.
Tags: Backtracking, Hash Table
分析
写程序解数独的基本解法与人类解数独的方法基本相同,都是采用回溯法逐一试探推进。数独初始表格给出后,剩余的空格所有可能的值全排列的结果即为解空间,在解空间中,对每个空格填入一个值进行试探,如果试探后数独表格合法,则这个值被暂时采纳,对下一个格子进行试探。如果下个格子所有可能的值(1~9)尝试后数独表格均不合法,则被暂时采纳的本格子的值试探失败,在本格子中填入下一个值再次进行试探,直到所有的空格都被填入数字,且整张数组表格合法为止。这时表格的状态,即为数独的解。如果出现所有可能的值都被试探过,而表格仍然不合法,则这个数独无解。
示例
width = 9 class Solution: def solveSudoku(self, board): for i in range(width): for j in range(width): if board[i][j] != ".": continue for k in range(width): board[i][j] = str(k + 1) if self.isValidSudoku(board, i, j): if self.solveSudokuTask(board): return True board[i][j] = '.' return False return True def isValidSudoku(self, board, x, y): for i in range(width): if i != x and board[i][y] == board[x][y]: return False for k in range(width): if k != y and board[x][k] == board[x][y]: return False for m in range(3 * (x // 3), 3 * (x // 3 + 1)): for n in range(3 * (y // 3), 3 * (y // 3 + 1)): if (m != x and n != y) and board[m] == board[x][y]: return False return True
Leetcode 笔记系列的Python代码共享在https://github.com/wizcabbit/leetcode.solution
常见问题
在回溯试探的过程中,可以看到判断数独当前状态是否合法是非常重要的环节,我第一反应也是“复用”相关题目Valid Sudoku中的验证方法,但是很快发现会产生严重的算法超时问题。这是因为在这里“暴力”的求解方法中,isValidSudoku函数被调用的次数过大,我随便找了一个数独进行测试,isValidSudoku的执行次数高达21万多次,因此Valid Sudoku中的方法显然需要优化。分析可知,每次对数独中的一个格子的值进行改变,只会影响其所在行、所在列、所在粗线宫的合法性,因此之前isValidSudoku函数每次遍历整张表格O(n^2)的复杂度就显得没有必要。优化后的isValidSudoku函数,只检查必须的检查项时间复杂度从O(n^2)降为O(n*3)。在数十万次执行后,总执行时间大大降低。
在调试、上传代码过程中,一定谨慎使用print等输出语句,即使只在isValidSudoku的首行加入一条输出语句也会被执行数十万次,导致实际执行时间严重超时,提交到OJ上基本都会TLE(Time Limit Exceeded)。
相关题目
Valid Sudoku相关文章推荐
- LeetCode 36 Sudoku Solver
- leetcode笔记:Sudoku Solver
- LeetCode 36. Sudoku Solver
- LeetCode解题笔记37 Sudoku Solver
- LeetCode 36 Sudoku Solver
- 【leetcode刷题笔记】Sudoku Solver
- LeetCode解题笔记36 Valid Sudoku
- 每天学习多一点flash(36) as2.0 游戏设计笔记
- IOS学习笔记36—解决键盘遮挡输入框(UITextField)问题
- effective C++笔记之条款36、37: 区分接口继承和实现继承、绝不要重新定义继承而来的非虚函数
- Leetcode 36: Combinations
- LeetCode题目笔记(三) -- Median of Two Sorted Arrays
- ASP.NET 3.5核心编程学习笔记(36):页面的视图状态和控件状态
- Java学习笔记36:Java log4j 基本配置和使用
- 巴巴运动网学习笔记(36-40)
- leetcode 36: Remove Duplicates from Sorted Array II
- [Leetcode] Sudoku Solver
- GCC-3.4.6源代码学习笔记(36)
- 网管笔记36:初试无线LINUX系统安装
- 解题笔记(36)——最大公约数问题