1.时间复杂度分析
- 1.1 迭代法求解:不断用变量的旧值递推新值的过程
- 1.2 递归树求解:是一种图像分析。将递推方程的表达式分为递归项和自由项,通过将递归树的子树替换掉叶子结点,实现结点全由自由项构成,确定递归树的层数。
- 1.3 主定理求解:直接有效。
主定理求解:
递推式需满足T(n)=aT(n/b)+f(n);
- f(n)小于n^(logb a),T(n)=O(n^(logb a)
- f(n)与n^(logb a)同阶,T(n)=O(n^(logb a)*log n
- f(n)大于n^(logb a),T(n)=O(f(n))
常见递推公式及时间复杂度:
- T(n)=T(n-1)+n-1,T(1)=0 T(n)=O(n^2)
- T(n)=2*T(n/2)+n-1,T(1)=0 T(n)=O(n*logn)
- T(n)=2/n*Σ(i->n-1) T(i)+c*n,T(1)=0 T(n)=O(n*logn)
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;
}