代码之家  ›  专栏  ›  技术社区  ›  Dennis Lee

可能的组合和转换为字母表算法-Javascript(Facebook要求)

  •  2
  • Dennis Lee  · 技术社区  · 7 年前

    我正在为下次面试学习算法,我发现了这个问题。

    这是Facebook提出的问题

    这就是问题所在。


    给定映射a=1,b=2。。。z=26,对于编码的消息,计算其解码方式的数量。

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


    我想我可以处理映射和转换为字母部分。但组合对我来说并不容易。

    考虑到我花了几个小时才想出下面的代码。

    function combinations(str) {
    var fn = function(active, rest, a) {
    
        // if nothing, just return
        if (!active && !rest)
            return;
    
    
        // there is nothing left in rest add active to A
        if (rest.length == 0) {
            a.push(active);
        } else {
    
            // append first number of rest to the end of the active item
            // [1] + 1 => 111
            // [1,2] + [3,4] = [1,2,3] + [4]
            if (rest.length > 0){
                fn(active.concat(rest[0]), rest.slice(1), a);
            }else {}
    
    
            // join 
    
            fn((active+rest[0]).split(","), rest.slice(1), a);
        }
        return a;
      }
      return fn([], str, []);
    }
    
    // run it
    combinations(1,2,3);
    

    我只有这个。

    [ [ 1, 2, 3 ],
    [ '1', '23' ],
    [ '12', 3 ],
    [ '123' ],
    [ '1', 2, 3 ],
    [ '1', '23' ],
    [ '12', 3 ],
    [ '123' ] ]
    

    请参见重复项。我想我现在可以除以2得到我想要的答案。但这并不是一个好答案。

    你能把它变成更好的代码吗?

    非常感谢。


    上面的代码几乎就是从这个 link

    3 回复  |  直到 7 年前
        1
  •  4
  •   גלעד ברקן    6 年前

    在这种情况下,我们不需要实际创建组合来计算它们。我们可以使用 dynamic programming .

    允许 f(i) 表示对字符串中的消息进行解码的有效方法数, S ,不超过并包括索引处的字符 i (基于零)。然后:

    f(0)  = 1
    f(i)  =
       if S[i] > 6 or S[i-1] > 2:
         // Nothing changes, we just
         // added a letter
         f(i-1)
    
       else:
         // All the ways to decode
         // up to (i-1) plus all the
         // ways to decode up to (i-2)
         // (let f(-1) equal 1)
         f(i-1) + f(i-2)
    

    例子:

    S = "123"
    
    f(0) = 1
    f(1) = f(0) + f(-1) = 2
    f(2) = f(1) + f(0) = 3
    

    这个过程的复杂性是 O(n) 时间和 O(1) 空间

        2
  •  0
  •   Dennis Lee    7 年前

    我把@×××××××××§§××答案改成了javascript,希望它不会破坏任何东西,我认为它正在工作。

    const Number = 11222;
    let sum = 0;
    
    const AlphabetGen = (i) => {
    
    if(i == 0 ){
        sum =+ 1;
    }else if ((Number[i] > 6) || (Number[i-1] > 3)){
    
        sum =+ AlphabetGen(i-1);
    }else if(i > 0){
        if(i > 1){
            sum =+ AlphabetGen (i-1) + AlphabetGen(i-2);
    
        }else if (i == 1){
            sum =+ AlphabetGen (0) + 1
        }
    
    }
    
    return sum;
    };
    
    console.log(AlphabetGen(4));
    
        3
  •  0
  •   Pavot    5 年前

    我使用JavaScript中的简单interator对此的看法:

    let processString = ( message, possibleWays = 0 ) => {
      if ( message.length ) {
        // First decode using single digit.
        // Shorten string by one and process again.
        possibleWays = processString( message.slice( 1 ,message.length), possibleWays );
    
        // Then check if current digit can be combined
        // with the next digit for cases like '11' for J, '12' for K, etc.
        const numCurr = parseInt( message[0] );
        const numNext = "undefined" === typeof message[1] ? null : parseInt(message[1]);
    
        if ( numCurr && numNext
            && numCurr < 3 // first digit can't be more that 2 as 26 letter max.
            && ( numCurr + numNext ) < 27 // sum of two should be < 26 as 26 letter max.
        ) {
          // Shorten string by two and process again.
          possibleWays = processString( message.slice( 2 ,message.length), possibleWays );
        }
      } else {
        // Reached end of the string: + 1 possible way to decode it.
        possibleWays++;
      }
    
      return possibleWays;
    }
    
    console.log( 'Total number of decoding possbilities: ' + processString('12325') );