回溯法,子集,组合问题
一.题源
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!) ,阶乘级别.