package com.zkdx.test;
import java.util.HashMap;
/**
* @Author: Chintsai Hwo
* @Date: Created on 8:37 PM 6/27/2019
*/
public class Test {
public static void main(String[] args) {
int[] a = {13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7};
// 用暴力破解法
HashMap<Integer, Integer> indices = findIndex(a);
System.out.println(indices);
System.out.println();
// 用分治法
int[] subarray = findMaximumSubarray(a, 0, a.length - 1);
for (int element : subarray)
System.out.println(element + " ");
}
/**
* brute-force method, which is of complexity n^2 and is not recommended.
*
* @param a
* @return
*/
private static HashMap<Integer, Integer> findIndex(int[] a) {
HashMap<Integer, Integer> indices = new HashMap<>();
int sum;
int maxSum = Integer.MIN_VALUE;
int min = 0;
int max = 0;
for (int i = 0; i < a.length; i++) {
sum = 0;
for (int j = i; j < a.length; j++) {
sum += a[j];
if (sum > maxSum) {
maxSum = sum;
max = j;
min = i;
}
}
}
indices.put(min, max);
return indices;
}
/**
* divide-and-conquer method, which is of complexity n*lg(n) and is highly recommended.
*/
private static int[] findMaxCrossingSubarray(int[] a) {
int[] subarray;
int low = 0;
int high = a.length - 1;
int mid = (low + high) / 2;
int sum = 0;
int maxLeft = mid;
int maxRight = mid + 1;
int leftSum = Integer.MIN_VALUE;
int rightSum = Integer.MIN_VALUE;
for (int i = mid; i > 0; i--) {
sum += a[i];
if (sum > leftSum) {
leftSum = sum;
maxLeft = i;
}
}
sum = 0;
for (int j = mid + 1; j <= high; j++) {
sum += a[j];
if (sum > rightSum) {
rightSum = sum;
maxRight = j;
}
}
subarray = new int[]{maxLeft, maxRight, leftSum + rightSum};
return subarray;
}
/**
* @param a
* @param low
* @param high
* @return
*/
private static int[] findMaximumSubarray(int[] a, int low, int high) {
int[] subarray;
if (low == high)
return new int[]{low, high, a[low]};
else {
int mid = (low + high) / 2;
int leftLow = findMaximumSubarray(a, low, mid)[0];
int leftHigh = findMaximumSubarray(a, low, mid)[1];
int leftSum = findMaximumSubarray(a, low, mid)[2];
int rightLow = findMaximumSubarray(a, mid + 1, high)[0];
int rightHigh = findMaximumSubarray(a, mid + 1, high)[1];
int rightSum = findMaximumSubarray(a, mid + 1, high)[2];
int crossLow = findMaxCrossingSubarray(a)[0];
int crossHigh = findMaxCrossingSubarray(a)[1];
int crossSum = findMaxCrossingSubarray(a)[2];
if (leftSum >= rightSum && leftSum >= crossSum)
return new int[]{leftLow, leftHigh, leftSum};
else if (rightSum >= leftSum && rightSum >= crossSum)
return new int[]{rightLow, rightHigh, rightSum};
else
return new int[]{crossLow, crossHigh, crossSum};
}
}
}