计算字符串的排列

时间:2011-06-12 10:35:24

标签: algorithm

我需要帮助解决问题。给定一个重复的输入字符串,说“aab”,如何 计算该字符串的不同排列数。 可以使用的一个公式是n!/ n1!n2!..... nr!。

然而,如果我们这样计算这些ni需要时间O(rn)和O(n) 使用查找表。

但是我需要一个不使用这些表的解决方案。任何递归或 动态编程解决方案可能解决这个问题。

提前致谢。

5 个答案:

答案 0 :(得分:2)

没有。不同的排列将是n!/(c1!*c2*..*cn!) 这里n是字符串的长度

ck表示否。每个不同角色的出现。

  

例如:string:aabb n = 4 ca = 2,cb = 2
  溶液= 4!/(2!×2!)= 6

答案 1 :(得分:0)

如果你想对非常大的字符串进行此操作,请考虑使用gamma函数(使用gamma(n + 1)= n!),这对于大n更快,并且即使在以下情况下仍然可以提供浮点精度你会得到一个int溢出。

如果你有任意精度算术,你可以通过利用你可以做到的事实,例如将努力降低到O(r + n)。写1 * 2 * 3 * 1 * 2 * 3 * 4 * 1 * 2 * 3 * 4 * 5 * 6 * 7为(1 * 2 * 3)^ 3 * 4 ^ 2 * 6 * 7。最终结果仍然是O(rn)数字,你仍然会有O(rn)时间消耗,因为乘法成本会随着数字的大小而增加。

我没有看到查找表和动态编程之间的区别 - 基本上,动态编程使用您即时构建的查找表。 (即使用查找表,但只按需填充它。)

答案 2 :(得分:0)

您需要大概的答案,还是确切的答案?您认为这个计算的哪一部分很慢?

如果您需要大致的答案,请使用@Yannick Versley建议的伽玛函数。

如果你需要确切的答案,我就是这样做的。我首先要弄清楚答案的主要因子分解,然后将这些因素相乘。这避免了分裂。弄清楚素数分解的困难部分是找出n!的素数因子分解。为此,你可以使用一个技巧。假设p是素数,kn/p'. Then the number of times that p divides n!is k plus the number of times that p {{1}的整数部分} {k} divides 3 . Proceed recursively and it is quick to see that, for instance, the number of times that 80!is a factor of 26 + 8 + 2 = 36`。所以在你发现素数达到'n'之后,找到'n!'的素数因子化并不难。

一旦你知道了素数分解,就可以将它乘以。你期望处理大数,所以尽量安排做很多小的乘法,只有几个大的。这是一种简单的方法。

制作一系列主要因素。争抢它(混淆大小因素)。然后只要你的数组中至少有2个因子抓住前两个,将它们相乘,将它们推到最后。如果剩下一个号码,那就是你的答案。

对于大字符串而言,这应该比使用一次一个数字的天真方法快得多。但是最后你会得到非常大的数字,没有什么可以使这些数字快速增加。

答案 3 :(得分:0)

您可以为每个角色保留一个运行计数,并在进行时构建结果。不可能比O(n)做得更好,因为如果不查看字符串中的每个字符,就无法知道每个字符有多少。

我在Python中编写了一些代码,并进行了一些简单的单元测试。当结果变小时,代码会小心地避免使用大的中间值(实际上,变量result永远不会大于len(s)乘以最终结果)。如果您打算用另一种语言编写代码,比如C,那么您可以使用大小为256而不是defaultdict的数组。

如果你想要一个确切的结果,那么我认为你不能比这更好。

from collections import defaultdict

def permutations(s):
    seen = defaultdict(int)
    for c in s:
        seen[c] +=  1
    result = 1
    n = 0
    for k, count in seen.iteritems():
        for j in xrange(count):
            n += 1
            result *= n
            result //= j + 1
    return result

test_cases = [
    ('abc', 6),
    ('aab', 3),
    ('abcd', 24),
    ('aabb', 6),
    ('aaaaa', 1),
    ('a', 1)]
for s, want in test_cases:
    got = permutations(s)
    if got != want:
        print 'permutations(%s) = %s want %s' % (s, got, want)

答案 4 :(得分:-1)

正如@MRalwasser所说,排列的数量应该是 n !。您可以相当简单地generate those排列,但运行时间将是指数级的,因为您必须按指数多次输出字符串。 (快速显示O( n !)= O(2 n )是使用Stirling's Formula。)