资讯详情

Leetcode T40: 组合总和II

题目描述

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

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

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

示例 1:

输入: candidates = [10,1,2,7,6,1,5] target = 8, 输出: [ [1,1,6], [1,2,5], [1,7], [2,6] ]

示例 2:

输入: candidates = [2,5,2,1,2], target = 5, 输出: [ [1,2,2], [5] ]

提示

1 <= candidates.length <= 100 1 <= candidates[i] <= 50 1 <= target <= 30

思路

和上一个问题一样,组合总和I一样使用dfs,但是,如果仍采用上一题的思路,尽管进行了剪枝,仍会超时。这里采用另一种dfs思路。 由于每个candidate[i][0, 因此,可以定义一个数组来记录每个元素的数量,然后根据这个数组dfs搜索。

代码

 List<List<Integer>> res = new ArrayList<List<Integer>>();  HashMap<List<Integer>, Integer> map = new HashMap<List<Integer>, Integer>();  int tar;  int[] nums = new int[51];    // 当前选择的组合选择了当前和, 剩下和  void dfs(List<Integer> lis, int cur,  int s, int ts) { 
           if(cur == 51) { 
            if(s == tar && map.getOrDefault(lis, -1)==-1) { 
        
				map.put(lis, 1);
			}
		} else { 
        
// for(int x: lis) System.out.print(x+","); System.out.println("\t"+cur+","+s);
			if(nums[cur] == 0) dfs(lis, cur+1, s, ts);
			else { 
        
				//对于当前数字
				//选,看是否超过,剪枝
				List<Integer> tmp = new ArrayList<Integer>(lis);
				for(int i = 1; i <= nums[cur]; i++) { 
        
					if(s + i*cur <= tar) { 
        
						tmp.add(cur);
						dfs(tmp, cur+1, s + i*cur, ts-i*cur);
					}
				}
				
				// 不选,如果剩下的都装仍不能满足,则剪枝
				if(s+ts-cur >= tar) { 
        
					List<Integer> tmp2 = new ArrayList<Integer>(lis);
					dfs(tmp2, cur+1, s, ts-cur);
				}
			}
		}
	}
	
    public List<List<Integer>> combinationSum2(int[] candidates, int target) { 
        
    	tar = target;
    	for(int x: candidates) nums[x]++;
    	int s = 0;
        for(int x: candidates) s += x;
        dfs(new ArrayList<Integer>(), 0, 0, s);
        for(List<Integer> lis: map.keySet()) { 
        
			res.add(lis);
		}
    	return res;
    }

标签: t40fm扭矩传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台