My code:
public class Solution {
public int maxProduct(int[] nums) {
if (nums == null || nums.length == 0)
return 0;
else if (nums.length == 1)
return nums[0];
int max = nums[0];
int currMax = nums[0];
int currMin = nums[0];
for (int i = 1; i < nums.length; i++) {
int temp = currMax;
currMax = Math.max(Math.max(currMax * nums[i], currMin * nums[i]), nums[i]);
currMin = Math.min(Math.min(temp * nums[i], currMin * nums[i]), nums[i]);
max = Math.max(max, currMax);
}
return max;
}
}
My test result:
這道題目還是沒(méi)能自己想出來(lái),看了提示。
http://bangbingsyb.blogspot.com/2014/11/leetcode-maximum-product-subarray.html
來(lái)仔細(xì)分析下。
這道題目和前面一題求和,有什么區(qū)別。
求和的話,當(dāng)你出現(xiàn)了和為負(fù)數(shù)的情況后,這個(gè)情況就結(jié)束了。就可以重新開始開頭遍歷了。
比如, -5, 2,1,1,1,1
當(dāng)遍歷到,-5, 2時(shí),和為-3 < 0, 那么后面的和一定是 >= 該和,只要后面存在正數(shù)。
于是,這段值,就不需要再考慮了。直接可以從下一個(gè)正數(shù)開始考慮了。
但是乘積不同。
-5, 2, 3, -4
遍歷到 -5, 2時(shí),此時(shí)是負(fù)數(shù),但不代表這段值就沒(méi)用了。如果后面還存在一個(gè)負(fù)數(shù),那么,這一段,積就是最大的,所以不能簡(jiǎn)單地舍棄。
于是我就在想,怎么保存這些一開始是負(fù)數(shù)最后卻可能變成最大正數(shù)的情況。
解決不了,于是看了提示。
設(shè)置兩個(gè)變量, currMax, currMin
主要在于這個(gè)currMin, 可以用來(lái)保存負(fù)數(shù),然后下次這個(gè)負(fù)數(shù)乘以負(fù)數(shù),說(shuō)不定就成了 currMax. 然后可以保存住這些情況。
所以可以這么理解。這段array,一定存在一個(gè)最大的正數(shù),以及一個(gè)絕對(duì)值最大的負(fù)數(shù)。
然后一個(gè)一定是整段array的乘積。還有一個(gè)一定是,在出現(xiàn)了一個(gè)負(fù)數(shù)之后的那段array的乘積。
這兩個(gè)乘積一定一個(gè)是最大正數(shù),一個(gè)是絕對(duì)值最大的負(fù)數(shù)。
然后剛剛我試了下,發(fā)現(xiàn)還有一種干擾情況。 0
如果出現(xiàn)0.是需要把之前的割舍掉的。然后從新的頭開始。
具體就不考慮了。
**
總結(jié): Array, DP
**
My code:
public class Solution {
public int maxProduct(int[] nums) {
if (nums == null || nums.length == 0)
return 0;
int ret = nums[0];
int prevMin = nums[0];
int prevMax = nums[0];
for (int i = 1; i < nums.length; i++) {
int currMax = Math.max(prevMax * nums[i], Math.max(prevMin * nums[i], nums[i]));
int currMin = Math.min(prevMax * nums[i], Math.min(prevMin * nums[i], nums[i]));
ret = Math.max(ret, currMax);
prevMax = currMax;
prevMin = currMin;
}
return ret;
}
}
這道題目第二遍還是不會(huì)。。。
DP真的是軟肋。想不清楚,不知道怎么做。
想這個(gè),仔細(xì)想來(lái),就是許多連續(xù)的正數(shù)被許多負(fù)數(shù)分割開。然后我們要找出最大值。不僅僅要考慮之前整段的積,還要考慮部分的積。
所以,每次找currMax and currMin 時(shí),都是考慮三個(gè)值,
prevMax * nums[i]
prevMin * nums[i]
nums[i]
所以,積是要和之前的連接在一起的。然后找最大值就是找這些散落部分的最大的一個(gè)。
下面是我參考的鏈接:
https://www.quora.com/How-do-I-solve-maximum-product-subarray-problems
感覺(jué)下次做這道題目還是做不出來(lái)。。
其實(shí)這道題,和 maximum subarray, 都有一個(gè)共同點(diǎn),需要兩種類型的變量。
- 一個(gè)變量用來(lái)記錄以前的結(jié)果, past
- 一個(gè)變量用來(lái)記錄最大值, max
max = Math.max(max, past + nums[i]);
或者,在乘積中,就是,past與當(dāng)前值的乘積,然后再取最大值給max,差不多。
Anyway, Good luck, Richardo!
My code:
public class Solution {
public int maxProduct(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
int min = nums[0];
int max = nums[0];
int ret = nums[0];
for (int i = 1; i < nums.length; i++) {
int temp_max = Math.max(nums[i], Math.max(max * nums[i], min * nums[i]));
int temp_min = Math.min(nums[i], Math.min(max * nums[i], min * nums[i]));
ret = Math.max(ret, temp_max);
max = temp_max;
min = temp_min;
}
return ret;
}
}
這次做是做出來(lái)了,但是代碼很丑。改了之后才成這樣。
Anyway, Good luck, Richardo!