LeetCode-组合总和 II -题号40-Java实现

1、题目链接

组合总和 II

2、题目大意

本题是在组合总和的基础上进行了些许修改,建议大家先看组合总数的题解,以下为题目大意:
给定一个正整数数组 candidates 和一个正整数目标数 target,在数组中选择任意个数字,使其和等于目标数,问这样的选择方法有哪些。其中每个数字在每个组合中,只能选择一次。
题目同样要求组合不能重复。

3、样例输入

candidates = [10,1,2,7,6,1,5], target = 8
candidates = [2,5,2,1,2], target = 5

4、样例输出

[ [1, 7], [1, 2, 5], [2, 6], [1, 1, 6] ]
[ [1,2,2], [5] ]

5、思路

由于我是先做了组合总和,再做的本题,因此我的方法是在组合总和的方法基础上进行了修改。


本题中给的数组是有重复数字的,且数字只能使用一次,
而在组合总和这个题中的数组是没有重复数字的,且数字使用次数无限,因此作如下转换:
首先通过 map 集合记录所给数组中所有数字的出现次数,而后将 map 的 key 值集合转换为没有重复数字的数组,那么就可以直接使用组合总和中的递归函数来进行运算,只需在剪枝的时候,判断当前数字的使用次数是否已经用完即可。

6、代码

class Solution {
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        List<List<Integer>> ans = new ArrayList<>();
        Map<Integer, Integer> map = new TreeMap<>();
        for (int candidate : candidates) {
            map.put(candidate, map.get(candidate) == null ? 1 : map.get(candidate) + 1);
        }
        //System.out.println(map);
        int[] candidates2 = new int[map.size()];
        int i = 0;
        for (int num : map.keySet()) {
            candidates2[i++] = num;
        }
        dfs(map, candidates2, target, 0, new ArrayList<>(), ans);
        return ans;
    }
    private void dfs(Map<Integer, Integer> map, int[] candidates, int target, int index, List<Integer> list, List<List<Integer>> ans) {
        if (target == 0) {
            ans.add(list);
            return;
        }
        for (int i = index; i < candidates.length; i++) {
            if (map.get(candidates[i]) > 0 && target >= candidates[i]) {
                map.put(candidates[i], map.get(candidates[i]) - 1);
                list.add(candidates[i]);
                dfs(map, candidates, target - candidates[i], i, new ArrayList<>(list), ans);
                list.remove(list.size() - 1);
                map.put(candidates[i], map.get(candidates[i]) + 1);
            }
        }
    }
}

7、注意事项

本题代码的注意事项与组合总和的注意事项一致。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值