我有一个资源调度问题的Java里的东西需要被测序,但有什么资源可以是彼此相邻的限制。一个很好的比喻是“数字”,其中只有某些数字可能是彼此相邻的字符串。我的解决办法是递归的,以及用于小弦工作正常,但运行时间为O(X ^ N),其中X是可能的数字(基)的数量,并且N是串的长度。它很快变得难以管理。

使用下面的兼容性矩阵,这里是允许字符串的几个例子,点击 的1长度:0,1,2,3,4,点击 的2长度:02,03,14,20,30,41,点击 的3长度:020,030,141,202,203,302,303,414,点击

     0  1  2  3  4
   ---------------------
0|  0  0  1  1  0
1|  0  0  0  0  1
2|  1  0  0  0  0
3|  1  0  0  0  0
4|  0  1  0  0  0

我的用于计数的长度为N的所有字符串溶液与空字符串启动,置换第一个数字,并进行了递归调用对于长度为N-1的所有字符串。递归调用检查添加的最后一位,并尝试所有的排列,可以是旁边的数字。有这样做,我不尝试和置换00,01,04,每次一些优化,例如 - 只有02,03,但表现仍然不佳,因为它从基地5(例子)立足4000 <秤/ p>

这是一个更好的方法来计算其他的排列不是试图枚举所有的人有什么想法?

有帮助吗?

解决方案

如果你只是想一定长度的字符串的数量,你可以只乘兼容性矩阵本身几次,总结它的值。

  

名词 = 串的长度结果    A = 兼容性矩阵结果   可能的串的数目 =的总和 A 名词 -1

一个例子:

n = 1
| 1 0 0 0 0 |
| 0 1 0 0 0 |
| 0 0 1 0 0 |
| 0 0 0 1 0 |
| 0 0 0 0 1 |
sum: 5

n = 3
| 2 0 0 0 0 |
| 0 1 0 0 0 |
| 0 0 1 1 0 |
| 0 0 1 1 0 |
| 0 0 0 0 1 |
sum: 8

n = 8
| 0 0 8 8 0 |
| 0 0 0 0 1 |
| 8 0 0 0 0 |
| 8 0 0 0 0 |
| 0 1 0 0 0 |
sum: 34

在原始矩阵(行 I 的,列Ĵ)可以被看作是与符号开头的字符串的数目的 I 的,并其下一个符号是符号的Ĵ。或者,可以把它看作长度的串的数目的 2 下,其与符号开始的 I 的,并用符号结束Ĵ

矩阵乘法保留这个不变的,所以求幂后, A 名词 -1 将含有与启动符号串的数量的 I 的,具有长度的名词的,并且在符号结束Ĵ

通过平方一个算法的矩阵权力更快的计算幂<:

请参阅维基百科。 / p>

(感谢stefan.ciobaca)

此特定情况减少了下式:

  

可能的串的数目 = ˚F名词的)= 4 +Σ<子> ķ = 1 .. 名词 2 ķ -1 / <子> 2 = ˚F名词的-1)+ 2 名词 -1 / <子> 2

n       f(n)
----    ----
   1       5
   2       6
   3       8
   4      10
   5      14
   6      18
   7      26
   8      34
   9      50
  10      66

其他提示

你只是想知道你可以给定长度的许多字符串与给定矩阵的规则建立?如果是这样,像这样的方法应该工作:

n = 5
maxlen = 100

combine = [
      [0, 0, 1, 1, 0],
      [0, 0, 0, 0, 1],
      [1, 0, 0, 0, 0],
      [1, 0, 0, 0, 0],
      [0, 1, 0, 0, 0]
   ]

# counts of strings starting with 0,1,...,4, initially for strings of length one:
counts = [1, 1, 1, 1, 1]

for size in range(2, maxlen+1):
   # calculate counts for size from count for (size-1)
   newcount = []
   for next in range(n):
      total = 0
      for head in range(n):
         if combine[next][head]:
            # |next| can be before |head|, so add the counts for |head|
            total += counts[head]
      # append, so that newcount[next] == total
      newcount.append(total)
   counts = newcount
   print "length %i: %i items" % (size, sum(counts))

您算法似乎是最佳的。

你如何使用这些排列?你积累他们在一个列表,或将其逐一?由于有大量这样的排列,所以表现不佳可能是由于大的内存使用情况(如果你正在收集所有的人),或者它只是需要这么多时间。你就不能做到百亿循环的琐碎时间。

回复到评价:

如果你只是想算来,那么你可以使用动态编程:

让计数[N] [M]是一个数组,其中计数[1] [j]为这样的排列,其长度为L,其中j结束的数目,

然后计算[1] [I] =计数[1- 1] [I1] +计数[1- 1] [12] + ...,其中I1,I2,...是数字,可以先I(这可以被保存在一个预先计算的阵列)。

计数的每一个细胞都可以通过求和K个(K取决于相容性基质)来填充,因此复杂性是O(KMN),M是置换的长度,而N是数字的总数。

也许我不明白这一点,但不会这个具有列出的表中的每一位拥有有效数字的列表,可以按照它来服务。

然后,你的例程,以产生将采取的累积结果,数字,和当前的数字。是这样的:

// not really Java - and you probably don't want chars, but you'll fix it
void GenerateDigits(char[] result, int currIndex, char currDigit)
{
    if (currIndex == kMaxIndex) {
        NotifyComplete(result);
        return;
    }
    char[] validFollows = GetValidFollows(currDigit); // table lookup
    foreach (char c in validFollows) {
        result[currIndex] = c;
        GenerateDigits(result, currIndex+1, c);
    }
}

在复杂性增加为一个数字,以产生数的函数,但功能取决于总数的有效遵循任何一个数字。如果后面的总数是每个数字相同,比方说,K,则生成所有可能的排列的时间将是O(K ^ n),其中n为位数。对不起,我不能改变数学。以产生在基座10 n个数字的时间是10 ^ N

我不完全相信你问什么,但既然有潜在的N! n个数字组成的字符串的排列,你不会是能够将它们列于n快!我不完全相信你是怎么想的,你得到的O运行时(N ^ 2)。

scroll top