8.1: triple set ✔️

This commit is contained in:
anebz 2020-06-04 18:51:19 +02:00
parent 8e2f7d3685
commit 26ef14f71a
3 changed files with 82 additions and 1 deletions

View File

@ -0,0 +1,81 @@
# 8.1. Triple step
> A child is running up a staircase with n steps and can hop either 1 step, 2 steps, or 3 steps at a time. Implement a method to count how many possible ways the child can run up the stairs.
I'm assuming the kid can't go back. Also, the result for n must be the addition/multiplication of the result for n-1.
* Example: 0 1 2
- 1x: 1, 012
- 2x: 1, 02
- 3x: -
- total: 2
* Example: 0 1 2 3
- 1x: 1, 0123
- 2x: 2, 023, 013
- 3x: 1, 03
- total: 4
* Example: 0 1 2 3 4 5
- 1x: 1, 01234
- 2x: 4, 0245, 0135, 01345, 02345
- 3x: 5, 035, 0345, 0145, 0125, 025
- total: 10
* Example: 0 1 2 3 4 5 6
- 1x: 1, 0123456
- 2x: 6, 0246, 02456, 02356, 01356, 01246, 012346
- 3x: 8, 036, 0346, 0356, 03456, 01456, 0146, 01256, 0256
- total, 22
* Example: 0 1 2 3 4 5 6 7
- 1x: 1, 0123456
- 2x: x, 0134567, 01357, 013457, 013467, 0234567, 02357, 023467, 023457, 024567, 02457, 02467, ?
## Hints
> Approach this from the top down. What is the very last hop the child made?
Either a hop from n-1, n-2, or n-3.
> If we knew the number of paths to each of the steps before step 100, could we compute the number of steps to 100?
That's the point of dynamic programming but I don't see it.
> We can compute the number of steps to 100 by the number of steps to 99, 98, and 97. This corresponds to the child hopping 1, 2, or 3 steps at the end. Do we add those or multiply them?That is: Is it f(100) = f(99) + f(98) + f(97) or f(100) = f(99) * f(98) * f(97)?
Add, either one path or the other is taken. Not all. Multiplying one path with another would signify taking one path and then taking the other.
## Solution
countWays(n) = countWays(n-1) + countWays(n-2) + countWays(n-3). What about base cases? We could say that if n==0, return 1.
```cpp
int countWays(int n) {
if (n < 0) {
return 0;
} else if (n == 0) {
return 1;
} else {
return countWays(n-1) + countWays(n-2)+ countWays(n-3);
}
}
```
But this is very inefficient, O(3<sup>n</sup>). Memoization:
```cpp
int countWays(int n) {
int[] memo = new int[n+ 1];
Arrays.fill(memo, -1);
return countWays(n, memo);
}
int countWays(int n, int[] memo) {
if (n < 0) return 0;
else if (n == 0) return 1;
else if (memo[n] > -1) return memo[n];
memo[n] = countWays(n-1, memo) + countWays(n-2, memo) + countWays(n-3, memo);
return memo[n];
}
```
First fill the memo with -1s. When we start with our `n`, n=4 for example, countWays(3), memo is empty so it's created. Memo is created from the bottom up.

View File

@ -1,6 +1,6 @@
# Chapter 8 Recursion and dynamic programming # Chapter 8 Recursion and dynamic programming
Questions p145, solutions p353 Questions p146, solutions p353
You can know a problem is recursive when it can be built off of subproblems. If a program says: compute the nth, or the first n, or all..., it might be recursive. You can know a problem is recursive when it can be built off of subproblems. If a program says: compute the nth, or the first n, or all..., it might be recursive.