【leetcode】Maximum Product Subarray

问题描述:
Find the contiguous subarray within an array (containing at least one number) which has the largest product.
For example, given the array [2,3,-2,4],
the contiguous subarray [2,3] has the largest product = 6.</p>


这题开始以为用DP可以解决,但是仔细想了想,每次子问题的解不可以重复利用。因此,DP应该解决不了。如果有解决的,请@我。

思路:
数字只有三种情况,正数,负数,0;
遇到有0的,数组肯定前后分开。即[数组A,0,数组B]。然后在数组A和B之间找出最大值。因此,我们只需要考虑正数和负数交叉的情况。
我们知道,连在一起的正数可以看作一个数,负数不行。原因[-5,1,-2,-1]明显[-2,-1]不能看作一个数。
对于存在负数的情况,我们只需要判断如下两种情况就行了。
1.数组开始到最后一个负数前一个数,
2.数组的第一个负数+1为到数组最后一个数即可。
中间判断下开始和结束位大小。最终判断1.2的大小,存到一个List里面(因为存在0的情况,所以每个分组都有最大值)。
最后从这个最大值的List找到一个最大的就行了。
下面代码已过Leetcode. 

package Max_Product_Subarray;

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

public class Max_Product_Subarray {

	/**
	 *  Find the contiguous subarray within an array (containing at least one number) which has the largest product.
     *	 For example, given the array [2,3,-2,4],
     *   the contiguous subarray [2,3] has the largest product = 6. 
	 */
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] A = {-1,-2,-3,0};
		Max_Product_Subarray mps = new Max_Product_Subarray();
		System.out.println(mps.maxProduct(A));
	}
	
	 public int theProduct(int start,int end,int[] A){
		 int result = 1;
		 for(int i=start;i<=end;i++)
			 result=result*A[i];
		 return result;
	 }
	 
	 public int max(int m,int n){
		 return m>n?m:n;
	 }
	/**
	 * 首先明确数字可能是正数、负数、0,其中相连的正数可看做整体,如此,只判断A[]中负数情况和0的情况:
	 * 1.A中负数为0,零的个数为0   ------> 最大值:整个A相乘
	 * 														|--  负数为偶数, 整个A相乘
	 * 2.A中负数不为0,零的个数为0  ---
	 * 														|-- 负数为奇数,数目为n,判断两种情况的最大值:从头乘到n-1负数的前一个书;or 从第一个负数后开始*到最后一个负数
	 * 3零的个数不为0;按0分割成小模块,判断所有小模块的最大值
	 * */
	 public int maxProduct(int[] A) {
		 if(A.length==1)
			 return A[0];
		 List<Integer> zero = new ArrayList<Integer>();
		 for(int i=0;i<A.length;i++){
			 if(A[i]==0)
				 zero.add(i);
		 }
		List<Integer> maxArray = new ArrayList<Integer>();
		if(zero.size()==0)
			maxArray.add(comProduct(0,A.length-1,A)) ;
		else{
			int i = 0;
			for( i=0;i<zero.size();i++)
				if(i==0)
					maxArray.add(comProduct(0,zero.get(i)-1,A));
				else{
					maxArray.add(comProduct(zero.get(i-1)+1, zero.get(i)-1, A));
				}
			    maxArray.add(comProduct(zero.get(i-1)+1, A.length-1, A));
		}
		int max = -2147483648;
		for(int temp:maxArray){
			if(temp>max)
				max=temp;
		}
	  return max>0?max:0;  
	}
	 
	public int comProduct(int start,int end,int[] A){
		System.out.println("start ="+start+"  end "+end);
		if(end<start)
			return -2147483648;
		if(end==start)
			return A[end];
		List<Integer> op  = new ArrayList<Integer>(); 
		for(int i=start;i<=end;i++)
			 if(A[i]<0)
				 op.add(i);
		//判断A中负号的个数
		 if(op.size()%2==0)
			 return theProduct(start,end,A);
		 else{
			 System.out.println("op.size()-1 "+(op.size()-1)+" op.get(0)+1  "+(op.get(0)+1));
			 return max(theProduct(start,op.get(op.size()-1)-1,A),theProduct(op.get(0)+1,end,A));
		 }
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值