【问题标题】:Why isn't my DP solution to decode numbers and letters working for all test cases?为什么我的解码数字和字母的 DP 解决方案不适用于所有测试用例?
【发布时间】:2019-11-28 19:58:03
【问题描述】:

上下文
这个问题被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 以通过所有测试用例,但输出并不总是等于预期的数字。

【问题讨论】:

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


    【解决方案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。

    代码上的一些cmets

    创建构造函数太过分了,因为您不会在该“类”的实例中维护状态。而是创建一个以函数为成员的对象。

    此外,您不需要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'));

    【讨论】:

    • 进行了更改并且可以正常工作。主要问题是我认为的双重比较
    • 是的。我添加了一些与您的问题无关的其他评论。希望它们有用。
    • 我想我理解这些修订。保留最后两个结果是否普遍适用于所有 DP 问题?
    • 不,当然不是。它是针对问题的。
    猜你喜欢
    • 2017-01-30
    • 2021-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-27
    • 1970-01-01
    • 2019-12-04
    相关资源
    最近更新 更多