LeetCodeMedium篇Maximum Product Subarray

題目

Given an integer array nums, find the contiguous subarray within an array (containing at least one number) which has the largest product.

Example 1:

Input: [2,3,-2,4]
Output: 6
Explanation: [2,3] has the largest product 6.

Example 2:

Input: [-2,0,-1]
Output: 0
Explanation: The result cannot be 2, because [-2,-1] is not a subarray.

 

十分鐘嘗試

需要尋找的結果滿足兩個條件,第一乘積最大,第二必須連續。

class Solution {
    public int maxProduct(int[] nums) {
        int max=0;
        for(int i=0;i<nums.length;i++){
            for(int j=i;j<nums.length;j++){
                int curr=nums[i]*nums[j];
                max=Math.max(max,nums[i]*nums[j]);
            }
            
        }
        return max;
        
    }
}

寫完了,發現不連續。不對。試着用dp思路解決,出現漏洞。代碼如下:

怎麼解決不連續呢?根據輸入2 3 -2 4,分析我原來的定義如下:

dp[i]=Math.max(dp[i-1],dp[i-1]*nums[i])

這個不對,dp[i]的最大值應該定義如下:

dp[i]=Math.max(nums[i],dp[i-1]*nums[i])

重新寫一次,代碼如下:

class Solution {
    public int maxProduct(int[] nums) {
        int[] dp=new int[nums.length];
        dp[0]=nums[0];
        int max=nums[0];
        for(int i=1;i<nums.length;i++){
           dp[i]=Math.max(nums[i],dp[i-1]*nums[i]);
            max=Math.max(max,dp[i]);
        }
        return max;
        
    }
}

此次代碼,正數沒問題,但是負數不對,因爲如果有負數,乘積雖然小於當前值,但是如果跟下一個負數相乘,便是最大乘積。如何去掉負數。測試用例爲  -2 ,3,-4

這種方法求和可以,因爲和只是加減,跟乘積不同,乘積兩個負數相乘就成爲最大了。看一下之前求連續數組最大和的問題:

https://leetcode.com/problems/maximum-subarray/submissions/

當時的解法是這樣:無非就是最大和,我們只是關係最近的一個dp值,所以不需要數組,只是需要一個變量就可以。

這道題可以用dp解決,當時對dp不熟悉,可以重新寫一下,代碼如下:

public int maxSubArray(int[] A) {
        int n = A.length;
        int[] dp = new int[n];//dp[i] means the maximum subarray ending with A[i];
        dp[0] = A[0];
        int max = dp[0];
        
        for(int i = 1; i < n; i++){
            dp[i] = A[i] + (dp[i - 1] > 0 ? dp[i - 1] : 0);
            max = Math.max(max, dp[i]);
        }
        
        return max;
}

我又嘗試瞭如下方法,dp 因爲dp[i]的最大值不能簡單取dp[i-1]的最大值,比如-2,3,-4,當前爲-4的時候,dp[i-1]取最小值反而能得到最大值。所以我們要區分一下,什麼時候取最大,什麼時候取最小。

nums[i] 爲負數,dp[i-1]取最小值

nums[i]爲正數,dp[i-1]取最大值

根據上面的思路,我還是沒有理清這個情況。算了,看看思路把

 

正確解法

思路的關鍵就是如果當前元素小於0,交換currMax和currMin。另外特別要注意的是swap函數寫的不對,原來寫法如下:

java中都是值傳遞,根本不會修改原來的currMax和currMin。有以下幾個方法:

1  類變量,最簡單

2  wrapper類傳入,比如類A,新建一個WrapperA,變量是A,傳入後進行交換

3 利用數組,很多排序算法都是這麼做的。怪不得以前的算法swap寫完都沒有問題,因爲我很自然的傳入了int[]數組進去。

public static void swap(int[] data, int a, int b) {
        int t = data[a];
        data[a] = data[b];
        data[b] = t;
    }

下面是錯誤寫法: 

 private void swap(int max,int min){
        int temp=max;
        max=min;
        min=temp;
    }

正確代碼,自己寫的,理解思路之後。 

class Solution {
    
    private int[] swap(int max,int min){
        int temp=max;
        max=min;
        min=temp;
        return new int[]{max,min};
    }
    
    public int maxProduct(int[] nums) {
        int max=nums[0];
        int currMax=nums[0];
        int currMin=nums[0];
        for(int i=1;i<nums.length;i++){
            if(nums[i]<0){
                int[] res=swap(currMax,currMin);
                currMax=res[0];
                currMin=res[1];
            }
            currMax=Math.max(nums[i],currMax*nums[i]);
            currMin=Math.min(nums[i],currMin*nums[i]);
            max=Math.max(max,currMax);
        }
        return max;
        
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章