回溯法简介:
用于:求解满足调节的全部解,类似于穷举
思想:类似于树的深度遍历,从根节点出发,有活结点与死节点
其他:有"通用解题法"之美誉
一点提醒:
在刷题过程中,尽量套用模板,在体现一种思路的模板上进行更改,由此可以达到降低思维难度,统一解题风格,降低出错概率的目的!
在
中, #二. 回溯法实现 - 递归和递推(迭代) ##1. 递归 部分, 给出了统一模板,结合该模板,能快速理解本题!
import java.util.*;
public class Solution {
/**
* 该递归函数完成后,result中是: 在 arr 中 选择k个数字的全部组合(无重复)。
* @param k 选择k个数字的组合
* @param start 从数组的 start位置 开始
* @param list 一个组合
* @param arr 原数组
* 第一次接触回溯法,羞耻参考大佬题解:NC27 集合的所有子集(一) (回溯) @小灰灰QAQ
* 答题来看,题解遵循https://blog.csdn.net/weiyuefei/article/details/79316653
*"二. 回溯法实现 - 递归和递推(迭代) 1. 递归"中的模板,看完该文章后,能更好理解!
*/
ArrayList<ArrayList<Integer>> result = new ArrayList<>();
int[] S1;
public ArrayList<ArrayList<Integer>> subsets(int[] S) {
S1=S;
for(int i=0;i<=S.length;i++){
backTracing(i,0,new ArrayList<>());
}
return result;
}
public void backTracing(int k, int start, List<Integer> list) {
if(k==0){
result.add(new ArrayList(list));
}else{
for (int i = start; i < S1.length; i++) {
list.add(S1[i]);
//上一行代码选择了一个数字 , 接着对于剩余数字 做组合。 k-1 表示接下来少选一个数,i+1表示 从数组的i+1开始
backTracing(k - 1, i + 1, list);
// 去掉 arr[i] , 下一轮循环跳过这个数。 数组内每一个元素 都有两种状态:选或者不选。
list.remove(list.size() - 1);
}
}
}
}
时间复杂度:2^n 空间复杂度:2^n (看着唬人,可是这题目时空复杂度确实必须这样,由运行结果可知,该解法还是较优的)
运行结果: