您的位置:首页 > 编程语言 > Java开发

[Java代码] [Leetcode] Combination Sum 组合数之和

2016-03-18 15:44 549 查看
Combination Sum I

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

The same repeated number may be chosen from C unlimited number of times.

Note: All numbers (including target) will be positive integers. Elements in a combination (a1, a2, … , ak) must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤ ak). The solution set must not contain duplicate combinations. For example, given candidate set 2,3,6,7
and target 7, A solution set is:

[7]

[2, 2, 3]

复制代码
深度优先搜索 复杂度

时间 O(N!) 空间 O(N) 递归栈空间
思路

因为我们可以任意组合任意多个数,看其和是否是目标数,而且还要返回所有可能的组合,所以我们必须遍历所有可能性才能求解。为了避免重复遍历,我们搜索的时候只搜索当前或之后的数,而不再搜索前面的数。因为我们先将较小的数计算完,所以到较大的数时我们就不用再考虑有较小的数的情况了。这题是非常基本且典型的深度优先搜索并返回路径的题。本题需要先排序,不然过不了Leetcode。
注意

要先问清楚什么样的组合是有效的,比如该题,是可以连续选择同一个数加入组合的。
代码

public class Solution {
http://www.nvzi91.cn/fujianyan/29948.html
List<List<Integer>> res;

public List<List<Integer>> combinationSum(int[] candidates, int target) {

res = new LinkedList<List<Integer>>();

List<Integer> tmp = new LinkedList<Integer>();

// 先将数组排序避免重复搜素

Arrays.sort(candidates);

helper(candidates, target, 0, tmp);

return res;

}http://www.nvzi91.cn/chunvmoxiufu/29949.html

private void helper(int[] nums, int target, int index, List<Integer> tmp){

// 如果当前和已经大于目标,说明该路径错误

if(target < 0){

return;

// 如果当前和等于目标,说明这是一条正确路径,记录该路径

} else if(target == 0){

List<Integer> oneComb = new LinkedList<Integer>(tmp);

res.add(oneComb);

// 否则,对剩余所有可能性进行深度优先搜索

} else {http://m.nvzi91.cn/gongjingjibin
4000
g/29360.html

// 选取之后的每个数字都是一种可能性

for(int i = index; i < nums.length; i++){

// 典型的先加入元素,再进行搜索,递归回来再移出元素的DFS解法

tmp.add(nums[i]);

helper(nums, target - nums[i], i, tmp);

tmp.remove(tmp.size() - 1);

}http://www.nvzi91.cn/niaodaoyan/29950.html

}

}

}http://www.nvzi91.cn/chunvmoxiufu/29951.html 

复制代码
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.http://m.nvzi91.cn/gongjingmilan/29359.html

Elements in a combination (a1, a2, … , ak) must be in non-descending

order. (ie, a1 ≤ a2 ≤ … ≤ ak). 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]http://www.nvzi91.cn/yindaoyan/29952.html

[1, 1, 6]www.nvzi91.cn    www.kmrlyy.com

复制代码
深度优先搜索 复杂度

时间 O(N!) 空间 O(N) 递归栈空间
思路

这题和I的区别在于同一个数只能取一次,比如数组中只有3个1,那结果中也最多只有3个1,而且结果也不能重复。所以我们在递归时首先要把下标加1,这样下轮搜索中就排除了自己。其次,对一个数完成了全部深度优先搜索后,比如对1完成了搜索,那么我们要把后面的1都跳过去。当然,跳过只是针对本轮搜索的,在对第一个1的下一轮的搜索中,我们还是可以加上第二个1。只是我们不能再以第二个1开头了而已。为了能连续跳过重复的数,这里我们必须先排序。
代码

public class Solution {
http://www.kmrlyy.com/fujianyan/33465.html
List<List<Integer>> res;
http://m.nvzi91.cn/gongjingfeida/29358.html
public List<List<Integer>> combinationSum2(int[] candidates, int target) {

res = new LinkedList<List<Integer>>();

List<Integer> tmp = new LinkedList<Integer>();

Arrays.sort(candidates);

helper(candidates, target, 0, tmp);

return res;m.nvzi91.cn

}http://www.kmrlyy.com/gongjingai/33469.html
http://www.kmrlyy.com/fujianyan/33466.html
private void helper(int[] nums, int target, int index, List<Integer> tmp){

if(target < 0){

return;

} else if(target == 0){

List<Integer> oneComb = new LinkedList<Integer>(tmp);

res.add(oneComb);

} else {

for(int i = index; i < nums.length; i++){

tmp.add(nums[i]);

// 递归时下标加1

helper(nums, target - nums[i], i+1, tmp);

tmp.remove(tmp.size() - 1);

// 跳过本轮剩余的重复元素

while(i < nums.length - 1 && nums[i] == nums[i + 1]){

i++;

}http://www.kmrlyy.com/penqiangyan/33467.html

}

}http://www.kmrlyy.com/gongjingai/33468.html

}

}

复制代码
Combination Sum III

Find all possible combinations of k numbers that add up to a number n, given that only numbers from 1 to 9 can be used and each combination should be a unique set of numbers.

Ensure that numbers within the set are sorted in ascending order.

Example 1:

Input: k = 3, n = 7

复制代码

Output:

[[1,2,4]]

复制代码

Example 2:

Input: k = 3, n = 9

复制代码

Output:

[[1,2,6], [1,3,5], [2,3,4]]

复制代码
深度优先搜索 复杂度

时间 O(9!) 空间 O(9) 递归栈空间
思路

这题其实是II的简化版,设想一个[1,2,3,4,5,6,7,8,9]的数组,同样一个元素只能取一次,但是已经预先确定没有重复了。所以可以省去跳过重复元素的部分。不过,我们在递归的时候要加一个额外的变量k来控制递归的深度,一旦超过了预设深度,就停止该分支的搜索。本质上是有限深度优先搜索。
代码

public class Solution {

List<List<Integer>> res;

public List<List<Integer>> combinationSum3(int k, int n) {

res = new LinkedList<List<Integer>>();

List<Integer> tmp = new LinkedList<Integer>();

helper(k, n, 1, tmp);

return res;

}

private void helper(int k, int target, int i, List<Integer> tmp){

if(target < 0 || k < 0){

return;

} else if (target == 0 && k == 0){

List<Integer> oneComb = new LinkedList<Integer>(tmp);

res.add(oneComb);

} else {

for(int j = i; j <= 9; j++){

tmp.add(j);

helper(k-1, target-j, j+1, tmp);

tmp.remove(tmp.size() - 1);

}

}

}

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