算法3、回溯全专题(构造子集/全排列/组合/背包)

 一.DFS-回溯引入

晴问算法

 (1)递归深度

输出斐波那契数列每一次递归对应的递归深度。

f771c0c157de4b830d92e4cf3f6d0dc2.png

主思想:在斐波那契数列递归基础上,因为要求调用一个递归就输出它对应的递归深度,即一个递归函数一个输出,那么就可以增加一个函数参数-depth,表示该函数的递归深度,每再函数里调用自己深度就加一:

int f(int n, int depth)
{
    printf("%d\n", depth);
    if(n <= 2)
        return 0;
    else
        return f(n-1, depth+1)+f(n-2, depth+1);
}

 (2)递归调试

829173c97c05391337d12cce9f4131ab.png

在递归深度的基础上增加输出空格,这题主要是提供对每一层递归的图像化表示 

#include <iostream>
 int f_debug(int n, int depth)
 {
     for(int i = 0; i < 4*(depth-1); i++)
        printf(" ");
     printf("n=%d\n", n);
     if(n <= 2)
            return 1;
        else
        {
            return f_debug(n-1, depth+1) + f_debug(n-2, depth+1);
        }
 }

 二.🫴构造所有可行解--回溯

  构造所有的可行解--->回溯,要有一个递归函数参数表示当前递归函数的递归层数/深度以进入下一层递归;要有记录当前已构造的子集temp, 且要知道当前位置🉑放的元素----->所以基础参数:F(int idx, xxx), 

⚠️⚠️⚠️🎉!特别注意若temp是全局变量(即所有递归函数共用一个temp)则加入/放入后必须移除该元素!(因为要选择别的元素放置在当前位置,或是返回上一层即返回上一个位置)如果temp设定为递归函数的参数,即每个函数都有一个temp,则加入后不需移除(但最好也移除,保持代码的一致)

1、构造子集:

🌰01串

a510611dfee05c649a4cc23513ab8ce1.png

主思想: 从头开始构造,每个位置可放元素就0/1; 当前位置先放0,然后进入下一个位置(即往下递归-构造剩下的元素)删除0(先删除才能放新的元素);再放1,然后进入下一个位置,删除1,(函数结束返回上一层,即返回上一个位置)。

框架:

   定义一个vector<int>temp可变长数组以存放构造中的01串; 定义一个result数组存放所有的可能01串; 定义递归函数参数为int idx以指示temp数组中当前需构造的元素。

  递归边界:当idx == n,就把当前构造的01串加入result中;

  构造流程:

vector<int> temp;
vector<vector<int>> result;
int n = 0;
void DFS(int idx)
{
    if(idx == n)
        result.push_back(temp);
    else
    {
        temp.push_back(0);
        DFS(idx+1);
        temp.pop_back();
        
        temp.push_back(1);
        DFS(idx+1);
        temp.pop_back();
        return ;//可以去掉
    }
}

  难点:想清楚递归流程,如下图1ab2b380d05ac1f8136c511e5fd86bd2.jpeg

  知识点复习:返回值为空的函数void xxxx(xxx),执行到函数体结尾}就会自动结束函数,不需要在结尾手动编写显式return ;  除非想提前结束函数。

🎉构造子集与全排列的区别:

构造子集考虑的是当前元素即origin[idx],加入(三步:push_back,  DFS(idx+1),  pop_back()   )与不加入(直接DFS

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值