递归算法与例题详解

本文探讨了递归在编程中的应用,如斐波那契数列的递归实现,以及如何通过矩阵算法优化。同时介绍了爬楼梯问题的递归与滚动窗口解决方案,以及全排列问题的回溯算法和去重版本。

递归

(1)自己调用自己

(2)讲将一个问题拆解成解决方案完全相同的子问题

(3)必须有一个明确的终点

(4)到终点后计算结果原路返回

这里例举一个经典问题,斐波那契数https://leetcode.cn/problemset/?page=1&search=509

递归做法:

#include<iostream>
using namespace std;

class Solution {
public:
    int fib(int n) {
     if(n==0)return 0;
     else if(n==1)return 1;
     else return fib(n-2)+fib(n-1); 
    }
    int main()
{
    int n;
    cin>>n;
    cout<<fib(n)<<endl;
  return 0;
}

};

矩阵算法:

当第一个数和第二个数为1时

\begin{bmatrix} f(n)\\ f(n-1) \end{bmatrix}= \begin{bmatrix} 1*f(n-1)+1*f(n-2)\\ 1*f(n-1)+0*f(n-2) \end{bmatrix}\Rightarrow \begin{bmatrix} 1 &1 \\ 1&0 \end{bmatrix}*\begin{bmatrix} f(n-1)\\ f(n-2) \end{bmatrix}

\begin{bmatrix} f(n-1)\\ f(n-2) \end{bmatrix}= \begin{bmatrix} 1*f(n-2)+1*f(n-3)\\ 1*f(n-2)+0*f(n-3) \end{bmatrix}\Rightarrow \begin{bmatrix} 1 &1 \\ 1&0 \end{bmatrix}*\begin{bmatrix} f(n-2)\\ f(n-3) \end{bmatrix}

就这么替换下去,可以得出

\begin{bmatrix} f(n)\\ f(n-2) \end{bmatrix}=\begin{bmatrix} 1 & 1\\ 1&0 \end{bmatrix}^{n-2}*\begin{bmatrix} f(2)\\ f(1) \end{bmatrix}=\begin{bmatrix} 1 &1 \\ 1&0 \end{bmatrix}^{n-2}*\begin{bmatrix} 1\\ 1 \end{bmatrix}

类似于斐波那契数的题:爬楼梯:https://leetcode.cn/problems/climbing-stairs/description/

因为一次能爬1 或 2级楼梯

(1)当只有一阶楼梯时,只有一种方法 1

(2)当有两阶楼梯时,有两种方法 1 1,2

(3)当有三阶楼梯时,如果我第一次迈一阶楼梯那就是1+(2)的步骤,如果我第一次迈二阶楼梯那就是2+(1)的步骤,也就是前两次步骤之和3

同理四阶楼梯是三阶楼梯+二阶楼梯步骤之和5

但是如果用递归会超时,所以我们利用滚动窗口思想,利用中间变量t实现优化

#include<iostream>
using namespace std;
class Solution {
public:
    int climbStairs(int n) {
        int a=0,b=1,t=0;
    for(int i=1;i<=n;i++)
    {
        t=b+a;
        a=b;
        b=t;
    }
    return t;
    }

    int main()
    {
        int n;
        scanf("%d",&n);
        printf("%d",climbStairs(n));
        return 0;
    }
};

LCR 083. 全排列 - 力扣(LeetCode)

递归回溯

class Solution {
public:
vector<vector<int>>res;
  void dfs(vector<int>&nums,int len,vector<int>&ans,int n,int vi[])
  {
    if(n==len){res.push_back(ans);return;}
        for(int i=0;i<len;i++)
        {
            if(vi[i]!=1&& n<len)
            {
                vi[i]=1;
                ans.push_back(nums[i]);
                dfs(nums,len,ans,n+1,vi);
                ans.pop_back();
                vi[i]=0;
            }
        }
  }
    vector<vector<int>> permute(vector<int>& nums) {
        vector<int>ans;
        int vi[nums.size()];
        memset(vi,0,sizeof(vi));
     dfs(nums,nums.size(),ans,0,vi);
     return res;
    }
};

LCR 084. 全排列 II - 力扣(LeetCode)

递归回溯加去重

class Solution {
public:
vector<vector<int>>res;
map<vector<int>,int>mp;
void dfs(vector<int>& nums,int len,int n,int vi[],vector<int>&ans)
{
if(len==n){
    mp[ans]++;
    if(mp[ans]==1)
    res.push_back(ans);
    return;
}
for(int i=0;i<len;i++)
{
    if(vi[i]==0)
    {
        vi[i]=1;
        ans.push_back(nums[i]);
        dfs(nums,len,n+1,vi,ans);
        ans.pop_back();
        vi[i]=0;
    }
}
}
    vector<vector<int>> permuteUnique(vector<int>& nums) {
     int vi[nums.size()];
     memset(vi,0,sizeof(vi));
     int n=0;
     int len=nums.size();
     vector<int>ans;
     dfs(nums,len,n,vi,ans);
     return res;
    }
};

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值