leetcode oj java 152. 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.

二、解决思路:

如果数组中出现0的话,就根据0把数组split成为多个部分存放在list中。依次求出每个list中的maximum Product, 取最大值。

针对每个不含0的list 分两种情况:

1、负数的数目是偶数,那么list中元素的乘积即为最大值。

2、负数的数目是奇数,要么去掉最前边的负数m(包括负数前边的所有数,假设乘积是mk,),要么去掉最后边的负数n(包括负数后边的所有数,假设乘积为nk)

如果m * mk < n * nk, 说明m*mk的绝对值更大一些,那么保留前边的m, 否则保留n.


三、代码:

package T12;

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

/**
 * @author 作者 : xcy
 * @version 创建时间:2016年12月31日 下午9:35:02
 *          类说明
 */
public class t152 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub  
        //        int[] nums = { 1, -5, 6, -5, 2, -4, -5, 0, 3, 2, -4, 0, -5, -3, -1, -4, -1, 4, 1, -1, -3, -1, 1, 3, -4, -6, -2,
        //                5, 1, -5, 0, -1, -5, 0, 1, 2, 6, 1, 2, -6, 5, 5, 0, 1, 0, 1, 1, -1, -1, 3, 1, 0, 4, -3, 0, 4, -4, -1, 6,
        //                5, 5, 6, -6, 1, 1, 3, 4, 3, -1, -3, 0, -5, -4, 1, 5, -2, 3, -1, 2, 1, 1, 6, 0, 5, -5, 6, -6, 3, 0, 4,
        //                -1, 3, 6, 0, -2, 0, -1, 6, 4, 1, -5, 1, 0, 1, -1, -1, 3, 5, 5, 4, 2, 5, 0, -1, 5, 2, 2, -3, -1, -1, 0,
        //                -6, -2, -5, 1, -2, 2, 0, 0, 2, -3, -2, -4, 1, 1, -4, -3, -1, 0, 0, 1, -3, -2, 3, -4, 5, 2, -1, 4, 1, 5,
        //                6, 0, 1, 1, -2, -1, 0, -1, -5, 5, 6, 6, -1, -1, 0, -4, 2, 1, 3, -5, 6, -5, -1, -1, -3, -1, -4, -2, -1,
        //                -1, 1, -3, -4, 0, 1, -3, 4, 3, 2, -2, 6, -3, -6, -6, -2, -5, 1, 2, 0, -1, 0, 0, -2, 3, -4, 2, 4, 3, -1,
        //                3, 1, 0, 2, 1, -1, 0, 5, -1, -3, -6, -5, 0, 6, 6, -6, -5, 4, -2, -1, 0, 4, 6, -3, 1, -1, 0, 1, -5, 5,
        //                -3, -3, -3, -1, -1, 4, 0, -2, -4, 3, 5, 5, -1, -1, -5, -2, -4, -4, 6, 0, -3, -1, -5, -3, -1, 6, 1, -5,
        //                -1, 0, 1, -4, -5, 0, 0, 0, -3, -5, -1, -4, -1, 5, 5, -4, 4, -1, 6, -1, 1, -1, 2, -2, -3, 0, 1, 0, 0, -3,
        //                0, 2, 5, -6, -3, -3, 3, -4, -2, -6, -1, 1, 4, 4, 0, -6, -5, -6, -3, 5, -3, 1, -4, 6, -2, 0, -4, -1, 0,
        //                -1, 0, 6, -6, 0, 5, 0, 1, -3, 6, 1, -1, 1, 0, -1, 1, -1, -6, -3, 4, -1, -4, 6, 4, -1, -3, 2, -6, 5, 0,
        //                4, -2, 1, 0, 4, -2, 2, 0, 0, 5, 5, -3, 4, 3, -5, 2, 2, 6, -1, -2, 1, -3, 1, -1, 6, -4, 0, 0, 0, 2, -5,
        //                -4, 2, 6, -3, -6, -1, -6, 0, 0, 2, -1, 6, -4, -5, -1, 0, -3, -3, -1, 0, -4, 3, 1, 5, 0, 2, 5, 0, 4, -5,
        //                -1, 3, 1, -1, -1, 1, 1, -2, 3, 5, 4, 6, 2, 6, -6, 5, 2, -3, 0, -1, -1, 3, 1, 1, 1, -2, -5, 3, -1, 3, 0,
        //                -1, 3, 1, 1, -2, 6, 3, -6, 5, -5, -5, 0, -2, -3, -3, -4, 6, -1, -6, 6, -3, -5, 1, -1, 0, 0, 1, 4, -5, 0,
        //                1, -2, 6, 1, -3, -5, 0, 4, -2, 1, -5, -4, 0, 0, -1, -2, 0, 2, -2, 5, 6 };
        int[] nums = { -2, 0, -1, 3 };
        System.out.println(maxProduct(nums));
    }

    public static int maxProduct(int[] nums) {
        if (nums.length == 0) {
            return 0;
        }
        if (nums.length == 1) {
            return nums[0];
        }
        // split :
        List<List<Integer>> lists = split(nums);
        // compute each list
        int max = nums[0];
        if (lists.size() > 1) {
            max = 0;
        }
        for (List<Integer> tmp : lists) {
            int k = countOneList(tmp);
            max = max > k ? max : k;
        }
        return max;

    }

    public static List<List<Integer>> split(int[] nums) {
        List<List<Integer>> lists = new ArrayList<List<Integer>>();
        List<Integer> list = new ArrayList<Integer>();
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] == 0) {
                List<Integer> tmp = new ArrayList<Integer>();
                tmp.addAll(list);
                lists.add(tmp);
                list.clear();
            } else {
                list.add(nums[i]);
            }
        }
        if (list.size() > 0) {
            lists.add(list);
        }
        return lists;
    }

    public static int countOneList(List<Integer> list) {
        if (list.size() == 0) {
            return 0;
        }
        if (list.size() == 1) {
            return list.get(0);
        }
        List<Integer> pro = new ArrayList<Integer>();
        List<Integer> split = new ArrayList<Integer>();
        int count = 1;
        for (int i = 0; i < list.size(); i++) {
            int k = list.get(i);
            if (k < 0) {
                split.add(k);
                pro.add(count);
                count = 1;
            }
            if (k > 0) {
                count = count * k;
            }
        }
        split.add(1);
        pro.add(count);

        int re = cpro(split, pro);
        return re;

    }

    public static int cpro(List<Integer> split, List<Integer> pro) {
        // 如果负数元素是偶数,因为最后add 1, 故list 长度为奇数,全部相乘即可
        int count = 1;
        if (split.size() % 2 == 1) {
            for (int i = 0; i < split.size(); i++) {
                count = count * split.get(i);
                count = count * pro.get(i);
            }
        }
        // 负数元素是奇数的话:每个元素面临取或者不取的情况
        if (split.size() % 2 == 0) {
            // 去掉头还是去掉尾
            if (split.size() == 2) {
                return pro.get(0) > pro.get(1) ? pro.get(0) : pro.get(1);
            }
            // 去掉头
            if (split.get(split.size() - 2) * pro.get(split.size() - 1) < split.get(0) * pro.get(0)) {
                for (int i = 1; i < split.size(); i++) {
                    count = count * split.get(i);
                    count = count * pro.get(i);
                }
            } else { // 去掉尾
                for (int i = 0; i < split.size() - 2; i++) {
                    count = count * split.get(i);
                    count = count * pro.get(i);
                }
                count = count * pro.get(pro.size() - 2);
            }
        }
        return count;
    }

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值