Merge pull request #19 from algorithmzuo/master

merge zuo
pull/3/head
ThankyouEverybody 5 years ago committed by GitHub
commit 1fcb003197
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -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<Integer> 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<Integer> 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);
}
}

@ -1,7 +1,5 @@
package class23;
import java.util.TreeSet;
public class Code02_SplitSumClosedSizeHalf {
public static int right(int[] arr) {
@ -12,29 +10,76 @@ public class Code02_SplitSumClosedSizeHalf {
for (int num : arr) {
sum += num;
}
TreeSet<Integer> ans = new TreeSet<>();
process(arr, 0, 0, 0, ans, sum >> 1);
return ans.last();
return process(arr, 0, 0, sum >> 1);
}
public static void process(int[] arr, int i, int sum, int picks, TreeSet<Integer> ans, int limit) {
public static int process(int[] arr, int i, int picks, int rest) {
if (i == arr.length) {
if ((arr.length & 1) == 0) {
if (picks == (arr.length >> 1) && sum <= limit) {
ans.add(sum);
}
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;
}
}
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);
}
}
} else {
process(arr, i + 1, sum, picks, ans, limit);
process(arr, i + 1, sum + arr[i], picks + 1, ans, limit);
}
return dp[0][0][sum];
}
public static int dp(int[] arr) {
public static int dp2(int[] arr) {
if (arr == null || arr.length < 2) {
return 0;
}
@ -74,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++) {
@ -82,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 + " ");
@ -89,6 +136,7 @@ public class Code02_SplitSumClosedSizeHalf {
System.out.println();
}
// for test
public static void main(String[] args) {
int maxLen = 20;
int maxValue = 50;
@ -98,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;
}

@ -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));

@ -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<Integer> qmax = new LinkedList<Integer>();
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");
}
}

@ -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<Integer> qmin = new LinkedList<Integer>();
LinkedList<Integer> qmax = new LinkedList<Integer>();
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));
}
}

@ -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<Integer> 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;
}
}

@ -1,4 +1,4 @@
package class23;
package class24;
import java.util.HashMap;
import java.util.Map.Entry;

@ -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<Integer> 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<List<Integer>> 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<Integer> 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<Integer> list = new ArrayList<>();
list.add(i);
stack.push(list);
}
}
while (!stack.isEmpty()) {
List<Integer> 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;
}
}
}
}

@ -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<Integer> stack = new Stack<Integer>();
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");
}
}

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

@ -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<Integer> stack = new Stack<Integer>();
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;
}
}
Loading…
Cancel
Save