博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[DP解题] 乘积最大子序列
阅读量:4040 次
发布时间:2019-05-24

本文共 3336 字,大约阅读时间需要 11 分钟。

[DP解题] 乘积最大子序列

原题链接:

[问题] 

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: 6Explanation: [2,3] has the largest product 6.

Example 2:

Input: [-2,0,-1]Output: 0Explanation: The result cannot be 2, because [-2,-1] is not a subarray.

题目的意思是给定一个整形数组nums,要求在数组中找到连续的子序列使得子序列的乘积最大(子序列至少包含一个整数)

例如:给定数组 [2,3,-2,4],最大连续子序列乘积为6。因为最大的连续子序列 [2,3],其最大乘积为6。

[算法分析]

这道题最直接的方法就是用DP来做,而且要用两个dp变量,其中:

dpMax:代表nums数组中下标从[0...i]时的最大乘积

dpMin:代表nums数组中下标从[0...i]时的最小乘积

为什么呢?

初始时,当i=0时,即数组中的第一个元素:

dpMax=dpMin=answer=nums[0] (可能为0,正值,负值)

i=1时:即数组中的第二个元素,这时要考虑几种情况,

乘积为0——有可能数组中的第一个元素为零,也可能数组中的第二个元素为零;无论哪一种结果,其乘积为零;

乘积为正值时——数组中的第一个元素和第二个元素均为正值或者均为负值时,则乘积为正值;

乘积为负值时——数组中的第一个元素为负值,或者第二个元素为负值,则乘积为负值;

综合起来,要取 Math.max(nums[i]*dpMax, nums[i]*dpMin)

然后在用这个乘积的值与nums[i]做比较得到当前的最大值

currentMax = Math.max(nums[i], Math.max(nums[i] * dpMax, nums[i] * dpMin));

举例来分析,先看第一个数组,仅包含两个数组元素

例如数组 [-2,-7]:

当i=0时:dpMax dpMin = answer = nums[0] = -2

当i=1时:dpMax是多少?要从 (-2)*(-7)=14,前面的dpMax (-2)和 nums[1] 中经过比较选出最大值,显然是 14。

                dpMin是多少?显然是 -7。为什么?Math.min(nums[i], Math.min(nums[i] * dpMax, nums[i] * dpMin))

如果把数组变为 [-2,7]:

当i=0时:dpMax dpMin = answer = nums[0] = -2

当i=1时:dpMax是多少?要从 (-2)* 7= -14,前面的dpMax (-2)和 nums[1] 中经过比较选出最大值,显然是7。

                dpMin是多少?-14。为什么?Math.min(nums[i], Math.min(nums[i] * dpMax, nums[i] * dpMin));

 

再看第二个数组,仅包含三个数组元素

例如数组 [-2,-7,-3]:

当i=0时:dpMax dpMin = answer = nums[0] = -2

当i=1时:dpMax是多少?要从 (-2)*(-7)=14,前面的dpMax (-2)和 nums[1] 中经过比较选出最大值,显然是 14。

                而此时dpMin是多少?显然此时dpMin的值为 -7.

当i=2时:dpMax是多少?这时num[2]为负值,当i=1时,dpMax=14,那么dpMax*nums[2] = 14*(-3) = -42 < nums[2]的值。

                显然 dpMax*nums[2] 不是最大值。那么 nums[2] 是最大值吗?显然也不是。

                那么最大值是多少? 用i=1时的dpMin*nums[2]看看,即 (-7)*(-3)=21. 这个最大值dpMax = 21.

                dpMax = Math.max(nums[i], Math.max(nums[i] * dpMax, nums[i] * dpMin));

                那么最小值是多少?-42. 用前面的最大值与当前元素的乘积得到。

                dpMin = Math.min(nums[i], Math.min(nums[i] * dpMax, nums[i] * dpMin));

从而可以推导出:

对于nums数组中的第i个元素为止:

dpMax = Math.max(nums[i], Math.max(nums[i] * dpMax, nums[i] * dpMin));

dpMin = Math.min(nums[i], Math.min(nums[i] * dpMax, nums[i] * dpMin));

所以,我们不仅仅要找dpMax,还要找dpMin。

看看其中有什么规律?

 

[算法设计]

package com.bean.algorithmexec;public class MaximumProductSubarray {		public static int maxProduct(int[] nums) {				/*		 * dpMax:代表nums数组中下标从[0...i]时的最大乘积		 * dpMin:代表nums数组中下标从[0...i]时的最小乘积		 * */		int dpMax = nums[0]; //初始时将nums[0]赋给dpMax		int dpMin = nums[0]; //初始时将nums[0]赋给dpMin		int answer = nums[0];//代表求得的结果,初始时将nums[0]赋给answer		//从下标i=1开始,遍历到nums数组的最后一个元素为止		for (int i = 1; i < nums.length; i++) {			/*			 * 如果下标为i的前一个元素,即i-1为0时,则前面元素的乘积必定为0;			 * 那么当前元素nums[i]			 * */			if (nums[i - 1] == 0) {				dpMax = nums[i];				dpMin = nums[i];			} else {				int currentMax = Math.max(nums[i], Math.max(nums[i] * dpMax, nums[i] * dpMin));				int currentMin = Math.min(nums[i], Math.min(nums[i] * dpMax, nums[i] * dpMin));				dpMax = currentMax;				dpMin = currentMin;			}			answer = Math.max(dpMax, answer);			//answer = Math.min(dpMin, answer);		}		return answer;	}	public static void main(String[] args) {		// TODO Auto-generated method stub		//int[] demo=new int[] {2,3,-2,4};		//int[] demo=new int[] {-1,4,-7,0,8,2,3};		int[] demo=new int[] {-2,-7,-3};		int result=0;		result = maxProduct(demo);		System.out.println("RESULT = "+result);			}}

执行结果

RESULT = 21

转载地址:http://ddtdi.baihongyu.com/

你可能感兴趣的文章
retext出现Could not parse file contents, check if you have the necessary module installed解决方案
查看>>
Matlab与CUDA C的混合编程配置出现的问题及解决方案
查看>>
python一句话之利用文件对话框获取文件路径
查看>>
PaperDownloader——文献命名6起来
查看>>
如何将PaperDownloader下载的文献存放到任意位置
查看>>
C/C++中关于动态生成一维数组和二维数组的学习
查看>>
JVM最简生存指南
查看>>
Java的对象驻留
查看>>
logback高级特性使用(二) 自定义Pattern模板
查看>>
JVM并发机制探讨—内存模型、内存可见性和指令重排序
查看>>
可扩展、高可用服务网络设计方案
查看>>
如何构建高扩展性网站
查看>>
微服务架构的设计模式
查看>>
持续可用与CAP理论 – 一个系统开发者的观点
查看>>
nginx+tomcat+memcached (msm)实现 session同步复制
查看>>
c++字符数组和字符指针区别以及str***函数
查看>>
c++类的操作符重载注意事项
查看>>
c++模板与泛型编程
查看>>
WAV文件解析
查看>>
WPF中PATH使用AI导出SVG的方法
查看>>