diff --git a/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/README.md b/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/README.md index 822e7c9fcfa41..53472c7d665c0 100644 --- a/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/README.md +++ b/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/README.md @@ -107,32 +107,166 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3154.Fi -### 方法一 +### 方法一:记忆化搜索 + +我们设计一个函数 $\text{dfs}(i, j, \text{jump})$,表示当前位于第 $i$ 级台阶,且进行了 $j$ 次操作 $1$ 和 $\text{jump}$ 次操作 $2$,到达第 $k$ 级台阶的方案数。那么答案就是 $\text{dfs}(1, 0, 0)$。 + +函数 $\text{dfs}(i, j, \text{jump})$ 的计算过程如下: + +- 如果 $i > k + 1$,由于无法连续两次向下走,所以无法再到达第 $k$ 级台阶,返回 $0$; +- 如果 $i = k$,表示已经到达第 $k$ 级台阶,答案初始化为 $1$,然后继续计算; +- 如果 $i > 0$ 且 $j = 0$,表示可以向下走,递归计算 $\text{dfs}(i - 1, 1, \text{jump})$; +- 递归计算 $\text{dfs}(i + 2^{\text{jump}}, 0, \text{jump} + 1)$,累加到答案中。 + +为了避免重复计算,我们使用记忆化搜索,将已经计算过的状态保存起来。 + +时间复杂度 $(\log ^2 k)$,空间复杂度 $(\log ^2 k)$。 #### Python3 ```python - +class Solution: + def waysToReachStair(self, k: int) -> int: + @cache + def dfs(i: int, j: int, jump: int) -> int: + if i > k + 1: + return 0 + ans = int(i == k) + if i > 0 and j == 0: + ans += dfs(i - 1, 1, jump) + ans += dfs(i + (1 << jump), 0, jump + 1) + return ans + + return dfs(1, 0, 0) ``` #### Java ```java - +class Solution { + private Map f = new HashMap<>(); + private int k; + + public int waysToReachStair(int k) { + this.k = k; + return dfs(1, 0, 0); + } + + private int dfs(int i, int j, int jump) { + if (i > k + 1) { + return 0; + } + long key = ((long) i << 32) | jump << 1 | j; + if (f.containsKey(key)) { + return f.get(key); + } + int ans = i == k ? 1 : 0; + if (i > 0 && j == 0) { + ans += dfs(i - 1, 1, jump); + } + ans += dfs(i + (1 << jump), 0, jump + 1); + f.put(key, ans); + return ans; + } +} ``` #### C++ ```cpp - +class Solution { +public: + int waysToReachStair(int k) { + this->k = k; + return dfs(1, 0, 0); + } + +private: + unordered_map f; + int k; + + int dfs(int i, int j, int jump) { + if (i > k + 1) { + return 0; + } + long long key = ((long long) i << 32) | jump << 1 | j; + if (f.contains(key)) { + return f[key]; + } + int ans = i == k ? 1 : 0; + if (i > 0 && j == 0) { + ans += dfs(i - 1, 1, jump); + } + ans += dfs(i + (1 << jump), 0, jump + 1); + f[key] = ans; + return ans; + } +}; ``` #### Go ```go +func waysToReachStair(k int) int { + f := map[int]int{} + var dfs func(i, j, jump int) int + dfs = func(i, j, jump int) int { + if i > k+1 { + return 0 + } + key := (i << 32) | jump<<1 | j + if v, has := f[key]; has { + return v + } + ans := 0 + if i == k { + ans++ + } + if i > 0 && j == 0 { + ans += dfs(i-1, 1, jump) + } + ans += dfs(i+(1< = new Map(); + + const dfs = (i: number, j: number, jump: number): number => { + if (i > k + 1) { + return 0; + } + + const key: bigint = (BigInt(i) << BigInt(32)) | BigInt(jump << 1) | BigInt(j); + if (f.has(key)) { + return f.get(key)!; + } + + let ans: number = 0; + if (i === k) { + ans++; + } + + if (i > 0 && j === 0) { + ans += dfs(i - 1, 1, jump); + } + + ans += dfs(i + (1 << jump), 0, jump + 1); + f.set(key, ans); + return ans; + }; + return dfs(1, 0, 0); +} ``` diff --git a/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/README_EN.md b/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/README_EN.md index bf37c952a8b6e..de0402782f111 100644 --- a/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/README_EN.md +++ b/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/README_EN.md @@ -105,32 +105,166 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3100-3199/3154.Fi -### Solution 1 +### Solution 1: Memoization Search + +We design a function `dfs(i, j, jump)`, which represents the number of ways to reach the $k$th step when currently at the $i$th step, having performed $j$ operation 1's and `jump` operation 2's. The answer is `dfs(1, 0, 0)`. + +The calculation process of the function `dfs(i, j, jump)` is as follows: + +- If $i > k + 1$, since we cannot go down twice in a row, we cannot reach the $k$th step again, so return $0$; +- If $i = k$, it means that we have reached the $k$th step. The answer is initialized to $1$, and then continue to calculate; +- If $i > 0$ and $j = 0$, it means that we can go down, recursively calculate `dfs(i - 1, 1, jump)`; +- Recursively calculate `dfs(i + 2^{jump}, 0, jump + 1)`, and add it to the answer. + +To avoid repeated calculations, we use memoization search to save the calculated states. + +The time complexity is $O(\log^2 k)$, and the space complexity is $O(\log^2 k)$. #### Python3 ```python - +class Solution: + def waysToReachStair(self, k: int) -> int: + @cache + def dfs(i: int, j: int, jump: int) -> int: + if i > k + 1: + return 0 + ans = int(i == k) + if i > 0 and j == 0: + ans += dfs(i - 1, 1, jump) + ans += dfs(i + (1 << jump), 0, jump + 1) + return ans + + return dfs(1, 0, 0) ``` #### Java ```java - +class Solution { + private Map f = new HashMap<>(); + private int k; + + public int waysToReachStair(int k) { + this.k = k; + return dfs(1, 0, 0); + } + + private int dfs(int i, int j, int jump) { + if (i > k + 1) { + return 0; + } + long key = ((long) i << 32) | jump << 1 | j; + if (f.containsKey(key)) { + return f.get(key); + } + int ans = i == k ? 1 : 0; + if (i > 0 && j == 0) { + ans += dfs(i - 1, 1, jump); + } + ans += dfs(i + (1 << jump), 0, jump + 1); + f.put(key, ans); + return ans; + } +} ``` #### C++ ```cpp - +class Solution { +public: + int waysToReachStair(int k) { + this->k = k; + return dfs(1, 0, 0); + } + +private: + unordered_map f; + int k; + + int dfs(int i, int j, int jump) { + if (i > k + 1) { + return 0; + } + long long key = ((long long) i << 32) | jump << 1 | j; + if (f.contains(key)) { + return f[key]; + } + int ans = i == k ? 1 : 0; + if (i > 0 && j == 0) { + ans += dfs(i - 1, 1, jump); + } + ans += dfs(i + (1 << jump), 0, jump + 1); + f[key] = ans; + return ans; + } +}; ``` #### Go ```go +func waysToReachStair(k int) int { + f := map[int]int{} + var dfs func(i, j, jump int) int + dfs = func(i, j, jump int) int { + if i > k+1 { + return 0 + } + key := (i << 32) | jump<<1 | j + if v, has := f[key]; has { + return v + } + ans := 0 + if i == k { + ans++ + } + if i > 0 && j == 0 { + ans += dfs(i-1, 1, jump) + } + ans += dfs(i+(1< = new Map(); + + const dfs = (i: number, j: number, jump: number): number => { + if (i > k + 1) { + return 0; + } + + const key: bigint = (BigInt(i) << BigInt(32)) | BigInt(jump << 1) | BigInt(j); + if (f.has(key)) { + return f.get(key)!; + } + + let ans: number = 0; + if (i === k) { + ans++; + } + + if (i > 0 && j === 0) { + ans += dfs(i - 1, 1, jump); + } + + ans += dfs(i + (1 << jump), 0, jump + 1); + f.set(key, ans); + return ans; + }; + return dfs(1, 0, 0); +} ``` diff --git a/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/Solution.cpp b/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/Solution.cpp new file mode 100644 index 0000000000000..bac94a2f6d756 --- /dev/null +++ b/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/Solution.cpp @@ -0,0 +1,28 @@ +class Solution { +public: + int waysToReachStair(int k) { + this->k = k; + return dfs(1, 0, 0); + } + +private: + unordered_map f; + int k; + + int dfs(int i, int j, int jump) { + if (i > k + 1) { + return 0; + } + long long key = ((long long) i << 32) | jump << 1 | j; + if (f.contains(key)) { + return f[key]; + } + int ans = i == k ? 1 : 0; + if (i > 0 && j == 0) { + ans += dfs(i - 1, 1, jump); + } + ans += dfs(i + (1 << jump), 0, jump + 1); + f[key] = ans; + return ans; + } +}; \ No newline at end of file diff --git a/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/Solution.go b/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/Solution.go new file mode 100644 index 0000000000000..96254401b51e8 --- /dev/null +++ b/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/Solution.go @@ -0,0 +1,24 @@ +func waysToReachStair(k int) int { + f := map[int]int{} + var dfs func(i, j, jump int) int + dfs = func(i, j, jump int) int { + if i > k+1 { + return 0 + } + key := (i << 32) | jump<<1 | j + if v, has := f[key]; has { + return v + } + ans := 0 + if i == k { + ans++ + } + if i > 0 && j == 0 { + ans += dfs(i-1, 1, jump) + } + ans += dfs(i+(1< f = new HashMap<>(); + private int k; + + public int waysToReachStair(int k) { + this.k = k; + return dfs(1, 0, 0); + } + + private int dfs(int i, int j, int jump) { + if (i > k + 1) { + return 0; + } + long key = ((long) i << 32) | jump << 1 | j; + if (f.containsKey(key)) { + return f.get(key); + } + int ans = i == k ? 1 : 0; + if (i > 0 && j == 0) { + ans += dfs(i - 1, 1, jump); + } + ans += dfs(i + (1 << jump), 0, jump + 1); + f.put(key, ans); + return ans; + } +} \ No newline at end of file diff --git a/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/Solution.py b/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/Solution.py new file mode 100644 index 0000000000000..67459c5a5e000 --- /dev/null +++ b/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/Solution.py @@ -0,0 +1,13 @@ +class Solution: + def waysToReachStair(self, k: int) -> int: + @cache + def dfs(i: int, j: int, jump: int) -> int: + if i > k + 1: + return 0 + ans = int(i == k) + if i > 0 and j == 0: + ans += dfs(i - 1, 1, jump) + ans += dfs(i + (1 << jump), 0, jump + 1) + return ans + + return dfs(1, 0, 0) diff --git a/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/Solution.ts b/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/Solution.ts new file mode 100644 index 0000000000000..33b17b9d49560 --- /dev/null +++ b/solution/3100-3199/3154.Find Number of Ways to Reach the K-th Stair/Solution.ts @@ -0,0 +1,29 @@ +function waysToReachStair(k: number): number { + const f: Map = new Map(); + + const dfs = (i: number, j: number, jump: number): number => { + if (i > k + 1) { + return 0; + } + + const key: bigint = (BigInt(i) << BigInt(32)) | BigInt(jump << 1) | BigInt(j); + if (f.has(key)) { + return f.get(key)!; + } + + let ans: number = 0; + if (i === k) { + ans++; + } + + if (i > 0 && j === 0) { + ans += dfs(i - 1, 1, jump); + } + + ans += dfs(i + (1 << jump), 0, jump + 1); + f.set(key, ans); + return ans; + }; + + return dfs(1, 0, 0); +}