思考🤔
这道题其实和经典的跳楼梯问题很像:
跳楼梯,每次跳 1 级或 2 级,问有多少种跳法 →
数字转字符串,每次可以转 1 位或 2 位,求最终转码结果种数
dp数组定义
dp[i]
表示前i位字符串中转码结果数。
转移方程
跳楼梯的转移方程是为dp[i] = dp[i - 1] + dp[i - 2]
【注意:当次转码行为不会增加总数。】
而这道题需要额外注意一点:不是所有时候都能加上dp[i - 1]
或 dp[i - 2]
dp[i] = '0'
,这一位无法转码,此时不能加dp[i - 1]
。只有在dp[i - 1] = '1' or '2'
的时候,dp[i] = dp[i - 2]
dp[i - 1] = '1'
,可以加dp[i - 2]
dp[i - 1] = '2' && 0 <= dp[i] <= 6
,可以加dp[i - 2]
/**
* @param {string} s
* @return {number}
*/
var numDecodings = function(s) {
let dp = [];
dp[-1] = 1; // 填充初始值
dp[-2] = 1;
for(let i = 0; i < s.length; i++){
if(s[i] === '0'){
if(s[i - 1] === '1' || s[i - 1] === '2'){ // 第一种情况
dp[i] = dp[i - 2];
continue;
} else {
return 0;
}
}
if(s[i - 1] === '1'){ // 第二种
dp[i] = dp[i - 1] + dp[i - 2];
continue;
}
if(s[i - 1] === '2' && s[i] <= 6 && s[i] >= 0){ // 第三种
dp[i] = dp[i - 1] + dp[i - 2];
continue;
}
dp[i] = dp[i - 1]; // 一般情况
}
return dp[s.length - 1];
}
附:利用滑动数组优化
a代表dp[i-1]
,b代表dp[i-2]
,temp代表dp[i]
/**
* @param {string} s
* @return {number}
*/
var numDecodings = function(s) {
let a = 1;
let b = 1;
for(let i = 0; i < s.length; i++){
if(s[i] === '0'){
if(s[i - 1] === '1' || s[i - 1] === '2'){
temp = b;
b = a;
a = temp;
continue;
} else {
return 0;
}
}
if(s[i - 1] === '1'){
temp = a + b;
b = a;
a = temp;
continue;
}
if(s[i - 1] === '2' && s[i] <= 6 && s[i] >= 0){
temp = a + b;
b = a;
a = temp;
continue;
}
temp = a;
b = a;
a = temp;
}
return temp;
}
菜鸡狂喜