題目描述:給乙個浮點數序列,取最大乘積連續子串的值,例如 -2.5,4,0,3,0.5,8,-1,則取出的最大乘積連續子串為3,0.5,8。也就是說,上述陣列中,3 0.5 8這3個數的乘積3*0.5*8=12是最大的,而且是連續的。
提醒:子串子串行不同,子串要求連續,子串行不要求連續。
分析:這個問題與「最大子陣列」問題極為相似,最大子陣列是求和的最大子串,該題是求積的最大子串。最大子陣列中,最巧妙的演算法是dp演算法,思想以及源**如下:
先看陣列a[0…i],已知它的最大子陣列,記為res(i),同時,也可求得包含元素a[i]的最大子陣列。記為sum(i)。
對於陣列a[0…i+1],它的最大子陣列,要麼包含元素a[i+1],要麼不包含元素a[i+1]:
包含元素a[i+1]的情況是:res(i+1) = sum(i+1)
不包含元素a[i+1]的情況是res(i+1) = res(i)
int dpmaxsum(int *a, int length)
else
res= (sum > res)?sum:res;
}returnres;
}注意到下面的**,實際上是需要根據(sum+a[i] >= a[i])?的不同情況做出不同的選擇:
if(sum >= 0)
else
sum+a[i] ? a[i],在求和的時候,只需要區分sum是否大於或者小於0即可,這是因為對於加法來說,如果a>b,那麼對於任意的數a+c > b+c,而不管c是整數還是負數。
但是對於乘法來說,如果a>b,那麼ac和bc的大小並不一定能夠確定,因為涉及到負數的問題。
根據最大子陣列的思想,假設包含a[i]的最大乘積為maxi,最小乘積為mini, 所以,mini < maxi,但是maxi* a[i], mini * a[i]與a[i]三個數之間的大小關係也是不確定的。所以,每次求maxi的同時,也需要求mini的大小,**如下;
double func(double *a,const int n)
return value; }
相關問題:給定乙個長度為n的整數陣列,只允許用乘法,不能用除法,計算任意(n-1)個數的組合中乘積最大的一組,並寫出演算法的時間複雜度。
分析:我們可以把所有可能的(n-1)個數的組合找出來,分別計算它們的乘積,並比較大小。由於總共有n個(n-1)個數的組合,總的時間複雜度為o( ),顯然這不是最好的解法。下面的解答來自程式設計之美
解法1
假設a[1..n]為初始陣列,
s[i]
表示從a[1]到a[i]的乘積,記s[0] = 1。所以s[i] = s[i-1] * a[i]。
t[i]
表示從a[i]到a[n]的乘積,記t[n+1] = 1,所以,t[i] = t[i+1]*a[i]。
p[i]表示除a[i]之外,其他n-1個元素的乘積,所以,p[i] = s[i-1]*t[i+1].
所以,只要從頭至尾掃瞄一遍,就可求得s[1..n],然後從尾至頭,就可求得t[1..n]。進而,線性時間內得到p[1..n],所以,總的時間複雜度為o(n)。
解法2
可以通過分析,進一步減少解答問題的計算量。假設n個整數的乘積為p,針對p的正負性進行如下分析: 1
:p=0
說明陣列中至少包含有乙個0。假設除去乙個0之外,其他n-1個數的乘積為q,根據q的正負性進行討論: q
為0:說明陣列中至少有兩個0,那麼n-1個數的乘積只能為0,返回0;
q為正數:則n-1個數的最大乘積為q,返回q
q為負數:返回0。 2
:p為負數
因為正*負=負,所以,可以從n個整數中去掉乙個負數,這樣其他n-1個數的乘積肯定為乙個正數。而要使這個正數最大,這個被去掉的負數必須是陣列中最大的(絕對值最小)。因而只需要掃瞄一遍陣列,把絕對值最小的負數給去掉就可以了。3:p
為正數
因為負*負=正 正*正=正。所以,如果陣列中存在正數值,那麼應該去掉最小的正數值,如果陣列中不存在正數,則應該去掉最小的負數值(絕對值最大)。
上面的解法採用了直接求n個整數的乘積p,進而判斷p的正負性的辦法,但是直接求乘積在編譯環境下往往會有溢位的危險(這也就是本題要求不使用除法的潛在用意),事實上可做乙個小的轉變,不需要直接求乘積,而是求出陣列中正數(+)、負數(-)和0的個數,從而判斷p的正負性,其餘部分與以上面的解法相同。
在時間複雜度方面,由於只需要遍歷陣列一次,在遍歷陣列的同時就可得到陣列中正數(+)、負數(-)和0的個數,以及陣列中絕對值最小的負數,絕對值最大的負數,最小的正數。時間複雜度為o(n)。
(
最大乘積連續子串
輸入一組浮點數,求出這個浮點陣列最大乘積的連續子串。舉個例子,浮點陣列為str 這時得出來的結果是前兩個浮點數的乘積,即15。需要注意的是,這個子串是要求連續的,另外,子串的長度可以為1.這裡給出兩種思路,後續可能還會加入新的思路。第一種是直接求解。即用雙層迴圈。外面一層是從1到浮點陣列的長度,裡面...
動態規劃 最大乘積子串
給定乙個陣列,求其中乘積最大的子串的乘積。如陣列 2,3,2,4 最大乘積為2 3 6.分析 最簡單的方法是設定乙個二維陣列p i j 表示從 i 到 j 這個子串的乘積,然後求p中的最大值。但這種方法時間複雜度和空間複雜度都比較高。計算子串的乘積,如果中間包含了0,那麼整個子串的乘積就是0。因此,...
最大乘積子陣列
程式設計之美 上有一道關於在長度為n的陣列中找到n 1個元素乘積最大的題目,不過這並不是本文要討論的。本文討論的是另一種情況,給定乙個長度為n的浮點陣列,找乙個長度任意的子陣列 子陣列的元素在原陣列中是連續存放的 這個子陣列的乘積最大。通常,找乙個滿足指定條件子陣列都會使用動態規劃。遞迴縮小問題規模...