LeetCode90 子集 II 排序+子问题求解

LeetCode90 子集 II 排序+子问题求解

nums={1,2,2,3}为例,将问题划分为求nums={1}nums={2,2}, nums={3}三个子问题,然后将子结果合并。这里子问题是求非空子集

求子问题

  1. nums={1} 的非空子集 {{1}}
  2. nums={2,2}的非空子集 {{2},{2,2}}
  3. nums={3} 的非空子集 {{3}}

合并子结果

  1. {{1}}{{2},{2,2}}的组合:

    • 只使用 nums={1}的结果,即{{1}}
    • 只使用nums={2,2}的结果,即{{2},{22}}
    • 使用nums={1}nums={2}组合的结果, {{1,2},{1,2,2}}
    • 综上三种情况:组合的结果为 {{1},{2},{22},{1,2},{1,2,2}},然后再将结果与nums={3}的结果组合
    // 组合代码
    /**
         * 将两个子结果组合
         * @param listA
         * @param listB
         * @return
         */
    public static List<List<Integer>> group(List<List<Integer>> listA, List<List<Integer>> listB) {
        List<List<Integer>> res = new ArrayList<>();
        // 只使用子结果A
        res.addAll(listA);
        // 只使用子结果B
        res.addAll(listB);
        // 即使用子结果A 也使用 子结果B
        for (List<Integer> itemA : listA) {
            for (List<Integer> itemB : listB) {
                List<Integer> sub = new ArrayList<>(itemA);
                sub.addAll(itemB);
                res.add(sub);
            }
        }
        return res;
    }
    

划分子问题

  1. 排序
  2. 将连续相等的数字作为一个子问题求解

代码

class Solution {
    public List<List<Integer>> subsetsWithDup(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        // 排序, 用于避免重复
        Arrays.sort(nums);
        // 当前下标
        int index = 0;
        // nums[index] = nums[j];  j in [index+1, index+continued)
        int continued = 1;

        while (index < nums.length) {
            // 这里需要重置 continued
            continued = 1;
            while (index + continued < nums.length && nums[index] == nums[index + continued]) {
                continued++;
            }
            List<List<Integer>> sub = subSolution(nums[index], continued);
            res = group(res, sub);
            index+=continued;
        }
        // 添加空集
        List<Integer> empty = new ArrayList<>();
        res.add(empty);
        return res;
    }

    /**
         * 求子结果
         * num: 数字
         * n  : 重复次数
         */
    public List<List<Integer>> subSolution(int num, int n){
        List<List<Integer>> res = new ArrayList<>();
        res.add(new ArrayList<>(Arrays.asList(num)));
        for (int i = 1; i < n; i++) {
            res.add(new ArrayList<>(res.get(i - 1)));
            res.get(i).add(num);
        }
        return res;
    }

    /**
         * 将两个子结果组合
         * @param listA
         * @param listB
         * @return
         */
    public static List<List<Integer>> group(List<List<Integer>> listA, List<List<Integer>> listB) {
        List<List<Integer>> res = new ArrayList<>();
        // 只使用子结果A
        res.addAll(listA);
        // 只使用子结果B
        res.addAll(listB);
        // 即使用子结果A 也使用 子结果B
        for (List<Integer> itemA : listA) {
            for (List<Integer> itemB : listB) {
                List<Integer> sub = new ArrayList<>(itemA);
                sub.addAll(itemB);
                res.add(sub);
            }
        }
        return res;
    }
}

唉,又臭又长,距离一行代码还很遥远

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值