一、问题描述:
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;
}
}