如何减少以下程序的时间复杂度?

时间:2014-09-10 17:12:02

标签: c rotation

问题:

马克是一名本科生,他对轮换感兴趣。马克希望赢得一个传送带比赛正在进行。在比赛中,有一条传送带,可以表示为1xN块的条带。每个块上都写有一个数字。皮带保持旋转,每次旋转后,每个程序段都会向左移动,第一个程序段将转到最后位置。

传送带附近有一个开关可以阻止皮带。每个参与者都有一次机会阻止腰带,他的PMEAN将被计算出来。

PMEAN使用皮带停止时的顺序计算。具有最高PMEAN的参与者是赢家。可以有多个获胜者。

马克希望成为赢家之一。他应该尝试哪种PMEAN来保证他成为赢家。

PMEAN=∑i=1ni×a[i]

其中a表示传送带停止时的配置。索引从1开始。

输入格式

First line contains N denoting the number of elements on the belt. 

Second line contains N space separated integers.

输出格式

Output the required PMEAN

约束

1 ≤ N ≤ 10^6 
-10^9 ≤ each number ≤ 10^9 

对于任何旋转,PMEAN将始终位于64位有符号整数的范围内。

示例输入

3
20 30 10 

示例输出

140

解释

顶部的数字可以用这些方式书写。

皮带上的初始数字,`

20 30 10 
PMEAN = 1x20 + 2x30 + 3x10 = 110` 

首次轮换后,

30 10 20 
PMEAN = 1x30 + 2x10 + 3x20 = 110 

第二次轮换后,

10 20 30 
PMEAN = 1x10 + 2x20 + 3x30 = 140 

因此最大可能值为140。

代码:

 #include <stdio.h>

int main() {

    int n,i;
    scanf("%d",&n);
    int b[n],a[n],k,ans,temp;
    int *sum = calloc(n,sizeof(int)) ;
    for(i=0;i<n;i++){
        scanf("%d",&a[i]);
    }
    for(k=0;k<n;k++){
    for(i=0;i<n;i++){
        b[i] = a[(i+k)%n];
        sum[k]+= (i+1)*b[i];
    }
        if(ans<sum[k] || k==0){
            ans = sum[k];
        }
    }
    printf("%d",ans);
    return 0;
}

代码很好,但执行时间太长。如何将其复杂度从N ^ 2降低到更低?

1 个答案:

答案 0 :(得分:0)

经过一段时间的思考,我得到了答案:

#include <stdio.h>

int main() {

    int n,i,k;
    scanf("%d",&n);
    long long int a[n],sum[n], ans, s=0,temp;
    sum[0] =0;
    for(i=0;i<n;i++){
        scanf("%lld",&a[i]);
        sum[0]+=(i+1)*a[i];
        s+= a[i];
    }
    ans = sum[0];
    for(k=1;k<n;k++){
        temp = n*a[k-1];
        sum[k]= sum[k-1] - s + temp;
        if(ans<sum[k])
            ans = sum[k];
    }


    printf("%lld",ans);
    return 0;
}