Skip to main content

Command Palette

Search for a command to run...

Climbing Stairs

Published
4 min readView as Markdown
Climbing Stairs

To intuitively solve the climbing stairs problem, it’s helpful to recognize its connection to the Fibonacci sequence. Here’s how you can approach it:

Climbing Stairs

1. Understanding the Problem: Start by understanding the problem statement. We need to find the number of distinct ways to climb n steps, where we can climb either 1 or 2 steps at a time.

2. Observation: Observe the pattern of climbing steps. For example, for n = 1, there’s only one way to climb (1 step). For n = 2, there are two ways (1+1 step or 2 steps). For n = 3, you can either climb (1+1+1 step) or (1+2 steps). Notice how the number of ways to climb n steps is related to the number of ways to climb n-1 steps and n-2 steps.

3. Connection to Fibonacci: Recognize that the problem exhibits a Fibonacci-like pattern. Each step corresponds to a Fibonacci number. For example, the number of ways to climb 1 step is the 1st Fibonacci number (1), and the number of ways to climb 2 steps is the 2nd Fibonacci number (1), and so on.

4. Recurrence Relation: Realize that the number of ways to climb n steps can be expressed as the sum of the number of ways to climb n-1 steps and the number of ways to climb n-2 steps. This forms the basis of the recurrence relation:

f(n) = f(n-1) + f(n-2)
where f(n) represents the number of ways to climb n steps.

5. Base Cases: Identify the base cases where the recurrence relation stops. In this problem, it’s when n = 1 and n = 2, where the number of ways to climb is 1 and 2, respectively.

6. Dynamic Programming or Matrix Exponentiation: Choose an appropriate approach to calculate the Fibonacci numbers efficiently. Dynamic programming can be used for an iterative solution with a time complexity of O(n), while matrix exponentiation can be used for a more efficient solution with a time complexity of O(log n).

7. Implementation: Implement the chosen approach, making sure to handle edge cases and base cases correctly.

Solution:

// Function to multiply two 2x2 matrices
func multiplyMatrix(matrix1, matrix2 [][]int) [][]int {
// Initialize the result matrix
result := make([][]int, 2)
for i := range result {
result[i] = make([]int, 2)
}
// Perform matrix multiplication
result[0][0] = matrix1[0][0]*matrix2[0][0] + matrix1[0][1]*matrix2[1][0]
result[0][1] = matrix1[0][0]*matrix2[0][1] + matrix1[0][1]*matrix2[1][1]
result[1][0] = matrix1[1][0]*matrix2[0][0] + matrix1[1][1]*matrix2[1][0]
result[1][1] = matrix1[1][0]*matrix2[0][1] + matrix1[1][1]*matrix2[1][1]
return result
}

// Function to raise a 2x2 matrix to the power of n
func matrixPower(matrix [][]int, n int) [][]int {
// Base case: if n is 0 or 1, return the matrix itself
if n <= 1 {
return matrix
}
// Initialize the result matrix as an identity matrix
result := [][]int{{1, 0}, {0, 1}}
// Perform binary exponentiation to raise the matrix to the power of n
for n > 0 {
// If the current power of 2 is included in the exponent, multiply the result by the matrix
if n&1 == 1 {
result = multiplyMatrix(result, matrix)
}
// Square the matrix to prepare for the next iteration
matrix = multiplyMatrix(matrix, matrix)
// Halve the exponent
n >>= 1
}
return result
}

// Function to calculate the nth Fibonacci number using matrix exponentiation
func climbStairs(n int) int {
// Define the base matrix representing the Fibonacci sequence transformation
baseMatrix := [][]int{{1, 1}, {1, 0}}
// Raise the base matrix to the power of n
resultMatrix := matrixPower(baseMatrix, n)
// Return the nth Fibonacci number, which is the top-left element of the resulting matrix
return resultMatrix[0][0]
}

Key Takeaway:

Question: What is Matrix Exponentiation ?

Matrix exponentiation is a technique used to efficiently raise a square matrix to a positive integer power. It is particularly useful in algorithmic problems where repeated multiplication of matrices is involved, such as calculating the nth term of a linear recurrence relation using matrix transformations.

Here’s how matrix exponentiation works:

Base Matrix:

Start with a base square matrix representing the transformation you want to apply repeatedly. For example, in problems related to linear recurrence relations, this matrix captures the transition from one state to the next.

Binary Exponentiation:

To raise the matrix to a certain power efficiently, use binary exponentiation, which leverages the binary representation of the exponent. The idea is to repeatedly square the matrix and use those squares to build the final result.

Algorithm:

  • Initialize the result matrix as the identity matrix (the matrix where the diagonal elements are 1 and others are 0).
  • Iterate over the binary representation of the exponent from the least significant bit to the most significant bit.
  • If the current bit is 1, multiply the result matrix by the base matrix.
  • Square the base matrix for the next iteration.
  • Shift the bits of the exponent to the right (i.e., divide it by 2) for the next iteration.
  • Repeat until all bits of the exponent have been processed.

Final Result:

After completing the iterations, the result matrix contains the desired power of the base matrix.

Example:

More from this blog

L

Lazy Ops

28 posts

Lazy Ops: A relaxed take on platform engineering and DevOps. Minimal effort, maximum automation, and plenty of humor for those who believe in working smarter, not harder. Sit back and enjoy!