递归学习笔记

1.时间复杂度分析

  • 1.1 迭代法求解:不断用变量的旧值递推新值的过程
  • 1.2 递归树求解:是一种图像分析。将递推方程的表达式分为递归项和自由项,通过将递归树的子树替换掉叶子结点,实现结点全由自由项构成,确定递归树的层数。
  • 1.3 主定理求解:直接有效。

主定理求解:

递推式需满足T(n)=aT(n/b)+f(n);

  1. f(n)小于n^(logb a),T(n)=O(n^(logb a)
  2. f(n)与n^(logb a)同阶,T(n)=O(n^(logb a)*log n
  3. f(n)大于n^(logb a),T(n)=O(f(n))

常见递推公式及时间复杂度:

  1. T(n)=T(n-1)+n-1,T(1)=0     T(n)=O(n^2)
  2.  T(n)=2*T(n/2)+n-1,T(1)=0  T(n)=O(n*logn)
  3. T(n)=2/n*Σ(i->n-1) T(i)+c*n,T(1)=0   T(n)=O(n*logn)

2.递归的基本思想

  1. 边界条件:确定递归到何时结束,也称为递归出口 (例如递归次数界限,小问题取值界限)
  2. 递归式:大问题如何分解为小问题的,通常以递归方程形式给出 

3.递归应用

  • 汉诺塔问题
#include<bits/stdc++.h>
using namespace std;
int n;
void hanoi(int x,char A,char B,char C)
{
    if(x==1)
        cout<<x<<A<<"->"<<C<<endl;  //第二步 将最后一个盘子从A移动到C
    else
    {
        hanoi(n-1,A,C,B);           //第一步 将n-1个盘子从A移动到B
        cout<<x<<A<<"->"<<C<<endl;
        hanoi(n-1,B,A,C);           //第三步 将n-1个盘子从B移动到C
    }
}
int main()
{
    cin>>n;
    hanoi(n,'A','B','C');
    return 0;
}
  • 全排列
#include<bits/stdc++.h>
using namespace std;
int n;
void permutation(int a[],int k,int len)
{
    if(k==len-1)
        {for(int i=0;i<len;i++)
        cout<<a[i]<<" ";
        cout<<endl;}
    else
    {
        int t;
        for(int j=k;j<len;j++)
        {
            t=a[j];
            a[j]=a[k];
            a[k]=t;
            perm(a,k+1,len);
            t=a[j];
            a[j]=a[k];
            a[k]=t;
        }
    }
}
int main()
{
    cin>>n;
    int a[100];
    for(int i=0;i<n;i++)
        cin>>a[i];
    permutation(a,0,n);
    return 0;
}

 递归法时间复杂度较大,用深搜来优化

#include<bits/stdc++.h>
using namespace std;
int n,pd[100],used[100];//pd是判断是否用过这个数
void print()//输出函数
{
    int i;
    for(i=1;i<=n;i++)
    printf("%5d",used[i]);
    cout<<endl;
}
void dfs(int k)//深搜函数,当前是第k格
{
    int i;
    if(k==n) //填满了的时候
    {
        print();//输出当前解
        return;
    }
    for(i=1;i<=n;i++)//1-n循环填数
    {
        if(!pd[i])//如果当前数没有用过
        {
            pd[i]=1;//标记一下
            used[k+1]=i;//把这个数填入数组
            dfs(k+1);//填下一个
            pd[i]=0;//回溯
        }
    }
}
int main()
{
    cin>>n;
    dfs(0);//注意,这里是从第0格开始的!
    return 0;
}
  • 整数划分  
#include<bits/stdc++.h>
using namespace std;
int divide(int n,int m)
{
    if(n==1||m==1)
        return 1;
    else if(n<m)
        return divide(n,n);
    else if(n==m)
        return 1+divide(n,n-1);
    else
        return divide(n,m-1)+divide(n-m,m);
}
int main()
{
    int n;
    cin>>n;
    cout<<divide(n,n);
    return 0;
}

 

 

 

4.思考题  

  • 3-3 判断回文字符串
#include <bits/stdc++.h>
using namespace std;
int fun(int low,int high,string str,int len)
{
    if(len==0||len==1)
        return 1;
    if(str[low]!=str[high])
        return 0;
    return fun(low+1,high-1,str,len-2);
}
int main()
{
    string str;
    cin>>str;
    int len=str.size();
    if(fun(0,len-1,str,len))
        cout<<"Yes";
    else
        cout<<"No";
    return 0;
}

又在网上找到其他思路(运用指针) 

//1
#include <iostream>
using namespace std;
bool isPalindrome(char str[], size_t n)
{
    if (n<=1)
    {
        return true;
    }
    else if (str[0]==str[n-1])
    {
        return isPalindrome(str+1,n-2);
    }
    else
        return false;
 
}
int main()
{
    char str[255];
    cin>>str;
    cout<<(isPalindrome(str,strlen(str))?"Yes":"No")<<endl;
    return 0;
}

//2
#include<stdio.h>
#include<math.h>
#include <string.h>
 
int hanshu(char *p)
{
 
	char *q=p;
	while(*q!='\0')
		q++;
	if(q==p)
		return 1;
	q--;
	if(*p==*q)
	{	*q='\0';
		return hanshu(p+1);
	}
	else
		return 0;
}
 
int main()
{
	char str[100];
	scanf("%s",str);
	if(hanshu(str))
		printf("Yes\n");
	else
		printf("No\n");
}
  • 3-4 倒序输出正整数 
#include<bits/stdc++.h>
using namespace std;
int reverse(int n)
{
    if(n!=0)
    {
        int x=n%10;
        n=n/10;
        printf("%d",x);
        return reverse(n);
    }
    else
        return 0;
}
int main()
{
    int n;
    cin>>n;
    reverse(n);
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值