From a1ca6537e25baec40d9f02e8a8ae058f3d25950a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B7=A6=E7=A8=8B=E4=BA=91?= Date: Wed, 24 Mar 2021 14:59:02 +0800 Subject: [PATCH] modify code --- src/class41/Code03_StoneMerge.java | 6 +- src/class41/Code04_SplitArrayLargestSum.java | 7 +- src/class42/Code01_PostOfficeProblem.java | 114 ++++++++++ src/class42/Code02_PostOfficeProblem.java | 215 ------------------ ...va => Code02_ThrowChessPiecesProblem.java} | 102 ++------- 5 files changed, 145 insertions(+), 299 deletions(-) create mode 100644 src/class42/Code01_PostOfficeProblem.java delete mode 100644 src/class42/Code02_PostOfficeProblem.java rename src/class42/{Code01_ThrowChessPiecesProblem.java => Code02_ThrowChessPiecesProblem.java} (50%) diff --git a/src/class41/Code03_StoneMerge.java b/src/class41/Code03_StoneMerge.java index d6e48b8..793d7d2 100644 --- a/src/class41/Code03_StoneMerge.java +++ b/src/class41/Code03_StoneMerge.java @@ -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("测试结束"); } } diff --git a/src/class41/Code04_SplitArrayLargestSum.java b/src/class41/Code04_SplitArrayLargestSum.java index 4b8af62..8d644e6 100644 --- a/src/class41/Code04_SplitArrayLargestSum.java +++ b/src/class41/Code04_SplitArrayLargestSum.java @@ -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("测试结束"); } } diff --git a/src/class42/Code01_PostOfficeProblem.java b/src/class42/Code01_PostOfficeProblem.java new file mode 100644 index 0000000..c5a120a --- /dev/null +++ b/src/class42/Code01_PostOfficeProblem.java @@ -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("测试结束"); + + } + +} diff --git a/src/class42/Code02_PostOfficeProblem.java b/src/class42/Code02_PostOfficeProblem.java deleted file mode 100644 index 8f91c03..0000000 --- a/src/class42/Code02_PostOfficeProblem.java +++ /dev/null @@ -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); - - } - -} diff --git a/src/class42/Code01_ThrowChessPiecesProblem.java b/src/class42/Code02_ThrowChessPiecesProblem.java similarity index 50% rename from src/class42/Code01_ThrowChessPiecesProblem.java rename to src/class42/Code02_ThrowChessPiecesProblem.java index 2aa44ff..d60411c 100644 --- a/src/class42/Code01_ThrowChessPiecesProblem.java +++ b/src/class42/Code02_ThrowChessPiecesProblem.java @@ -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("测试结束"); } }