问题是从字母表中可以制作多少长度为N的字符串。
条件是:
我有N的答案:
当N = 50时,我需要找到答案。我已经做出的算法正确地获取答案,直到30秒为止。然而,30后,我认为由于我的算法的递归性质,它继续运行,我没有得到答案。
这是我的java代码:
class Alphabet {
public int n;
public long counter = 0;
public static void main(String[] args) {
Alphabet a = new Alphabet(15);
a.run();
}
public Alphabet(int n) {
this.n = n;
}
public void run() {
for (int i = 0; i < 13; i++) {
this.attach(i, 1);
}
System.out.println(this.counter * 2);
}
public boolean attach(int letter, int length) {
if (length == this.n) {
this.counter++;
return true;
}
if (letter == 0) {
this.attach(1, length + 1);
return true;
}
if (letter == 25) {
this.attach(24, length + 1);
return true;
}
this.attach(letter - 1, length + 1);
this.attach(letter + 1, length + 1);
return true;
}
}
是否有更有效的方法来获得答案?
答案 0 :(得分:4)
对于每个字母,计算以该字母结尾的长度为1的字符串数。对于所有字母,这是1。
如果您知道每个字母中以n字母字符串结尾的数字,那么很容易计算每个字母结尾的n + 1个字母字符串的数量。根据您的规则,这需要O(alphabet_size)时间。反复这样做,直到你达到n = N.然后只需将所有字母的计数加起来即可。
答案 1 :(得分:2)
如果x[i][j]
是以字母j
开头的i
个字母的字符串数(从0开始编号),那么x[i][j]
就会满足这些递归关系:
x[i][1] = 1
x[0][j] = x[1][j-1]
x[25][j] = x[24][j-1]
x[i][j] = x[i-1][j-1] + x[i+1][j-1]
这为您提供了一种解决问题的动态编程风格方法。 (这里是Python,因为它使算法更清晰,但是将它转换为Java没有根本的困难):
def strings(n):
x = [1] * 26
for _ in xrange(n-1):
x = [x[1]] + [x[i-1] + x[i+1] for i in xrange(1, 25)] + [x[24]]
return sum(x)
print strings(40)
这是一个O(n)(算术运算)解决方案。通过计算26x26矩阵的n次幂,可以在O(log n)算术运算中解决它。
让A
成为a[i][j]
的矩阵i
,j
= 0..25其中a[i][j] = 1
如果|i-j]=1
则为0。 / p>
然后:
x[][j] = A * (x[][j-1])
(这只是以矩阵形式写的递归关系)。
然后:
x[][n] = A^(n-1) (x[][1])
由于矩阵功率可以在O(log n)算术运算中计算(通过平方乘幂),因此可以在O(log n)时间内计算最终的x[][n]
向量。这在实践中并没有多大帮助,因为数字变大了,但是如果你需要为某些K计算结果mod K,那么这是一个很好的方法。