查找由数字拼出的单词的算法

时间:2009-10-27 00:34:49

标签: algorithm tree

考虑到字母到值的映射,我正试图找到一种方法来确定可以由给定数字拼出的所有可能的单词。

我最终希望找到适用于字母的任何1位或2位数值映射的解决方案,但为了说明,假设A = 1,B = 2,... Z = 26。

示例:12322可以等于abcbb (1,2,3,2,2)lcbb (12,3,2,2)awbb (1,23,2,2)abcv (1,2,3,22)awv (1,23,22)lcv (12,3,22)


这是我到目前为止所想到的:

我将使用数字构建一个包含所有可能单词的树。

为此,我将从一棵树开始,其中一个根节点带有虚拟数据。

我将从最低有效数字开始逐位解析数字。

在每一步,我将取数字剩余部分的最后一位数字并将其插入当前节点的左子树,并从该节点的左子树的数字中删除该数字。对于同一节点,我将检查先前的两个数字是否一起形成一个有效的字母表,如果是,我将把它们放入正确的子树(并从该节点的右子树的数字中删除2位数)。

然后,我将使用剩下的数字部分递归地为每个节点重复上述步骤,直到没有剩余数字为止。

为了说明,对于12322,我的树将看起来像这样:

                *
             /     \
            /       \
           2         22
         /         /   \
        2         3     23
      /   \      / \    /
    3      23   2   12 1
   / \    /    /
  2   12 1    1
 /
1 

为了获得单词,我将遍历从叶子到节点的所有可能路径。


对于我认为是一个相当简单的问题,这似乎是一个过于复杂的解决方案,我试图找出是否有一种更简单的方法来解决这个问题。

4 个答案:

答案 0 :(得分:5)

您无需实际构建树 - 只需递归:

  1. 取一个数字。看看我们是否可以形成一个单词,将其视为一个字母本身,然后递归。
  2. 当我们从递归返回时,尝试添加另一个数字(如果我们之前是1或2),并重新递归。

答案 1 :(得分:2)

假设您已经拥有[2, 3, 2, 2]的所有可能组合,那么[1, 2, 3, 2, 2](将[1]添加到头部)的组合是什么?推断它应该是不难的:

  A1: put [1] to the head of all_the_combinations_of[1,2,3,2,2] and 
  A2: put [1*10 + 2] to the head of all_the_combinations_of[2,3,2,2] if [1*10 + 2 <=26]

一旦我们得到了这个,以下应该很容易。我实现了一个带有recusion trace的Ruby版本供你参考。

def comb a
    c = []
    puts a.inspect
    return [a] if a.length <= 1

    c =  comb(a[1..-1]).map {|e| [a[0]] + e}
    if a[0] * 10 + a[1] <= 26
            c += comb(a[2..-1]).map { |f| [a[0] * 10 + a[1]] + f }
    end
    c
end

h = Hash[*(1..26).to_a.zip(('A'..'Z').to_a).flatten]
#h.keys.sort.each {|k| puts "#{k}=>#{h[k]}"}

comb([1,2,3,2,2]).each do |comb|
    puts comb.map {|k| h[k]}.join
end

[1, 2, 3, 2, 2]
  A1 [2, 3, 2, 2]
      [3, 2, 2]
         [2, 2]
            [2]
             []
      [2, 2]
         [2]
          []
  A2 [3, 2, 2]
      [2, 2]
         [2]
          []
ABCBB
ABCV
AWBB
AWV
LCBB
LCV

答案 2 :(得分:1)

蛮力解决方案是将数组从1动态填充到N,其中a[i]元素包含一组在扩展后形成a[1]a[2]a[3]...a[i]的字符串。您可以从stratch填充[1],然后根据a[2] set和字符串中的第二个字符填充a[1]。然后你填写[3]等等。在每个场景中,你只需要回顾a[i-1]a[i-2](以及s[i-1]s[i],其中{{1}是你的数字序列。)

最后,填写s后,它将包含答案。

对于示例'12322',序列变为:

a[n]

这实际上是上面递归解决方案的动态编程版本。

答案 3 :(得分:0)

另一种方法是扭转问题:

  • 给定单词字典,计算将生成的数字字符串,并将此数据存储到地图/字典结构中,即表['85'] ='hi'
  • 对于您正在查找的数字的前x位数,请查看它是否在表格中,即table.ContainsKey('1'),table.ContainsKey('12'),...
  • 如果您正在尝试查找单词序列,请生成从数字字符串中的每个位置开始的单词,然后执行递归查找以查找其中的所有短语。