以下是 HackerEarth 挑战的问题 -
Roy有一个大小为NxN的矩阵。行和列的编号从0到N-1。 第i行的第j列包含i和j之间的绝对差。 换句话说,Matrix [i] [j] = abs(i-j)其中0≤i,j <1。 N. 你的任务是找到这个矩阵的总和,即
sum = 0
for i=0 to N-1
for j=0 to N-1
sum += Matrix[i][j]
这是我解决这个问题的方法 -
public static long getSum(int num, long acc) {
if (num == 1)
return acc;
long sum = 0;
for (int i = 0; i < num; i++) {
sum += i;
}
sum = sum * 2;
return getSum(num - 1, acc + sum);
}
但是这个函数失败了,就像说大于4500的大数字一样。我得到Stack Over Flow Error。 在这里,我基本上尝试了两件事来保持代码优化 -
所以请告诉我,我是否已经正确地完成了这两件事。如果是,我还可以做些什么来优化此代码。谢谢你的帮助。
答案 0 :(得分:4)
矩阵结构非常简单(我只画了右上半部分,左下角是相同的,镜像的)
0 1 2 3 4 5 ...
. 0 1 2 3 4 ...
. . 0 1 2 3 ...
. . . 0 1 2 ...
. . . . 0 1 ...
. . . . . 0 ...
很明显,Kth行包含算术级数0..(N - K - 1)
,所以它的总和是
Sk = (N - K - 1) * (N - K) / 2
和总和是(O(N)解)
S = 2 * Sum[k = 0..N-1] (Sk)
此外,虽然每一行的总和是“三角形”和“三角形”。数字,三角数的总和是&#39; Tetrahedral number&#39;,并且有封闭的公式,导致O(1)解决方案
S = 2 * ((N-1)*N*(N+1)/6) = N*(N+1)*(N-1)/3
示例:for N=4 S = 3*4*5/3 = 20
答案 1 :(得分:1)
尾递归并不能保护您免受Java中的堆栈溢出。其他一些语言可以识别tail-calls并在编译期间对它们进行优化,因此它们不会扩展堆栈。
...由于安全模型以及始终需要堆栈跟踪的需要,在JVM中很难进行尾调用优化。
(来自Does the JVM prevent tail call optimizations?)
然而,用循环替换尾递归很容易:
public static long getSum(int num, long acc) {
while (num > 1) {
long sum = 0;
for (int i = 0; i < num; i++) {
sum += i;
}
sum = sum * 2;
//set up values for next loop
num--;
acc += sum;
}
return acc;
}
保持此命令'n'
的功能的运行时间
你还没有实现这个目标。很明显,num
上有2个嵌套循环,而num
正在减少,我认为这使得 O(n log n)