512、java-求最大子数组
求最大子数组
方式一:穷举出所有子数组
public static void main(String[] args) {
int[] arr = new int[]{1,2,-4,5,-3,5,3,-9,3};
querySubArr(arr);
querySubArrExhaustively(arr);
}
/**
* @description: 穷举的方式,罗列出所有子数组
* @param ${tags}
* @return ${return_type}
* @throws
* @author chenjy
*/
public static void querySubArrExhaustively(int[] arr) {
if (arr == null || arr.length == 0)
throw new IllegalArgumentException("数组为空");
//1. 子数组容器
Map<Integer,String> map = new HashMap<>();
//穷举出所有子数组
for (int i = 0; i < arr.length; i++) {
int key = arr[i];
String value = arr[i]+"";
map.put(key,value);
for (int j = i+1; j < arr.length ; j++){
key = key+arr[j];
value = value+"_"+arr[j];
map.put(key,value);
}
}
//比较最大的key
Set<Integer> keySet = map.keySet();
Integer max = keySet.stream().max(new ComparableComparator<>()).get();
//取子数组
System.out.println("max:"+max);
System.out.println("maxSubArray:"+ JSON.toJSONString(map.get(max).split("_")));
}
方式二:O(N)复杂度
理解:当前子数组、最大子数组两个概念
int[] arr = new int[]{1,2,-4,5,-3,5,3,-9,3};
例如:
从坐标 0 开始,最大、当前子数组都是1
1+2 最大、当前子数组都是 1、2
1+2-4,则当前子数组是1、2、3;最大子数组1、2
1+2-4+5,这里有个概念 a+b+c<c 则可以推出, c > a+b,所以当前子数组需要初始化,从5开始,因为 a+b+c<c,此时当前子数组为5,又因为1+2 < 5,所以最大子数组也变为了5,如果这个坐标数是2,则最大子数组不变
/**
* @description: 获取数组中最大和的子数组,O(n)复杂度
* @author chenjy
*/
public static void querySubArr(int[] arr) {
if (arr == null || arr.length == 0)
throw new IllegalArgumentException("数组为空");
//1. 定义
//最大子数组和
int max = arr[0];
//当前子数组和
int curr = arr[0];
//数组字符串
String maxStr = arr[0]+"_";
String subStr = arr[0]+"_";
//遍历数组
for (int i = 1; i < arr.length; i++) {
curr = curr + arr[i] > arr[i] ? curr+arr[i] : arr[i];
//2. 计算 a+b+c < c 那么可知a、b只会减小c的值,所以a、b舍去,从c开始
if(curr == arr[i]){
//重新计算当前子字符串
subStr="";
}
subStr += arr[i]+"_";
//当前子数组和,大于前一段的和则替换为最大子数组和
if(curr > max){
max = curr;
maxStr=subStr;
}
}
System.out.println("max:"+max);
System.out.println("maxSubArray:"+ JSON.toJSONString(maxStr.split("_")));
}
max:10
maxSubArray:["5","-3","5","3"]
max:10
maxSubArray:["5","-3","5","3"]