题目
一条包含字母 A-Z 的消息通过以下方式进行了编码:
'A' -> 1
'B' -> 2
...
'Z' -> 26
给定一个只包含数字的非空字符串,请计算解码方法的总数。
题目数据保证答案肯定是一个 32 位的整数。
示例 1:
输入:s = "12"
输出:2
解释:它可以解码为 "AB"(1 2)或者 "L"(12)。
示例 2:
输入:s = "226"
输出:3
解释:它可以解码为 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6) 。
动态规划四步走
1. 定义状态
2. 初始状态
3. 状态转移方程
4. 从dp[]中获取结果
具体到题目
定义状态
定义dp 数组,第 i 个元素表示从第一个字符到第i个字符的解码数。
初始状态
若输入不为空,且第一个字符不为0,则dp[i]=1,否则直接返回0
状态转移方程
if s[i] === 0 => s[i-1]是1或者2,则dp[i]=dp[i - 2]
else
if s[i - 1] === '0' => dp[i] = dp[i - 1]
else 判断s[i-1]与s[i]组成的数字是否小于等于26,若是则dp[i] =dp[i - 1]+dp[i - 2],否则dp[i] = dp[i - 1]
完整代码
/**
* @param {string} s
* @return {number}
*/
var numDecodings = function (s) {
// dp[i]表示第i个字符的所有可能
const list = s.split('');
if (list.length === 0 || list[0] === '0') {
return 0;
}
const dp = [];
dp[0] = 1;
for (let i = 1; i < list.length; i++) {
const curChar = list[i];
if (curChar === '0') {
if (['1', '2'].includes(list[i - 1])) {
dp[i] = i >= 2 ? dp[i - 2] : 1;
} else {
return 0;
}
} else {
if (list[i - 1] === '0') {
dp[i] = dp[i - 1];
} else {
const number = Number(list[i - 1]) * 10 + Number(list[i]);
if (number <= 26) {
dp[i] = i >= 2 ? dp[i - 1] + dp[i - 2] : 2;
} else {
dp[i] = dp[i - 1];
}
}
}
}
console.log(dp);
return dp.pop();
总结
第一次思路清晰的做对了动态规划的题目,需要做的是冷静思考,慢慢分析,得到状态转移方程。