.net 给定一个数字,给出所有可能的匹配字母组合

uemypmqf  于 2022-12-20  发布在  .NET
关注(0)|答案(1)|浏览(89)

给定字母到数字的转换,其中a为1,b为2,依此类推...
一个单词可以转换成数字,这些数字可以连接起来形成一个数字:

dog   → 4|15|7  → 4157

我想做相反的操作,为一个数字创建一个可能的前象 * 单词 * 列表:

512   → 5|1|2   → eab
        5|12    → el

4157  → 4|1|5|7 → daeg
      → 4|15|7  → dog

我目前的尝试:
一个二个一个一个

rjee0c15

rjee0c151#

获得所有可能组合的一种方法是在递归算法中使用两个堆栈inStackoutStack,其中验证单个或成对的数字。
第一个inStack由输入的数字位数填充,而outStack为空。
然后调用这个递归算法:

  • 如果inStack为空,则返回outStack的内容。
  • 如果inStack的第一个元素有效(非0)
  • 将其从inStack中删除并放入outStack
  • 调用递归
  • 恢复堆栈
  • 如果inStack的前两个元素组合为有效值
  • 将它们从inStack中移除,并将它们合并到outStack
  • 调用递归
  • 恢复堆栈

512的调用日志如下所示(栈头位于右侧):

// Initial call
GetCombinations(inStack: '5 1 2', outStack: '')
│
│   // Pass '2' form inStack to outStack and call recursion
├─► GetCombinations(inStack: '5 1', outStack: '2')
│   │
│   │   // Pass '1' form inStack to outStack and call recursion
│   ├─► GetCombinations(inStack: '5', outStack: '2 1')
│   │   │
│   │   │   // Pass '5' form inStack to outStack and call recursion
│   │   ├─► GetCombinations(inStack: '', outStack: '2 1 5')
│   │   │   │
│   │   │   │   // inStack is empty. stop the recursion.
│   │   │   └─► returns 5 1 2
│   │   │
│   │   │   // Not enough digits to combine
│   │   └─► Skip
│   │
│   │   // First two digits combine to 51, which is invalid.
│   └─► Skip
│
│   // Pass '1' and '2' combined as '12'
└─► GetCombinations(inStack: '5', outStack: '12')
    │
    │   // Pass '5' form inStack to outStack and call recursion
    ├─► GetCombinations(inStack: '', outStack: '12 5')
    │   │
    │   │   // inStack is empty. stop the recursion.
    │   └─► returns 5 12
    │
    │   // Not enough digits to combine
    └─► Skip

请注意,inStackoutStack的内容是相反的,必须在某个点执行Reverse调用。
实现将如下所示:

static IEnumerable<IReadOnlyList<int>> GetCombinationsImplem(Stack<int> inStack, Stack<int> outStack)
{
    // recursion end point
    if (inStack.Count is 0)
    {
        yield return outStack.ToArray();
        yield break;
    }

    var digit1 = inStack.Pop();

    // Try put one digit from in to out
    if (digit1 is >= 1 and <= 26)
    {
        outStack.Push(digit1);
        foreach (var combinaison in GetCombinationsImplem(inStack, outStack))
        {
            yield return combinaison;
        }

        outStack.Pop();
    }

    // Try put two combined digit (ex: 1,2 => 12) from in to out
    // First, test for the presence of a digit
    if (inStack.TryPop(out var digit2))
    {
        var v = digit1 + 10 * digit2;

        // Continue only if the value is acceptable
        if (v is >= 1 and <= 26)
        {
            outStack.Push(v);
            foreach (var combinaison in GetCombinationsImplem(inStack, outStack))
            {
                yield return combinaison;
            }

            // restore outStack
            outStack.Pop();
        }

        // restore inStack
        inStack.Push(digit2);
    }

    // restore inStack
    inStack.Push(digit1);
}

从这个到字母的转换是一个琐事(char)('a' + digit - 1)将1转换为a,2转换为b,等等...不需要字典。
工作代码可用here
在线演示可用here

相关问题