Leetcode - Maximum Product Subarray

Paste_Image.png

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),需要兩種類型的變量。

  1. 一個(gè)變量用來(lái)記錄以前的結(jié)果, past
  2. 一個(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!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容