modify code

pull/6/head
左程云 5 years ago
parent f40d7ac336
commit a1ca6537e2

@ -76,7 +76,7 @@ public class Code03_StoneMerge {
int choose = -1;
for (int leftEnd = best[L][R - 1]; leftEnd <= best[L + 1][R]; leftEnd++) {
int cur = dp[L][leftEnd] + dp[leftEnd + 1][R];
if (cur < next) {
if (cur <= next) {
next = cur;
choose = leftEnd;
}
@ -100,7 +100,7 @@ public class Code03_StoneMerge {
int N = 15;
int maxValue = 100;
int testTime = 1000;
System.out.println("test begin");
System.out.println("测试开始");
for (int i = 0; i < testTime; i++) {
int len = (int) (Math.random() * N);
int[] arr = randomArray(len, maxValue);
@ -111,7 +111,7 @@ public class Code03_StoneMerge {
System.out.println("Oops!");
}
}
System.out.println("test end");
System.out.println("测试结束");
}
}

@ -97,8 +97,7 @@ public class Code04_SplitArrayLargestSum {
// 这里是<对数器和leetcode都能通过
// 这里面会让同学们感到困惑的点:
// 为啥==的时候,不移动,只有<的时候,才移动呢?例子懂了,但是道理何在?
// 这是因为你用最后一个画匠来做的可能性划分,而最后一个画匠对划分点往右移动敏感!
// 划分点往右滑动,会让最后一个画匠的可能性变少,所以划分点一定要贪到足够的好处,才能往右划
// 哈哈哈哈哈看了邮局选址问题你更懵请看42节
if (cur < ans) {
ans = cur;
bestChoose = leftEnd;
@ -170,7 +169,7 @@ public class Code04_SplitArrayLargestSum {
int N = 100;
int maxValue = 100;
int testTime = 10000;
System.out.println("test begin");
System.out.println("测试开始");
for (int i = 0; i < testTime; i++) {
int len = (int) (Math.random() * N) + 1;
int M = (int) (Math.random() * N) + 1;
@ -189,6 +188,6 @@ public class Code04_SplitArrayLargestSum {
break;
}
}
System.out.println("test end");
System.out.println("测试结束");
}
}

@ -0,0 +1,114 @@
package class42;
import java.util.Arrays;
public class Code01_PostOfficeProblem {
public static int min1(int[] arr, int num) {
if (arr == null || num < 1 || arr.length < num) {
return 0;
}
int N = arr.length;
int[][] w = new int[N + 1][N + 1];
for (int L = 0; L < N; L++) {
for (int R = L + 1; R < N; R++) {
w[L][R] = w[L][R - 1] + arr[R] - arr[(L + R) >> 1];
}
}
int[][] dp = new int[N][num + 1];
for (int i = 0; i < N; i++) {
dp[i][1] = w[0][i];
}
for (int i = 1; i < N; i++) {
for (int j = 2; j <= Math.min(i, num); j++) {
dp[i][j] = Integer.MAX_VALUE;
for (int k = 0; k <= i; k++) {
dp[i][j] = Math.min(dp[i][j], dp[k][j - 1] + w[k + 1][i]);
}
}
}
return dp[N - 1][num];
}
public static int min2(int[] arr, int num) {
if (arr == null || num < 1 || arr.length < num) {
return 0;
}
int N = arr.length;
int[][] w = new int[N + 1][N + 1];
for (int L = 0; L < N; L++) {
for (int R = L + 1; R < N; R++) {
w[L][R] = w[L][R - 1] + arr[R] - arr[(L + R) >> 1];
}
}
int[][] dp = new int[N][num + 1];
int[][] best = new int[N][num + 1];
for (int i = 0; i < N; i++) {
dp[i][1] = w[0][i];
best[i][1] = -1;
}
for (int j = 2; j <= num; j++) {
for (int i = N - 1; i >= j; i--) {
int down = best[i][j - 1];
int up = i == N - 1 ? N - 1 : best[i + 1][j];
int ans = Integer.MAX_VALUE;
int bestChoose = -1;
for (int leftEnd = down; leftEnd <= up; leftEnd++) {
int leftCost = leftEnd == -1 ? 0 : dp[leftEnd][j - 1];
int rightCost = leftEnd == i ? 0 : w[leftEnd + 1][i];
int cur = leftCost + rightCost;
if (cur <= ans) {
ans = cur;
bestChoose = leftEnd;
}
}
dp[i][j] = ans;
best[i][j] = bestChoose;
}
}
return dp[N - 1][num];
}
// for test
public static int[] randomSortedArray(int len, int range) {
int[] arr = new int[len];
for (int i = 0; i != len; i++) {
arr[i] = (int) (Math.random() * range);
}
Arrays.sort(arr);
return arr;
}
// for test
public static void printArray(int[] arr) {
for (int i = 0; i != arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
// for test
public static void main(String[] args) {
int N = 30;
int maxValue = 100;
int testTime = 10000;
System.out.println("测试开始");
for (int i = 0; i < testTime; i++) {
int len = (int) (Math.random() * N) + 1;
int[] arr = randomSortedArray(len, maxValue);
int num = (int) (Math.random() * N) + 1;
int ans1 = min1(arr, num);
int ans2 = min2(arr, num);
if (ans1 != ans2) {
printArray(arr);
System.out.println(num);
System.out.println(ans1);
System.out.println(ans2);
System.out.println("Oops!");
}
}
System.out.println("测试结束");
}
}

@ -1,215 +0,0 @@
package class42;
import java.util.Arrays;
public class Code02_PostOfficeProblem {
public static int minDis1(int[] arr, int num) {
if (arr == null || arr.length < 2 || num < 1) {
return 0;
}
// record[L][R]表示如果arr[L...R]上只建立一个邮局,总距离最小是多少?
int[][] record = getRecord(arr);
int N = arr.length;
int[][] dp = new int[N][num + 1];
// dp[...][0] 0个邮局的时候如何如何
// dp[0][...] 0
for (int i = 0; i < N; i++) {
// 0...i 1
dp[i][1] = record[0][i];
}
for (int i = 1; i < N; i++) {
for (int j = 2; j <= Math.min(num, i); j++) {
// dp[i][j]
// 枚举最后一个邮局负责的范围K...i
// i..i
// i-1..i
// i-2..i
// 1....i
// 0....i 单列
// 0...k-1 j-1个邮局 +
dp[i][j] = record[0][i];
for (int k = i; k > 0; k--) { // 1 .... i
dp[i][j] = Math.min(dp[i][j], dp[k - 1][j - 1] + record[k][i]);
}
}
}
return dp[N - 1][num];
}
public static int minDis2(int[] arr, int num) {
if (arr == null || arr.length < 2 || num < 1) {
return 0;
}
// record[L][R]表示如果arr[L...R]上只建立一个邮局,总距离最小是多少?
int[][] record = getRecord(arr);
int N = arr.length;
int[][] dp = new int[N][num + 1];
// dp[...][0]
// dp[0][...] 0..0 0
// choose[0][..] 0
// choose[i][j] 当时在求dp[i][j]的时候,
// 最右的邮局如果是在负责k...i这一段的时候取得的最优解请把choose[i][j] = k
int[][] choose = new int[N][num + 1];
for (int i = 0; i < N; i++) {
// 0..i 1个邮局 0...i 0
dp[i][1] = record[0][i];
}
for (int i = 1; i < N; i++) {
for (int j = Math.min(num, i); j >= 2; j--) {
int down = choose[i - 1][j];
int up = j == Math.min(num, i) ? i : choose[i][j + 1];
dp[i][j] = record[0][i];
for (int k = Math.max(1, down); k <= Math.min(up, i); k++) {
if (dp[k - 1][j - 1] + record[k][i] < dp[i][j]) {
dp[i][j] = dp[k - 1][j - 1] + record[k][i];
choose[i][j] = k;
}
}
}
}
return dp[N - 1][num];
}
public static int[][] getRecord(int[] arr) {
int N = arr.length;
int[][] record = new int[N][N];
for (int L = 0; L < N; L++) {
for (int R = L + 1; R < N; R++) {
record[L][R] = record[L][R - 1] + arr[R] - arr[(L + R) >> 1];
}
}
return record;
}
public static int minDistances1(int[] arr, int num) {
if (arr == null || num < 1 || arr.length < num) {
return 0;
}
int[][] w = new int[arr.length + 1][arr.length + 1];
for (int i = 0; i < arr.length; i++) {
for (int j = i + 1; j < arr.length; j++) {
w[i][j] = w[i][j - 1] + arr[j] - arr[(i + j) / 2];
}
}
int[][] dp = new int[num][arr.length];
for (int j = 0; j != arr.length; j++) {
dp[0][j] = w[0][j];
}
for (int i = 1; i < num; i++) {
for (int j = i + 1; j < arr.length; j++) {
dp[i][j] = Integer.MAX_VALUE;
for (int k = 0; k <= j; k++) {
dp[i][j] = Math.min(dp[i][j], dp[i - 1][k] + w[k + 1][j]);
}
}
}
return dp[num - 1][arr.length - 1];
}
public static int minDistances2(int[] arr, int num) {
if (arr == null || num < 1 || arr.length < num) {
return 0;
}
int[][] w = new int[arr.length + 1][arr.length + 1];
for (int i = 0; i < arr.length; i++) {
for (int j = i + 1; j < arr.length; j++) {
w[i][j] = w[i][j - 1] + arr[j] - arr[(i + j) / 2];
}
}
int[][] dp = new int[num][arr.length];
int[][] s = new int[num][arr.length];
for (int j = 0; j != arr.length; j++) {
dp[0][j] = w[0][j];
s[0][j] = 0;
}
int minK = 0;
int maxK = 0;
int cur = 0;
for (int i = 1; i < num; i++) {
for (int j = arr.length - 1; j > i; j--) {
minK = s[i - 1][j];
maxK = j == arr.length - 1 ? arr.length - 1 : s[i][j + 1];
dp[i][j] = Integer.MAX_VALUE;
for (int k = minK; k <= maxK; k++) {
cur = dp[i - 1][k] + w[k + 1][j];
if (cur <= dp[i][j]) {
dp[i][j] = cur;
s[i][j] = k;
}
}
}
}
return dp[num - 1][arr.length - 1];
}
// for test
public static int[] getSortedArray(int len, int range) {
int[] arr = new int[len];
for (int i = 0; i != len; i++) {
arr[i] = (int) (Math.random() * range);
}
Arrays.sort(arr);
return arr;
}
// for test
public static void printArray(int[] arr) {
for (int i = 0; i != arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
// for test
public static void main(String[] args) {
int[] arr = { 1,3,8,10,12 };
int num = 3;
System.out.println(minDis1(arr, num));
System.out.println(minDistances1(arr, num));
System.out.println(minDistances2(arr, num));
int times = 100; // test time
int len = 1000; // test array length
int range = 2000; // every number in [0,range)
int p = 50; // post office number max
long time1 = 0; // method1 all run time
long time2 = 0;// method2 all run time
long time3 = 0;
long start = 0;
long end = 0;
int res1 = 0;
int res2 = 0;
int res3 = 0;
for (int i = 0; i != times; i++) {
int office = (int) (Math.random() * p) + 1;
arr = getSortedArray(len, range);
start = System.currentTimeMillis();
res1 = minDistances1(arr, office);
end = System.currentTimeMillis();
time1 += end - start;
start = System.currentTimeMillis();
res2 = minDis2(arr, office);
end = System.currentTimeMillis();
time2 += end - start;
start = System.currentTimeMillis();
res3 = minDis1(arr, office);
end = System.currentTimeMillis();
time3 += end - start;
if (res1 != res2 || res1 != res3) {
printArray(arr);
break;
}
if (i % 10 == 0) {
System.out.print(". ");
}
}
System.out.println();
System.out.println("method1 all run time(ms): " + time1);
System.out.println("method2 all run time(ms): " + time2);
System.out.println("method3 all run time(ms): " + time3);
}
}

@ -1,8 +1,12 @@
package class42;
public class Code01_ThrowChessPiecesProblem {
// leetcode测试链接https://leetcode.com/problems/super-egg-drop
// 方法1和方法2会超时
// 方法3勉强通过
// 方法4打败100%
public class Code02_ThrowChessPiecesProblem {
public static int solution1(int nLevel, int kChess) {
public static int superEggDrop1(int kChess, int nLevel) {
if (nLevel < 1 || kChess < 1) {
return 0;
}
@ -22,13 +26,12 @@ public class Code01_ThrowChessPiecesProblem {
}
int min = Integer.MAX_VALUE;
for (int i = 1; i != rest + 1; i++) { // 第一次扔的时候仍在了i层
min = Math.min(min,
Math.max(Process1(i - 1, k - 1), Process1(rest - i, k)));
min = Math.min(min, Math.max(Process1(i - 1, k - 1), Process1(rest - i, k)));
}
return min + 1;
}
public static int solution2(int nLevel, int kChess) {
public static int superEggDrop2(int kChess, int nLevel) {
if (nLevel < 1 || kChess < 1) {
return 0;
}
@ -51,34 +54,7 @@ public class Code01_ThrowChessPiecesProblem {
return dp[nLevel][kChess];
}
public static int solution3(int nLevel, int kChess) {
if (nLevel < 1 || kChess < 1) {
return 0;
}
if (kChess == 1) {
return nLevel;
}
int[] preArr = new int[nLevel + 1];
int[] curArr = new int[nLevel + 1];
for (int i = 1; i != curArr.length; i++) {
curArr[i] = i;
}
for (int i = 1; i != kChess; i++) {
int[] tmp = preArr;
preArr = curArr;
curArr = tmp;
for (int j = 1; j != curArr.length; j++) {
int min = Integer.MAX_VALUE;
for (int k = 1; k != j + 1; k++) {
min = Math.min(min, Math.max(preArr[k - 1], curArr[j - k]));
}
curArr[j] = min + 1;
}
}
return curArr[curArr.length - 1];
}
public static int solution4(int nLevel, int kChess) {
public static int superEggDrop3(int kChess, int nLevel) {
if (nLevel < 1 || kChess < 1) {
return 0;
}
@ -112,7 +88,7 @@ public class Code01_ThrowChessPiecesProblem {
return dp[nLevel][kChess];
}
public static int solution5(int nLevel, int kChess) {
public static int superEggDrop4(int kChess, int nLevel) {
if (nLevel < 1 || kChess < 1) {
return 0;
}
@ -146,49 +122,21 @@ public class Code01_ThrowChessPiecesProblem {
}
public static void main(String[] args) {
System.out.println(solution1(21, 2));
System.out.println(solution2(21, 2));
System.out.println(solution3(21, 2));
System.out.println(solution4(21, 2));
System.out.println(solution5(21, 2));
System.out.println("==============");
System.out.println(solution2(105, 2));
System.out.println(solution3(105, 2));
System.out.println(solution4(105, 2));
System.out.println(solution5(105, 2));
System.out.println("==============");
System.out.println(solution2(3000, 10));
System.out.println(solution3(3000, 10));
System.out.println(solution4(3000, 10));
System.out.println(solution5(3000, 10));
System.out.println("==============");
System.out.println(solution2(6884, 5));
System.out.println(solution3(6884, 5));
System.out.println(solution4(6884, 5));
System.out.println(solution5(6884, 5));
System.out.println("==============");
System.out.println(solution2(6885, 5));
System.out.println(solution3(6885, 5));
System.out.println(solution4(6885, 5));
System.out.println(solution5(6885, 5));
System.out.println("==============");
int nLevel = 100000000;
int kChess = 10;
long start = System.currentTimeMillis();
System.out.println(solution5(nLevel, kChess));
long end = System.currentTimeMillis();
System.out.println("cost time: " + (end - start) + " ms");
int maxN = 500;
int maxK = 30;
int testTime = 1000;
System.out.println("测试开始");
for (int i = 0; i < testTime; i++) {
int N = (int)(Math.random() * maxN) + 1;
int K = (int)(Math.random() * maxK) + 1;
int ans2 = superEggDrop2(K, N);
int ans3 = superEggDrop3(K, N);
int ans4 = superEggDrop4(K, N);
if(ans2 != ans3 || ans2 != ans4) {
System.out.println("Oops!");
}
}
System.out.println("测试结束");
}
}
Loading…
Cancel
Save