题目来源:https://leetcode-cn.com/problems/decode-ways/
个人公众号:小猿君的算法笔记
题目描述
一条包含字母 A-Z 的消息通过以下方式进行了编码:
‘A’ -> 1,‘B’ -> 2,…,‘Z’ -> 26
给定一个只包含数字的非空字符串,请计算解码方法的总数。
示例 1:
输入:s = “12”
输出:2
解释:它可以解码为 “AB”(1 2)或者 “L”(12)。
提示:
1 <= s.length <= 100
s 只包含数字,并且可能包含前导零。
思路分析
这道题要求我们对给定的字符串进行解码,并获取解码方式总和。这里进行举例说明解题方式,假设s = “1122”。我们首先取出最后一个2,看有几种情况。很明显,只有一种情况B。
如果我们取后两位22进行解码,共有两种情况,BB或V。
我们继续增加一位变成122,增加的这个1可以单独作为A使用,也可以和其后的2组合,作为L使用。如果单独使用,那么解码数取决于22的解码数,即A BB或A V。如果和后面的2合并作为L使用,那么解码数取决于最后一位2的解码数,即L V。也就是说,122一共有三种解码方式。
再增加一位变为1122,新增的这个1可以单独作为A使用,也可以和第二位的1组合,作为K使用。如果单独使用,那么解码方式取决于122的解码方式,即A ABB或A AV或A LV。如果和后面的1合并作为K使用,那么解码方式取决于22的解码方式,即K BB或K V。因此,1122共有五种解码方式。
通过以上分析,我们可以看出,当前位N的解码方法总数,取决于N+1位长度时的解码方式总数与N+2长度时的解码方式总数的和,即dp[n] = dp[n + 1] + dp[n + 2]。
「约束条件」
如果再新增的一位0时,即01122,事实上对于这串数,我们是无法进行解码的,解码方式为0,即dp[n] = 0。
如果新增一位数使得其与后一位的组合超过了26,那么新增的这一位只能单独使用,即dp[n] = dp[n + 1]。
代码描述
class Solution {
public int numDecodings(String s) {
int len = s.length();
int[] dp = new int[len + 1];
dp[len] = 1; // 最末尾赋值为1,方便处理
if (s.charAt(len - 1) != '0') { // 计算最后一位解码数量
dp[len - 1] = 1;
}
for (int i = len - 2; i >= 0; i--) {
if (s.charAt(i) == '0') {
continue;
}
int sum = (s.charAt(i) - '0') * 10 + s.charAt(i + 1) - '0';
if (sum <= 26) {
dp[i] = dp[i + 1] + dp[i + 2];
} else {
dp[i] = dp[i + 1];
}
}
return dp[0];
}
}