11,201
社区成员
发帖
与我相关
我的任务
分享
给定一个数组 candidates
和一个目标数 target
,找出 candidates
中所有可以使数字和为 target
的组合。
candidates
中的每个数字在每个组合中只能使用一次。
说明:
示例 1:
输入: candidates = [10,1,2,7,6,1,5], target = 8,
所求解集为:[[1, 7],[1, 2, 5],[2, 6],[1, 1, 6]]
示例 2:
输入: candidates = [2,5,2,1,2], target = 5,
所求解集为:[[1,2,2],[5]]
这个不对?
class Solution {
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);
List<List<Integer>> res = new ArrayList<List<Integer>>();
if (target == 0)
return res;
List<Integer> tmp = new ArrayList<Integer>();
helper(candidates, target, 0, tmp, res);
return res;
}
public void helper(int[] a, int target, int start, List<Integer> tmp, List<List<Integer>> res) {
if (target < 0)
return;
if (target == 0) {
res.add(new ArrayList<Integer>(tmp));
return;
}
for (int i = start; i < a.length; i++) {
tmp.add(a[i]);
int newtarget = target - a[i];
helper(a, newtarget, i + 1, tmp, res);
tmp.remove(tmp.size() - 1);
if (newtarget <= 0)
break;
while (i + 1 < a.length && a[i] == a[i + 1])// 组合中有重复元素,不要重复开头
i++;
}
}
}
传参名有问题是真的眼睛快看瞎了
有个愚见,全排列组合,不知道是不是计算量太大了
import itertools
candidates = [10,1,2,7,6,1,5]
candidates.sort()
target = 8
list1=[]
for j in range(1,len(candidates)+1):
for i in list(itertools.combinations(candidates,j)):
if sum(i)==target and i not in list1:
list1.append(i)
print(list1)
#include <stdio.h>
#include <stdlib.h>
#define N 32
int main(int argc,char* argv[])
{
void cbk_print(int * arr,int len);
void mySort(int * arr,int len);
void combine( int* data , int dataLen,int * out , int outLen ,int tag );
int s[N]={10,1,2,7,6,1,5} , r[N] , tag=8;
int len= 7 ;
mySort(s,len);
printf("\n");
combine( s,len ,r,0 ,tag);
return 0 ;
}
void mySort(int * arr,int len)
{
for(int i=0 ;i<len-1 ; i++)
for(int j=i+1 ;j<len ; j++)
{
if(arr[i]<arr[j])
{
int tmp=arr[i] ;
arr[i]=arr[j] ;
arr[j]=tmp ;
}
}
}
void cbk_print(int * arr,int len)
{
printf("[ %d",arr[0]);
for(int i = 1; i < len; i++)
{
printf(" , %d", arr[i]);
}
printf(" ]\n");
}
void combine( int* data , int dataLen,int * out , int outLen ,int tag )
{
for(int i = dataLen; i >0; i--)
{
int vol=data[i-1] ;
if(i != dataLen && vol==data[i])continue ;
if(vol==tag)
{
out[outLen]=vol ;
cbk_print(out,outLen+1) ;
break ;
}
if(vol>tag)
{
break ;
}
out[outLen]=vol ;
combine(data , i-1,out , outLen+1 , tag-vol);
}
}
candidates.sort()
能够保证元素从小到大排序,方便进行元素搜索;dp
数组用于存储构成各目标数值的所有组合的索引;target == 0
的情况,只可能是空集;target > 0
的情况,从小到大依次选择 1 个元素x
,查找是否有组合方式的所有元素位于选取的元素左侧,且累加值为target - x
,将x
添加刀组合末尾,构成满足元素综合为target
的新组合方式;dp
中组合方式的索引值转换为实际元素值,用字典进行去重。class Solution(object):
def combinationSum2(self, candidates, target):
"""
:type candidates: List[int]
:type target: int
:rtype: List[List[int]]
"""
candidates.sort()
dp = [[] for _ in range(target + 1)]
dp[0].append([])
for i in range(1, target + 1):
for j in range(len(candidates)):
if candidates[j] > i:
break
for k in range(len(dp[i - candidates[j]])):
temp = dp[i - candidates[j]][k][:]
if len(temp) > 0 and temp[-1] >= j:
continue
temp.append(j)
dp[i].append(temp)
res = []
check = {}
for temp in dp[target]:
value = [candidates[t] for t in temp]
try:
check[str(value)] += 1
except KeyError:
check[str(value)] = 1
res.append(value)
return res
通过try-except进行解集去重时,check[str(value)] /= 1
、check[str(value)] %= 1
等等应该也对吧。
回溯算法解决
假的吧