此功能用于生成楼梯上的大步和短步的组合数(由用户给出的值)。一个短步骤涉及一个步骤,一个大步幅涉及两个步骤。
但是,我不理解这里使用的递归洞察力。我真的很感激为什么会产生所需组合的数量。通过它,我可以看到它的工作原理,但我不确定自己将如何达到这个逻辑。
有人可以对此有所了解吗?
以下是代码:
int CountWays(int numStairs);
int combination_strides = 0;
const int LARGE_STEP = 2;
const int SMALL_STEP = 1;
int main() {
cout << "Enter the number of stairs you wish to climb: ";
int response = GetInteger();
int combinations = CountWays(response);
cout << "The number of stride combinations is: " << combinations << endl;
return 0;
}
int CountWays(int numStairs) {
if (numStairs < 4) {
return numStairs;
} else {
return CountWays(numStairs - SMALL_STEP) + CountWays(numStairs - LARGE_STEP);
}
}
答案 0 :(得分:6)
要关注numStairs
,您可以:
(numStairs - SMALL_STEP)
;或(numStairs - LARGE_STEP)
。因此,总路数是下降(numStairs - SMALL_STEP)
的方式数和(numStairs - LARGE_STEP)
下降方式的总和,因此递归。
很简单,看到有一种方法可以向下一步(S),两种向下运行两步(SS或L),三种向下运行三步(SSS,SL或LS),因此终止条件。
您可能会将此递归视为Fibonacci sequence的定义。对于奖励积分,您可能希望重新计算计算,使其以线性而非指数时间运行。
答案 1 :(得分:1)
好吧让我们这样想吧。我左边有一些楼梯。如果numStars&lt; 4,比组合的数量总是数字:
ss=small step (1)
ls=large step (2)
1 step-{{ss}}==1
2 steps-{{ss,ss},{ls}}==2
3 steps-{{ss,ss,ss},{ls,ss},{ss,ls}}==3
比这更大,它可能会变得更复杂。但如果我离开了,我可以采取一大步或一小步。如果我迈出了一大步,那么将会有numStars-LARGE_STEP
步骤,所以我只需要找到这么多步骤的组合总数。如果我迈出一小步,我只需要找到numStais-SMALL_STEP
的组合总数。
加入递归项,组合[n] =组合[n-1] +组合[n-2]。
应该注意的是,这不是以任何方式执行此操作的最快方法。这为每次迭代重做了大量的工作。动态编程方法更为可取。
int* num_combinations = new int[num_stairs];
for (int i = 0; i < 4; i++) num_combinations[i]=i;
for (int i = 4; i < num_stairs; i++) num_combinations[i]=num_combinations[i-1]+num_combinations[i-2];
int ret = num_combinations[num_stairs-1]+num_combinations[num_stairs-2]
delete[] num_conbinations;
return ret;
O(n)
vs O(n ^ 2)
答案 2 :(得分:1)
在这种情况下,这是递归逻辑:
假设您N
步骤编号为1
至N
。
在任何时候,您都可以选择以下两个选项之一:
你想计算爬上楼梯的不同组合的数量。
现在,假设您目前正站在K
步。
您可以选择攀登步骤K+1
或步骤K+2
。
所以你需要做的就是添加:
K+1
升级到步骤N
K+2
升级到步骤N
或者等效地,您可以添加:
N-(K+1)
N-(K+2)
话虽如此,这是递归函数的工作原理:
int CountWays(int numStairs)
{
if (numStairs < 4)
return numStairs;
// If there is 1 step , then there is 1 combination to climb it up
// If there are 2 steps, then there are 2 combinations to climb them up
// If there are 3 steps, then there are 3 combinations to climb them up
int x = CountWays(numStairs - SMALL_STEP);
// The number of different combinations to climb up
// from the bottom of the staircase to step N-(K+1)
int y = CountWays(numStairs - LARGE_STEP);
// The number of different combinations to climb up
// from the bottom of the staircase to step N-(K+2)
return x+y;
}
你可能已经注意到这个函数只是产生 Fibonacci序列 1,2,3,5,8,13 ......
BTW,在这种情况下,迭代实现会更有效率(与许多其他情况一样):int CountWays(int numStairs)
{
int prev = 0;
int curr = 1;
for (int i=0; i<numStairs; i++)
{
int next = prev+curr;
prev = curr;
curr = next;
}
return prev;
}
答案 3 :(得分:0)
代码尝试通过在每个步骤中缩小问题来分解问题。
如果步骤少于四个,则可能的组合数量等于楼梯数:
- 对于一个楼梯,唯一可能的组合是一小步
- 对于两个楼梯,可能的组合是一大步或两个小步骤
- 对于三个楼梯,你可以走三个小台阶,一个小台阶,一个大台阶或一个大台阶和一个小台阶
这些案例将结束递归
对于其他每一个楼梯,你可以走一小步,然后走楼梯,或者一大步,然后是其他楼梯。 &#34;其余的楼梯&#34;是递归发生的地方:它只计算减少楼梯数的可能性数量(减少一到两步,取决于第一步的大小)。
将它们全部加在一起,就可以得到走上楼梯的组合总数。
答案 4 :(得分:0)
让f(n)为从开始到达第n个楼梯的方式(楼梯号0)。
要获得stair n
,首先必须到达开始n-1
或n-2
。
类似于到达楼梯n-1
,您需要到达n-2
或n-3
楼梯,并且递归就像这样.......
但它必须在某个地方停止,否则你继续评估f(-1)
,f(-2)
,... f(- infinity)
...所以有stopping condition
:到达{ {1}},您只能在stair 1
步骤中执行此操作,即直接从1
到stair 0
。
要stair 1
,stair 2
:2 ways
+ stair 0
步,2
+ stair 1
步。
因此
1
答案 5 :(得分:0)
关于这种递归特别令人困惑的一件事是,它是根据常量SMALL_STEP
和LARGE_STEP
进行参数化的,但终止条件(if (numsteps < 4)
)只是正确的对于SMALL_STEP = 1
和LARGE_STEP = 2
的具体值 - 如果更改其中任何一个,则代码不正确。可以说代码应该:
int CountWays(int numStairs) {
if (numStairs < 0) {
return 0;
} else if (numStairs == 0) {
return 1;
} else {
return CountWays(numStairs - SMALL_STEP) + CountWays(numStairs - LARGE_STEP);
}
}
效率稍差(需要几次额外的迭代才能得到答案)但仍具有相同的渐近复杂度 - O(2 n )