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.
拿到这道题的时候,我第一个想法就是用回溯来做,结果会漏掉数组中的单个值,而且回溯的时间复杂度较高。:(,没办法只好参考网上的答案,然后我发现几乎每一个动态规划,都是一种新的思路,每个思路都有新感觉:)。除了一些简单的背包的什么问题有相似的模板外,其余的题目都是新思路。比如这道题找出最大子数组乘积,要用两个DP数组,其中f[i] 表示子数组[0,i]范围内且包含nums[i]数字的最大乘积,g[i]表示子数组[0,i]范围内且包含nums[i]数字的最小乘积(这个就是考虑到有负数,负负得正可以得到更大的乘积);初始化时f[0]=g[0]=nums[0],然后从第二个数字开始遍历,此时最小值和最大值都是从(f[i-1]*nums[i], g[i-1]*nums[i], nums[i])中产生,用最大值来更新f[i],用最小值来更新g[i],然后用 f[i]的值来更新res的值,由于最终的结果不一定会包含nums[n-1]最后一个数字,所以f[n-1]不一定是最终解,更新后的res才是。
public int maxProduct(int[] nums) {
int[] f=new int[nums.length];//f[i]代表nums中下标i及以前所有数字的最大值
int[] g=new int[nums.length];//g[i]代表nums中下标i及以前所有数字的最小值
f[0]=g[0]=nums[0];
int res=nums[0];
for(int i=1;i<nums.length;i++){
f[i]=Math.max(Math.max(f[i-1]*nums[i],g[i-1]*nums[i]),nums[i]);
g[i]=Math.min(Math.min(f[i-1]*nums[i],g[i-1]*nums[i]),nums[i]);
res=Math.max(res,f[i]);
}
return res;
}
参考来源: