回溯算法学习
描述:在算法问题中,先试探某一条路径是否可行,不可行则回到上一步换一条路径再次尝试。
在回溯算法中,不断向前尝试,失败则回退继续尝试,一直到所有的可能性尝试完后得到最终的结果。
算法示例:八皇后问题。
leetcode中两个相似的回溯算法问题:
给定集合的所有子集
给定整数(数组)的指定长度的所有组合。给定的整数相当于从 1 到 n 的数组。
例如:给定整数 4,指定组合长度 2 , 则所有组合为[[1, 2], [1, 3], [1, 4], [2, ,3], [2, 4], [3, 4]];
在leetcode中,上述两个问题的采用回溯法,利用递归基本代码十分相似。
采用回溯法中,现在集合中加入当前元素,在尝试下一个元素,回溯到当前元素时,集合中没有当前元素,然后再次向下尝试。(这两个问题的相似点都是在一条路径的某个节点,都是产生有或没有当前元素两种情况)。
public class Combination {
private List<List<Integer>> result;
public List<List<Integer>> combine(int n, int k) {
result = new ArrayList<List<Integer>>();
List<Integer> list = new ArrayList<Integer>();
combineRecursive(n, k, list, 1);
return result;
}
public void combineRecursive(int n, int k, List<Integer> list, int curPos) {
if (list.size() == k) {
result.add(new ArrayList<Integer>(list));
return;
}
if (curPos <= n) {
//有当前元素的组合
list.add(curPos);
combineRecursive(n, k, list, curPos + 1);
//没有当前元素的组合
list.remove(new Integer(curPos));
combineRecursive(n, k, list, curPos + 1);
}
}
}
public class Subset {
private List<List<Integer>> result;
public List<List<Integer>> subset(int[] nums) {
result = new ArrayList<List<Integer>>();
List<Integer> list = new ArrayList<Integer>();
subsetRecursive(nums, 0, list);
return result;
}
public void subsetRecursive(int[] nums, int pos, List<Integer> list) {
if (pos == nums.length) {
result.add(new ArrayList<Integer>(list));
return;
}
//当前位置有该元素
list.add(nums[pos]);
subsetRecursive(nums, pos + 1, list);
//当前位置没有该元素
list.remove(new Integer(nums[pos]));
subsetRecursive(nums, pos + 1, list);
}
}
其他类似问题有待添加!