LeetCode-组合总和 II

132 阅读1分钟

算法记录

LeetCode 题目:

  给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。


说明

一、题目

  candidates 中的每个数字在每个组合中只能使用 一次 。

  注意: 解集不能包含重复的组合。

二、分析

  • 分析题意可知就是一个全排列的问题,但是针对于边界的处理需要注意分析。
  • 从前往后进行贪心排列,但是一旦相同位置出现相同的数据这种情况肯定是已经记录过的,所以此种情况需要进行筛出。
  • 上面的边界判断不能解决下一个位置重复的情况,也就是不在当前的整个贪心过程中,这样有可能就会出现数据完全相同的情况,这种边界的处理就是直接进行记录即可,因为是完全相同的数据,因此很好进行判断。
  • 注意数组的前期排序解决相邻数据重复问题。
class Solution {
    private List<List<Integer>> ret = new ArrayList();
    private Set<Integer> map = new HashSet();
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        List<Integer> temp = new ArrayList();
        Arrays.sort(candidates);
        dfs(candidates, target, 0, temp);
        return ret;
    }
    private void dfs(int[] candidates, int target, int start, List<Integer> temp) {
        if(target == 0) {
            if(map.contains(get(temp))) return;
            map.add(get(temp));
            ret.add(new ArrayList(temp));
            return;
        }
        for(int i = start; i < candidates.length; i++) {
            if(candidates[i] > target) continue;
            if(start != i && candidates[i] == candidates[start]) continue;
            temp.add(candidates[i]);
            dfs(candidates, target - candidates[i], i + 1, temp);
            temp.remove(temp.size() - 1);
        }
    }
    public int get(List<Integer> temp) {
        int ret = 0;
        for(int i : temp) ret = ret * 10 + i;
        return ret;
    }
}

总结

硬编码能力,注意边界的判断。