优化此代码以检查总和

时间:2013-12-26 04:40:21

标签: c algorithm

这是问题所在,我试图在SPOJ中解决。我的时间限制超出了问题。我无法找到优化算法的方法。你能给我一些提示吗?

问题在于:

  

伦纳德必须找到连续数字序列的数量   他们的总和是零。

     

例如,如果序列是-5,2,-2,5,-5,9

     

有3个这样的序列

     

2,-2

     

5,-5

     

2,-2,5,-5

     

因为这是伦纳德重写室友的绝佳机会   协议和摆脱谢尔顿的荒谬条款,他无法承受   失去。所以他转向你寻求帮助。别让他失望。

     

输入

     

第一行包含T个测试用例数

     

第二行包含n - 特定测试中的元素数   情况下。

     

下一行包含n个元素,ai(1< = i< = n)用空格分隔。

     

输出

     

此类序列的数量,其总和为零。

     

约束

     

1·; = T< = 5

     

1·; = N&LT = 10 ^ 6

     

-10< = ai< = 10

以下是我的代码:

#include<stdio.h>


main()
{
 int t, j, k, l, sum;
 long long int num, out = 0;
 long long int ai[1000001];
 scanf("%d",&t);

 while(t--)
 {
    for(j=0;j<=num;j++)
    {   
    scanf("%lld",&ai[j]);
    }
    for(l=0;l<=num;l++)
    {

        for(k=l; k<=num; k++)
        {
          if(sum == 0)
          {
            num++;
          }
          else
          {
            sum = sum + ai[k];
          }

        }
        printf("%d", &num);
    }

 }
 return 0;
}

2 个答案:

答案 0 :(得分:0)

设S [i]是从索引0到索引i(前缀和)的元素之和。设置S [-1] = 0。

你可以观察到,如果从索引i到索引j(j> i)的序列总和为0,则S [j] - S [i-1] = 0,或者S [j] = S [i- 1]。

为了解决这个问题,只需将S [i](i = -1 .. n-1)的值映射到总和的频率。如果特定和总和重复k次,则可以选择2种方法来配对索引以创建不同的序列。您可以通过总结所有方法来获得序列总数,方法是通过所有键并检查最后的频率。

对于插入和更新操作,映射的实现最多应为 O(log n)。这将允许您解决 O(n log n)的总体复杂性问题:前缀sum O(n),插入/更新地图 O (n log n),浏览整个地图以总结结果 O(n)

伪代码:

a[n] // Array of elements

m = new Map[Int->Int] // Frequency mapping

s = 0 // Prefix sum

m[s] += 1

for (i = 0; i < n; i++) {
  s += a[i] // Prefix sum of array of elements a
  m[s] += 1 // Increment frequency of the prefix sum by 1
}

out = 0

// Go through all key values in the map
m.traverse(function (key, value) {
    // Add the number of pairs of indices that has the same prefix sum
    out += value * (value - 1) / 2
})

return out

答案 1 :(得分:0)

这是我的解决方案,它类似于nhahtdh,但时间复杂度为O(n)
伪代码:

        int pos[10000001];
        int neg[10000001];
        int sum = 0;
        int result = 0;
        for(int i = 0; i < arr.length; i++){
            sum += arr[i];
            if(sum > 0){
                result += pos[sum];
                pos[sum]++;

            }else{
                result += neg[-sum];
                neg[-sum]++;
            }


        }
        return result;