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;
        
    }
}

 

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