乘积最大子序列

原创 2018年04月16日 14:07:05
 算法题:乘积最大子序列
写一个函数找出一个序列中乘积最大的连续子序列,其中序列中至少包含一个数)。

格式:

第一行输入一个数组,最后依次输出最大乘积的子序列及其乘积的大小。

样例输入

[ 2,3,-2,4 ]

样例输出

[ 2,3 ]

6


java版本的代码实现:

package cn.cat.algorithm;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class MaxProductSubSequence {

	/**
	 * 分析:拆分数组,然后分别计算各数组的乘积,乘积最大的数组即为乘积最大子序列。
	 * 拆分规则:
	 * 	1、先根据0进行拆分。
	 *  2、然后判断负数的元素个数,如果个数为偶数,则无须再拆分(因为偶数个负数相乘必定为正数)。
	 *  3、如果负数个数为奇数,则需要细分为两种情况:
	 *  		情况一:负数只有一个,则直接以负数为中点,把数组拆分为三个。
	 *  		情况二:负数个数大于1,也是将数组分为两个	:
	 *  						第一个数组范围为 数组最前端 至 倒数第二个负数索引
	 *  						第二个数组范围为 第二个负数 索引至 数组最末端。
	 * @Description: 
	 * @author gwj
	 * @Created 2018年4月16日 下午2:05:30 
	 * @param args
	 */
	public static void main(String[] args) {
		int[] data = new int[]{ 2, 3, -2, 4 };
		
		//统计0的个数和负数个数
		int countZero  = 0;
		for (int ele : data) {
			if (ele == 0 ) {
				countZero ++;
			}
		}
		
		//1、按零进行分割
		List<ArrRang> segmentsByZero = new ArrayList<ArrRang>(countZero + 1);
		if (countZero == 0) {
			segmentsByZero.add(newArrRang(0, data.length - 1));
		} else {
			//被拆分的数组元素起始索引
			int startDataIndex = 0;
			for (int i = 0; i < data.length; i++) {
				if (data[i] == 0) {
					//0被单独分割是一组
					segmentsByZero.add(newArrRang(i, i));
					//0前面的所有非0元素被分割为一组。
					if (i > 0) {
						segmentsByZero.add(newArrRang(startDataIndex, i - 1));
					}
					startDataIndex = i + 1;
				}
			}
			//0后面的元素被分割为一组
			if (startDataIndex < data.length) {
				segmentsByZero.add(newArrRang(startDataIndex, data.length - 1));
			}
			
		}
		
		//2、按负数进行分割
		List<ArrRang> segmentsByNegative = new ArrayList<ArrRang>();
		for (ArrRang arrRang : segmentsByZero) {
			int countNegative = 0;
			for (int i = arrRang.startIndex; i <= arrRang.endIndex; i++) {
				if (data[i] < 0) {
					countNegative ++;
				}
			}
			
			if (countNegative == 0 || countNegative % 2 == 0) {
				//没有负数,或负数个数为偶数,则不用再分割
				
				segmentsByNegative.add(arrRang);
				
			} else if (countNegative == 1) {
				//负数个数为1个,以负数中心,将数组拆分为三段。
				
				for (int i = arrRang.startIndex; i <= arrRang.endIndex; i++) {
					if (data[i] < 0) {
						//负数单独为一组
						segmentsByNegative.add(newArrRang(i, i));
						//负数左边为一组
						if (i > arrRang.startIndex) {
							segmentsByNegative.add(newArrRang(arrRang.startIndex, i - 1));
						}
						//负数右边为一组
						if (i < arrRang.endIndex) {
							segmentsByNegative.add(newArrRang(i + 1, arrRang.endIndex));
						}
					}
				}
				
			} else {
				//奇数个负数,且个数大于1,需要分割为左右两段数组。
				
				//第二个负数的索引
				int secondNegativeIndex = -1;
				//倒数第二个负数的索引
				int reverseSecondNegativeIndex = -1;
				int newCountNegative = 0;
				for (int i = arrRang.startIndex; i <= arrRang.endIndex; i++) {
					if (data[i] < 0) {
						newCountNegative ++;
					}
					
					if (newCountNegative == 2 && secondNegativeIndex == -1) {
						secondNegativeIndex = i;
					}
					
					if (newCountNegative + 1 == countNegative) {
						reverseSecondNegativeIndex = i;
					}
				}
				
				segmentsByNegative.add(newArrRang(0, reverseSecondNegativeIndex));
				segmentsByNegative.add(newArrRang(secondNegativeIndex, data.length - 1));
				
			}
			
		}
		
		
		int maxProduct = Integer.MIN_VALUE;
		ArrRang maxArrRang = null;
		for (ArrRang arrRang : segmentsByNegative) {
			int product = 1;
			for (int i = arrRang.startIndex; i <= arrRang.endIndex; i++) {
				product *= data[i];
			}
			if (maxProduct < product) {
				maxProduct = product;
				maxArrRang = arrRang;
			}
			
		}
		
		int[] maxSequence = Arrays.copyOfRange(data, maxArrRang.startIndex, maxArrRang.endIndex + 1);
		System.out.println("原数组为:" + Arrays.toString(data));
		System.out.println("最大乘积的子序列为:" + Arrays.toString(maxSequence) + " , 乘积为:"+ maxProduct);
	}

	
	/**
	 * 创建表示数组范围的对象。
	 */
	static ArrRang newArrRang(int startIndex, int endIndex) {
		return new ArrRang(startIndex, endIndex);
	}

	
	/**
	 * 数组范围类。标识下标的起点和终点。
	 */
	static class ArrRang{
		int startIndex;
		int endIndex;
		public ArrRang(int startIndex, int endIndex) {
			this.startIndex = startIndex;
			this.endIndex = endIndex;
		}
	}
}








版权声明:本文为博主原创文章,如需转载,必须在转载处声明原作者,已经加入博客原链接地址。 https://blog.csdn.net/u013777382/article/details/79959838

激励故事[n篇]

激励故事[n篇](1)鸡与大蟒蛇   在一个动物园,饲养员每天都要喂一大盆肉给大蟒蛇吃。  这一天,饲养员突然想看看给大蟒蛇吃鸡会是什么样子。于是他就关了一只鸡到大蟒蛇的笼子里。  这只鸡突然遭遇这飞...
  • citymeteor
  • citymeteor
  • 2002-11-10 10:54:00
  • 990

LintCode -- 乘积最大子序列

LintCode -- maximum-product-subarray(乘积最大子序列) 原题链接:http://www.lintcode.com/zh-cn/problem/maximu...
  • chan15
  • chan15
  • 2015-09-30 19:46:34
  • 451

LeetCode -- 最大连续乘积子序列

LeetCode -- 最大连续乘积子序列
  • csharp25
  • csharp25
  • 2015-07-23 11:39:03
  • 1279

LintCode-乘积最大子序列

找出一个序列中乘积最大的连续子序列(至少包含一个数)。 样例 比如, 序列 [2,3,-2,4] 中乘积最大的子序列为 [2,3] ,其乘积为6。 分析:访问到每个点的时候,以该点为子序...
  • wangyuquanliuli
  • wangyuquanliuli
  • 2015-05-15 21:21:23
  • 3063

乘积最大的连续子序列

问题:输入n个元素组成的序列S,你需要找出一个乘积最大的连续子序列。如果这个最大的乘积不是正数,应该输出-1(表示无解)。(可以输入小数,输出保留两位小数)输入: 3         2 4 -3输出...
  • AIlfw
  • AIlfw
  • 2018-02-26 22:25:22
  • 45

动态规划:最大连续子序列乘积

题目描述: 给定一个浮点数序列(可能有正数、0和负数),求出一个最大的连续子序列乘积。 分析:若暴力求解,需要O(n^3)时间,太低效,故使用动态规划。 设data[i]:第i个数据,dp[i]...
  • u010839382
  • u010839382
  • 2014-09-30 17:03:19
  • 1478

Java实现-乘积最大子序列

找出一个序列中乘积最大的连续子序列(至少包含一个数)。 您在真实的面试中是否遇到过这个题?  Yes 样例 比如, 序列 [2,3,-2,4] 中乘积最大的子序...
  • qq_14927217
  • qq_14927217
  • 2017-08-20 16:35:29
  • 513

python求解最大子序列乘积问题,子序列可连续也可不连续

题目意思很简单,与之前博文中的最大子序列和问题其实是如出一辙的,只是这里需要考虑的问题会多一点,因为加法的话不会出现负负得正的情况,在这里要求最大子序列乘积就需要维持两个动态遍历,一个保存上一次乘积留...
  • Together_CZ
  • Together_CZ
  • 2017-09-02 15:23:48
  • 531

九度OJ 1501 最大连续子序列乘积 -- 动态规划

题目地址:http://ac.jobdu.com/problem.php?pid=1501 题目描述: 给定一个浮点数序列(可能有正数、0和负数),求出一个最大的连续子序列乘积。 输入: ...
  • JDPlus
  • JDPlus
  • 2014-03-02 15:29:22
  • 4391

[LeetCode]Maximum Product Subarray 新题152 最大乘积子序列

public int maxProduct(int[] A) { int n=A.length; if (n==0) return 0; ...
  • jhbxlx
  • jhbxlx
  • 2014-09-25 05:52:16
  • 676
收藏助手
不良信息举报
您举报文章:乘积最大子序列
举报原因:
原因补充:

(最多只允许输入30个字)