#每日n题# 91. 解码方法

58 阅读1分钟

思考🤔

这道题其实和经典的跳楼梯问题很像:
跳楼梯,每次跳 1 级或 2 级,问有多少种跳法 →
数字转字符串,每次可以转 1 位或 2 位,求最终转码结果种数

dp数组定义

dp[i]表示前i位字符串中转码结果数。

转移方程

跳楼梯的转移方程是为dp[i] = dp[i - 1] + dp[i - 2]
【注意:当次转码行为不会增加总数。】
而这道题需要额外注意一点:不是所有时候都能加上dp[i - 1]dp[i - 2]

  1. dp[i] = '0',这一位无法转码,此时不能加dp[i - 1]。只有在dp[i - 1] = '1' or '2'的时候,dp[i] = dp[i - 2]
  2. dp[i - 1] = '1',可以dp[i - 2]
  3. 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;
}

菜鸡狂喜 image.png