如何找到所有加起来一定长度的单词组合?

时间:2015-06-27 21:44:51

标签: arrays algorithm math

我需要一些帮助来提出一种算法来遍历排序的单词数组并找到所有可能的组合,这些组合加起来一定长度。任何帮助是极大的赞赏!谢谢:))

3 个答案:

答案 0 :(得分:1)

如果数组按长度排序,则可以保留两对索引,一个从低端遍历(最短的单词),另一个从高端遍历。

查找相同长度的单词范围。

在高端找到一系列具有相同长度的单词,并且当与低范围单词长度相加时,其长度为您提供所需的长度。

然后将第一个范围中的每个单词与第二个范围中的每个单词组合在一起。

答案 1 :(得分:0)

0)将长度放入一个单独的数组中。

1)对该数组进行排序。

2)使用算法“两和”问题来查找长度。

两个求和算法的工作原理如何:

假设您要查找一对加起来一定长度的单词。

你需要2个循环。

假设长度为x。

0)外环线性地遍历整个数组。

1)内循环二进制搜索x - a [i] .length,其中x是2个字符串的长度。

要仅获取不同的对,请将找到的对存储在哈希集中。

修改 因为您之后将问题更改为“任意数量的单词”。然后您可以使用以下算法。我不确定你使用的语言。但通常,要从集合中获取所有子集:

for(int i = 0; i < 1 << n; ++i)
{
  for(int j = 0; j < n; ++j)
  {
     if(i >> j & 1)
     {
         // concatenate strings here
         // add them to a list
     }
  }
  if(concatenatedStr.length == k)
  {
      // store those strings in a hash set
  }
}

由于int是任意数量元素的32位数,因此您可以使用BigInteger之类的东西。但是,老实说,我不认为你想要为超过32个元素的任何东西做这个,因为算法本身就是O(2 ^ n +我们在这些循环中所做的其他事情)。

这是如何运作的?

嗯,在一组n个元素中有2 ^ n个子集,当你做1&lt;&lt; n,它向左移动1 n个位置,使其位于第(n + 1)个位置,然后是全零。

1&lt;&lt; n - 1给你n 1。如果你做i = 0; i&lt; = 1&lt;&lt; n - 1(或i = 0; i&lt; 1&lt;&lt; n)你基本上生成所有子集,因为二进制数增加如下:

0

1

10

11

100

101

110

等...

所以你基本上生成所有子集...当你生成它们时,你可以用它们做任何你想做的事情,包括找到长度总和等于k的子集,就像我在那个算法中所展示的那样。

答案 2 :(得分:0)

您可以使用动态编程执行此操作。设a [i,j]是将前i个单词与总长度j组合的方式的列表。设L是i +第1个字的长度。然后a [i + 1,j] = a [i,j] + [i,j-L]中的所有内容,其中附加了单词i + 1。 (如果你只需要计数,你可以计算为b [i + 1,j] = b [i,j] + b [i,jL]。只计算计数需要O(| dictionary | * target length)以这种方式步骤。)

这样做的一个问题是,您可能会计算许多无法为最终列表做出贡献的大型列表。例如,假设有一些长度为5的单词,以及大量长度为6的单词,并且您的总长度为25.这些只会来自长度为5的单词组合。创建长度为18的组合的努力浪费了24。为了避免计算对最终答案没有贡献的长列表,首先计算一个布尔值c [i,j],表示如果在使用了前面的一些单词之后是否可以到达目标,则组合的长度为j 。您可以再次使用动态编程,从i = target开始并向下工作到i = 0。计算数组c [i,j]后,仅当c [i,j]为真时才计算列表a [i,j]的数组,如果c [i,j]为,则忽略a [i,j]假。