绝对矩阵之和

时间:2015-03-05 08:32:59

标签: java algorithm time-complexity tail-recursion

以下是 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。 在这里,我基本上尝试了两件事来保持代码优化 -

  1. 使用尾递归和
  2. 保持此功能的运行时间&#39; n&#39;
  3. 所以请告诉我,我是否已经正确地完成了这两件事。如果是,我还可以做些什么来优化此代码。谢谢你的帮助。

2 个答案:

答案 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;
}

大O

  

保持此命令'n'

的功能的运行时间

你还没有实现这个目标。很明显,num上有2个嵌套循环,而num正在减少,我认为这使得 O(n log n)