回溯算法:求子集问题

78. 子集

给你一个整数数组nums,数组中的元素互不相同。返回该数组所有可能的子集(幂集)。

解集不能包含重复的子集。你可以按任意顺序返回解集。

输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]

输入:nums = [0]
输出:[[],[0]]

思路

如果把子集问题、组合问题、分割问题都抽象为一棵树的话,那么组合问题和分割问题都是收集树的叶子节点,而子集问题是找树的所有节点!

回溯三部曲

1.递归函数参数
全局变量temp为子集收集元素,ans存放子集组合。
取过的元素不会重复取,写回溯算法的时候,for就要从startIndex开始,而不是从0开始。

    List<Integer> temp = new ArrayList<Integer>();
    List<List<Integer>> ans = new ArrayList<List<Integer>>();
    private void backtracking(int[] nums, int startIndex) {}

2.递归终止条件
剩余集合为空的时候,就是叶子节点。就是startIndex已经大于数组的长度了,就终止了,因为没有元素可取了。

3.单层搜索逻辑
求取子集问题,不需要任何剪枝!因为子集就是要遍历整棵树。

代码

class Solution {
    List<Integer> temp = new ArrayList<Integer>();
    List<List<Integer>> ans = new ArrayList<List<Integer>>();

    public List<List<Integer>> subsets(int[] nums) {
        backtracking(nums,0);
        return ans;
    }
    private void backtracking(int[] nums, int startIndex) {
        ans.add(new ArrayList<>(temp)); // 收集子集
        if (startIndex >= nums.length) { // 终止条件可以不加
            return;
        }
        for (int i = startIndex; i < nums.length; i++) {
            temp.add(nums[i]);
            backtracking(nums, i + 1);
            temp.remove(temp.size()-1);
        }
    }
}
posted @ 2021-05-19 11:17  当康  阅读(402)  评论(0编辑  收藏  举报