- 菜
- 中 46. 全排列(C)47. 全排列 II(C-)
- 危 37. 解数独(S-)51. N皇后(A)52. N皇后 II(A)
回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。
解题关键:
出口 通常规律把出口语句放在递归函数的第一行。
递归函数的参数 这个参数是随着每一次的递归操作而发生改变的。而回溯法很关键的一点就是:如果当前操作行不通,如何回溯到上一步操作。
递归函数的处理过程 如果当前递归过程的处理参数符合要求,则执行相关赋值或其它操作,然后转入下一次递归,如果下一次递归不能找到出口,则把之前相关赋值或其它操作重置为初始状态。
37. 解数独(A+)
分析:考虑两种编程概念,约束编程和回溯法。
没填一个空单元格判断3个条件。如果,不满足回溯到上一个。
1 | class Solution: |
1 | class Solution: |
python2版本,最快代码。应该是用了哈希
1 | class Solution(object): |
46. 全排列(C)
分析:整体就是简单的递归思想。
1 | class Solution: |
47. 全排列 II(C-)
分析:根据上题稍微变动一下,加一个条件去重即可
1 | class Solution: |
回溯法常规写法
1 | class Solution: |
51. N皇后(A)
分析:回溯法经典问题。思路需要梳理清楚。主要学习了两种方式。一种递归方式,另一种非递归方式。最优的方法应该是位排序。利用二进制的特性进行排序。在后一题有详解。
回溯算法也叫试探法,它是一种系统地搜索问题的解的方法。回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。
在现实中,有很多问题往往需要我们把其所有可能穷举出来,然后从中找出满足某种要求的可能或最优的情况,从而得到整个问题的解。回溯算法就是解决这种问题的“通用算法”,有“万能算法”之称。N皇后问题在N增大时就是这样一个解空间很大的问题,所以比较适合用这种方法求解。这也是N皇后问题的传统解法,很经典。
把棋盘存储为一个N维数组a[N],数组中第i个元素的值代表第i行的皇后位置,这样便可以把问题的空间规模压缩为一维O(N),在判断是否冲突时也很简单,首先每行只有一个皇后,且在数组中只占据一个元素的位置,行冲突就不存在了,其次是列冲突,判断一下是否有a[i]与当前要放置皇后的列j相等即可。至于斜线冲突,通过观察可以发现所有在斜线上冲突的皇后的位置都有规律即它们所在的行列互减的绝对值相等,即| row – i | = | col – a[i] |
第一种递归方式。python
1 | class Solution: |
cpp
1 | class Solution { |
python另一种写法
1 | from itertools import permutations |
python一种优化方式。记录冲突的位置。。
1 | class Solution: |
第二种非递归法
cpp
1 | class Solution { |
一行邪教
1 | class Solution: |
52. N皇后 II(A)
分析:有了上一题的基础,做起来还是挺简单的。符合条件的放入列表。
1 | class Solution: |
方法二:记录不能放置的位置。
1 | # @author:leacoder |
方法三:位运算的表示,应该是最优方法之一。
1 | # @author:leacoder |