返回介绍

solution / 0000-0099 / 0070.Climbing Stairs / README_EN

发布于 2024-06-17 01:04:40 字数 10063 浏览 0 评论 0 收藏 0

70. Climbing Stairs

中文文档

Description

You are climbing a staircase. It takes n steps to reach the top.

Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?

 

Example 1:

Input: n = 2
Output: 2
Explanation: There are two ways to climb to the top.
1. 1 step + 1 step
2. 2 steps

Example 2:

Input: n = 3
Output: 3
Explanation: There are three ways to climb to the top.
1. 1 step + 1 step + 1 step
2. 1 step + 2 steps
3. 2 steps + 1 step

 

Constraints:

  • 1 <= n <= 45

Solutions

Solution 1: Recursion

We define $f[i]$ to represent the number of ways to climb to the $i$-th step, then $f[i]$ can be transferred from $f[i - 1]$ and $f[i - 2]$, that is:

$$ f[i] = f[i - 1] + f[i - 2] $$

The initial conditions are $f[0] = 1$ and $f[1] = 1$, that is, the number of ways to climb to the 0th step is 1, and the number of ways to climb to the 1st step is also 1.

The answer is $f[n]$.

Since $f[i]$ is only related to $f[i - 1]$ and $f[i - 2]$, we can use two variables $a$ and $b$ to maintain the current number of ways, reducing the space complexity to $O(1)$.

The time complexity is $O(n)$, and the space complexity is $O(1)$.

class Solution:
  def climbStairs(self, n: int) -> int:
    a, b = 0, 1
    for _ in range(n):
      a, b = b, a + b
    return b
class Solution {
  public int climbStairs(int n) {
    int a = 0, b = 1;
    for (int i = 0; i < n; ++i) {
      int c = a + b;
      a = b;
      b = c;
    }
    return b;
  }
}
class Solution {
public:
  int climbStairs(int n) {
    int a = 0, b = 1;
    for (int i = 0; i < n; ++i) {
      int c = a + b;
      a = b;
      b = c;
    }
    return b;
  }
};
func climbStairs(n int) int {
  a, b := 0, 1
  for i := 0; i < n; i++ {
    a, b = b, a+b
  }
  return b
}
function climbStairs(n: number): number {
  let p = 1;
  let q = 1;
  for (let i = 1; i < n; i++) {
    [p, q] = [q, p + q];
  }
  return q;
}
impl Solution {
  pub fn climb_stairs(n: i32) -> i32 {
    let (mut p, mut q) = (1, 1);
    for i in 1..n {
      let t = p + q;
      p = q;
      q = t;
    }
    q
  }
}
/**
 * @param {number} n
 * @return {number}
 */
var climbStairs = function (n) {
  let a = 0,
    b = 1;
  for (let i = 0; i < n; ++i) {
    const c = a + b;
    a = b;
    b = c;
  }
  return b;
};
class Solution {
  /**
   * @param Integer $n
   * @return Integer
   */
  function climbStairs($n) {
    if ($n <= 2) {
      return $n;
    }
    $dp = [0, 1, 2];
    for ($i = 3; $i <= $n; $i++) {
      $dp[$i] = $dp[$i - 2] + $dp[$i - 1];
    }
    return $dp[$n];
  }
}

Solution 2: Matrix Quick Power to Accelerate Recursion

We set $Fib(n)$ to represent a $1 \times 2$ matrix $\begin{bmatrix} F_n & F_{n - 1} \end{bmatrix}$, where $F_n$ and $F_{n - 1}$ are the $n$-th and $(n - 1)$-th Fibonacci numbers respectively.

We hope to derive $Fib(n)$ based on $Fib(n-1) = \begin{bmatrix} F_{n - 1} & F_{n - 2} \end{bmatrix}$. That is to say, we need a matrix $base$, so that $Fib(n - 1) \times base = Fib(n)$, that is:

$$ \begin{bmatrix} F_{n - 1} & F_{n - 2} \end{bmatrix} \times base = \begin{bmatrix} F_n & F_{n - 1} \end{bmatrix} $$

Since $F_n = F_{n - 1} + F_{n - 2}$, the first column of the matrix $base$ is:

$$ \begin{bmatrix} 1 \ 1 \end{bmatrix} $$

The second column is:

$$ \begin{bmatrix} 1 \ 0 \end{bmatrix} $$

Therefore:

$$ \begin{bmatrix} F_{n - 1} & F_{n - 2} \end{bmatrix} \times \begin{bmatrix}1 & 1 \ 1 & 0\end{bmatrix} = \begin{bmatrix} F_n & F_{n - 1} \end{bmatrix} $$

We define the initial matrix $res = \begin{bmatrix} 1 & 1 \end{bmatrix}$, then $F_n$ is equal to the first element of the first row of the result matrix of $res$ multiplied by $base^{n - 1}$. We can solve it using matrix quick power.

The time complexity is $O(\log n)$, and the space complexity is $O(1)$.

class Solution:
  def climbStairs(self, n: int) -> int:
    def mul(a: List[List[int]], b: List[List[int]]) -> List[List[int]]:
      m, n = len(a), len(b[0])
      c = [[0] * n for _ in range(m)]
      for i in range(m):
        for j in range(n):
          for k in range(len(a[0])):
            c[i][j] = c[i][j] + a[i][k] * b[k][j]
      return c

    def pow(a: List[List[int]], n: int) -> List[List[int]]:
      res = [[1, 1]]
      while n:
        if n & 1:
          res = mul(res, a)
        n >>= 1
        a = mul(a, a)
      return res

    a = [[1, 1], [1, 0]]
    return pow(a, n - 1)[0][0]
class Solution {
  private final int[][] a = {{1, 1}, {1, 0}};

  public int climbStairs(int n) {
    return pow(a, n - 1)[0][0];
  }

  private int[][] mul(int[][] a, int[][] b) {
    int m = a.length, n = b[0].length;
    int[][] c = new int[m][n];
    for (int i = 0; i < m; ++i) {
      for (int j = 0; j < n; ++j) {
        for (int k = 0; k < a[0].length; ++k) {
          c[i][j] += a[i][k] * b[k][j];
        }
      }
    }
    return c;
  }

  private int[][] pow(int[][] a, int n) {
    int[][] res = {{1, 1}, {0, 0}};
    while (n > 0) {
      if ((n & 1) == 1) {
        res = mul(res, a);
      }
      n >>= 1;
      a = mul(a, a);
    }
    return res;
  }
}
class Solution {
public:
  int climbStairs(int n) {
    vector<vector<long long>> a = {{1, 1}, {1, 0}};
    return pow(a, n - 1)[0][0];
  }

private:
  vector<vector<long long>> mul(vector<vector<long long>>& a, vector<vector<long long>>& b) {
    int m = a.size(), n = b[0].size();
    vector<vector<long long>> res(m, vector<long long>(n));
    for (int i = 0; i < m; ++i) {
      for (int j = 0; j < n; ++j) {
        for (int k = 0; k < a[0].size(); ++k) {
          res[i][j] += a[i][k] * b[k][j];
        }
      }
    }
    return res;
  }

  vector<vector<long long>> pow(vector<vector<long long>>& a, int n) {
    vector<vector<long long>> res = {{1, 1}, {0, 0}};
    while (n) {
      if (n & 1) {
        res = mul(res, a);
      }
      a = mul(a, a);
      n >>= 1;
    }
    return res;
  }
};
type matrix [2][2]int

func climbStairs(n int) int {
  a := matrix{{1, 1}, {1, 0}}
  return pow(a, n-1)[0][0]
}

func mul(a, b matrix) (c matrix) {
  m, n := len(a), len(b[0])
  for i := 0; i < m; i++ {
    for j := 0; j < n; j++ {
      for k := 0; k < len(a[0]); k++ {
        c[i][j] += a[i][k] * b[k][j]
      }
    }
  }
  return
}

func pow(a matrix, n int) matrix {
  res := matrix{{1, 1}, {0, 0}}
  for n > 0 {
    if n&1 == 1 {
      res = mul(res, a)
    }
    a = mul(a, a)
    n >>= 1
  }
  return res
}
function climbStairs(n: number): number {
  const a = [
    [1, 1],
    [1, 0],
  ];
  return pow(a, n - 1)[0][0];
}

function mul(a: number[][], b: number[][]): number[][] {
  const [m, n] = [a.length, b[0].length];
  const c = Array(m)
    .fill(0)
    .map(() => Array(n).fill(0));
  for (let i = 0; i < m; ++i) {
    for (let j = 0; j < n; ++j) {
      for (let k = 0; k < a[0].length; ++k) {
        c[i][j] += a[i][k] * b[k][j];
      }
    }
  }
  return c;
}

function pow(a: number[][], n: number): number[][] {
  let res = [
    [1, 1],
    [0, 0],
  ];
  while (n) {
    if (n & 1) {
      res = mul(res, a);
    }
    a = mul(a, a);
    n >>= 1;
  }
  return res;
}
/**
 * @param {number} n
 * @return {number}
 */
var climbStairs = function (n) {
  const a = [
    [1, 1],
    [1, 0],
  ];
  return pow(a, n - 1)[0][0];
};

function mul(a, b) {
  const [m, n] = [a.length, b[0].length];
  const c = Array(m)
    .fill(0)
    .map(() => Array(n).fill(0));
  for (let i = 0; i < m; ++i) {
    for (let j = 0; j < n; ++j) {
      for (let k = 0; k < a[0].length; ++k) {
        c[i][j] += a[i][k] * b[k][j];
      }
    }
  }
  return c;
}

function pow(a, n) {
  let res = [
    [1, 1],
    [0, 0],
  ];
  while (n) {
    if (n & 1) {
      res = mul(res, a);
    }
    a = mul(a, a);
    n >>= 1;
  }
  return res;
}

Solution 3

import numpy as np


class Solution:
  def climbStairs(self, n: int) -> int:
    res = np.mat([(1, 1)], np.dtype("O"))
    factor = np.mat([(1, 1), (1, 0)], np.dtype("O"))
    n -= 1
    while n:
      if n & 1:
        res *= factor
      factor *= factor
      n >>= 1
    return res[0, 0]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文