Reputation:
This function is designed to generate the number of combinations of large and short strides up a staircase (a value that is given by the user). A short stride involves 1 step, and a large stride involves 2 steps.
However, I don't understand the recursive insight used here. I'd really appreciate an explanation of why this generates the number of combinations required. Working through it, I can see it works, but I am not sure how I would have arrived at this logic myself.
Would it be possible for someone to shed some light on this?
Here is the code:
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);
}
}
Upvotes: 4
Views: 1017
Reputation: 126378
One thing that is particularly confusing about this recursion is the fact that it is parameterized in terms of the constants SMALL_STEP
and LARGE_STEP
, but the termination condition (if (numsteps < 4)
) is only correct for the specific values of SMALL_STEP = 1
and LARGE_STEP = 2
-- if you change either of those, the code is incorrect. Arguably the code should be:
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);
}
}
This is marginally less efficient (requires a couple of extra iterations to get the answer) but still has the same asymptotic complexity -- O(2n)
Upvotes: 0
Reputation: 30136
Here is the recursion-logic in this case:
Suppose you have N
steps numbered 1
thru N
.
At any point, you can choose one of two options:
You want to calculate the number of different combinations to climb up the staircase.
Now, let's say you're currently standing on step K
.
You can choose to climb either to step K+1
or to step K+2
.
So all you need to do is add:
K+1
to step N
K+2
to step N
Or equivalently, you can add:
N-(K+1)
N-(K+2)
Having said that, here is how the recursive function works:
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;
}
You may have noticed that this function simply yields the Fibonacci Sequence 1, 2, 3, 5, 8, 13, ...
BTW, an iterative implementation would be much more efficient in this case (as in many other cases):
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;
}
Upvotes: 1
Reputation: 7881
Well Lets think of it this way. I have a number of stairs n left. If numStars < 4, than the number of combinations is always numstairs:
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
Bigger than that, it may get more complicated. But if I have n left, i can take Either a big step, or a small step. If I take a big step, than there will be numStars-LARGE_STEP
steps left, so I just need to find the total number of combinations of that many steps. If I take a small step, than I just need to find the total number of combinations of numStais-SMALL_STEP
.
Put in the terms of a recursion, combinations[n]=combinations[n-1]+combinations[n-2].
It should be noted that this is not the fastest way to do this by any means. This redoes a ton of work for each iteration. A dynamic programming approach would be much preferable.
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)
Upvotes: 1
Reputation: 2723
let f(n) be the number of ways to reach nth stair from starting (stair number 0) .
To reach stair n
, you 1st have to reach start n-1
or n-2
.
similarly to reach stair n-1
, you need to reach n-2
th or n-3
th stair , and recursion goes like this ....
But it has to stop somewhere otherwise you keep on evaluating f(-1)
, f(-2)
, ... f(- infinity)
... so there is the stopping condition
: to reach stair 1
, you can ONLY do so in 1
step i.e from stair 0
to stair 1
directly .
To reach stair 2
, 2 ways
: stair 0
+ step of 2
, or stair 1
+ step of 1
.
Therefore
f(1) = 1
f(2) = 2
f(3) = 3
f(n) = f(n-1) + f(n-2) // n>3
Upvotes: 0
Reputation: 254631
To go down numStairs
, you can either:
(numStairs - SMALL_STEP)
; or(numStairs - LARGE_STEP)
.So the total number of ways is the sum of the number of ways to go down (numStairs - SMALL_STEP)
and the number of ways to go down (numStairs - LARGE_STEP)
, hence the recursion.
It's simple enough to see that there's one way to go down one step (S), two to go down two (SS or L) and three to go down three (SSS, SL or LS), hence the termination condition.
You might recognise this recursion as the definition of the Fibonacci sequence. For bonus points, you might like to restructure the calculation so that it runs in linear, rather than exponential, time.
Upvotes: 6
Reputation: 747
The code tries to decompose the problem by making it smaller in every step.
If there are less than four steps to go , the number of possible combination is equal to the number of stairs:
- For one stair the only possible combination is a small step.
- For two stairs the possible combinations are a large step or two small steps.
- For three stairs you can go either three small steps, a small step and a large step or a large step and a small step.
These cases will end the recursion.
For every other number of stairs you can go either a small step and then the rest of the stairs, or a large step and then the rest of the stairs. The "rest of the stairs" is where the recursion happens: It will just calculate the number of possibilities for the reduced number of stairs (one or two steps less, depending on size of the first step).
Add them all together and you get the total number of combinations for walking up the stairs.
Upvotes: 0