package class41; public class Code02_BestSplitForEveryPosition { public static int[] bestSplit1(int[] arr) { if (arr == null || arr.length == 0) { return new int[0]; } int N = arr.length; int[] ans = new int[N]; ans[0] = 0; for (int range = 1; range < N; range++) { for (int s = 0; s < range; s++) { int sumL = 0; for (int L = 0; L <= s; L++) { sumL += arr[L]; } int sumR = 0; for (int R = s + 1; R <= range; R++) { sumR += arr[R]; } ans[range] = Math.max(ans[range], Math.min(sumL, sumR)); } } return ans; } // 求原来的数组arr中,arr[L...R]的累加和 public static int sum(int[] sum, int L, int R) { return sum[R + 1] - sum[L]; } public static int[] bestSplit2(int[] arr) { if (arr == null || arr.length == 0) { return new int[0]; } int N = arr.length; int[] ans = new int[N]; ans[0] = 0; int[] sum = new int[N + 1]; for (int i = 0; i < N; i++) { sum[i + 1] = sum[i] + arr[i]; } for (int range = 1; range < N; range++) { for (int s = 0; s < range; s++) { int sumL = sum(sum, 0, s); int sumR = sum(sum, s + 1, range); ans[range] = Math.max(ans[range], Math.min(sumL, sumR)); } } return ans; } public static int[] bestSplit3(int[] arr) { if (arr == null || arr.length == 0) { return new int[0]; } int N = arr.length; int[] ans = new int[N]; ans[0] = 0; // arr = {5, 3, 1, 3} // 0 1 2 3 // sum ={0, 5, 8, 9, 12} // 0 1 2 3 4 // 0~2 -> sum[3] - sum[0] // 1~3 -> sum[4] - sum[1] int[] sum = new int[N + 1]; for (int i = 0; i < N; i++) { sum[i + 1] = sum[i] + arr[i]; } // 最优划分 // 0~range-1上,最优划分是左部分[0~best] 右部分[best+1~range-1] int best = 0; for (int range = 1; range < N; range++) { while (best + 1 < range) { int before = Math.min(sum(sum, 0, best), sum(sum, best + 1, range)); int after = Math.min(sum(sum, 0, best + 1), sum(sum, best + 2, range)); // 注意,一定要是>=,只是>会出错 // 课上会讲解 if (after >= before) { best++; } else { break; } } ans[range] = Math.min(sum(sum, 0, best), sum(sum, best + 1, range)); } return ans; } public static int[] randomArray(int len, int max) { int[] ans = new int[len]; for (int i = 0; i < len; i++) { ans[i] = (int) (Math.random() * max); } return ans; } public static boolean isSameArray(int[] arr1, int[] arr2) { if (arr1.length != arr2.length) { return false; } int N = arr1.length; for (int i = 0; i < N; i++) { if (arr1[i] != arr2[i]) { return false; } } return true; } public static void main(String[] args) { int N = 20; int max = 30; int testTime = 1000000; System.out.println("测试开始"); for (int i = 0; i < testTime; i++) { int len = (int) (Math.random() * N); int[] arr = randomArray(len, max); int[] ans1 = bestSplit1(arr); int[] ans2 = bestSplit2(arr); int[] ans3 = bestSplit3(arr); if (!isSameArray(ans1, ans2) || !isSameArray(ans1, ans3)) { System.out.println("Oops!"); } } System.out.println("测试结束"); } }