比较典型的动态规划。一刷的时候看code_ganker做法,对他局部 全局的想法很震惊,五体投地。
让乘积最大有2种来源:
2个正数相乘,越来越大。
2个负数相乘,也可以变大。
所以最终结果可能是正数乘以正数,也可能是一个非常小的负数乘以另一个负数,然后一下子牛逼了。。
所以既需要保留最大的正数,也需要保留最小的负数。
public class Solution
{
public int maxProduct(int[] nums)
{
if(nums.length == 0) return 0;
int global = nums[0];
int max = nums[0];
int min = nums[0];
for(int i = 1; i < nums.length;i++)
{
int temp = max;
max = Math.max(nums[i] * min, Math.max(nums[i],nums[i] * max));
min = Math.min(nums[i] * temp, Math.min(nums[i],nums[i] * min));
global = Math.max(global,max);
}
return global;
}
}
global就不解释了,每次比较取最大。
max是局部最大值,如果写成DP是localMax[i],表示包含nums[i]的最大值。
可以是localMax[i-1]*nums[i],例子是前面是正的,当前nums[i]也是正的;
可以是nums[i],前面是负的,nums[i]是正的,那我干脆不要前面的了,就要现在的正数。
还有种可能是,前面是负的,现在也是负的,就是localMin[i-1] * nums[i]
这3种情况取最大。
min是对应的局部最小,和上面的算法正好相反。
然后每次取一下global
如果不能理解,可以先尝试写成localMax[] localMin[],
localMax[i] = nums[i], localMax[i-1]*nums[i] , localMin[i-1]*nums[i]. 里面最大的。
localMin[i] 一样。