每日一练-----返回乘积最大的子数组的积

问题:

给定一个double类型的数组arr,其中元素可正可负,返回子数组累乘的最大乘积;

如:

arr  = [-2.5,4,0,3,0.5,8,-1]

则子数组[3,0.5,8]累乘获得最大乘积,返回12;

思想:

采用一个临时变量来存储遍历到当前位置的情况下所能够得到的最大乘积,这个值无非有三种可能性:

情况1:当前位置上的值是正数的话,那么有可能得到到达当前位置的时候的最大值是当前位置上的元素值乘以前面获得的最大值:如2,3,5到达5的时候,5>0,所以到达5之后的可能最大值是max*5,max是5之前获得的最大值;

情况2:当前位置上的值是负数的话,那么有可能得到到达当前位置的时候的最大值是当前位置上的元素值乘以前面获得的最小值:如-2,3,-5到达-5的时候,-5<0,所以到达-5之后的可能最大值是min*-5,min是-5之前获得的最小值;

情况3:就是当前位置上的值,如:0.1,0.1,50,那么到达当前位置50处的最大值可能是50;

之后只要求出上面三种情况的最大值,然后与临时变量的最大值取最大值即可;

代码:

public class MaxMulti {
	public static void main(String[] args) {
		double[] arr = {-2.5,4,0,3,0.5,8,-1};
		System.out.println(getMaxMulti(arr));
	}
	
	public static double getMaxMulti(double[] arr)
	{
		double max = arr[0];
		double min = arr[0];
		double result = 0.0;
		for(int i = 1;i < arr.length;i++)
		{
			max = max * arr[i];
			min = min * arr[i];
			max = Math.max(Math.max(max, min), arr[i]);
			min = Math.min(Math.min(max, min), arr[i]);
			result = Math.max(max, result);
		}
		return result;
	}
}

如果想要计算出子数组乘积最大的这个子数组的话,定义一个长度为2的一维数组用来记录这个子数组的开始和结束位置,因为数组中可能会存在0元素,为了避免0元素,我们在遍历的过程中可能只会计算出正确的start或者end位置,为了标志到底是start正确还是end正确,我们使用了flag布尔型标志,最后根据flag来对相应的start以及end进行修正即可,修正策略是循环除以当前遍历到的元素,知道乘积为1结束即可;

代码:

public class MaxMulti {
	public static void main(String[] args) {
		double[] arr = {-2.5,4,0,3,0.5,0,8,-1};
		int[] result = getMaxMultiStartAndEnd(arr);
		print(arr, result[0], result[1]);
	}
	
	public static int[] getMaxMultiStartAndEnd(double[] arr)
	{
		int start = 0;
		int end = 0;
		int[] result = new int[2];
		boolean flag = true;//用flag来表示最后start的值是真正的start还是end是真正的end
		if(arr == null)
			return null;
		if(arr.length == 0)
		{
			result[0] = 0;
			result[1] = 0;
			return result;
		}
		double max = arr[0];
		double min = arr[0];
		double tempMax = arr[0];
		double tempMin = arr[0];
		double resultMax = arr[0];
		for(int i = 1;i < arr.length;i++)
		{
			tempMax = max * arr[i];
			tempMin = min * arr[i];
			max = Math.max(Math.max(tempMax, tempMin), arr[i]);
			min = Math.min(Math.max(tempMax, tempMin), arr[i]);
			if(max > resultMax && max == arr[i])
			{
				//设置开始位置为当前位置
				start = i;
				flag = true;
			}else if(max > resultMax && max == Math.max(tempMax, tempMin))
			{
				//设置结束位置向后移动
				end = i;
				flag = false;
			}
		    resultMax = Math.max(max, resultMax);
		}
		if(flag == false)
		{
			//计算start的值(修正start的值)
			int i = end;
			while(resultMax != 1)
			{
				resultMax = resultMax / arr[i];
				i--;
			}
			result[0] = i+1;
			result[1] = end;
		}else
		{
			//计算end的值(修正end的值)
			int i = start;
			while(resultMax != 1)
			{
				resultMax = resultMax / arr[i];
				i++;
			}
			result[0] = start;
			result[1] = i-1;
		}
		return result;
	}
	
	public static void print(double[] arr,int start,int end)
	{
		for(int i = start;i <= end;i++)
			System.out.print(arr[i]+" ");
	}
}




评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值