From 78e5dc4d7c9bd8b98ce307c7358d8d291e979616 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B7=A6=E7=A8=8B=E4=BA=91?= Date: Wed, 20 Jan 2021 13:37:46 +0800 Subject: [PATCH] modify code --- src/class23/Code01_SplitSumClosed.java | 38 ++--- .../Code02_SplitSumClosedSizeHalf.java | 146 ++++++++++++++---- src/class23/Code03_NQueens.java | 27 ++-- 3 files changed, 147 insertions(+), 64 deletions(-) diff --git a/src/class23/Code01_SplitSumClosed.java b/src/class23/Code01_SplitSumClosed.java index 7a95f0e..6f82c49 100644 --- a/src/class23/Code01_SplitSumClosed.java +++ b/src/class23/Code01_SplitSumClosed.java @@ -10,14 +10,17 @@ public class Code01_SplitSumClosed { for (int num : arr) { sum += num; } - return process(arr, 0, sum >> 1); + return process(arr, 0, sum / 2); } + // arr[i...]可以自由选择,请返回累加和尽量接近rest,但不能超过rest的情况下,最接近的累加和是多少? public static int process(int[] arr, int i, int rest) { if (i == arr.length) { return 0; - } else { + } else { // 还有数,arr[i]这个数 + // 可能性1,不使用arr[i] int p1 = process(arr, i + 1, rest); + // 可能性2,要使用arr[i] int p2 = 0; if (arr[i] <= rest) { p2 = arr[i] + process(arr, i + 1, rest - arr[i]); @@ -34,29 +37,22 @@ public class Code01_SplitSumClosed { for (int num : arr) { sum += num; } - sum >>= 1; + sum /= 2; int N = arr.length; - boolean[][] dp = new boolean[N][sum + 1]; - for (int i = 0; i < N; i++) { - dp[i][0] = true; - } - if (arr[0] <= sum) { - dp[0][arr[0]] = true; - } - for (int i = 1; i < N; i++) { - for (int j = 1; j <= sum; j++) { - dp[i][j] = dp[i - 1][j]; - if (j - arr[i] >= 0) { - dp[i][j] |= dp[i - 1][j - arr[i]]; + int[][] dp = new int[N + 1][sum + 1]; + for (int i = N - 1; i >= 0; i--) { + for (int rest = 0; rest <= sum; rest++) { + // 可能性1,不使用arr[i] + int p1 = dp[i + 1][rest]; + // 可能性2,要使用arr[i] + int p2 = 0; + if (arr[i] <= rest) { + p2 = arr[i] + dp[i + 1][rest - arr[i]]; } + dp[i][rest] = Math.max(p1, p2); } } - for (int j = sum; j >= 1; j--) { - if (dp[N - 1][j]) { - return j; - } - } - return 0; + return dp[0][sum]; } public static int[] randomArray(int len, int value) { diff --git a/src/class23/Code02_SplitSumClosedSizeHalf.java b/src/class23/Code02_SplitSumClosedSizeHalf.java index d87f0d6..0da40fb 100644 --- a/src/class23/Code02_SplitSumClosedSizeHalf.java +++ b/src/class23/Code02_SplitSumClosedSizeHalf.java @@ -10,30 +10,33 @@ public class Code02_SplitSumClosedSizeHalf { for (int num : arr) { sum += num; } - return process(arr, 0, 0, sum >> 1); + if ((arr.length & 1) == 0) { + return process(arr, 0, arr.length / 2, sum / 2); + } else { + return Math.max(process(arr, 0, arr.length / 2, sum / 2), process(arr, 0, arr.length / 2 + 1, sum / 2)); + } } + // arr[i....]自由选择,挑选的个数一定要是picks个,累加和<=rest, 离rest最近的返回 public static int process(int[] arr, int i, int picks, int rest) { if (i == arr.length) { - if ((arr.length & 1) == 0) { - return picks == (arr.length >> 1) ? 0 : -1; - } else { - return (picks == (arr.length >> 1) || picks == (arr.length >> 1) + 1) ? 0 : -1; + return picks == 0 ? 0 : -1; + } else { + int p1 = process(arr, i + 1, picks, rest); + // 就是要使用arr[i]这个数 + int p2 = -1; + int next = -1; + if (arr[i] <= rest) { + next = process(arr, i + 1, picks - 1, rest - arr[i]); } + if (next != -1) { + p2 = arr[i] + next; + } + return Math.max(p1, p2); } - int p1 = process(arr, i + 1, picks, rest); - int p2 = -1; - int next2 = -1; - if (arr[i] <= rest) { - next2 = process(arr, i + 1, picks + 1, rest - arr[i]); - } - if (next2 != -1) { - p2 = arr[i] + next2; - } - return Math.max(p1, p2); } - public static int dp1(int[] arr) { + public static int dp(int[] arr) { if (arr == null || arr.length < 2) { return 0; } @@ -41,9 +44,9 @@ public class Code02_SplitSumClosedSizeHalf { for (int num : arr) { sum += num; } - sum >>= 1; + sum /= 2; int N = arr.length; - int M = (arr.length + 1) >> 1; + int M = (N + 1) / 2; int[][][] dp = new int[N + 1][M + 1][sum + 1]; for (int i = 0; i <= N; i++) { for (int j = 0; j <= M; j++) { @@ -52,33 +55,110 @@ public class Code02_SplitSumClosedSizeHalf { } } } - for (int k = 0; k <= sum; k++) { - dp[N][M][k] = 0; - } - if ((arr.length & 1) != 0) { - for (int k = 0; k <= sum; k++) { - dp[N][M - 1][k] = 0; - } + for (int rest = 0; rest <= sum; rest++) { + dp[N][0][rest] = 0; } for (int i = N - 1; i >= 0; i--) { for (int picks = 0; picks <= M; picks++) { for (int rest = 0; rest <= sum; rest++) { int p1 = dp[i + 1][picks][rest]; + // 就是要使用arr[i]这个数 int p2 = -1; - int next2 = -1; - if (picks + 1 <= M && arr[i] <= rest) { - next2 = dp[i + 1][picks + 1][rest - arr[i]]; + int next = -1; + if (picks - 1 >= 0 && arr[i] <= rest) { + next = dp[i + 1][picks - 1][rest - arr[i]]; } - if (next2 != -1) { - p2 = arr[i] + next2; + if (next != -1) { + p2 = arr[i] + next; } dp[i][picks][rest] = Math.max(p1, p2); } } } - return dp[0][0][sum]; + if ((arr.length & 1) == 0) { + return dp[0][arr.length / 2][sum]; + } else { + return Math.max(dp[0][arr.length / 2][sum], dp[0][(arr.length / 2) + 1][sum]); + } } +// public static int right(int[] arr) { +// if (arr == null || arr.length < 2) { +// return 0; +// } +// int sum = 0; +// for (int num : arr) { +// sum += num; +// } +// return process(arr, 0, 0, sum >> 1); +// } +// +// public static int process(int[] arr, int i, int picks, int rest) { +// if (i == arr.length) { +// if ((arr.length & 1) == 0) { +// return picks == (arr.length >> 1) ? 0 : -1; +// } else { +// return (picks == (arr.length >> 1) || picks == (arr.length >> 1) + 1) ? 0 : -1; +// } +// } +// int p1 = process(arr, i + 1, picks, rest); +// int p2 = -1; +// int next2 = -1; +// if (arr[i] <= rest) { +// next2 = process(arr, i + 1, picks + 1, rest - arr[i]); +// } +// if (next2 != -1) { +// p2 = arr[i] + next2; +// } +// return Math.max(p1, p2); +// } +// +// public static int dp1(int[] arr) { +// if (arr == null || arr.length < 2) { +// return 0; +// } +// int sum = 0; +// for (int num : arr) { +// sum += num; +// } +// sum >>= 1; +// int N = arr.length; +// int M = (arr.length + 1) >> 1; +// int[][][] dp = new int[N + 1][M + 1][sum + 1]; +// for (int i = 0; i <= N; i++) { +// for (int j = 0; j <= M; j++) { +// for (int k = 0; k <= sum; k++) { +// dp[i][j][k] = -1; +// } +// } +// } +// for (int k = 0; k <= sum; k++) { +// dp[N][M][k] = 0; +// } +// if ((arr.length & 1) != 0) { +// for (int k = 0; k <= sum; k++) { +// dp[N][M - 1][k] = 0; +// } +// } +// for (int i = N - 1; i >= 0; i--) { +// for (int picks = 0; picks <= M; picks++) { +// for (int rest = 0; rest <= sum; rest++) { +// int p1 = dp[i + 1][picks][rest]; +// int p2 = -1; +// int next2 = -1; +// if (picks + 1 <= M && arr[i] <= rest) { +// next2 = dp[i + 1][picks + 1][rest - arr[i]]; +// } +// if (next2 != -1) { +// p2 = arr[i] + next2; +// } +// dp[i][picks][rest] = Math.max(p1, p2); +// } +// } +// } +// return dp[0][0][sum]; +// } + public static int dp2(int[] arr) { if (arr == null || arr.length < 2) { return 0; @@ -138,7 +218,7 @@ public class Code02_SplitSumClosedSizeHalf { // for test public static void main(String[] args) { - int maxLen = 20; + int maxLen = 10; int maxValue = 50; int testTime = 10000; System.out.println("测试开始"); @@ -146,7 +226,7 @@ public class Code02_SplitSumClosedSizeHalf { int len = (int) (Math.random() * maxLen); int[] arr = randomArray(len, maxValue); int ans1 = right(arr); - int ans2 = dp1(arr); + int ans2 = dp(arr); int ans3 = dp2(arr); if (ans1 != ans2 || ans1 != ans3) { printArray(arr); diff --git a/src/class23/Code03_NQueens.java b/src/class23/Code03_NQueens.java index b3dbbb7..a9e454a 100644 --- a/src/class23/Code03_NQueens.java +++ b/src/class23/Code03_NQueens.java @@ -10,11 +10,17 @@ public class Code03_NQueens { return process1(0, record, n); } + // 当前来到i行,一共是0~N-1行 + // 在i行上放皇后,所有列都尝试 + // 必须要保证跟之前所有的皇后不打架 + // int[] record record[x] = y 之前的第x行的皇后,放在了y列上 + // 返回:不关心i以上发生了什么,i.... 后续有多少合法的方法数 public static int process1(int i, int[] record, int n) { if (i == n) { return 1; } int res = 0; + // i行的皇后,放哪一列呢?j列, for (int j = 0; j < n; j++) { if (isValid(record, i, j)) { record[i] = j; @@ -25,6 +31,7 @@ public class Code03_NQueens { } public static boolean isValid(int[] record, int i, int j) { + // 0..i-1 for (int k = 0; k < i; k++) { if (j == record[k] || Math.abs(record[k] - j) == Math.abs(i - k)) { return false; @@ -43,30 +50,30 @@ public class Code03_NQueens { return process2(limit, 0, 0, 0); } - public static int process2( - int limit, - int colLim, - int leftDiaLim, - int rightDiaLim) { + // 7皇后问题 + // limit : 0....0 1 1 1 1 1 1 1 + // 之前皇后的列影响:colLim + // 之前皇后的左下对角线影响:leftDiaLim + // 之前皇后的右下对角线影响:rightDiaLim + public static int process2(int limit, int colLim, int leftDiaLim, int rightDiaLim) { if (colLim == limit) { return 1; } - int pos = limit & ( ~(colLim | leftDiaLim | rightDiaLim) ); + // pos中所有是1的位置,是你可以去尝试皇后的位置 + int pos = limit & (~(colLim | leftDiaLim | rightDiaLim)); int mostRightOne = 0; int res = 0; while (pos != 0) { mostRightOne = pos & (~pos + 1); pos = pos - mostRightOne; - res += process2(limit, - colLim | mostRightOne, - (leftDiaLim | mostRightOne) << 1, + res += process2(limit, colLim | mostRightOne, (leftDiaLim | mostRightOne) << 1, (rightDiaLim | mostRightOne) >>> 1); } return res; } public static void main(String[] args) { - int n = 14; + int n = 15; long start = System.currentTimeMillis(); System.out.println(num2(n));