基本概念:
backtracking(回溯算法)也叫试探法,它是一种系统地搜索问题的解的方法。回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。
回溯算法说白了就是穷举法。不过回溯算法使用剪枝函数,剪去一些不可能到达最终状态(即答案状态)的节点,从而减少状态空间树节点的生成。
回溯法是一个既带有系统性又带有跳跃性的的搜索算法。它在包含问题的所有解的解空间树中,按照深度优先的策略,从根结点出发搜索解空间树。算法搜索至解空间树的任一结点时,总是先判断该结点是否肯定不包含问题的解。如果肯定不包含,则跳过对以该结点为根的子树的系统搜索,逐层向其祖先结点回溯。否则,进入该子树,继续按深度优先的策略进行搜索。
- 回溯法在用来求问题的所有解时,要回溯到根,且根结点的所有子树都已被搜索遍才结束。
- 而回溯法在用来求问题的任一解时,只要搜索到问题的一个解就可以结束。
这种以深度优先的方式系统地搜索问题的解的算法称为回溯法,它适用于解一些组合数较大的问题。
解题思路:
在leetcode中比较经典的backtracking问题有以下几个:
51. N-Queens
52. N-Queens II
39. Combination Sum
40. Combination Sum II
216. Combination Sum III
46. Permutations
47. Permutations II
78. Subsets
90. Subsets II
131. Palindrome Partitioning
permutations
首先看 permutations 这个问题,是求一个数组的全排列,思路就是将数组当做一个池子,第一次取出一个数,然后在池子里剩下的数中再任意取一个数此时组成两个数,然后再在池子中剩下的数里取数,直到无数可取,即取完一次,形成一个排列。
public class Solution {
private List<List<Integer>> result = new ArrayList<List<Integer>>();
private int length;
public List<List<Integer>> permute(int[] nums) {
length = nums.length;
List<Integer> select = new ArrayList<Integer>();
helper(select,nums,0);
return result;
}
//s代表已取出的数,nums则是有所有数的池子,pos代表要取第几个位置的数
public void helper(List<Integer> s,int[] nums,int pos){
//跳出条件是已取了池子里所有的数,完成一次排列
if(pos == length){
result.add