回溯法求解组合(c语言)

 int* path;

 int pathSize;

 int** ans;

 int ansTop;

void backtracking(int n,int k,int startIndex){

    //当path中元素个数为k个时,我们需要将path数组放入ans二维数组中

    if(pathSize==k){

        //path数组为我们动态申请,若直接将其地址放入二维数组,path数组中的值会随着我们回溯而逐渐变化

        //因此创建新的数组存储path中的值

        int* temp=(int*)malloc(sizeof(int)*k);

        int i;

        for(i=0;i<k;i++){

            temp[i]=path[i];

        }

        ans[ansTop++]=temp;

        return;

    }

    int j;

    for(j=startIndex;j<=n;j++){

        //将当前结点放入path数组

        path[pathSize++]=j;

        //进行递归

        backtracking(n,k,j+1);

        //进行回溯,将数组最上层结点弹出

        pathSize--;

    }

}

// 让我们通过一个更详细的例子来解释这段代码的工作原理,以从数字1到5中选择3个数字的所有组合为例(n=5, k=3)。

// 初始化

// 假设pathSize = 0, ansTop = 0, startIndex = 1。

// path和ans已预先分配足够的内存。

// 第一次递归调用

// 入口检查: pathSize != k,开始循环。

// 尝试第一个元素 (j=1):

// path[pathSize++] = j; => path现在包含[1], pathSize=1。

// 递归调用backtracking(5, 3, 2)。

// 第二次递归调用

// 入口检查: pathSize != k,继续循环。

// 尝试第二个元素 (j=2):

// path[pathSize++] = j; => path现在包含[1, 2], pathSize=2。

// 递归调用backtracking(5, 3, 3)。

// 第三次递归调用(找到一个组合)

// 入口检查: pathSize == k(此时pathSize=2, 但此处应修正为判断失误,

// 正确的逻辑应在pathSize达到3时停止循环并处理组合),此处描述按照逻辑修正。

// 尝试第三个元素 (j=3):

// path[pathSize++] = j; => path现在包含[1, 2, 3], pathSize=3。

// 找到组合: pathSize == k,创建临时数组temp,复制path到temp,然后ans[ansTop++] = temp;

// ,此时ansTop=1,表示收集到了第一个组合。

// 递归调用结束,开始回溯,pathSize--; => pathSize=2,移除path中的最后一个元素(3)。

// 回溯至第二次递归调用

// 接着尝试j=4:

// path[pathSize++] = 4; => path现在包含[1, 2, 4], pathSize=3。

// 发现组合,同上处理,收集组合,回溯,pathSize--; => pathSize=2,移除4。

// 继续回溯至第一次递归调用

// 探索j=5:

// path[pathSize++] = 5; => path现在包含[1, 2, 5], pathSize=3。

// 收集组合,回溯,pathSize--; => pathSize=2,移除5。

// 回到第一次循环的后续步骤

// 接下来,由于j已经在第一次循环中递增到5,循环结束,开始回溯,pathSize--; => pathSize=1,移除2。

// 第一轮循环结束

// 继续探索以j=2开始的新一轮,类似过程,会找到包含[1, 3, 4]、[1, 3, 5]、[1, 4, 5]等所有可能的组合,

// 每次完成一个组合的探索后都会进行回溯,为下一次探索做准备。

int** combine(int n, int k, int* returnSize, int** returnColumnSizes) {

    //path数组存储符合条件的结果

    path=(int*)malloc(sizeof(int)*k);

    //ans二维数组存储符合条件的结果数组的集合。(数组足够大,避免极端情况)

    ans=(int**)malloc(sizeof(int*)*10000);

    pathSize=ansTop=0;

    backtracking(n,k,1);

    //最后的返回大小为ans数组大小

    *returnSize=ansTop;

    //returnColumnSizes数组存储ans二维数组对应下标中一维数组的长度(都为k)

    *returnColumnSizes=(int*)malloc(sizeof(int)*(*returnSize));

    int i;

    for(i=0;i<*returnSize;i++){

        (*returnColumnSizes)[i]=k;

    }

    //返回ans二维数组

    return ans;

}

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值