1、解题思路
- 动态规划:定义 dp[i] 为前 i 个数字可以解码的方式数。递推关系:
如果当前数字 s[i] 不是 '0',则可以单独解码,dp[i] += dp[i-1]。如果前两个数字 s[i-1] 和 s[i] 组成的数字在 10 到 26 之间,则可以组合解码,dp[i] += dp[i-2]。初始条件:
dp[0] = 1(空字符串有一种解码方式)。dp[1] = 1(如果第一个字符不是 '0')。
- 边界条件:如果字符串以 '0' 开头,直接返回 0(无法解码)。如果字符串中有 '0' 但前面无法组合(如 '30'),则直接返回 0。
- 空间优化:使用两个变量 prev 和 curr 代替 dp 数组,将空间复杂度降为 O(1)。
2、代码实现
C++
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* 解码
* @param nums string字符串 数字串
* @return int整型
*/
int solve(string nums) {
// write code here
if (nums.empty() || nums[0] == '0') {
return 0;
}
int n = nums.size();
vector<int> dp(n + 1, 0);
dp[0] = 1;
dp[1] = 1;
for (int i = 2; i <= n; ++i) {
if (nums[i - 1] != '0') {
dp[i] += dp[i - 1];
}
int two_digits = stoi(nums.substr(i - 2, 2));
if (two_digits >= 10 && two_digits <= 26) {
dp[i] += dp[i - 2];
}
}
return dp[n];
}
};
Java
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* 解码
* @param nums string字符串 数字串
* @return int整型
*/
public int solve (String nums) {
// write code here
if (nums.isEmpty() || nums.charAt(0) == '0') return 0;
int n = nums.length();
int[] dp = new int[n + 1];
dp[0] = 1;
dp[1] = 1;
for (int i = 2; i <= n; ++i) {
if (nums.charAt(i - 1) != '0') {
dp[i] += dp[i - 1];
}
int two_digits = Integer.parseInt(nums.substring(i - 2, i));
if (two_digits >= 10 && two_digits <= 26) {
dp[i] += dp[i - 2];
}
}
return dp[n];
}
}
Python
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 解码
# @param nums string字符串 数字串
# @return int整型
#
class Solution:
def solve(self , nums: str) -> int:
# write code here
if not nums or nums[0] == '0':
return 0
n = len(nums)
dp = [0] * (n + 1)
dp[0] = 1
dp[1] = 1
for i in range(2, n + 1):
if nums[i-1] != '0':
dp[i] += dp[i-1]
two_digits = int(nums[i-2:i])
if 10 <= two_digits <= 26:
dp[i] += dp[i-2]
return dp[n]
3、复杂度分析
- 时间复杂度:O(n),其中
n
是字符串的长度。 - 空间复杂度:O(n),用于存储
dp
数组。