您的位置:首页 > 其它

【LeetCode】Combination Sum - Medium

2018-03-05 17:16 357 查看
数字组合

给出一个候选数字的set(C)和目标数字(T),找到C中所有的组合,使找出的数字和为T。C中的数字可以无限制重复被选取。

例如,给出候选数组[2,3,6,7]和目标数字7,所求的解为:

[7],

[2,2,3]

注意事项

所有的数字(包括目标数字)均为正整数。

元素组合(a1, a2, … , ak)必须是非降序(ie, a1 ≤ a2 ≤ … ≤ ak)。

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

您在真实的面试中是否遇到过这个题?

样例

给出候选set[2,3,6,7]和目标数字7

返回 [[7],[2,2,3]]

标签

数组 回溯法

(1)Java

// version 2: reuse candidates array
public class Combination_Sum {

public List<List<Integer>> combinationSum(int[] nums, int targetSum) {
List<List<Integer>> result = new ArrayList<>();
if (nums == null) {
return result;
}

List<Integer> item = new ArrayList<>();
Arrays.sort(nums);
helper(nums, 0, targetSum, item, result);
return result;
}

private void helper(int[] nums, int startIndex, int targetSum,
List<Integer> item,
List<List<Integer>> result) {
if (targetSum == 0) {
result.add(new ArrayList<>(item));
return;
}

for (int i = startIndex; i < nums.length; i++) {
if (nums[i] > targetSum) {
break;
}
if (i != startIndex && nums[i] == nums[i - 1]) {// 去重: 若集合中有重复数字,则跳过
continue;
}

item.add(nums[i]);
helper(nums, i, targetSum - nums[i], item, result);
item.remove(item.size() - 1);
}
}
}

<
b693
span class="hljs-comment">// version 1: Remove duplicates & generate a new array
class Solution2 {
/**
* @param candidates: A list of integers
* @param target:An integer
* @return: A list of lists of integers
*/
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> results = new ArrayList<>();
if (candidates == null || candidates.length == 0) {
return results;
}

int[] nums = removeDuplicates(candidates);

dfs(nums, 0, new ArrayList<Integer>(), target, results);

return results;
}

private int[] removeDuplicates(int[] candidates) {
Arrays.sort(candidates);

int index = 0;
for (int i = 0; i < candidates.length; i++) {
if (candidates[i] != candidates[index]) {
candidates[++index] = candidates[i];
}
}

int[] nums = new int[index + 1];
for (int i = 0; i < index + 1; i++) {
nums[i] = candidates[i];
}

return nums;
}

private void dfs(int[] nums,
int startIndex,
List<Integer> combination,
int remainTarget,
List<List<Integer>> results) {
if (remainTarget == 0) {
results.add(new ArrayList<Integer>(combination));
return;
}

for (int i = startIndex; i < nums.length; i++) {
if (remainTarget < nums[i]) {
break;
}
combination.add(nums[i]);
dfs(nums, i, combination, remainTarget - nums[i], results);
combination.remove(combination.size() - 1);
}
}
}


(2)C++

class Combination_Sum{
public:
vector<vector<int>> combinationSum2(vector<int>& nums, int target){
vector<vector<int>> result;
vector<int> item;
set<vector<int>> res_set;
sort(nums.begin(), nums.end());
generate(0, nums, result, item, res_set, 0, target);
return result;
}
private:
void generate(int i, vector<int>& nums,
vector<vector<int>>& result,
vector<int>& item,
set<vector<int>> res_set,
int sum, int target){// 比上例多定义一个sum,用于"剪枝"。(sum为当前子集item中的元素和)
if(sum > target || i >= nums.size())
return;
sum += nums[i];
item.push_back(nums[i]);
if(target == sum && res_set.find(item) == res_set.end()){// 当item中的元素和sum即为target 且该结果尚未添加(未发生重复)时
result.push_back(item);
res_set.insert(item);
}
generate(i + 1, nums, result, item, res_set, sum, target);
sum -= nums[i];// 新增: 回溯后,sum将nums[i]减去 并从item集合中移除。
item.pop_back();
generate(i + 1, nums, result, item, res_set, sum, target);
}

};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: