原題鏈結
某大佬:天啊!普及-的題你都要寫部落格,太菜了吧!
主要是這個題教會了我時間複雜度o(n),空間複雜度o(1)的演算法來求最大欄位和。
一起來看一下吧:
我們先設乙個temp來暫時存幾個數的和,maxn是最大欄位和,a是每次讀入的數:
先讀入乙個a,記錄在temp裡,然後for(i=2;i<=n;i++) 讀入剩下的數,如果temp小於0就將temp賦值成0,如果大於0就不用了,然後temp+=a,最後maxn=max(maxn,temp)就好啦!
#include#include解釋一下正確性:using
namespace
std;
intread()
while(ch>='
0'&&ch<='9'
)
return a*x;
}int n,temp=0
,maxn,a;
intmain()
cout
<
return0;
}
對於這個題,temp如果是小於0的話,如果不捨棄的話,再加上乙個正數,肯定會拖累那個正數成為最大值(在成為最大值的道路上誰會甘心讓自己加乙個負數使自己變小呢?)所以我們要在讀入每個數之前判斷temp是不是小於0,若小於0就將它賦值成0(就是相當於捨棄了前幾個數的和);若maxn>temp>0,說明temp有成為最大值的潛力,可能再加上幾個正數就會一舉超過最大值達到人生巔峰,所以當temp大於0時我們就不要捨棄了。下面舉個例子方便理解:
但是有些毒瘤題的資料很大咋辦?---------我們可以用二分!
假設我們要求區間[1,n]的最大欄位和,它們的值分別是a[1],a[2]……,a[n],我們可以將區間[1,n]分成兩個長度相等的小區間[1,n/2]和[n/2+1,n],那麼這個最大子段有三種情況:
1. 最大子段在區間[1,n/2]裡;
2. 最大子段再區間[n/2+1,n]裡;
3. 最大子段的左端點再區間[1,n/2],右端點在[n/2+1,n]裡;
對於第一和第二種情況,我們可以遞迴解決,我們重點看第三種情況:
我們已經知道兩個端點分別在兩個小區間,設這兩個端點為p,q,那麼區間[p,n/2]和區間[n/2+1,q]這一段一定是連續被包含在最大子段裡的,且要是整個子段最大,那麼久盡量讓左子段和右子段最大,所以我們可以從n/2分別往左和往右掃求出最大子段,再加起來就是整個區間的最大子段。
P1115 最大子段和
給出一段序列,選出其中連續且非空的一段使得這段和最大。輸入格式 輸入檔案maxsum1.in的第一行是乙個正整數n,表示了序列的長度。第2行包含n個絕對值不大於10000的整數a i 描述了這段序列。輸出格式 輸入檔案maxsum1.out僅包括1個整數,為最大的子段和是多少。子段的最小長度為1。輸...
P1115 最大子段和
給出一段序列,選出其中連續且非空的一段使得這段和最大。輸入格式 輸入檔案maxsum1.in的第一行是乙個正整數n,表示了序列的長度。第2行包含n個絕對值不大於10000的整數a i 描述了這段序列。輸出格式 輸入檔案maxsum1.out僅包括1個整數,為最大的子段和是多少。子段的最小長度為1。輸...
P1115 最大子段和
給出一段序列,選出其中連續且非空的一段使得這段和最大。輸入格式 輸入檔案maxsum1.in的第一行是乙個正整數n,表示了序列的長度。第2行包含n個絕對值不大於10000的整數a i 描述了這段序列。輸出格式 輸入檔案maxsum1.out僅包括1個整數,為最大的子段和是多少。子段的最小長度為1。輸...