首先,題目概述:
這裡的問題針對的是整形陣列,即像a[10]=這樣的陣列。
因此,可以知道陣列的數可以分為三種型別:
1.正數
2.零3.負數
除此之外,還有乘法的特性:正正得正,正負得負,負負得正,以及乘零等於零。
明白了上述基本數學內容後,現在給出兩種分析思路,都可以o(n)的時間解決問題
方法1:
求取包含a[i-1]連續往左的最大和最小乘積,並與a[i]相乘,得到的結果和a[i]共同比較,從前面得到的三個數里再次挑選最大和最小值作為包含a[i]連續往左的最大和最小乘積。依次迴圈,同時每次迴圈都要比較包含a[i]連續往左的最大乘積和整個過程中的最大乘積,記錄下來,最後返回。**如下:
//以下**是本人所寫
//從左往右遍歷整個陣列,記錄乘以a[i]後的最大imax和最小imin乘積
//imax和imin都是包含a[i]及向左連續的子序乘積
//之所記錄最大和最小,是因為乘法的特性——負負得正
//a[i]之前的最小乘積可能因為a[i]>0,而使得最大乘積翻倍
//因此需要記錄下最大和最小的乘積方便求取最大的乘積
int maxproduct(int a, int n)
return resmax;
}
方法2:
注意兩點:1.遇到零則重新計算;2.不包含零的情況下,連續最大乘積必然從最左或者最右端開始,即不可能存在於中間。
現在對第二點給出證明如下:
假設非零陣列中存在處於中間的最大子序乘積a2,那麼位於a2左邊的乘積記錄為a1,位於a2右邊的乘積記錄為a3。且a2最大不僅說明a1和a3都比a2小,即a2>a1,a2>a3,而且說明a2*a1
當a2>0時,a1<1和a3<1,即a1和a3都是負數,那麼顯然a1*a2*a3比a2,與假設相反
當a2<0時,a1>1和a3>1,即a1和a3都是正數,那麼顯然a1和a3都大於a2,與假設相反
因此,題設中的假設最大子序乘積位於陣列中間是不成立的。也就能從上面的結論知道,最大子序乘積應該位於陣列的兩端,即包含最左或者最右的數。
**如下:
//這段**非本人所寫,原作者可以在discuss裡找到
//在看過此段**後,立即明白了之前一直忽略的地方,總共有兩處(我對原作者思路的復現):
//1.如果陣列中有零,則零應該被特殊對待,因為任何數乘零都等於零,而最大乘積的趨向正整數
//2.對於非零陣列段中的最大連續子段乘積只能出現在最左或者最右,即必須包含a[0]或則a[n-1]。具體證明將在csdn的部落格中給出
//基於上述觀點2,我們只需要從陣列的首位兩端同時連乘,並比較取最大,然後根據觀點1,當連乘中遇到0的結果,則從下乙個數重新開始連乘。
int maxproduct(int a, int n) {
int b=1, f=1, res=a[0]; //b儲存從左往右的連乘積,f儲存從右往左的連乘積,res代表最大乘積
for(int i=0; i
LintCode 191 乘積最大子序
找出乙個序列中乘積最大的連續子串行 至少包含乙個數 樣例 比如,序列 2,3,2,4 中乘積最大的子串行為 2,3 其乘積為6。思路 動態規劃,每一步只需要記住其前一步的整數最大值和負數的最小值。因為涉及到正負,所以要儲存最小值和最大值兩種情況,因為負負得正。最小值的比較包括nums i min n...
最大子序和問題
給定乙個整數陣列 nums 找到乙個具有最大和的連續子陣列 子陣列最少包含乙個元素 返回其最大和。示例 輸入 2,1,3,4,1,2,1,5,4 輸出 6 解釋 連續子陣列 4,1,2,1 的和最大,為 6。思路 1 動態規劃首先需要對序列進行遍歷,當前最大子串行的和為sum,最終結果為ans。2 ...
最大子串乘積
最大子串乘積 輸入n個數,求它的最大的連續子串乘積。例 輸入 1 2 3 7 0 2 3 輸出 實現 include int max subsegment int arr int len 最大子段乘積函式 else if arr j 0 else return max int main main p...