0040_Combination Sum II

来源:互联网 发布:幼儿园营养分析软件 编辑:程序博客网 时间:2024/06/05 07:39

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]]

JAVA

方法一

  与上一题相似,这里还是采用递归的方式,只不过由于输入的数组中存在重复元素,而要求的结果中不允许有重复的结果集合,因此需要向对输入的数组排序,然后通过移动下标跳过重复的元素。
  最初只考虑的不从同一个元素开始,所以只在第一次进入循环的时候跳过了重复元素。在实际运行过程中发现,当输入数组是{2,2,2,2},target=4的时候,依然会出现多个重复的结果{2,2}。这是由于虽然由于起始不重复的限制,进入递归的初始下标为0,下标1,2,3均不会作为初始值进入递归,但是在递归内部,会出现下标为{0,1}{0,2}{0,3}的组合,由于下标1、2、3对应的值是相同的,所以最终形成的结果是重复的。
  因此需要在递归的过程中,也加入重复值的判断,但是还要保证可以出现相同的数字构成target,例如上例中的结果就是{2,2},两个元素是相同的。一开始没想出来如何避免重复的同时又允许重复数字出现,在经过3个星期的加班之后,忽然发现有办法实现:当每次递归结束返回上一层时,上一层来判断进入下一层递归的起始位置。本质上还是要控制递归的起始下标来跳过重复元素。但是由于下标在最开始的时候回指向重复数字中的第一个,该位置后面的值都是可用的,因此可以满足使用重复的数字构成target。当起始下标后移的时候跳过重复元素,即可实现最终的结果中不存在重复集合的目的。
  当输入集合为{1,2,2,2,3,4,7},target=5的时候,第一层递归的起始下标为0,第二层递归的起始下标为1,第三层递归的起始下标为2,此时对应的元素和=target,所以将下标为{0,1,2}的数字加入结果集合中。然后第三层递归结束,返回上一层,第二层递归的下标加1等于2,此时由于NUMS[2]==NUMS[1],因此跳过,下标再加1变为3,此时仍然NUMS[3]==NUMS[2],再次跳过,下标再加1变为4,以此类推。
  效率排在前1/5。

public class Solution {    public List<List<Integer>> combinationSum2(int[] candidates, int target) {        List<List<Integer>> result = new LinkedList<List<Integer>>();        LinkedList<Integer> tempResult = new LinkedList<Integer>();        if(candidates.length != 0){            Arrays.sort(candidates);            for (int i = 0; i < candidates.length; i++) {                if (i != 0 && candidates[i] == candidates[i-1]){                    continue;                }                getResult(candidates,target,result,i,0,tempResult);            }        }        return result;    }    public void getResult(int[] candidates, int target,List<List<Integer>> result,                          int currentIndex,int currentSum,LinkedList<Integer> tempResult){        currentSum += candidates[currentIndex];        tempResult.add(candidates[currentIndex]);        if(currentSum == target){            result.add((LinkedList)tempResult.clone());        }        while(currentIndex+1 < candidates.length && currentSum + candidates[currentIndex] <= target){            getResult(candidates,target,result,currentIndex+1,currentSum,tempResult);            ++currentIndex;            while(currentIndex < candidates.length - 1 && candidates[currentIndex] == candidates[currentIndex + 1]){                ++currentIndex;            }        }        tempResult.removeLast();    }}
原创粉丝点击