Published on

Staircase problem

Authors

Problem

LeetCode 70 - Climbing Stairs [easy]

You are climbing a stair case. It takes n steps to reach to the top. Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?

Note:

Given n will be a positive integer.

Example 1:


_5
Input: 2
_5
Output: 2
_5
Explanation: There are two ways to climb to the top.
_5
--> 1 step + 1 step
_5
--> 2 steps

Example 2:


_6
Input: 3
_6
Output: 3
_6
Explanation: There are three ways to climb to the top.
_6
--> 1 step + 1 step + 1 step
_6
--> 1 step + 2 steps
_6
--> 2 steps + 1 step

Solution

Brute Force

bruteforce.go
Output

_27
package main
_27
_27
import (
_27
"testing"
_27
)
_27
_27
func Climb(n int) int {
_27
if n < 3 {
_27
return n
_27
}
_27
return Climb(n-1) + Climb(n-2)
_27
}
_27
_27
func TestClimb(t *testing.T) {
_27
tests := []struct {
_27
input int
_27
want int
_27
}{
_27
{input: 2, want: 2},
_27
{input: 3, want: 3},
_27
}
_27
for _, tt := range tests {
_27
if got := Climb(tt.input); got != tt.want {
_27
t.Errorf("LastIndex(%v) = %v, want %v", tt.input, got, tt.want)
_27
}
_27
}
_27
}

See https://go.dev/play/p/tPlQuYwe8bp

Time Complexity: O(2N)O(2^N) because we are making 2 recursive calls in the same function.

Space Complexity: O(N)O(N) which is used to store the recursion stack.

Ugh so slow, how to improve that? We must visualize the call stack first to be able to understand where is the problem.


_7
f(4)
_7
+---------------+
_7
f(3) f(2)
_7
+---------+ +-------+
_7
f(2) f(1) f(1) f(0)
_7
+------+
_7
f(1) f(0)

As you can see, there are a lot of overlapping sub-problem that we only calculate it once.

Top-Down DP with memoization


_40
package main
_40
_40
import (
_40
"testing"
_40
)
_40
_40
func Climb(n int) int {
_40
dp := make([]int, n+1)
_40
_40
var recursive func(n int) int
_40
_40
recursive = func(n int) int {
_40
if n < 3 {
_40
return n
_40
}
_40
_40
if dp[n] == 0 {
_40
dp[n] = recursive(n-1) + recursive(n-2)
_40
}
_40
_40
return dp[n]
_40
}
_40
_40
return recursive(n)
_40
}
_40
_40
func TestClimb(t *testing.T) {
_40
tests := []struct {
_40
input int
_40
want int
_40
}{
_40
{input: 2, want: 2},
_40
{input: 3, want: 3},
_40
}
_40
for _, tt := range tests {
_40
if got := Climb(tt.input); got != tt.want {
_40
t.Errorf("LastIndex(%v) = %v, want %v", tt.input, got, tt.want)
_40
}
_40
}
_40
}

See https://go.dev/play/p/1BlZ6_GF_AI

Time Complexity: O(N) because memoization array dp[n+1] stores the results of all sub-problems. We can conclude that we will not have more than n + 1 sub-problems.

Space Complexity: O(N) which is used to store the recursion stack.

Bottom-Up DP with tabulation


_32
package main
_32
_32
import (
_32
"testing"
_32
)
_32
_32
func Climb(n int) int {
_32
dp := make([]int, n+1)
_32
dp[0] = 1
_32
dp[1] = 1
_32
_32
for i := 2; i < n+1; i++ {
_32
dp[i] = dp[i-1] + dp[i-2]
_32
}
_32
_32
return dp[n]
_32
}
_32
_32
func TestClimb(t *testing.T) {
_32
tests := []struct {
_32
input int
_32
want int
_32
}{
_32
{input: 2, want: 2},
_32
{input: 3, want: 3},
_32
}
_32
for _, tt := range tests {
_32
if got := Climb(tt.input); got != tt.want {
_32
t.Errorf("LastIndex(%v) = %v, want %v", tt.input, got, tt.want)
_32
}
_32
}
_32
}

See https://go.dev/play/p/wEPgFxASeUn

Time Complexity: O(N)

Space Complexity: O(N) which is used to store the recursion stack.

Memory optimization

From the visualization of the recursive stack and other solution, we only required n-1 and n-2 to calculate n


_29
package main
_29
_29
import (
_29
"testing"
_29
)
_29
_29
func Climb(n int) int {
_29
a, b := 1, 1
_29
for i := 0; i < n; i++ {
_29
a, b = b, a+b
_29
}
_29
_29
return a
_29
}
_29
_29
func TestClimb(t *testing.T) {
_29
tests := []struct {
_29
input int
_29
want int
_29
}{
_29
{input: 2, want: 2},
_29
{input: 3, want: 3},
_29
}
_29
for _, tt := range tests {
_29
if got := Climb(tt.input); got != tt.want {
_29
t.Errorf("LastIndex(%v) = %v, want %v", tt.input, got, tt.want)
_29
}
_29
}
_29
}

Try it in playground https://go.dev/play/p/mBTiZjs2q0y

Time Complexity: O(N)

Space Complexity: O(1)