From eb6b907cc7157f41788456768706a4db4689e184 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B7=A6=E7=A8=8B=E4=BA=91?= Date: Mon, 18 Jan 2021 16:09:10 +0800 Subject: [PATCH 1/5] add class 24 & 25 --- src/class24/Code01_SlidingWindowMaxArray.java | 103 ++++++++++++ src/class24/Code02_AllLessNumSubArray.java | 85 ++++++++++ src/class24/Code03_GasStation.java | 53 ++++++ .../Code04_MinCoinsOnePaper.java | 2 +- src/class25/Code01_MonotonousStack.java | 158 ++++++++++++++++++ src/class25/Code02_AllTimesMinToMax.java | 67 ++++++++ src/class25/Code03_SumOfSubarrayMinimums.java | 153 +++++++++++++++++ .../Code04_LargestRectangleInHistogram.java | 58 +++++++ 8 files changed, 678 insertions(+), 1 deletion(-) create mode 100644 src/class24/Code01_SlidingWindowMaxArray.java create mode 100644 src/class24/Code02_AllLessNumSubArray.java create mode 100644 src/class24/Code03_GasStation.java rename src/{class23 => class24}/Code04_MinCoinsOnePaper.java (99%) create mode 100644 src/class25/Code01_MonotonousStack.java create mode 100644 src/class25/Code02_AllTimesMinToMax.java create mode 100644 src/class25/Code03_SumOfSubarrayMinimums.java create mode 100644 src/class25/Code04_LargestRectangleInHistogram.java diff --git a/src/class24/Code01_SlidingWindowMaxArray.java b/src/class24/Code01_SlidingWindowMaxArray.java new file mode 100644 index 0000000..23671dc --- /dev/null +++ b/src/class24/Code01_SlidingWindowMaxArray.java @@ -0,0 +1,103 @@ +package class24; + +import java.util.LinkedList; + +public class Code01_SlidingWindowMaxArray { + + public static int[] getMaxWindow(int[] arr, int w) { + if (arr == null || w < 1 || arr.length < w) { + return null; + } + // 其中放的是位置,头代表 (大->小)尾 + LinkedList qmax = new LinkedList(); + int[] res = new int[arr.length - w + 1]; + int index = 0; + // L...R + // i + for (int R = 0; R < arr.length; R++) { // 当前让 i -> [i] 进窗口 , i 就是 r + // R -> 值 可以放在比他大的数后,或者空 + while (!qmax.isEmpty() && arr[qmax.peekLast()] <= arr[R]) { + qmax.pollLast(); + } + qmax.addLast(R); + // 数进来了 + // 如果窗口没有形成W的长度之前,不弹出数字的 + if (qmax.peekFirst() == R - w) { + qmax.pollFirst(); + } + // 以上窗口更新做完了 + if (R >= w - 1) { + res[index++] = arr[qmax.peekFirst()]; + } + } + return res; + } + + // for test + public static int[] rightWay(int[] arr, int w) { + if (arr == null || w < 1 || arr.length < w) { + return null; + } + int[] res = new int[arr.length - w + 1]; + int index = 0; + int L = 0; + int R = w - 1; + while (R < arr.length) { + int max = arr[L]; + for (int i = L + 1; i <= R; i++) { + max = Math.max(max, arr[i]); + + } + res[index++] = max; + L++; + R++; + } + return res; + } + + // for test + public static int[] generateRandomArray(int maxSize, int maxValue) { + int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; + for (int i = 0; i < arr.length; i++) { + arr[i] = (int) (Math.random() * (maxValue + 1)); + } + return arr; + } + + // for test + public static boolean isEqual(int[] arr1, int[] arr2) { + if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) { + return false; + } + if (arr1 == null && arr2 == null) { + return true; + } + if (arr1.length != arr2.length) { + return false; + } + for (int i = 0; i < arr1.length; i++) { + if (arr1[i] != arr2[i]) { + return false; + } + } + return true; + } + + public static void main(String[] args) { + int testTime = 100000; + int maxSize = 100; + int maxValue = 100; + System.out.println("test begin"); + for (int i = 0; i < testTime; i++) { + int[] arr = generateRandomArray(maxSize, maxValue); + int w = (int) (Math.random() * (arr.length + 1)); + int[] ans1 = getMaxWindow(arr, w); + int[] ans2 = rightWay(arr, w); + if (!isEqual(ans1, ans2)) { + System.out.println("Oops!"); + } + } + System.out.println("test finish"); + } + +} diff --git a/src/class24/Code02_AllLessNumSubArray.java b/src/class24/Code02_AllLessNumSubArray.java new file mode 100644 index 0000000..40f6107 --- /dev/null +++ b/src/class24/Code02_AllLessNumSubArray.java @@ -0,0 +1,85 @@ +package class24; + +import java.util.LinkedList; + +public class Code02_AllLessNumSubArray { + + public static int getNum(int[] arr, int num) { + if (arr == null || arr.length == 0) { + return 0; + } + LinkedList qmin = new LinkedList(); + LinkedList qmax = new LinkedList(); + int L = 0; + int R = 0; + // [L..R) -> [0,0) 窗口内无数 [1,1) + // [0,1) -> [0~0] + int res = 0; + while (L < arr.length) { // L是开头位置,尝试每一个开头 + + // 如果此时窗口的开头是L,下面的while工作:R向右扩到违规为止 + + while (R < arr.length) { // R是最后一个达标位置的再下一个 + while (!qmin.isEmpty() && arr[qmin.peekLast()] >= arr[R]) { + qmin.pollLast(); + } + qmin.addLast(R); + // R -> arr[R], + while (!qmax.isEmpty() && arr[qmax.peekLast()] <= arr[R]) { + qmax.pollLast(); + } + qmax.addLast(R); + + if (arr[qmax.getFirst()] - arr[qmin.getFirst()] > num) { + break; + } + R++; + } + + // R是最后一个达标位置的再下一个,第一个违规的位置 + res += R - L; + + if (qmin.peekFirst() == L) { + qmin.pollFirst(); + } + if (qmax.peekFirst() == L) { + qmax.pollFirst(); + } + + L++; + + } + return res; + } + + // for test + public static int[] getRandomArray(int len) { + if (len < 0) { + return null; + } + int[] arr = new int[len]; + for (int i = 0; i < len; i++) { + arr[i] = (int) (Math.random() * 10); + } + return arr; + } + + // for test + public static void printArray(int[] arr) { + if (arr != null) { + for (int i = 0; i < arr.length; i++) { + System.out.print(arr[i] + " "); + } + System.out.println(); + } + } + + public static void main(String[] args) { + int[] arr = getRandomArray(30); + int num = 5; + printArray(arr); + System.out.println(getNum(arr, num)); + + } + +} diff --git a/src/class24/Code03_GasStation.java b/src/class24/Code03_GasStation.java new file mode 100644 index 0000000..b80906f --- /dev/null +++ b/src/class24/Code03_GasStation.java @@ -0,0 +1,53 @@ +package class24; + +import java.util.LinkedList; + +// 测试链接:https://leetcode.com/problems/gas-station +public class Code03_GasStation { + + // 这个方法的时间复杂度O(N),额外空间复杂度O(N) + public static int canCompleteCircuit(int[] gas, int[] cost) { + boolean[] good = goodArray(gas, cost); + for (int i = 0; i < gas.length; i++) { + if (good[i]) { + return i; + } + } + return -1; + } + + public static boolean[] goodArray(int[] g, int[] c) { + int N = g.length; + int M = N << 1; + int[] arr = new int[M]; + for (int i = 0; i < N; i++) { + arr[i] = g[i] - c[i]; + arr[i + N] = g[i] - c[i]; + } + for (int i = 1; i < M; i++) { + arr[i] += arr[i - 1]; + } + LinkedList w = new LinkedList<>(); + for (int i = 0; i < N; i++) { + while (!w.isEmpty() && arr[w.peekLast()] >= arr[i]) { + w.pollLast(); + } + w.addLast(i); + } + boolean[] ans = new boolean[N]; + for (int offset = 0, i = 0, j = N; j < M; offset = arr[i++], j++) { + if (arr[w.peekFirst()] - offset >= 0) { + ans[i] = true; + } + if (w.peekFirst() == i) { + w.pollFirst(); + } + while (!w.isEmpty() && arr[w.peekLast()] >= arr[j]) { + w.pollLast(); + } + w.addLast(j); + } + return ans; + } + +} diff --git a/src/class23/Code04_MinCoinsOnePaper.java b/src/class24/Code04_MinCoinsOnePaper.java similarity index 99% rename from src/class23/Code04_MinCoinsOnePaper.java rename to src/class24/Code04_MinCoinsOnePaper.java index bf48243..a0a73b8 100644 --- a/src/class23/Code04_MinCoinsOnePaper.java +++ b/src/class24/Code04_MinCoinsOnePaper.java @@ -1,4 +1,4 @@ -package class23; +package class24; import java.util.HashMap; import java.util.Map.Entry; diff --git a/src/class25/Code01_MonotonousStack.java b/src/class25/Code01_MonotonousStack.java new file mode 100644 index 0000000..c9bb357 --- /dev/null +++ b/src/class25/Code01_MonotonousStack.java @@ -0,0 +1,158 @@ +package class25; + +import java.util.List; +import java.util.ArrayList; +import java.util.Stack; + +public class Code01_MonotonousStack { + + public static int[][] getNearLessNoRepeat(int[] arr) { + int[][] res = new int[arr.length][2]; + Stack stack = new Stack<>(); + for (int i = 0; i < arr.length; i++) { + while (!stack.isEmpty() && arr[stack.peek()] > arr[i]) { + int popIndex = stack.pop(); + int leftLessIndex = stack.isEmpty() ? -1 : stack.peek(); + res[popIndex][0] = leftLessIndex; + res[popIndex][1] = i; + } + stack.push(i); + } + while (!stack.isEmpty()) { + int popIndex = stack.pop(); + int leftLessIndex = stack.isEmpty() ? -1 : stack.peek(); + res[popIndex][0] = leftLessIndex; + res[popIndex][1] = -1; + } + return res; + } + + public static int[][] getNearLess(int[] arr) { + int[][] res = new int[arr.length][2]; + Stack> stack = new Stack<>(); + for (int i = 0; i < arr.length; i++) { // i -> arr[i] 进栈 + // 底 -> 顶, 小 -> 大 + while (!stack.isEmpty() && arr[stack.peek().get(0)] > arr[i]) { + List popIs = stack.pop(); + // 取位于下面位置的列表中,最晚加入的那个 + int leftLessIndex = stack.isEmpty() ? -1 : stack.peek().get(stack.peek().size() - 1); + for (Integer popi : popIs) { + res[popi][0] = leftLessIndex; + res[popi][1] = i; + } + } + // 相等的、比你小的 + if (!stack.isEmpty() && arr[stack.peek().get(0)] == arr[i]) { + stack.peek().add(Integer.valueOf(i)); + } else { + ArrayList list = new ArrayList<>(); + list.add(i); + stack.push(list); + } + } + while (!stack.isEmpty()) { + List popIs = stack.pop(); + // 取位于下面位置的列表中,最晚加入的那个 + int leftLessIndex = stack.isEmpty() ? -1 : stack.peek().get(stack.peek().size() - 1); + for (Integer popi : popIs) { + res[popi][0] = leftLessIndex; + res[popi][1] = -1; + } + } + return res; + } + + // for test + public static int[] getRandomArrayNoRepeat(int size) { + int[] arr = new int[(int) (Math.random() * size) + 1]; + for (int i = 0; i < arr.length; i++) { + arr[i] = i; + } + for (int i = 0; i < arr.length; i++) { + int swapIndex = (int) (Math.random() * arr.length); + int tmp = arr[swapIndex]; + arr[swapIndex] = arr[i]; + arr[i] = tmp; + } + return arr; + } + + // for test + public static int[] getRandomArray(int size, int max) { + int[] arr = new int[(int) (Math.random() * size) + 1]; + for (int i = 0; i < arr.length; i++) { + arr[i] = (int) (Math.random() * max) - (int) (Math.random() * max); + } + return arr; + } + + // for test + public static int[][] rightWay(int[] arr) { + int[][] res = new int[arr.length][2]; + for (int i = 0; i < arr.length; i++) { + int leftLessIndex = -1; + int rightLessIndex = -1; + int cur = i - 1; + while (cur >= 0) { + if (arr[cur] < arr[i]) { + leftLessIndex = cur; + break; + } + cur--; + } + cur = i + 1; + while (cur < arr.length) { + if (arr[cur] < arr[i]) { + rightLessIndex = cur; + break; + } + cur++; + } + res[i][0] = leftLessIndex; + res[i][1] = rightLessIndex; + } + return res; + } + + // for test + public static boolean isEqual(int[][] res1, int[][] res2) { + if (res1.length != res2.length) { + return false; + } + for (int i = 0; i < res1.length; i++) { + if (res1[i][0] != res2[i][0] || res1[i][1] != res2[i][1]) { + return false; + } + } + + return true; + } + + // for test + public static void printArray(int[] arr) { + for (int i = 0; i < arr.length; i++) { + System.out.print(arr[i] + " "); + } + System.out.println(); + } + + public static void main(String[] args) { + int size = 10; + int max = 20; + int testTimes = 2000000; + for (int i = 0; i < testTimes; i++) { + int[] arr1 = getRandomArrayNoRepeat(size); + int[] arr2 = getRandomArray(size, max); + if (!isEqual(getNearLessNoRepeat(arr1), rightWay(arr1))) { + System.out.println("Oops!"); + printArray(arr1); + break; + } + if (!isEqual(getNearLess(arr2), rightWay(arr2))) { + System.out.println("Oops!"); + printArray(arr2); + break; + } + } + } +} diff --git a/src/class25/Code02_AllTimesMinToMax.java b/src/class25/Code02_AllTimesMinToMax.java new file mode 100644 index 0000000..d0cdef8 --- /dev/null +++ b/src/class25/Code02_AllTimesMinToMax.java @@ -0,0 +1,67 @@ +package class25; + +import java.util.Stack; + +public class Code02_AllTimesMinToMax { + + public static int max1(int[] arr) { + int max = Integer.MIN_VALUE; + for (int i = 0; i < arr.length; i++) { + for (int j = i; j < arr.length; j++) { + int minNum = Integer.MAX_VALUE; + int sum = 0; + for (int k = i; k <= j; k++) { + sum += arr[k]; + minNum = Math.min(minNum, arr[k]); + } + max = Math.max(max, minNum * sum); + } + } + return max; + } + + public static int max2(int[] arr) { + int size = arr.length; + int[] sums = new int[size]; + sums[0] = arr[0]; + for (int i = 1; i < size; i++) { + sums[i] = sums[i - 1] + arr[i]; + } + int max = Integer.MIN_VALUE; + Stack stack = new Stack(); + for (int i = 0; i < size; i++) { + while (!stack.isEmpty() && arr[stack.peek()] >= arr[i]) { + int j = stack.pop(); + max = Math.max(max, (stack.isEmpty() ? sums[i - 1] : (sums[i - 1] - sums[stack.peek()])) * arr[j]); + } + stack.push(i); + } + while (!stack.isEmpty()) { + int j = stack.pop(); + max = Math.max(max, (stack.isEmpty() ? sums[size - 1] : (sums[size - 1] - sums[stack.peek()])) * arr[j]); + } + return max; + } + + public static int[] gerenareRondomArray() { + int[] arr = new int[(int) (Math.random() * 20) + 10]; + for (int i = 0; i < arr.length; i++) { + arr[i] = (int) (Math.random() * 101); + } + return arr; + } + + public static void main(String[] args) { + int testTimes = 2000000; + System.out.println("test begin"); + for (int i = 0; i < testTimes; i++) { + int[] arr = gerenareRondomArray(); + if (max1(arr) != max2(arr)) { + System.out.println("FUCK!"); + break; + } + } + System.out.println("test finish"); + } + +} diff --git a/src/class25/Code03_SumOfSubarrayMinimums.java b/src/class25/Code03_SumOfSubarrayMinimums.java new file mode 100644 index 0000000..12e4741 --- /dev/null +++ b/src/class25/Code03_SumOfSubarrayMinimums.java @@ -0,0 +1,153 @@ +package class25; + +import java.util.Stack; + +// 测试链接:https://leetcode.com/problems/sum-of-subarray-minimums/ +// subArrayMinSum1是暴力解 +// subArrayMinSum2是最优解的思路 +// sumSubarrayMins是最优解思路下的单调栈优化 +// Leetcode上只提交sumSubarrayMins方法,时间复杂度O(N),可以直接通过 +public class Code03_SumOfSubarrayMinimums { + + public static int subArrayMinSum1(int[] arr) { + int ans = 0; + for (int i = 0; i < arr.length; i++) { + for (int j = i; j < arr.length; j++) { + int min = arr[i]; + for (int k = i + 1; k <= j; k++) { + min = Math.min(min, arr[k]); + } + ans += min; + } + } + return ans; + } + + public static int subArrayMinSum2(int[] arr) { + int[] left = leftNearLessEqual2(arr); + int[] right = rightNearLess2(arr); + int ans = 0; + for (int i = 0; i < arr.length; i++) { + int start = i - left[i]; + int end = right[i] - i; + ans += start * end * arr[i]; + } + return ans; + } + + public static int[] leftNearLessEqual2(int[] arr) { + int N = arr.length; + int[] left = new int[N]; + for (int i = 0; i < N; i++) { + int ans = -1; + for (int j = i - 1; j >= 0; j--) { + if (arr[j] <= arr[i]) { + ans = j; + break; + } + } + left[i] = ans; + } + return left; + } + + public static int[] rightNearLess2(int[] arr) { + int N = arr.length; + int[] right = new int[N]; + for (int i = 0; i < N; i++) { + int ans = N; + for (int j = i + 1; j < N; j++) { + if (arr[i] > arr[j]) { + ans = j; + break; + } + } + right[i] = ans; + } + return right; + } + + public static int sumSubarrayMins(int[] arr) { + int[] left = nearLessEqualLeft(arr); + int[] right = nearLessRight(arr); + long ans = 0; + for (int i = 0; i < arr.length; i++) { + long start = i - left[i]; + long end = right[i] - i; + ans += start * end * (long) arr[i]; + ans %= 1000000007; + } + return (int) ans; + } + + public static int[] nearLessEqualLeft(int[] arr) { + int N = arr.length; + int[] left = new int[N]; + Stack stack = new Stack<>(); + for (int i = N - 1; i >= 0; i--) { + while (!stack.isEmpty() && arr[i] <= arr[stack.peek()]) { + left[stack.pop()] = i; + } + stack.push(i); + } + while (!stack.isEmpty()) { + left[stack.pop()] = -1; + } + return left; + } + + public static int[] nearLessRight(int[] arr) { + int N = arr.length; + int[] right = new int[N]; + Stack stack = new Stack<>(); + for (int i = 0; i < N; i++) { + while (!stack.isEmpty() && arr[stack.peek()] > arr[i]) { + right[stack.pop()] = i; + } + stack.push(i); + } + while (!stack.isEmpty()) { + right[stack.pop()] = N; + } + return right; + } + + public static int[] randomArray(int len, int maxValue) { + int[] ans = new int[len]; + for (int i = 0; i < len; i++) { + ans[i] = (int) (Math.random() * maxValue) + 1; + } + return ans; + } + + public static void printArray(int[] arr) { + for (int i = 0; i < arr.length; i++) { + System.out.print(arr[i] + " "); + } + System.out.println(); + } + + public static void main(String[] args) { + int maxLen = 100; + int maxValue = 50; + int testTime = 100000; + System.out.println("测试开始"); + for (int i = 0; i < testTime; i++) { + int len = (int) (Math.random() * maxLen); + int[] arr = randomArray(len, maxValue); + int ans1 = subArrayMinSum1(arr); + int ans2 = subArrayMinSum2(arr); + int ans3 = sumSubarrayMins(arr); + if (ans1 != ans2 || ans1 != ans3) { + printArray(arr); + System.out.println(ans1); + System.out.println(ans2); + System.out.println(ans3); + System.out.println("出错了!"); + break; + } + } + System.out.println("测试结束"); + } + +} diff --git a/src/class25/Code04_LargestRectangleInHistogram.java b/src/class25/Code04_LargestRectangleInHistogram.java new file mode 100644 index 0000000..1123ef7 --- /dev/null +++ b/src/class25/Code04_LargestRectangleInHistogram.java @@ -0,0 +1,58 @@ +package class25; + +import java.util.Stack; + +// 测试链接:https://leetcode.com/problems/largest-rectangle-in-histogram +public class Code04_LargestRectangleInHistogram { + + public static int largestRectangleArea1(int[] height) { + if (height == null || height.length == 0) { + return 0; + } + int maxArea = 0; + Stack stack = new Stack(); + for (int i = 0; i < height.length; i++) { + while (!stack.isEmpty() && height[i] <= height[stack.peek()]) { + int j = stack.pop(); + int k = stack.isEmpty() ? -1 : stack.peek(); + int curArea = (i - k - 1) * height[j]; + maxArea = Math.max(maxArea, curArea); + } + stack.push(i); + } + while (!stack.isEmpty()) { + int j = stack.pop(); + int k = stack.isEmpty() ? -1 : stack.peek(); + int curArea = (height.length - k - 1) * height[j]; + maxArea = Math.max(maxArea, curArea); + } + return maxArea; + } + + public static int largestRectangleArea2(int[] height) { + if (height == null || height.length == 0) { + return 0; + } + int N = height.length; + int[] stack = new int[N]; + int si = -1; + int maxArea = 0; + for (int i = 0; i < height.length; i++) { + while (si != -1 && height[i] <= height[stack[si]]) { + int j = stack[si--]; + int k = si == -1 ? -1 : stack[si]; + int curArea = (i - k - 1) * height[j]; + maxArea = Math.max(maxArea, curArea); + } + stack[++si] = i; + } + while (si != -1) { + int j = stack[si--]; + int k = si == -1 ? -1 : stack[si]; + int curArea = (height.length - k - 1) * height[j]; + maxArea = Math.max(maxArea, curArea); + } + return maxArea; + } + +} From b2f0d7f9ec6a7c8b089644366960f673b5e8ee8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B7=A6=E7=A8=8B=E4=BA=91?= Date: Tue, 19 Jan 2021 17:29:48 +0800 Subject: [PATCH 2/5] modify code --- .../Code02_SplitSumClosedSizeHalf.java | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/class23/Code02_SplitSumClosedSizeHalf.java b/src/class23/Code02_SplitSumClosedSizeHalf.java index 2930349..0f08fd1 100644 --- a/src/class23/Code02_SplitSumClosedSizeHalf.java +++ b/src/class23/Code02_SplitSumClosedSizeHalf.java @@ -1,7 +1,5 @@ package class23; -import java.util.TreeSet; - public class Code02_SplitSumClosedSizeHalf { public static int right(int[] arr) { @@ -12,26 +10,27 @@ public class Code02_SplitSumClosedSizeHalf { for (int num : arr) { sum += num; } - TreeSet ans = new TreeSet<>(); - process(arr, 0, 0, 0, ans, sum >> 1); - return ans.last(); + return process(arr, 0, 0, sum >> 1, (arr.length & 1) == 0); } - public static void process(int[] arr, int i, int sum, int picks, TreeSet ans, int limit) { + public static int process(int[] arr, int i, int picks, int rest, boolean sizeEven) { if (i == arr.length) { - if ((arr.length & 1) == 0) { - if (picks == (arr.length >> 1) && sum <= limit) { - ans.add(sum); - } + if (sizeEven) { + return picks == (arr.length >> 1) ? 0 : -1; } else { - if ((picks == (arr.length >> 1) || picks == (arr.length >> 1) + 1) && sum <= limit) { - ans.add(sum); - } + return (picks == (arr.length >> 1) || picks == (arr.length >> 1) + 1) ? 0 : -1; } - } else { - process(arr, i + 1, sum, picks, ans, limit); - process(arr, i + 1, sum + arr[i], picks + 1, ans, limit); } + int p1 = process(arr, i + 1, picks, rest, sizeEven); + int p2 = -1; + int next2 = -1; + if (arr[i] <= rest) { + next2 = process(arr, i + 1, picks + 1, rest - arr[i], sizeEven); + } + if (next2 != -1) { + p2 = arr[i] + next2; + } + return Math.max(p1, p2); } public static int dp(int[] arr) { From 02272879aebca7271af540b8381c9453e0859b69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B7=A6=E7=A8=8B=E4=BA=91?= Date: Tue, 19 Jan 2021 17:41:14 +0800 Subject: [PATCH 3/5] modify code --- src/class23/Code01_SplitSumClosed.java | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/class23/Code01_SplitSumClosed.java b/src/class23/Code01_SplitSumClosed.java index 605c930..7a95f0e 100644 --- a/src/class23/Code01_SplitSumClosed.java +++ b/src/class23/Code01_SplitSumClosed.java @@ -1,7 +1,5 @@ package class23; -import java.util.TreeSet; - public class Code01_SplitSumClosed { public static int right(int[] arr) { @@ -12,19 +10,19 @@ public class Code01_SplitSumClosed { for (int num : arr) { sum += num; } - TreeSet ans = new TreeSet<>(); - process(arr, 0, 0, 0, ans, sum >> 1); - return ans.last(); + return process(arr, 0, sum >> 1); } - public static void process(int[] arr, int i, int sum, int picks, TreeSet ans, int limit) { + public static int process(int[] arr, int i, int rest) { if (i == arr.length) { - if (sum <= limit) { - ans.add(sum); - } + return 0; } else { - process(arr, i + 1, sum, picks, ans, limit); - process(arr, i + 1, sum + arr[i], picks + 1, ans, limit); + int p1 = process(arr, i + 1, rest); + int p2 = 0; + if (arr[i] <= rest) { + p2 = arr[i] + process(arr, i + 1, rest - arr[i]); + } + return Math.max(p1, p2); } } From 067da841a01c13351e7d2c061ce2fdd02e4400ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B7=A6=E7=A8=8B=E4=BA=91?= Date: Tue, 19 Jan 2021 17:43:00 +0800 Subject: [PATCH 4/5] modify code --- src/class23/Code03_NQueens.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class23/Code03_NQueens.java b/src/class23/Code03_NQueens.java index 9264e0c..b3dbbb7 100644 --- a/src/class23/Code03_NQueens.java +++ b/src/class23/Code03_NQueens.java @@ -66,7 +66,7 @@ public class Code03_NQueens { } public static void main(String[] args) { - int n = 15; + int n = 14; long start = System.currentTimeMillis(); System.out.println(num2(n)); From d13b2a1c22d05e11d5f8c15d75490af269845d6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B7=A6=E7=A8=8B=E4=BA=91?= Date: Tue, 19 Jan 2021 19:45:51 +0800 Subject: [PATCH 5/5] modify code --- .../Code02_SplitSumClosedSizeHalf.java | 67 ++++++++++++++++--- 1 file changed, 59 insertions(+), 8 deletions(-) diff --git a/src/class23/Code02_SplitSumClosedSizeHalf.java b/src/class23/Code02_SplitSumClosedSizeHalf.java index 0f08fd1..d87f0d6 100644 --- a/src/class23/Code02_SplitSumClosedSizeHalf.java +++ b/src/class23/Code02_SplitSumClosedSizeHalf.java @@ -10,22 +10,22 @@ public class Code02_SplitSumClosedSizeHalf { for (int num : arr) { sum += num; } - return process(arr, 0, 0, sum >> 1, (arr.length & 1) == 0); + return process(arr, 0, 0, sum >> 1); } - public static int process(int[] arr, int i, int picks, int rest, boolean sizeEven) { + public static int process(int[] arr, int i, int picks, int rest) { if (i == arr.length) { - if (sizeEven) { + 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, sizeEven); + 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], sizeEven); + next2 = process(arr, i + 1, picks + 1, rest - arr[i]); } if (next2 != -1) { p2 = arr[i] + next2; @@ -33,7 +33,53 @@ public class Code02_SplitSumClosedSizeHalf { return Math.max(p1, p2); } - public static int dp(int[] arr) { + 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; } @@ -73,6 +119,7 @@ public class Code02_SplitSumClosedSizeHalf { return Math.max(dp[N - 1][M][sum], dp[N - 1][N - M][sum]); } + // for test public static int[] randomArray(int len, int value) { int[] arr = new int[len]; for (int i = 0; i < arr.length; i++) { @@ -81,6 +128,7 @@ public class Code02_SplitSumClosedSizeHalf { return arr; } + // for test public static void printArray(int[] arr) { for (int num : arr) { System.out.print(num + " "); @@ -88,6 +136,7 @@ public class Code02_SplitSumClosedSizeHalf { System.out.println(); } + // for test public static void main(String[] args) { int maxLen = 20; int maxValue = 50; @@ -97,11 +146,13 @@ public class Code02_SplitSumClosedSizeHalf { int len = (int) (Math.random() * maxLen); int[] arr = randomArray(len, maxValue); int ans1 = right(arr); - int ans2 = dp(arr); - if (ans1 != ans2) { + int ans2 = dp1(arr); + int ans3 = dp2(arr); + if (ans1 != ans2 || ans1 != ans3) { printArray(arr); System.out.println(ans1); System.out.println(ans2); + System.out.println(ans3); System.out.println("Oops!"); break; }