“子集”型回溯真的懂了呀系列《回溯:选子集和子序列的哪一个或者不选》

70 阅读1分钟

如果有明显的递推痕迹,直接dp表顺序填写,考虑初始化的意义。如果没有规则需要探索,就考虑回溯,考虑合法的边界

Problem: LCR 079. 子集

[TOC]

思路

// 子集:子集型回溯,“选择不选” 和 “枚举选哪个”

//生成子集的思考方式:
// ===========【从 “输入” 的角度】=====================
// 递归入口和入口:枚举范围从 i [ 0 ~ n)

// 当前操作?:每一层要做的事情,这个元素,选择 或者 不选择

// 子问题: 下标 >= i层 “选择” 或 “不选择”,构造子集

// 下一个子问题:下标 >= i+1 层 “选择” 或 “不选择”,构造子集

Code

class Solution {
    int[] nums;
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> pick = new ArrayList();
    public List<List<Integer>> subsets(int[] nums) {
        this.nums = nums;
        int n = nums.length;
        dfs(0);
        return res;
    }

    public void dfs(int i){
        if(i == nums.length){
            //有效结果
            //全局变量拷贝为每个有效答案,形成结果
            ArrayList<Integer> copy = new ArrayList<>();
            copy.addAll(pick);
            res.add(copy);
            return;
        }

        //“不选”
        dfs(i+1);

        //“选择”
        int x = nums[i];
        pick.add(x);
        dfs(i+1);
        //"恢复递归前的样子"
        pick.remove(pick.size()-1);
    }
}