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