From 62012521801a07f4372c6dacb5d815aa4f91d2db Mon Sep 17 00:00:00 2001 From: ITCharge Date: 2022年7月29日 17:03:11 +0800 Subject: [PATCH 01/11] =?UTF-8?q?Update=200045.=20=E8=B7=B3=E8=B7=83?= =?UTF-8?q?=E6=B8=B8=E6=88=8F=20II.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...045. 350円267円263円350円267円203円346円270円270円346円210円217円 II.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/Solutions/0045. 350円267円263円350円267円203円346円270円270円346円210円217円 II.md" "b/Solutions/0045. 350円267円263円350円267円203円346円270円270円346円210円217円 II.md" index 215b536b..96c04ba1 100644 --- "a/Solutions/0045. 350円267円263円350円267円203円346円270円270円346円210円217円 II.md" +++ "b/Solutions/0045. 350円267円263円350円267円203円346円270円270円346円210円217円 II.md" @@ -44,7 +44,7 @@ 初始状态下,跳到下标 `0` 需要的最小跳跃次数为 `0`,即 `dp[0] = 0`。 -##### 5. 最终结果 +###### 5. 最终结果 根据我们之前定义的状态,`dp[i]` 表示为:跳到下标 `i` 所需要的最小跳跃次数。则最终结果为 `dp[size - 1]`。 From fe68c8e279b1614941067aa0a8cd9319ce064c51 Mon Sep 17 00:00:00 2001 From: ITCharge Date: 2022年7月29日 17:03:15 +0800 Subject: [PATCH 02/11] =?UTF-8?q?Update=200198.=20=E6=89=93=E5=AE=B6?= =?UTF-8?q?=E5=8A=AB=E8=88=8D.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../0198. 346円211円223円345円256円266円345円212円253円350円210円215円.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/Solutions/0198. 346円211円223円345円256円266円345円212円253円350円210円215円.md" "b/Solutions/0198. 346円211円223円345円256円266円345円212円253円350円210円215円.md" index 773164c4..565603ad 100644 --- "a/Solutions/0198. 346円211円223円345円256円266円345円212円253円350円210円215円.md" +++ "b/Solutions/0198. 346円211円223円345円256円266円345円212円253円350円210円215円.md" @@ -48,7 +48,7 @@ - 如果只有一间房,则直接偷这间屋子就能偷到最高金额,即 `dp[0] = nums[i]`。 - 如果只有两间房,那么就选择金额最大的那间屋进行偷窃,就可以偷到最高金额,即 `dp[1] = max(nums[0], nums[1])`。 -##### 5. 最终结果 +###### 5. 最终结果 根据我们之前定义的状态,`dp[i]` 表示为:前 `i` 间房屋所能偷窃到的最高金额。则最终结果为 `dp[size - 1]`,`size` 为总的房屋数。 From 4b30a5a1ae0c01cb8fd8e5e056078d7abfb26586 Mon Sep 17 00:00:00 2001 From: ITCharge Date: 2022年7月29日 17:03:19 +0800 Subject: [PATCH 03/11] =?UTF-8?q?Update=200213.=20=E6=89=93=E5=AE=B6?= =?UTF-8?q?=E5=8A=AB=E8=88=8D=20II.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...213. 346円211円223円345円256円266円345円212円253円350円210円215円 II.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/Solutions/0213. 346円211円223円345円256円266円345円212円253円350円210円215円 II.md" "b/Solutions/0213. 346円211円223円345円256円266円345円212円253円350円210円215円 II.md" index 9b47f369..36aa19f4 100644 --- "a/Solutions/0213. 346円211円223円345円256円266円345円212円253円350円210円215円 II.md" +++ "b/Solutions/0213. 346円211円223円345円256円266円345円212円253円350円210円215円 II.md" @@ -56,7 +56,7 @@ - 如果只有一间房,则直接偷这间屋子就能偷到最高金额,即 `dp[0] = nums[i]`。 - 如果只有两间房,那么就选择金额最大的那间屋进行偷窃,就可以偷到最高金额,即 `dp[1] = max(nums[0], nums[1])`。 -##### 5. 最终结果 +###### 5. 最终结果 根据我们之前定义的状态,`dp[i]` 表示为:前 `i` 间房屋所能偷窃到的最高金额。假设求解 `[0, size - 2]` 和 `[1, size - 1]` 范围下( `size` 为总的房屋数)首尾不相连的房屋所能偷窃的最高金额问题分别为 `ans1`、`ans2`,则最终结果为 `max(ans1, ans2)`。 From cc92a119eabcf5046609b3afa5da5e224b484178 Mon Sep 17 00:00:00 2001 From: ITCharge Date: 2022年7月29日 17:03:22 +0800 Subject: [PATCH 04/11] =?UTF-8?q?Update=200300.=20=E6=9C=80=E9=95=BF?= =?UTF-8?q?=E9=80=92=E5=A2=9E=E5=AD=90=E5=BA=8F=E5=88=97.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...200円222円345円242円236円345円255円220円345円272円217円345円210円227円.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/Solutions/0300. 346円234円200円351円225円277円351円200円222円345円242円236円345円255円220円345円272円217円345円210円227円.md" "b/Solutions/0300. 346円234円200円351円225円277円351円200円222円345円242円236円345円255円220円345円272円217円345円210円227円.md" index 92978704..ed790fde 100644 --- "a/Solutions/0300. 346円234円200円351円225円277円351円200円222円345円242円236円345円255円220円345円272円217円345円210円227円.md" +++ "b/Solutions/0300. 346円234円200円351円225円277円351円200円222円345円242円236円345円255円220円345円272円217円345円210円227円.md" @@ -51,7 +51,7 @@ 默认状态下,把数组中的每个元素都作为长度为 `1` 的递增子序列。即 `dp[i] = 1`。 -##### 5. 最终结果 +###### 5. 最终结果 根据我们之前定义的状态,`dp[i]` 表示为:以 `nums[i]` 结尾的最长递增子序列长度。那为了计算出最大的最长递增子序列长度,则需要再遍历一遍 `dp` 数组,求出最大值即为最终结果。 From 13ff934d60f6501af5885e4d4cc18f06789d66ac Mon Sep 17 00:00:00 2001 From: ITCharge Date: 2022年7月29日 17:03:25 +0800 Subject: [PATCH 05/11] =?UTF-8?q?Update=200338.=20=E6=AF=94=E7=89=B9?= =?UTF-8?q?=E4=BD=8D=E8=AE=A1=E6=95=B0.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...257円224円347円211円271円344円275円215円350円256円241円346円225円260円.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/Solutions/0338. 346円257円224円347円211円271円344円275円215円350円256円241円346円225円260円.md" "b/Solutions/0338. 346円257円224円347円211円271円344円275円215円350円256円241円346円225円260円.md" index fd0087d4..98ff7c04 100644 --- "a/Solutions/0338. 346円257円224円347円211円271円344円275円215円350円256円241円346円225円260円.md" +++ "b/Solutions/0338. 346円257円224円347円211円271円344円275円215円350円256円241円346円225円260円.md" @@ -59,7 +59,7 @@ 整数 `0` 对应二进制表示中 `1` 的个数为 `0`。 -##### 5. 最终结果 +###### 5. 最终结果 整个 `dp` 数组即为最终结果,将其返回即可。 From 405aa85affff65be3ac7f7e38c22d5b1243b87ff Mon Sep 17 00:00:00 2001 From: ITCharge Date: 2022年7月29日 17:03:27 +0800 Subject: [PATCH 06/11] =?UTF-8?q?Update=200403.=20=E9=9D=92=E8=9B=99?= =?UTF-8?q?=E8=BF=87=E6=B2=B3.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../0403. 351円235円222円350円233円231円350円277円207円346円262円263円.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/Solutions/0403. 351円235円222円350円233円231円350円277円207円346円262円263円.md" "b/Solutions/0403. 351円235円222円350円233円231円350円277円207円346円262円263円.md" index 5f4f84cc..1a927d61 100644 --- "a/Solutions/0403. 351円235円222円350円233円231円350円277円207円346円262円263円.md" +++ "b/Solutions/0403. 351円235円222円350円233円231円350円277円207円346円262円263円.md" @@ -61,7 +61,7 @@ 刚开始青蛙站在序号为 `0` 石子上(即 `stones[0]`),肯定能以长度为 `0` 的距离,到达第 `0` 块石子,即 `dp[0][0] = True`。 -##### 5. 最终结果 +###### 5. 最终结果 根据我们之前定义的状态,`dp[i][k]` 表示为:青蛙能否以长度为 `k` 的距离,到达第 `i` 块石子。则如果 `dp[size - 1][k]` 为真,则说明青蛙能成功过河(即能在最后一步跳到最后一块石子上);否则则说明青蛙不能成功过河。 From 08d1fadfbb4ad50fa576605a6f83a8685486ba9b Mon Sep 17 00:00:00 2001 From: ITCharge Date: 2022年7月29日 17:03:33 +0800 Subject: [PATCH 07/11] =?UTF-8?q?Update=200674.=20=E6=9C=80=E9=95=BF?= =?UTF-8?q?=E8=BF=9E=E7=BB=AD=E9=80=92=E5=A2=9E=E5=BA=8F=E5=88=97.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...55351円200円222円345円242円236円345円272円217円345円210円227円.md" | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git "a/Solutions/0674. 346円234円200円351円225円277円350円277円236円347円273円255円351円200円222円345円242円236円345円272円217円345円210円227円.md" "b/Solutions/0674. 346円234円200円351円225円277円350円277円236円347円273円255円351円200円222円345円242円236円345円272円217円345円210円227円.md" index 4f4ede4e..9968701c 100644 --- "a/Solutions/0674. 346円234円200円351円225円277円350円277円236円347円273円255円351円200円222円345円242円236円345円272円217円345円210円227円.md" +++ "b/Solutions/0674. 346円234円200円351円225円277円350円277円236円347円273円255円351円200円222円345円242円236円345円272円217円345円210円227円.md" @@ -27,11 +27,11 @@ ### 思路 1:动态规划 -##### 1. 定义状态 +###### 1. 定义状态 定义状态 `dp[i]` 表示为:以 `nums[i]` 结尾的最长且连续递增的子序列长度。 -##### 2. 状态转移方程 +###### 2. 状态转移方程 因为求解的是连续子序列,所以只需要考察相邻元素的状态转移方程。 @@ -45,11 +45,11 @@ 综上,我们的状态转移方程为:`dp[i] = dp[i - 1] + 1`,`nums[i - 1] < nums[i]`。 -##### 3. 初始化 +###### 3. 初始条件 默认状态下,把数组中的每个元素都作为长度为 `1` 的最长且连续递增的子序列长度。即 `dp[i] = 1`。 -##### 4. 最终结果 +###### 4. 最终结果 根据我们之前定义的状态,`dp[i]` 表示为:以 `nums[i]` 结尾的最长且连续递增的子序列长度。则为了计算出最大值,则需要再遍历一遍 `dp` 数组,求出最大值即为最终结果。 From 899c542879e26263a243b33a517eec166d4df61e Mon Sep 17 00:00:00 2001 From: ITCharge Date: 2022年7月29日 17:03:37 +0800 Subject: [PATCH 08/11] =?UTF-8?q?Update=201143.=20=E6=9C=80=E9=95=BF?= =?UTF-8?q?=E5=85=AC=E5=85=B1=E5=AD=90=E5=BA=8F=E5=88=97.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...54345円205円261円345円255円220円345円272円217円345円210円227円.md" | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git "a/Solutions/1143. 346円234円200円351円225円277円345円205円254円345円205円261円345円255円220円345円272円217円345円210円227円.md" "b/Solutions/1143. 346円234円200円351円225円277円345円205円254円345円205円261円345円255円220円345円272円217円345円210円227円.md" index aa76026e..595ec589 100644 --- "a/Solutions/1143. 346円234円200円351円225円277円345円205円254円345円205円261円345円255円220円345円272円217円345円210円227円.md" +++ "b/Solutions/1143. 346円234円200円351円225円277円345円205円254円345円205円261円345円255円220円345円272円217円345円210円227円.md" @@ -28,11 +28,11 @@ ### 思路 1:动态规划 -##### 1. 定义状态 +###### 1. 定义状态 定义状态 `dp[i][j]` 表示为:前 `i` 个字符组成的字符串 `str1` 与前 `j` 个字符组成的字符串 `str2` 的最长公共子序列长度为 `dp[i][j]`。 -##### 2. 状态转移方程 +###### 2. 状态转移方程 双重循环遍历字符串 `text1` 和 `text2`,则状态转移方程为: @@ -41,11 +41,11 @@ - `text1` 前 `i - 1` 个字符组成的字符串 `str1` 与 `text2` 前 `j` 个字符组成的 `str2` 的最长公共子序列长度,即 `dp[i - 1][j]`。 - `text1` 前 `i` 个字符组成的字符串 `str1` 与 `text2` 前 `j - 1` 个字符组成的 str2 的最长公共子序列长度,即 `dp[i][j - 1]`。 -##### 3. 初始化 +###### 3. 初始化 初始状态下,默认前 `i` 个字符组成的字符串 `str1` 与前 `j` 个字符组成的字符串 `str2` 的最长公共子序列长度为 `0`,即 `dp[i][j] = 0`。 -##### 4. 最终结果 +###### 4. 最终结果 根据状态定义,最后输出 `dp[sise1][size2]`(即 `text1` 与 `text2` 的最长公共子序列长度)即可,其中 `size1`、`size2` 分别为 `text1`、`text2` 的字符串长度。 From 2c9860b86fba718ddc3df5f61a5d7100318ced21 Mon Sep 17 00:00:00 2001 From: ITCharge Date: 2022年7月29日 17:03:42 +0800 Subject: [PATCH 09/11] =?UTF-8?q?Create=200576.=20=E5=87=BA=E7=95=8C?= =?UTF-8?q?=E7=9A=84=E8=B7=AF=E5=BE=84=E6=95=B0.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...04350円267円257円345円276円204円346円225円260円.md" | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 "Solutions/0576. 345円207円272円347円225円214円347円232円204円350円267円257円345円276円204円346円225円260円.md" diff --git "a/Solutions/0576. 345円207円272円347円225円214円347円232円204円350円267円257円345円276円204円346円225円260円.md" "b/Solutions/0576. 345円207円272円347円225円214円347円232円204円350円267円257円345円276円204円346円225円260円.md" new file mode 100644 index 00000000..d37b1173 --- /dev/null +++ "b/Solutions/0576. 345円207円272円347円225円214円347円232円204円350円267円257円345円276円204円346円225円260円.md" @@ -0,0 +1,85 @@ +# [0576. 出界的路径数](https://leetcode.cn/problems/out-of-boundary-paths/) + +- 标签:动态规划 +- 难度:中等 + +## 题目大意 + +**描述**:有一个大小为 `m * n` 的网络和一个球。球的起始位置为 `[startRow, startColumn]`。你可以将球移到在四个方向上相邻的单元格内(可以穿过网格边界到达网格之外)。最多可以移动 `maxMove` 次球。 + +现在给定五个整数 `m`、`n`、`maxMove`、`startRow` 以及 `startColumn`。 + +**要求**:找出并返回可以将球移出边界的路径数量。因为答案可能非常大,返回对 10ドル^9 + 7$ 取余后的结果。 + +**说明**: + +- 1ドル \le m, n \le 50$。 +- 0ドル \le maxMove \le 50$。 +- 0ドル \le startRow < m$。 +- 0ドル \le startColumn < n$。 + +**示例**: + +```Python +输入 m = 2, n = 2, maxMove = 2, startRow = 0, startColumn = 0 +输出 6 +``` + +![](https://assets.leetcode.com/uploads/2021/04/28/out_of_boundary_paths_1.png) + +## 解题思路 + +### 思路 1:动态规划 + +我们需要统计从 `[startRow, startColumn]` 位置出发,最多移动 `maxMove` 次能够穿过边界的所有路径数量。则我们可以根据位置和移动步数来划分阶段和定义状态。 + +###### 1. 划分阶段 + +按照位置进行阶段划分。 + +###### 2. 定义状态 + +定义状态 `dp[i][j][k]` 表示为:从位置 `[i, j]` 最多移动 `k` 次最终穿过边界的所有路径数量。 + +###### 3. 状态转移方程 + +因为球可以在上下左右四个方向上进行移动,所以对于位置 `[i, j]`,最多移动 `k` 次最终穿过边界的所有路径数量取决于周围四个方向上最多经过 `k - 1` 次穿过对应位置上的所有路径数量和。 + +即 `dp[i][j][k] = dp[i - 1][j][k - 1] + dp[i + 1][j][k - 1] + dp[i][j - 1][k - 1] + dp[i][j + 1][k - 1]`。 + +###### 4. 初始条件 + +如果位置 `[i, j]` 已经处于边缘,只差一步就穿过边界。则此时位置 `[i, j]` 最多移动 `k` 次最终穿过边界的所有路径数量取决于有相邻多少个方向是边界。也可以通过对上面 `[i - 1, j]`、`[i + 1][j]`、`[i][j - 1]`、`[i, j + 1]` 是否已经穿过边界进行判断(每一个方向穿过一次,就累积一次),来计算路径数目。然后将其作为初始条件。 + +###### 5. 最终结果 + +根据我们之前定义的状态,`dp[i][j][k]` 表示为:从位置 `[i, j]` 最多移动 `k` 次最终穿过边界的所有路径数量。则最终答案为 `dp[startRow][startColumn][maxMove]`。 + +### 思路 1:动态规划代码 + +```Python +class Solution: + def findPaths(self, m: int, n: int, maxMove: int, startRow: int, startColumn: int) -> int: + directions = {(1, 0), (-1, 0), (0, 1), (0, -1)} + mod = 10 ** 9 + 7 + + dp = [[[0 for _ in range(maxMove + 1)] for _ in range(n)] for _ in range(m)] + for i in r + for k in range(1, maxMove + 1): + for i in range(m): + for j in range(n): + for direction in directions: + new_i = i + direction[0] + new_j = j + direction[1] + if 0 <= new_i < m and 0 <= new_j < n: + dp[i][j][k] = (dp[i][j][k] + dp[new_i][new_j][k - 1]) % mod + else: + dp[i][j][k] = (dp[i][j][k] + 1) % mod + + return dp[startRow][startColumn][maxMove] +``` + +### 思路 1:复杂度分析 + +- **时间复杂度**: +- **空间复杂度**: From 69383ab8cfed890179ff8f82b7f1dcb7ffbf4855 Mon Sep 17 00:00:00 2001 From: ITCharge Date: 2022年7月29日 17:12:55 +0800 Subject: [PATCH 10/11] =?UTF-8?q?Update=200576.=20=E5=87=BA=E7=95=8C?= =?UTF-8?q?=E7=9A=84=E8=B7=AF=E5=BE=84=E6=95=B0.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...25214円347円232円204円350円267円257円345円276円204円346円225円260円.md" | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git "a/Solutions/0576. 345円207円272円347円225円214円347円232円204円350円267円257円345円276円204円346円225円260円.md" "b/Solutions/0576. 345円207円272円347円225円214円347円232円204円350円267円257円345円276円204円346円225円260円.md" index d37b1173..a0c61e5b 100644 --- "a/Solutions/0576. 345円207円272円347円225円214円347円232円204円350円267円257円345円276円204円346円225円260円.md" +++ "b/Solutions/0576. 345円207円272円347円225円214円347円232円204円350円267円257円345円276円204円346円225円260円.md" @@ -81,5 +81,5 @@ class Solution: ### 思路 1:复杂度分析 -- **时间复杂度**: -- **空间复杂度**: +- **时间复杂度**:$O(m * n * maxMove)$。三重循环遍历的时间复杂度为 $O(m * n * maxMove)$。 +- **空间复杂度**:$O(m * n * maxMove)$。使用了三维数组保存状态,所以总体空间复杂度为 $O(m * n * maxMove)$。 From c174f88a993db4bf5000372118533f0d0eed38ff Mon Sep 17 00:00:00 2001 From: ITCharge Date: 2022年7月29日 17:41:27 +0800 Subject: [PATCH 11/11] =?UTF-8?q?Update=200091.=20=E8=A7=A3=E7=A0=81?= =?UTF-8?q?=E6=96=B9=E6=B3=95.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...43347円240円201円346円226円271円346円263円225円.md" | 68 ++++++++++++++----- 1 file changed, 51 insertions(+), 17 deletions(-) diff --git "a/Solutions/0091. 350円247円243円347円240円201円346円226円271円346円263円225円.md" "b/Solutions/0091. 350円247円243円347円240円201円346円226円271円346円263円225円.md" index cc33b2c5..71dc4592 100644 --- "a/Solutions/0091. 350円247円243円347円240円201円346円226円271円346円263円225円.md" +++ "b/Solutions/0091. 350円247円243円347円240円201円346円226円271円346円263円225円.md" @@ -5,16 +5,42 @@ ## 题目大意 -给定一个数字字符串 s,按照要求映射为 26 个字母。`1` 映射为 `A`,`2` 映射为 `B`,...,`26` 映射为 `Z`。 +**描述**:给定一个数字字符串 `s`,按照要求映射为 `26` 个字母。`1` 映射为 `A`,`2` 映射为 `B`,...,`26` 映射为 `Z`。 -要求:计算出共有多少种可能的翻译方案。 +**要求**:计算出共有多少种可能的翻译方案。 + +**说明**: + +- 1ドル \le s.length \le 100$。 +- `s` 只包含数字,并且可能包含前导零。 +- 题目数据保证答案肯定是一个 `32` 位的整数。 + +**示例**: + +```Python +输入 s = "226" +输出 3 +解释 它可以解码为 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6) 。 +``` ## 解题思路 -可用动态规划来做。设 dp[i] 表示字符串 s 前 i 个字符 s[0: i] 的翻译方案数。dp[i] 的来源有两种情况: +### 思路 1:动态规划 + +###### 1. 划分阶段 + +按照字符串的结尾位置进行阶段划分。 -1. 对 s[i] 进行翻译。那么只要 s[i] != 0,就可以被翻译为 A~I 的某个字母,此时方案数为 dp[i] = dp[i-1] -2. 对 s[i-1] 和 s[i] 进行翻译,s[i-1] != 0,且 s[i-1] 和 s[i] 组成的整数必须小于等于 26 才能翻译,这样才能翻译为 J~Z 中的某字母,此时方案数为 dp[i] = dp[i-2]。 +###### 2. 定义状态 + +定义状态 `dp[i]` 表示为:字符串 `s` 前 `i` 个字符构成的字符串可能构成的翻译方案数。 + +###### 3. 状态转移方程 + +`dp[i]` 的来源有两种情况: + +1. 使用了一个字符,对 `s[i]` 进行翻译。只要 `s[i] != 0`,就可以被翻译为 `A` ~ `I` 的某个字母,此时方案数为 `dp[i] = dp[i - 1]`。 +2. 使用了两个字符,对 `s[i - 1]` 和 `s[i]` 进行翻译,只有 `s[i - 1] != 0`,且 `s[i - 1]` 和 `s[i]` 组成的整数必须小于等于 `26` 才能翻译,可以翻译为 `J` ~ `Z` 中的某字母,此时方案数为 `dp[i] = dp[i - 2]`。 这两种情况有可能是同时存在的,也有可能都不存在。在进行转移的时候,将符合要求的方案数累加起来即可。 @@ -22,25 +48,33 @@ $dp[i] += \begin{cases} \begin{array} \ dp[i-1] & s[i] \ne 0 \cr dp[i-2] & s[i-1] \ne 0,s[i-1:i] \le 26 \end{array} \end{cases}$ -现在考虑初始边界条件。字符串为空时,只有一个翻译方案,翻译为空字符串,即 dp[0] = 1。 +###### 4. 初始条件 -字符串只有一个字符时,需要考虑该字符是否为 0,不为 0 的话,dp[1] = 1,为 0 的话,dp[0] = 0。 +- 字符串为空时,只有一个翻译方案,翻译为空字符串,即 `dp[0] = 1`。 +- 字符串只有一个字符时,需要考虑该字符是否为 `0`,不为 `0` 的话,`dp[1] = 1`,为 `0` 的话,`dp[0] = 0`。 -字符串长度大于等于 2 时,就需要根据上边的状态转移方程来获取了,最终答案为 dp[n]。 +###### 5. 最终结果 -## 代码 +根据我们之前定义的状态,`dp[i]` 表示为:字符串 `s` 前 `i` 个字符构成的字符串可能构成的翻译方案数。则最终结果为 `dp[size]`,`size` 为字符串长度。 + + +### 思路 1:动态规划代码 ```Python class Solution: def numDecodings(self, s: str) -> int: - n = len(s) - dp = [0 for _ in range(n+1)] + size = len(s) + dp = [0 for _ in range(size + 1)] dp[0] = 1 - for i in range(1, n+1): - if s[i-1] != '0': - dp[i] += dp[i-1] - if i> 1 and s[i-2] != '0' and int(s[i-2:i]) <= 26: - dp[i] += dp[i-2] - return dp[n] + for i in range(1, size + 1): + if s[i - 1] != '0': + dp[i] += dp[i - 1] + if i> 1 and s[i - 2] != '0' and int(s[i - 2: i]) <= 26: + dp[i] += dp[i - 2] + return dp[size] ``` +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n)$。一重循环遍历的时间复杂度是 $O(n)$。 +- **空间复杂度**:$O(n)$。用到了一维数组保存状态,所以总体空间复杂度为 $O(n)$。

AltStyle によって変換されたページ (->オリジナル) /