java combinationsum_[Leetcode] Combination Sum 组合数之和

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 {

List> res;

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

res = new LinkedList>();

List tmp = new LinkedList();

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

Arrays.sort(candidates);

helper(candidates, target, 0, tmp);

return res;

}

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

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

if(target < 0){

return;

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

} else if(target == 0){

List oneComb = new LinkedList(tmp);

res.add(oneComb);

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

} else {

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

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);

}

}

}

}

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.

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]

[1, 1, 6]

深度优先搜索

复杂度

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

思路

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

代码

public class Solution {

List> res;

public List> combinationSum2(int[] candidates, int target) {

res = new LinkedList>();

List tmp = new LinkedList();

Arrays.sort(candidates);

helper(candidates, target, 0, tmp);

return res;

}

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

if(target < 0){

return;

} else if(target == 0){

List oneComb = new LinkedList(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++;

}

}

}

}

}

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> res;

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

res = new LinkedList>();

List tmp = new LinkedList();

helper(k, n, 1, tmp);

return res;

}

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

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

return;

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

List oneComb = new LinkedList(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);

}

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
package com.hexiang.utils.arrange; public class TryCombination{ public static void main(String[] args){ System.out.println("对整数数组进行组合:C(n,n)"); int[] intArray=new int[4]; for(int i=0;i<intArray.length;i++){ intArray[i]=i+1; } System.out.println("对整数数组进行组合:C(4,4)"); Combination intCombination1=new Combination(intArray.length); while(intCombination1.hasMore()){ int[] index=intCombination1.getNext(); for(int i=0;i<intArray.length;i++){ if(index[i]!=0){ System.out.print(intArray[index[i]*i]+" "); } } System.out.println(); } System.out.println("对整数数组进行组合:C(4,3)"); Combination intCombination2=new Combination(intArray.length,3); while(intCombination2.hasMore()){ int[] index=intCombination2.getNext(); for(int i=0;i<intArray.length;i++){ if(index[i]!=0){ System.out.print(intArray[index[i]*i]+" "); } } System.out.println(); } String str="abcd"; char[] chArray=str.toCharArray(); System.out.println("对字符数组进行组合:C(4,4)"); Combination strCombination1=new Combination(chArray.length); while(strCombination1.hasMore()){ int[] index=strCombination1.getNext(); for(int i=0;i<chArray.length;i++){ if(index[i]!=0){ System.out.print(chArray[index[i]*i]+" "); } } System.out.println(); } System.out.println("对字符数组进行组合:C(4,3)"); Combination strCombination2=new Combination(chArray.length,3); while(strCombination2.hasMore()){ int[] index=strCombination2.getNext(); for(int i=0;i<chArray.length;i++){ if(index[i]!=0){ System.out.print(chArray[index[i]*i]+" "); } } System.out.println(); } } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值