题目描述:给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为
target 的组合。
candidates 中的数字可以无限制重复被选取
说明:
所有数字(包括 target)都是正整数。
解集不能包含重复的组合。
示例 1:
输入: candidates = [2,3,6,7], target = 7,
所求解集为:
[
[7],
[2,2,3]
]
示例 2:
输入: candidates = [2,3,5], target = 8,
所求解集为:
[
[2,2,2,2],
[2,3,3],
[3,5]
]
算法分析
- 首先判断特殊情况
如果数组为空,或者数组的长度为0或者目标值小于0,直接返回创建的空列表。 - 创建一个list用于存放满足条件的元组
执行函数process ,0为开始处理的下标,candidates为待处理数组,target为目标值,list同上。 - 因为target是在不停的自减,所以如果减去某一个数小于0,这种情况可以不需要考虑,如果targrt==0,表示之前递归的组合都是和为target,所以lists添加结果list,否则,需要依次从当前下标开始,迭代直到数组的最后一个数字,每次迭代list添加一个数,同时递归下一次,i为下一次的处理下标,candidates还是待处理数组,target-candidates【i】表示寻找和的组合需要发生变化了,list同上。
- 最后每一个递归结束后,都需要进行回溯,将选定的删除,回溯其他情况。
java语言实现
可以首先去了解一下ArrayDeque类的使用详解,再来看。
class Solution{
List<List<Integer>> lists = new ArrayList<>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
if (candidates == null || candidates.length == 0 || target < 0) {
return lists;
}
Arrays.sort(candidates);
process(0, candidates, target, new ArrayDeque<>());
return lists;
}
private void process(int start, int[] candidates, int target, Deque<Integer> path) {
//递归的终止条件
if (target < 0) {
return;
}
if (target == 0) {
lists.add(new ArrayList<>(path));
} else {
for (int i = start; i < candidates.length; i++) {
if(target-candidates[i]<0)
return ;
path.addLast(candidates[i]);
//因为每个数字都可以使用无数次,所以递归还可以从当前元素开始
process(i, candidates, target - candidates[i], path);
path.removeLast();
}
}
}
}
C语言实现
补习一下知识点
- 函数原型
void *memcpy(void *dest, const void *src, size_t n); - 功能
从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中 - 所需头文件
C语言中使用#include <string.h>; - 返回的值
函数返回指向dest的指针。
/**
* Return an array of arrays of size *returnSize.
* The sizes of the arrays are returned as *returnColumnSizes array.
* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
*/
#define maxanslen 1000
#define maxansnum 1000
int **res;
int *can;
int cansize;
int *retsize;
int cnt;
int path[maxanslen];
void addAns(int len)
{
res[cnt] = (int *)malloc(sizeof(int) * (len));
memcpy(res[cnt], path, sizeof(int) * (len));
retsize[cnt] = len;
cnt++;
}
void getans(int target,int ind,int start)
{
int newtar=0;
for(int i=start;i<cansize;i++)
{
newtar=target-can[i];
if(newtar<0)
continue;
else if(newtar==0)
{
path[ind]=can[i];
addAns(ind+1);
}
else{
path[ind]=can[i];
getans(newtar,ind+1,i);
}
}
}
int** combinationSum(int* candidates, int candidatesSize, int target, int* returnSize, int** returnColumnSizes){
if(target==0||candidatesSize==0){
*returnSize=0;;
return 0;
}
res=(int **)malloc(sizeof(int*) *maxansnum);
*returnColumnSizes=(int*)malloc(sizeof(int)*maxansnum);
retsize=*returnColumnSizes;
can=candidates;
cansize=candidatesSize;
cnt=0;
getans(target,0,0);
*returnSize=cnt;
return res;
}