leetcode 39 -- 组合总和 查询所有子集的和等于targert 的组合 C语言解法

本文详细介绍了回溯法的基本概念,将其定义为深度优先搜索加剪枝策略,并通过具体示例阐述了如何利用递归实现回溯法解决组合问题,提供了清晰的代码模板和实践案例。

回溯法 = 深度搜索 + 剪枝  且深度搜索一般使用递归来实现,程序代码相对简洁

代码模板
/**
* dfs 模板.
* @param[in] input 输入数据指针
* @param[inout] cur or gap 标记当前位置或距离目标的距离
* @param[out] path 当前路径,也是中间结果
* @param[out] result 存放最终结果
* @return 路径长度,如果是求路径本身,则不需要返回长度
*/
void dfs(type *input, type *path, int cur or gap, type *result) {
    if (数据非法) return; // 终止条件    
    if (cur == input.size( or gap == 0)) { // 收敛条件(找到结果)
        将path 放入result
    }
    for(...) { // 执行所有可能的扩展动作
        if (可以剪枝) return;
        执行动作,修改path
        dfs(input, step + 1 or gap--, result);
        恢复path
    }
}

递归函数的参数的选择,要遵循四个原则:
1、必须要有一个临时变量(可以就直接传递一个字面量或者常量进去)传递不完整的解,因为每一步选择后,暂时还没构成完整的解,这个时候这个选择的不完整解,也要想办法传递给递归函数。也就是,把每次递归的不同情况传递给递归调用的函数。
2、可以有一个全局变量,用来存储完整的每个解,一般是个集合容器(也不一定要有这样一个变量,因为每次符合结束条件,不完整解就是完整解了,直接打印即可)。
3、最重要的一点,一定要在参数设计中,可以得到结束条件。一个选择是可以传递一个量n,也许是数组的长度,也许是数量,等等。
4、要保证递归函数返回后,状态可以恢复到递归前,以此达到真正回溯。

给定一个无重复元素的数组 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]
]

gap-- 的使用方法

void dfs(int start,int *path,int index,int *candidates,int candidatesSize, int target, int value,int **result,int *size,int *returnColumnSizes)
{
    if (value == target) {
         result[*size]=(int *)malloc(sizeof(int) * index);
         for(int i = 0; i < index; i++) {
                result[*size][i] = path[i];
        }
        returnColumnSizes[*size] = index;
        *size += 1;
        return;
    }
    for(int i = start;i < candidatesSize; i++)
    {
        if ((target - value) < candidates[i]) return;
        path[index++] = candidates[i];
        dfs(i, path, index, candidates, candidatesSize, target, value + candidates[i], result, size, returnColumnSizes);
        index--;
    }
}
int cmp (const void *a , const void *b)
{
    return *((int *)a) - *((int *)b);
}
int** combinationSum(int* candidates, int candidatesSize, int target, int* returnSize, int** returnColumnSizes){
    if (!candidates || candidatesSize < 0) {
        *returnSize = 0;
        *returnColumnSizes = NULL;
        return NULL;
    }
    qsort(candidates, candidatesSize, sizeof(candidatesSize), cmp);
    for (int i = 0; i < candidatesSize; i++) {
        //printf("%d, ", candidates[i]);
    }
    *returnColumnSizes = (int *)calloc(1024, sizeof(int));
    int path[1024];
    int **result = (int **)calloc(1024, sizeof(int*));
    int size = 0;
    dfs(0 , path, 0, candidates, candidatesSize, target, 0, result, &size, *returnColumnSizes);
    
    *returnSize = size;
    return result;
}

 step + 1 的使用方法

/**
 * 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().
 */
void dfs(int start,int *path,int index,int *candidates,int candidatesSize, int target, int value,int **result,int *size,int *returnColumnSizes)
{
    if (value == target) {
         result[*size]=(int *)malloc(sizeof(int) * index);
         for(int i = 0; i < index; i++) {
                result[*size][i] = path[i];
        }
        returnColumnSizes[*size] = index;
        *size += 1;
        return;
    }
    for(int i = start;i < candidatesSize; i++)
    {
        if ((target - value) < candidates[i]) return;
        path[index++] = candidates[i];
        dfs(i, path, index, candidates, candidatesSize, target, value + candidates[i], result, size, returnColumnSizes);
        index--;
    }
}
int cmp (const void *a , const void *b)
{
    return *((int *)a) - *((int *)b);
}
int** combinationSum(int* candidates, int candidatesSize, int target, int* returnSize, int** returnColumnSizes){
    if (!candidates || candidatesSize < 0) {
        *returnSize = 0;
        *returnColumnSizes = NULL;
        return NULL;
    }
    qsort(candidates, candidatesSize, sizeof(candidatesSize), cmp);
    for (int i = 0; i < candidatesSize; i++) {
        //printf("%d, ", candidates[i]);
    }
    *returnColumnSizes = (int *)calloc(1024, sizeof(int));
    int path[1024];
    int **result = (int **)calloc(1024, sizeof(int*));
    int size = 0;
    dfs(0 , path, 0, candidates, candidatesSize, target, 0, result, &size, *returnColumnSizes);
    
    *returnSize = size;
    return result;
}

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值