首尾相連數組的最大子數組和
- 描述
- 給定一個由N個整數元素組成的數組arr,數組中有正數也有負數,這個數組不是一般的數組,其首尾是相連的。數組中一個或多個連續元素可以組成一個子數組,其中存在這樣的子數組arr[i],…arr[n-1],arr[0],…,arr[j],現在請你這個ACM_Lover用一個最高效的方法幫忙找出所有連續子數組和的最大值(如果數組中的元素全部爲負數,則最大和爲0,即一個也沒有選)。
- 輸入
- 輸入包含多個測試用例,每個測試用例共有兩行,第一行是一個整數n(1=<n<=100000),表示數組的長度,第二行依次輸入n個整數(整數絕對值不大於1000)。
- 輸出
- 對於每個測試用例,請輸出子數組和的最大值。
- 樣例輸入
-
6 1 -2 3 5 -1 2 5 6 -1 5 4 -7
- 樣例輸出
-
10 14
算法1:
普通的最大子段和,然後依據不同的起點,進行n次最大子段和的計算
時間複雜度過高,無法通過:
優化:
當此次尋找中,如果本組的最大子段和是從ai開始的,那麼下次計算是就從ai開始,而不用從上次的起點相鄰點開始
代碼:
#include <stdio.h>
#include <iostream>
using namespace std;
long long a[100010];
int main()
{
int n;
while(cin>>n)
{
for(int i = 0; i < n; i++)
{
cin>>a[i];
}
long long s1 = a[0],s2 = a[0],v1 = 0,v2 = 0,s = 0;
for(int i = 0; i < n; i++)
{
if(v1 <= 0)
v1 = a[i];
else
v1 += a[i];
s1 = max(s1,v1);
if(v2 <= 0)
v2 += a[i];
else
v2 = a[i];
s2 = min(s2,v2);
s += a[i];
}
//printf("%d %d %d\n",s1,s,s2);
cout<<max(s1,s-s2)<<endl;
}
return 0;
}
算法2:
先查找當前順序的最大子段和a
在查找當前順序的最小子段和b
計算數組綜合su
答案就是max(a,su-b)
代碼:
#include <stdio.h>
#include <iostream>
using namespace std;
long long a[100010];
int main()
{
int n;
while(cin>>n)
{
for(int i = 0; i < n; i++)
{
cin>>a[i];
}
long long s1 = a[0],s2 = a[0],v1 = 0,v2 = 0,s = 0;
for(int i = 0; i < n; i++)
{
if(v1 <= 0)
v1 = a[i];
else
v1 += a[i];
s1 = max(s1,v1);
if(v2 <= 0)
v2 += a[i];
else
v2 = a[i];
s2 = min(s2,v2);
s += a[i];
}
//printf("%d %d %d\n",s1,s,s2);
cout<<max(s1,s-s2)<<endl;
}
return 0;
}