【演算法拾遺】子陣列的最大乘積
轉載請註明出處:http://blog.csdn.net/ns_code/article/details/29224185
給定一個長度為N的整數陣列,只允許使用乘法,不能使用除法,計算任意N-1個數的組合乘積的最大值。
這道題目重點要注意陣列中有負數、0的情況。最直觀的做法就是把所有可能的N-1個數的組合找出來,分別計算他們的乘積,並比較大小。找出所有組合需要O(N)時間,計算每個組合的乘積需要O(N)時間,因此該演算法的時間複雜度為O(N*N)。
程式設計之美上給出了兩種O(N)的解法。
第一種比較直觀,假設去掉第i個元素後的剩下的N-1個元素的成績為p[i],則從左向右掃描陣列,計算第0到第i-1個元素的乘積s[i],再從右向左掃描陣列,計算從第N-1個元素到第i+1個元素的乘積t[i],二者相乘便是除去第i個元素的剩下N-1個元素的乘積p[i],而後比較所有的p[i]即可。由於每次計算s[i+1]和t[i-1]時直接可以利用s[i]和t[i]的結果,因此掃描一次過去的時間複雜度為O(N),找出p[i]的最大值也是O(N),因此時間複雜度為O(N)。
第二種方法,將問題轉化到對去掉的那個元素的分析上,只在最後計算一次乘積即可。這種方法要先掃描一次陣列,得到陣列中正整數的個數、負整數的個數、0的個數,最小的正整數、絕對值最大的負整數和絕對值最小的負整數。而後詳細地根據陣列中正負數以及0的個數來判斷要剔除的元素。
1、如果陣列中0的個數大於1,則任意N-1個元素的乘積都為0,去掉任一元素均可;
2、如果陣列中0的個數為1,則需要分兩種情況;
{
1、如果陣列中負數的個數為偶數個,此時去掉0,剩下的N-1個數的乘積最大,為正值;
2、如果陣列中負數的個數為奇數個,此時N-1個數的乘積最大值為0,去掉任意一個非0元素即可。
}
3、如果陣列中沒有0,則需要分兩種情況:
{
1、如果陣列中的負數個數為奇數個,此時去掉一個負數後的剩下N-1個數的乘積為正值,要保證這個正值最大,我們需要去掉絕對值最小的負 數,即最大的負數;
2、如果陣列中的負數個數為偶數個,則需要分兩種情況:
{
1、如果陣列中沒有正整數,則去掉一個負數後,剩下的N-1個數的乘積為負值,要保證這個負值最大,我們需要去掉絕對值大的負數 , 即最小的負數;
2、如果陣列中有正整數,則去掉最小的正整數,剩下的N-1個元素的乘積即為最大的。
}
}
按照這種思路實現的程式碼如下:
bool flag;
long long MaxProduct(int *arr,int len)
{
if(arr==NULL || len<1)
{
flag = false;
return 0;
}
int minus = 0; //負數個數
int plus = 0; //正數個數
int zero = 0; //0的個數
int minAbsMinus = (signed int)0x80000000; //絕對值最小的負整數,先初始化為最小的int負數
int maxAbsMinus = -1; //絕對值最大的負整數,先初始化為最大的負整數
int minPlus = 0x7FFFFFFF; //最小的正整數,先初始化為最大的int正數
int i;
for(i=0;i<len;i++)
{
if(arr[i] == 0)
zero++;
else if(arr[i] < 0)
minus++;
else
plus++;
if(arr[i]<0 && arr[i]>minAbsMinus)
minAbsMinus = arr[i];
if(arr[i]<0 && arr[i]<maxAbsMinus)
maxAbsMinus = arr[i];
if(arr[i]>0 && arr[i]<minPlus)
minPlus = arr[i];
}
int outNum; //不參與乘積的數
long long result = 1; //n-1個數的最大乘積
//0的個數大於1的情況,這時任意n-1個數的乘積都為0,
if(zero > 1)
return 0;
//如果有一個0,則需要根據正負數的個數來決定
if(zero == 1)
{
//如果負數的個數為偶數個,
//則去掉0後的n-1個數的乘積為正,即為最大值
if((minus&1) == 0)
outNum = 0;
//如果負數的個數為奇數個,
//則去掉0後的n-1個數的乘積為負,因此最大值應該為0,
//去掉任一個非0元素即可
else
return 0;
}
//如果沒有0,則需要根據正負數的個數來決定
else
{
//如果負數個數為奇數個,則去掉一個負數後,剩下的n-1個元素的乘積為正,
//此時去掉絕對值最小的負數,剩下的n-1個數的乘積便最大
if((minus&1) != 0)
outNum = minAbsMinus;
//如果負數個數為偶數個,這時候要分兩種情況,
//陣列中有正數和沒正數
else
{
//如果陣列中沒有正數,則n-1個負數的乘積肯定為負數,
//去掉絕對值最大的負數,便可得n-1個負數乘積的最大值
if(plus == 0)
outNum = maxAbsMinus;
//如果陣列中有正數,則去掉最小的正數,便可得n-1個數乘積最大值
else
outNum = minPlus;
}
}
//計算乘積
for(i=0;i<len;i++)
{
if(arr[i] != outNum)
result *= arr[i];
}
return result;
}
相關文章
- 【演算法拾遺】三種方法求連續子陣列的最大和演算法陣列
- [LeetCode] Maximum Product Subarray 求連續子陣列的最大乘積LeetCode陣列
- 子陣列的乘積陣列
- leetcode-陣列中兩元素的最大乘積(Java)LeetCode陣列Java
- 【演算法拾遺】階乘演算法
- [C#.NET 拾遺補漏]02:陣列的幾個小知識C#陣列
- 978 最長湍流子陣列陣列
- 【演算法拾遺】最大公約數演算法
- mongoose 拾遺Go
- 演算法學習-零子陣列,最大連續子陣列演算法陣列
- Leetcode 陣列中和為給定值的最長子陣列LeetCode陣列
- 【演算法拾遺】最大數和最小數演算法
- 前端技能拾遺前端
- Linux拾遺Linux
- Java Web 拾遺JavaWeb
- [MASM拾遺]OffsetASM
- 物件導向拾遺物件
- 【java web】--Ajax拾遺JavaWeb
- C語言拾遺C語言
- 【演算法拾遺】阿里實習生電面題目:輸出給定字串的全部連續子串演算法阿里字串
- [藍橋杯][演算法提高VIP]最大乘積 貪心 雙指標演算法指標
- 分詞問題;及最大乘積分析分詞
- 最長公共子串 二維陣列 Go實現陣列Go
- 演算法學習-數字連續的子陣列演算法陣列
- [資料結構拾遺]字串排序演算法總結資料結構字串排序演算法
- 重拾Kotlin(3)-陣列、字串模板Kotlin陣列字串
- golang拾遺:嵌入型別Golang型別
- docker拾遺-之再入坑Docker
- Unix廣告拾遺 by Dennis Ritchie
- 【JS拾遺】函式的引數JS函式
- [C#.NET 拾遺補漏]11:最基礎的執行緒知識C#執行緒
- [C#.NET 拾遺補漏]07:迭代器和列舉器C#
- 【DP】乘積最大子陣列陣列
- 和為 K 的子陣列陣列
- Vue.js基礎拾遺Vue.js
- PHP 使用 Kafka 安裝拾遺PHPKafka
- AS拾遺--向PM學習二
- golang拾遺:指標和介面Golang指標