思路:这题和前面的39.组合 有区别,当前数组有重复元素,并且每个数字在组合中只能使用一次。我们要让其没有重复的组合,就相当于在每一层中不可重复选取同一个元素。
我们首先要做的就是对数组排序,关于快速排序:C语言:qsort()解析
还是一样的回溯三部曲。
- 参数:需要sum来计算总和和startIndex来控制开始的位置。
- 终止条件:当sum==target时,以及sum>target时。
- 单层逻辑:从startIndex开始搜索candidates。对比之前,递归时j+1,因为这题不可以重复选取集合中的元素。在里面做一个判断,如果
candidates[j]==candidates[j-1]
,就代表同一层中已经选取过了相同元素,continue。
剪枝:j<candidatesSize && sum<=target。当sum>target时,就没必要再进入下一层递归了。
int *path;
int **result;
int pathTop;
int resultTop;
int *length;
//从小到大排序
int cmp(const void* a1, const void* a2) {
return *((int*)a1) - *((int*)a2);
}
void backTrack(int *candidates,int candidatesSize,
int target,int sum,int startIndex){
if(sum>target)
return;
if(sum==target){
int *temp = malloc(sizeof(int)*pathTop);
for(int i =0;i<pathTop;i++)
temp[i] = path[i];
result[resultTop] = temp;
length[resultTop++] = pathTop;
return ;
}
for(int j=startIndex;j<candidatesSize&&sum<=target ;j++){
if(j>startIndex && candidates[j] ==candidates[j-1])
continue;
sum = sum + candidates[j];
path[pathTop++] = candidates[j];
backTrack(candidates,candidatesSize,target,sum,j+1);
sum = sum - candidates[j];
pathTop--;
}
}
int** combinationSum2(int* candidates, int candidatesSize, int target, int* returnSize, int** returnColumnSizes){
pathTop = resultTop = 0;
path =malloc(sizeof(int)*100);
result = malloc(sizeof(int*)*100);
length = malloc(sizeof(int)*100);
qsort(candidates, candidatesSize, sizeof(int), cmp);
backTrack(candidates,candidatesSize,target,0,0);
*returnSize = resultTop;
*returnColumnSizes=malloc(sizeof(int)*resultTop);
for(int i=0;i<resultTop;i++)
(*returnColumnSizes)[i] = length[i];
return result;
}