回溯法,子集,组合问题
一.题源
https://www.lintcode.com/problem/subsets/description
https://leetcode-cn.com/problems/subsets/
二.代码
public class Solution {
public static void main(String[] args) {
int[] arr = new int[]{0,1,2,3,4} ;
ArrayUtils.displayArrayList(subsets(arr));
}
public static List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
backTrace(result,new ArrayList<Integer>(),nums,0);
return result;
}
/**
* 回溯法找子集
* @param result 结果集
* @param list 局部结果
* @param nums 原始数据
* @param pos 记录当前回溯的位置
*/
private static void backTrace( List<List<Integer>> result,List<Integer> list,int[] nums,int pos){
//将局部结果加入结果集中,包括空集
result.add(new ArrayList<>(list));
for (int i = pos; i < nums.length; i++) {
//当前遍历到的数加入局部集
list.add(nums[i]);
//递归,从i+1开始找
backTrace(result,list,nums,i+1);
//移除上一次加入的数
list.remove(list.size()-1);
}
}
}
输出结果
[
[],
[0],
[0,1],
[0,1,2],
[0,1,2,3],
[0,1,2,3,4],
[0,1,2,4],
[0,1,3],
[0,1,3,4],
[0,1,4],
[0,2],
[0,2,3],
[0,2,3,4],
[0,2,4],
[0,3],
[0,3,4],
[0,4],
[1],
[1,2],
[1,2,3],
[1,2,3,4],
[1,2,4],
[1,3],
[1,3,4],
[1,4],
[2],
[2,3],
[2,3,4],
[2,4],
[3],
[3,4],
[4]
]
三.图解分析

一次循环:
for(0:4)
list.add(0) (list :[0])----->第一层递归
for(1:4)
list.add(1) (list [0,1])------->第二层递归
for(2:4)
list.add(2) (list [0,1,2]) ------>第三层递归
list.remove(2) (list[0,1])
list.add(3) (list [0,1,3]) ----->第三层递归
list.remove(1) (list [0])
list.add(2) (list [0,2])------->第二次递归
.........
list.remove(0) (list [])
list.add(1) (list [1])---->第一层递归
.....
四.总结
好处:实现简单,代码简洁。
适用场景:数据集规模不大。
缺点:复杂度略高,复杂度为 O(n!) ,阶乘级别.
浙公网安备 33010602011771号