经典算法系列——递归

算法题一:求斐波那契数列的第n项

这道题比较常见,是很多书上的经典案例,都比较熟悉,因此能很快写出代码。需要注意的是:案例一般会用递归求解,递归的好处是可以使代码简洁易懂。但是利用递归需要反复调用函数,进行重复的计算,有很严重的效率问题,若是作为面试题的话,显然这种解法是不会得到面试官的满意的。我们可以借用动态规划的思想来解决此问题,若是不理解什么是动态规划也无所谓。为了避免重复的计算,我们把已经得到的数列保存下来,以便下次需要时直接使用。代码如下:

#include 
using namespace std;

int Fibonacci(int n) {

 if (n <= 0) return 0;
 if (n == 1) return 1;
  int tempOne = 0;
  int tempTwo = 1;
  int tempN = 0;
  
  for (int i = 2; i <= n; i++)
 {
   tempN = tempOne + tempTwo;
   tempOne = tempTwo;
   tempTwo = tempN;
   }  
 return tempN;
 }

 int main()
{
  int n;
  cin >> n;
  cout << Fibonacci(n)<<endl;
}

算法题二:青蛙跳台阶问题

一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个n级的台阶总共有多少种跳法?

该题本质也就是斐波那契数列的应用,如果只有1级台阶,显然只有一种跳法,如果有2级台阶,就有2种跳法:一种是分两次跳每次跳1级;另一种就是一次跳2级。当n>2时,我们发现,第一次跳我们只有两种选择:一是跳1级,此时的跳法数目就是剩下(n-1)级台阶的跳法数目,即为f(n-1);第二种就是第一次跳2级,此时跳法数目等于剩下的(n-2)级台阶的跳法数目,即f(n-2)。所以,f(n)=f(n-1)+f(n-2),本质就是从第二项开始的斐波那契数列。

代码就不再重复了,详见算法题一,这点学习能力还是有的吧。

算法题三:青蛙变态跳台阶问题

一只变异的青蛙一次可以跳上1级台阶,也可以跳上2级台阶,也可以跳上3级·····也可以一次跳上n级台阶。求该青蛙跳上一个n级的台阶总共有多少种跳法?

这次青蛙第一次跳的时候就有n中选择了,它可以选择
跳1级,剩下n-1级,则剩下跳法是f(n-1)
跳2级,剩下n-2级,则剩下跳法是f(n-2)
······
跳n级,剩下0级,则剩下跳法是f(0),就是一下跳上去

所有n级台阶的跳法加一起就是:
f(n) = f(n-1) + f(n-2) + … + f(1)+f(0)
同理若是跳n-1级台阶就是:
f(n-1) = f(n-2) + f(n-3 )+ … + f(1)+f(0)

可以得出:
f(n) = 2 * f(n-1)

通过上述分析利用递归很容易就能写出实现代码,但正如我们之前说的,递归固然简单,但实际的效率却不高,所以我觉得还是用动态规划的思想来解决更加实用。就是自底向上遍历,依次保存求得的值,便于下次使用。代码如下:

#include 
using namespace std;

public int AbnormalJumpFloor(int n){

int result[1024] = {};//申请一个足够大的数组用来存储上到每级台阶的跳法
//int result[]=new int[n+1];这种写法不行 ,c++中不能用变量来定义数组长度,c#中可以
//当然在c++中你可以利用指针动态申请内存int *result= new int[n+1];也行,但要记得释放

result[1] =1;//这时已知的条件,跳1级有1种跳法,存储到数组中

for(int i=2;i<=n;i++){

result[i]=2*result[i-1];//通过之前分析出的公式,将跳i级的跳法存入数组中

}
return result[n];

}

int main(){
  int n;
  cin >> n;
cout<<AbnormalJumpFloor(n)<<endl;
}

虽然是递归篇,却没用递归实现,不过这些都是递归的经典案例,如果对递归算法感兴趣的可以去查看相关的资料,O(∩_∩)O哈哈~。

你可能感兴趣的:(面试经典算法大全)