(Java)LeetCode-40. Combination Sum II

Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.

Each number in C may only be used once in the combination.

Note:

  • All numbers (including target) will be positive integers.
  • The solution set must not contain duplicate combinations.

For example, given candidate set [10, 1, 2, 7, 6, 1, 5] and target 8
A solution set is: 

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

这道题和前一题很像,只不过这题的数组里面的数只能用一次,而且会有重复。

我本来采用跟上一题一样的算法,代码都快写好了,又想到了一个更简便更直观的,就是正宗的回溯,感觉上一题的不够成熟,有点难读。

此题数组里重复数字,带来一个问题就是会得到重复的List,我之前的想法是用Set来去除重复,经过检验会大大拖慢速度,需要在算法中改进。后来百度了一下看了别人的代码,发现假设如果数组里有多个1的话,那么将第一个1放入list之后回溯会得到所有包含这个1的情况,那么就不再需要将后面的1再放入数组中再回溯了,从而去除了重复的情况。比如数组为[1,1,1,1,2],目标是3,那么将第一个1放入list后回溯,变成[1,1,1,2],目标是2,会得到两个数组[1,1][2],再加上第一个1,就是[1,1,1][1,2],这包含了所有的含有1的情况,不需再考虑后面的1了,从而避免重复数组。这是比较容易理解的,实际模拟一下算法运行过程即可。 

代码如下:

public class Solution {public List> combinationSum2(int[] candidates, int target) {
		Arrays.sort(candidates);
		List> result = new ArrayList>();
		List list = new ArrayList();
		combinationSum(result, list, candidates, target, 0);
		return result;
    }
	
	private void combinationSum(List> result, List list, int[] candidates, int target, int index){

		for(int i = index; i < candidates.length; i++){
			int temp = candidates[i];
			if(temp == target){
				list.add(temp);
				result.add(new ArrayList(list));
				list.remove(list.size()-1);
				break;
			}
			if(candidates[i] < target){
				list.add(candidates[i]);
				combinationSum(result, list, candidates, target - temp, i + 1);
				list.remove(list.size()-1);
				while(i < candidates.length-1 && candidates[i] == candidates[i+1]){
					i++;
				}
			}
			if(temp > target){
				break;
			}
		}
	}}





你可能感兴趣的:(JAVA,LeetCode)