You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
3.1 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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("测试结束");
}
}