LeetCode 40. 组合总和 II 回溯+去重

思路:这题和前面的39.组合 有区别,当前数组有重复元素,并且每个数字在组合中只能使用一次。我们要让其没有重复的组合,就相当于在每一层中不可重复选取同一个元素。
我们首先要做的就是对数组排序,关于快速排序:C语言:qsort()解析

还是一样的回溯三部曲。

  1. 参数:需要sum来计算总和和startIndex来控制开始的位置。
  2. 终止条件:当sum==target时,以及sum>target时。
  3. 单层逻辑:从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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值