递归思想
是指函数/过程/子程序在运行过程序中直接或间接调用自身而产生的重入现象。在计算机编程里,递归指的是一个过程:函数不断引用自身,直到引用的对象已知。使用递归解决问题,思路清晰,代码少。但是在主流高级语言中(如C语言、Pascal语言等)使用递归算法要耗用更多的栈空间,所以在堆栈尺寸受限制时(如嵌入式系统或者内核态编程),应避免采用。所有的递归算法都可以改写成与之等价的非递归算法。
1. 子问题须与原始问题为同样的事,且更为简单;
2. 不能无限制地调用本身,须有个出口,化简为非递归状况处理。
一个题目:HDU爬楼梯
有一个楼梯共m阶,刚开始时你在第一阶,若每次只能跨上一级或两级,要走上M级共有多少种走法?
第一种方法:递归法
#include<stdio.h>
int fn(int n)
{
if (n == 1 || n == 2)
{
return 1;
}
if (n > 2)
{
return fn(n - 1) + fn(n - 2);
}
}
int main()
{
int n, i, m;
while(scanf_s("%d", &n)!=EOF)
for (i = 0; i < n; i++)
{
scanf_s("%d", &m);
printf("%d\n", fn(m));
}
return 0;
}
因为HDU上无法AC,即当n过大时会导致时间长度大于1000ms.无法通过。
#include<stdio.h>
typedef unsigned long long ULL;
#define N 40
ULL stairs[N + 1];
void setstairs(int n)
{
ULL s1=1, s2=1, temp;
stairs[0] = 0;
stairs[1] = 1;
stairs[2] = 1;
for (int i = 3; i <= n; i++)
{
temp = s1 + s2;
s1 = s2;
s2 = temp;
stairs[i] = s2;
}
}
int main()
{
int m, i, n;
setstairs(N);//打表
while (scanf_s("%d", &m) != EOF)
{
for (int i = 0; i < m; i++)
{
scanf_s("%d", &n);
printf("%lld\n", stairs[n]);
}
}
return 0;
}
LeetCode题解
题目
考虑:这个题的难点在于处理各种极端输入,例如指数为0,指数为负等,需要考虑全面。在实现乘方的过程中,使用递推关系式减小乘法次数,缩短运行时间。题的难点主要是在边界条件:如果 n < 0,是不是 n = -n, x = 1 / x ,再进行递归就能解决了呢?如果 n = Intege.MIN_VALUE,n = -n 会出现溢出,怎么办呢?我们可以先将 n / 2 赋值给 t,再将 t = -n,就不会出现溢出问题。(static int MAX_VALUE 值为 231-1 的常量,它表示 int 类型能够表示的最大值。
static int MIN_VALUE 值为 -231 的常量,它表示 int 类型能够表示的最小值。 )
由我们对递推的了解可知它是每一次都需调用这个函数,那么我们需要了解这个函数的规律。
第一次实现
double myPow(double x, int n) {
return pow(x,n);
}
第二次实现
double myPow(double x, int n) {
if(n==0) return 1;
if(n==1) return x;
if(x==0) return 1;
int t=n/2;
if(n<0)
{
t=-t;
x=1.0/x;
}
double ret=myPow(x,t);
if(n%2==0)
return ret*ret;
else
return ret*ret*x;
}
第三次实现
double myPow(double x, int n) {
if(n==0) return 1;
int t=n/2;
if(n<0)
{
t=-t;
x=1.0/x;
}
double ret=myPow(x,t);
if(n%2==0)
return ret*ret;
else
return ret*ret*x;
}