阶梯问题

Posted Leo_wlCnBlogs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了阶梯问题相关的知识,希望对你有一定的参考价值。

1、阶梯问题

问题描述:一个阶梯有n个级,一个人要走完这个阶梯,一步可以走一级或两级,问:共有多少个方案?

解决思路:当n=1时候,只有一种走法,当n=2时候有3种走法;那么n=3时候呢?到第三层的走法是到第一层的走法加上到第二层的走法所以显然这是个经典的递归问题。

  因此有a1=1,a2=2,an= an-1 + an-2,其中n>2;

方法1:

  设斐波那契数列的通项为An,An = (p^n - q^n)/√5,其中p = (√5 - 1)/2,q = (√5 + 1)/2

方法2:

复制代码
 1 #include<iostream>
 2 using namespace std;
 3 
 4 int Fibonacci(int n)
 5 {
 6     if(n==1)
 7         return 1;
 8     else if(n==2)
 9         return 2;
10     else
11         return ( Fibonacci(n-1)+Fibonacci(n-2) );
12 }
13 
14 int main()
15 {
16     int result=0;
17     for(int i=1;i<=10;i++)
18     {
19         result=Fibonacci(i);
20         cout<<"result="<<result<<endl;
21     }
22     return 0;
23 }
复制代码

执行结果:

方法3:当要求解的n很大的时候,递归耗时很大,因为其中存在很多重复计算的问题,所以采用动态规划,记录计算值,以减少耗时;

复制代码
 1 #include<iostream>
 2 using namespace std;
 3 
 4 #define N 11
 5 int main()
 6 {
 7     int i;
 8     int A[N] = {0,1,2};
 9     for(i=3;i<N;i++)
10     {
11         A[i] = A[i-1] + A[i-2];
12         cout<<"result="<<A[i]<<endl;
13     }
14     return 0;
15 }
复制代码

执行结果:

问题延伸:一步可以走一级或两级或者三级,问:共有多少个方案?

  则有a1=1,a2=2,a3=4,an= an-1 + an-2 + an-3其中n>3

2、不通过比较,找出两个数的最大值

一旦涉及到不用比较找最大值,一般只能通过位运算来实现

方法一:max = a - ( (a-b) & ( (a-b)>>31 ) )

  如果a > b,则后面部分将会出现(a - b)&(全0),即实现max = a - 0;

  如果a < b,则后面部分将会出现(a - b)&(全1),即实现max = a - (a - b) ;

方法二:max = ( (a+b) + |a-b| ) / 2

  加上 |a-b| 实际上是为了加上a与b的差值,( (a+b) + |a-b| )是想获得最大数的两倍

3、字符串反转

只需要遍历数组的一半就可以实现

复制代码
 1 void StrReverse(string &s)
 2 {
 3     int i,len = s.length();
 4     char temp;
 5     for(i=0;i<len/2;i++)
 6     {
 7         temp = s[i];
 8         s[i] = s[len-i-1];
 9         s[len-i-1] = temp;
10     }
11 }
复制代码

 

4、不用循环反转字符串

不能用到循环就只能——递归实现

复制代码
 1 string Reverse(string s,int index)
 2 {
 3     if(index==0)
 4         return s.substr(0,1);
 5     return s.substr(index,1) + "" + Reverse(s,index-1);
 6 }
 7 int main()
 8 {
 9     string s;
10     cin>>s;
11     string str_test = Reverse(s,s.length()-1);
12     cout<<str_test<<endl;
13     return 0;
14 }
复制代码

 

5、十度好友

问题描述:在社交网络中,如果A、B是好友,B、C是好友,且A、C不是好友,则C成为A的二度好友;同理定义十度好友;若给定一张社交网络图,求A的所有十度好友;

解决思路:两种方式求解

(1)想求十度好友,很容易想到的是利用DFS,把A节点作为根部,用DFS搜索到深度为十的所有节点;

  还有一个细节问题,因为网络是复杂的,从一个结点到另外一个结点的路径不止一条,即D可能是A的三度结点,也可能是A的8度结点,这时应该以三度结点为准;

  因此,如果利用DFS解决问题,需要对遍历过的结点做标记,并且该结点度数信息应该更新为更小的值;

(2)利用BFS解决,总体思路如下:

复制代码
 1 把A放在queue_1里,设置degree = 0;
 2 while(degree != 0 && !queue_1.empty() )
 3 {
 4     遍历queue_1里所有元素
 5   {
 6         if(queue_1.element的邻居结点没有被访问过)
 7     {
 8             邻居结点放入queue_2中;
 9       从queue_1中删除queue_1.element;
10     }
11   }
12   把queue_2中的所有元素放入queue_1中;
13     degree++;
14 }
15 输出queue_1里的所有元素,即为A的十度好友;
复制代码

以上是关于阶梯问题的主要内容,如果未能解决你的问题,请参考以下文章

将 printf 重定向到 UART 时,输出行呈阶梯状

T-SQL的阶梯:超越基础水平9:动态T-SQL代码

java内外循环打印阶梯*号

我如何打印 BFS 路径本身而不是这个单词阶梯的路径长度?

条件语句在 if-else-if 阶梯的两个部分都为真

POJ 1704 Georgia and Bob(阶梯博弈+证明)