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