javascript - 为什么我的 DP 解码数字和字母解决方案不能适用于所有测试用例?

标签 javascript algorithm dynamic-programming decode off-by-one

上下文
这个问题是dailycodingproblem和leetcode问的

/* 给定映射 a = 1、b = 2、... z = 26 和编码消息,计算可以解码的方式数量。

例如,消息“111”将给出 3,因为它可以被解码为“aaa”、“ka”和“ak”。

您可以假设消息是可解码的。例如,不允许使用“001”。 */

var AlphabetCode = function(){};
AlphabetCode.prototype.decode = function(message) {
    //dp is optimal substructure, account for zero length string such as dp[0]
    let dp = Array(1+message.length).fill(0);
    //string is of length zero
    dp[0] = 0; // no ways to decode empty (tried toggling between 0 and 1)  
    //string is of length one
    dp[1] = parseInt(message[0]) == 0 ? 0 : 1; // there is no alphabet code for 0, 'a' starts at 1 

    //string is of length two or greater
    // go up to string length inclusive because index 0 is reserved for zero string
    for (let i = 2; i <= message.length; i++){
        let singleDigit = message.substring(i-1, i);
        let doubleDigit = message.substring(i-2, i);
        //console.log(singleDigit + ' ' + doubleDigit);
        //console.log(singleDigit[0]);
        if (1 <= parseInt(singleDigit) <= 9){
            dp[i] += dp[i-1];
            //console.log(dp[i]);
        }
        //console.log(doubleDigit[0]);
        if (doubleDigit[0] !='0' && 10 <= parseInt(doubleDigit) <= 26){
            //console.log('double valid');
            dp[i] += dp[i-2];
        }
    }
    // filled out the dp array and returning the accumulation of all subproblems
    return dp[message.length];
};
combinations = new AlphabetCode();
console.log('Number of ways to decode 10 are: (expect 1) ' + combinations.decode('10'));
console.log('Number of ways to decode 12 are: (expect 2) ' + combinations.decode('12'));
console.log('Number of ways to decode 226 are: (expect 3) ' + combinations.decode('226'));
console.log('Number of ways to decode 27 are: (expect 1) ' + combinations.decode('27'));

输出

Number of ways to decode 10 are: (expect 1) 1 
Number of ways to decode 12 are: (expect 2) 1
Number of ways to decode 226 are: (expect 3) 2
Number of ways to decode 27 are: (expect 1) 1

dp 是最优子结构。尝试将 dp[0] 更改为 0 或 1 以通过所有测试用例,但输出并不总是等于预期数字。

最佳答案

两个问题:

  • 正如您已经尝试过的那样,但 dp[0] 应该为 1,因为实际上空字符串是空消息的有效编码。所以它很重要。

  • 您无法在 JavaScript 中进行 Python 风格的双重比较,因此这两个条件均无效:

    if (1 <= parseInt(singleDigit) <= 9)
    if (doubleDigit[0] !='0' && 10 <= parseInt(doubleDigit) <= 26)
    

    将它们更改为;

    if (1 <= parseInt(singleDigit))
    if (doubleDigit[0] !='0' && parseInt(doubleDigit) <= 26)
    

    删除的“条件”已经保证为真:当您已经验证第一位数字不是零时,单个数字不能大于 9,并且双位数至少为 10。

代码的一些注释

创建构造函数是多余的,因为您不维护该“类”的实例中的状态。相反,创建一个以函数作为成员的对象。

此外,您不需要 dp 为每个可能的字符串长度都有一个条目,因为您只需要“最后”两个结果来计算下一个结果,因此您只需两个结果即可值。

最后,使用三元运算符和一元加号(用于转换为数字),您可以非常简洁地计算下一个计数:

const combinations = {
    decode(message) {
        // Only need memory of past two results (for string length - 1, and - 2)
        let dp = [1, 1];
        // No need to reject a starting zero, as the challenge says only valid input is given.
        for (let i = 2; i <= message.length; i++){
            let singleDigit = +message[i-1];
            let doubleDigit = +message.substring(i-2, i);
            dp = [
                dp[1], 
                (1 <= singleDigit) * dp[1]
                    + (10 <= doubleDigit && doubleDigit <= 26) * dp[0]
            ];
        }
        return dp[1];
    }
};

console.log('Number of ways to decode 10 are: (expect 1) ' + combinations.decode('10'));
console.log('Number of ways to decode 12 are: (expect 2) ' + combinations.decode('12'));
console.log('Number of ways to decode 226 are: (expect 3) ' + combinations.decode('226'));
console.log('Number of ways to decode 27 are: (expect 1) ' + combinations.decode('27'));

关于javascript - 为什么我的 DP 解码数字和字母解决方案不能适用于所有测试用例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57118956/

相关文章:

javascript - 在 DHTML 中用 ActionScript 替换 JavaScript

javascript - Twitter Bootstrap Accordion 功能

java - 搜索算法(已经实现了排序算法)

algorithm - 计算两个列表之间的相似度

c# - 在类中展平数组的动态方法?

javascript - JS/HTML 当表单不完整时,我的表单提交按钮不会显示错误消息

javascript - jQueryUI 多个可放置元素

android - 在android中找到最短路径/距离的任何算法?

c++ - 迭代地编写递归代码

algorithm - 组成字符串的最小路径