典型的輸入能幫助我們測試演算法的邏輯。
在寫具體演算法前列出各種可能輸入,可以幫助明確題目的要求。
最直接的方法:
記 sum[i, …, j] 為 陣列a中第i個元素到第j個元素的和(其中 0≤i
≤j
<
n0\leq i\leq j< n
0≤i≤
j<
n),遍歷所有可能的sum[i, …, j] ,那麼時間複雜度為o(n
3)
o(n^3)
o(n3):
改進的直接法:int
maxsum
(int
* a,
int n)
if(sum>maximum)
maximum=sum;}}
return maximum;
}
注意到 sum[i, …, j]= sum[i, …, j-1]+a[j],則可以將演算法中的最後乙個for迴圈省略,避免重複計算,從而使得演算法得以改進,改進後的演算法複雜度為o(n
2)
o(n^2)
o(n2):
分治演算法:int
maxsum
(int
* a,
int n)
}return maximum;
}
把問題分解為兩個規模減半的子問題,再採用一次遍歷演算法。
總的時間複雜度為t(n
)=o(
n∗lo
g2n)
t(n)=o(n*log_2n)
t(n)=o
(n∗l
og2
n)問題規模減半的相同子問題,可以通過遞迴求得。
跨越中間元素的處理方法:
兩個子陣列分別為 (a[0],…,a[n/2-1]) 和 (a[n/2],…,a[n-1])
跨越中間元素的情況只要找到以a[n/2-1]結尾的最大陣列和s1=
sum(
a[i]
,...
,a[n
/2−1
])(0
≤i
−1
)s_1=sum(a[i],...,a[n/2-1]) (0\leq i < \frac-1)
s1=su
m(a[
i],.
..,a
[n/2
−1])
(0≤i
<2n
−1)
與以 a[n/2] 開始的最大陣列和s2=
sum(
a[n/
2],.
..,a
[j])
(n2≤
j
s_2=sum(a[n/2],...,a[j]) (\frac \leq j < n)
s2=su
m(a[
n/2]
,...
,a[j
])(2
n≤j
。那麼這種情況下的最大值為s1+
s2=a
[i]+
...+
a[n/
2−1]
+a[n
/2]+
...+
a[j]
s_1+s_2=a[i]+...+a[n/2-1]+a[n/2]+...+a[j]
s1+s2
=a[
i]+.
..+a
[n/2
−1]+
a[n/
2]+.
..+a
[j],只需對原陣列進行一次遍歷即可。
動態規劃:
選與不選a[0]
考慮陣列的第乙個元素a[0],以及和最大的一段陣列 (a[i],…,a[j]) 跟 a[0] 之間的關係,有以下幾種情況:
當 0=i=j 時,元素 a[0] 本身構成和最大的一段;
當 0=i當 0
m ax
max\
max
上述方法的時間複雜度已經降到o(nint
max(
int x,
int y)
//返回x,y兩者中較大的值
intmaxsum
(int
* a,
int n)
return all[0]
;//遍歷完陣列,all[0]中存放著結果
}
)了
。o(n)了。
o(n)了。
思考:上述**額外申請了兩個陣列all,start,能否在空間方面節省一些?
進一步改進只需要o(1
)o(1)
o(1)
的空間
int
max(
int x,
int y)
//返回x,y兩者中較大的值
intmaxsum
(int
* a,
int n)
return nall;
求子陣列和的最大值
題目要求 輸入乙個一維整形陣列,陣列裡有正數也有負數。一維陣列首尾相接,像個一條首尾相接帶子一樣。陣列中連續的乙個或多個整數組成乙個子陣列,每個子陣列都有乙個和。求所有子陣列的和的最大值。程式設計思路 1 首先建立乙個一維陣列a,進行資料儲存。2 定義變數,n用於求和,m為和最大值 3 開始for迴...
求子陣列的和的最大值
一 題目 輸入乙個整型陣列,陣列裡有正數也有負數。陣列中乙個或連續的多個整數組成乙個子陣列。求所有子陣列的和的最大值。要求時間複雜度為o n 例子說明 例如輸入的陣列為,和最大的子陣列為 3,10,4,7,2 因此輸出為該子陣列的和18 二 解題思路 舉例分析陣列的規律。我們試著從頭到尾逐個累加示例...
erlang 求子陣列和的最大值
前段時間修改為簡單方法 module son export son 1 son a son a,0,0 son max,sum max son head list max,sum new sum head sum,new max case new sum max of true new sum ma...