DFS递归回溯求排列组合的C实现

深度优先搜索DFS本身很好理解,即按照一定顺序递归遍历一个图,但是如何把所有的满足要求的遍历方式给求出来,这里就需要结合回溯backtrace了。

在LeetCode中,回溯标签下的很多题目都是求排列组合的,这也算是一类经典类型的题目了。C/C++写的多人都会有个特点:写代码的时候脑子里都是内存布局,栈帧结构,以及代码执行时各个对象的生命周期等等,写的多了某种程度可以对这些东西做到可视化了都。理解DFS回溯,就把这个递归调用的调用栈帧以及关键全局变量的修改在脑子给推演一下,就很容易理解了。如果还做不到这点,到时可以动笔画图辅助一下。

组合 C n k C_n^k Cnk

https://leetcode-cn.com/problems/combinations/

int g_retNum = 0;
int g_arr[10240];
int g_pos = 0;

void dfs(int **re, int n, int k, int start)
{
    // 深搜的递归终止条件
    if (g_pos == k) {
        re[g_retNum] = malloc(sizeof(int) * k);
        memcpy(re[g_retNum], g_arr, sizeof(int) * k);
        g_retNum++;
        return;
    }
    for (int i = start; i <= n; i++) {
        g_arr[g_pos++] = i;
        dfs(re, n, k, i + 1);
        g_pos--;  // 递归路径的回溯
    }
}

int **combine(int n, int k, int *returnSize, int **returnColumnSizes)
{
	// 初始化全局变量,C没有class,变量都通过入参传递太麻烦,适当用全局变量
	// 控制好这些全局变量的访问就好,可以加上static修饰等
    g_retNum = 0;
    g_pos = 0;
    
    int **re = malloc(sizeof(int *) * 10240);
    dfs(re, n, k, 1);
    *returnSize = g_retNum;
    *returnColumnSizes = malloc(sizeof(void *) * g_retNum);
    for (int i = 0; i < g_retNum; i++) {
        (*returnColumnSizes)[i] = k;
    }
    return re;
}

全排列 A n k A_n^k Ank

https://leetcode-cn.com/problems/permutations/

int g_num = 0;
int g_arr[10240];
int g_pos = 0;
bool g_visited[10240];

void dfs(int **re, int *nums, int numsSize, int start)
{
	// DFS递归的终止条件,并搜集一轮结果
    if (g_pos == numsSize) {
        re[g_num] = malloc(sizeof(int) * numsSize);
        memcpy(re[g_num], g_arr, sizeof(int) * numsSize);
        g_num++;
        return;
    }

    for (int i = start; i < numsSize; i++) {
        if (g_visited[i]) continue; // 访问过的减枝
        g_arr[g_pos++] = nums[i];
        g_visited[i] = true;
        dfs(re, nums, numsSize, 0); // 排列每次都从头访问,,略过前面访问过
        g_pos--;
        g_visited[i] = false;
    }

}

int **permute(int *nums, int numsSize, int *returnSize, int **returnColumnSizes)
{
	// 初始化全局变量,C没有class,变量都通过入参传递太麻烦,适当用全局变量
	// 控制好这些全局变量的访问就好,可以加上static修饰等
    g_num = 0;
    g_pos = 0;
    
    memset(g_visited, false, sizeof(g_visited));
    int **re = malloc(sizeof(int *) * 10240);
    dfs(re, nums, numsSize, 0);
    *returnSize = g_num;
    *returnColumnSizes = malloc(sizeof(void *) * g_num);
    for (int i = 0; i < g_num; i++) {
        (*returnColumnSizes)[i] = numsSize;
    }
    return re;
}

还有很多类似题目,基本都可以用这种方法解决。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值