You have an N step staircase that you can climb either 1 or 2 steps at a time. How many ways are there to climb it?
It was clear that this was a recurrence relation, and my instinct was to cache the computed values. This would be a better attack for a more complex problem; this is just a Fibonacci sequence!
I did do the cached one first, and I am very proud of myself for properly passing the cache through:
func climbStairs(n int) int {
// this smells of caching...and a Fibonacci recurrence.
// we know that if we're at N, it takes 0 steps to finish.
// if we're at n - 1, there is one option: take 1 step.
// if we're at n - 2, there are two options, 2 1 step, or 1 2 step.
cache := map[int]int{
0: 0,
1: 1,
2: 2,
}
return assist(n, &cache)
}
func assist(n int, cache *map[int]int) int {
if steps, ok := (*cache)[n]; ok {
return steps
}
(*cache)[n] = assist(n-1, cache) + assist(n-2, cache)
return (*cache)[n]
}
A huge winner on runtime: 100%! But poor on memory: bottom 9%. An iterative Fibonacci calculation’s probably going to win on this one…Interestingly, it doesn’t! Runtime 82%, memory 33%.
func climbStairs(n int) int {
// this smells of caching...and a Fibonacci recurrence.
backTwo := 1
backOne := 2
sum := 0
if n == 1 {
return 1
}
if n == 2 {
return 2
}
for current := n; current > 2; current-- {
sum = backOne + backTwo
backTwo = backOne
backOne = sum
}
return sum
}
Off to the solutions to see what’s there.. the most compact iterative solution still isn’t any better on memory, but is the same speed as the cached one I wrote:
func climbStairs(n int) int {
next, secondNext := 0, 1
for ; n > 0; n-- {
next, secondNext = secondNext, next + secondNext
}
return secondNext
}
I’ll call this a win, and ++ for dynamic programming.
Leave a Reply
You must be logged in to post a comment.