└── src ├── class01 ├── Code01_CordCoverMaxPoint.java ├── Code02_NeedParentheses.java ├── Code03_ParenthesesDeep.java ├── Code04_ColorLeftRight.java ├── Code05_MaxOneBorderSize.java ├── Code06_MakeNo.java └── Code07_MaxSumInTree.java ├── class02 ├── Code01_FindNumInSortedMatrix.java ├── Code02_PackingMachine.java ├── Code03_MaxABSBetweenLeftAndRight.java ├── Code04_TrappingRainWater.java ├── Code05_TrappingRainWaterII.java ├── Code06_PrintUniquePairAndTriad.java └── Code07_KthMinPair.java ├── class03 ├── Code01_ChooseWork.java ├── Code02_SnacksWays.java ├── Code03_MinPathSum.java ├── Code04_LCSubsequence.java ├── Code05_LCSubstring.java ├── Code06_TopKTimes.java ├── Code07_TopKTimesRealTime.java ├── Main.java └── TopK.java ├── class04 ├── Code01_GetFolderTree.java ├── Code02_BSTtoDoubleLinkedList.java ├── Code03_PreAndInArrayToPosArray.java ├── Code04_LIS.java ├── Code05_EnvelopesProblem.java ├── Code06_SubArrayMaxSum.java └── Code07_SubMatrixMaxSum.java ├── class05 ├── Code01_DeleteMinCost.java ├── Code02_EditCost.java ├── Code03_CompleteTreeNodeNumber.java ├── Code04_LeastRecentlyUsedCache.java ├── Code05_WordMinPaths.java └── Code06_MaxRevenue.java ├── class06 ├── Code01_MaxEOR.java ├── Code02_ExpressionNumber.java ├── Code02_MostEOR.java ├── Code03_JumpGame.java ├── Code04_TopKSumCrossTwoArrays.java ├── Code05_Split4Parts.java ├── Code06_StringCross.java ├── Code07_PMinParts.java └── Main.java ├── class07 ├── Code01_MinLengthForSort.java ├── Code02_SmallestUnFormedSum.java ├── Code03_MinPatches.java ├── Code04_LargestComponentSizebyCommonFactor.java ├── Code05_RemoveDuplicateLettersLessLexi.java ├── Code06_LongestNoRepeatSubstring.java └── Code07_MaxPointsOneLine.java └── class08 ├── Code01_ReceiveAndPrintOrderLine.java ├── Code02_MoneyWays.java ├── Code03_OneNumber.java ├── Code04_MoneyProblem.java ├── Code05_LongestIntegratedLength.java ├── Code06_PalindromeMinAdd.java └── Main.java /src/class01/Code01_CordCoverMaxPoint.java: -------------------------------------------------------------------------------- 1 | package class01; 2 | 3 | import java.util.Arrays; 4 | 5 | public class Code01_CordCoverMaxPoint { 6 | 7 | public static int maxPoint1(int[] arr, int L) { 8 | int res = 1; 9 | for (int i = 0; i < arr.length; i++) { 10 | int nearest = nearestIndex(arr, i, arr[i] - L); 11 | res = Math.max(res, i - nearest + 1); 12 | } 13 | return res; 14 | } 15 | 16 | public static int nearestIndex(int[] arr, int R, int value) { 17 | int L = 0; 18 | int index = R; 19 | while (L <= R) { 20 | int mid = L + ((R - L) >> 1); 21 | if (arr[mid] >= value) { 22 | index = mid; 23 | R = mid - 1; 24 | } else { 25 | L = mid + 1; 26 | } 27 | } 28 | return index; 29 | } 30 | 31 | public static int maxPoint2(int[] arr, int L) { 32 | int left = 0; 33 | int right = 0; 34 | int N = arr.length; 35 | int max = 0; 36 | while (left < N) { 37 | while (right < N && arr[right] - arr[left] <= L) { 38 | right++; 39 | } 40 | max = Math.max(max, right - (left++)); 41 | } 42 | return max; 43 | } 44 | 45 | // for test 46 | public static int test(int[] arr, int L) { 47 | int max = 0; 48 | for (int i = 0; i < arr.length; i++) { 49 | int pre = i - 1; 50 | while (pre >= 0 && arr[i] - arr[pre] <= L) { 51 | pre--; 52 | } 53 | max = Math.max(max, i - pre); 54 | } 55 | return max; 56 | } 57 | 58 | // for test 59 | public static int[] generateArray(int len, int max) { 60 | int[] ans = new int[(int) (Math.random() * len) + 1]; 61 | for (int i = 0; i < ans.length; i++) { 62 | ans[i] = (int) (Math.random() * max); 63 | } 64 | Arrays.sort(ans); 65 | return ans; 66 | } 67 | 68 | public static void main(String[] args) { 69 | int len = 100; 70 | int max = 1000; 71 | int testTime = 100000; 72 | System.out.println("测试开始"); 73 | for (int i = 0; i < testTime; i++) { 74 | int L = (int) (Math.random() * max); 75 | int[] arr = generateArray(len, max); 76 | int ans1 = maxPoint1(arr, L); 77 | int ans2 = maxPoint2(arr, L); 78 | int ans3 = test(arr, L); 79 | if (ans1 != ans2 || ans2 != ans3) { 80 | System.out.println("oops!"); 81 | break; 82 | } 83 | } 84 | 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/class01/Code02_NeedParentheses.java: -------------------------------------------------------------------------------- 1 | package class01; 2 | 3 | public class Code02_NeedParentheses { 4 | 5 | public static boolean valid(String s) { 6 | char[] str = s.toCharArray(); 7 | int count = 0; 8 | for (int i = 0; i < str.length; i++) { 9 | count += str[i] == '(' ? 1 : -1; 10 | if (count < 0) { 11 | return false; 12 | } 13 | } 14 | return count == 0; 15 | } 16 | 17 | public static int needParentheses(String s) { 18 | char[] str = s.toCharArray(); 19 | int count = 0; 20 | int need = 0; 21 | for (int i = 0; i < str.length; i++) { 22 | if (str[i] == '(') { 23 | count++; 24 | } else { // 遇到的是')' 25 | if (count == 0) { 26 | need++; 27 | } else { 28 | count--; 29 | } 30 | } 31 | } 32 | return count + need; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/class01/Code03_ParenthesesDeep.java: -------------------------------------------------------------------------------- 1 | package class01; 2 | 3 | public class Code03_ParenthesesDeep { 4 | 5 | public static boolean isValid(char[] str) { 6 | if (str == null || str.length == 0) { 7 | return false; 8 | } 9 | int status = 0; 10 | for (int i = 0; i < str.length; i++) { 11 | if (str[i] != ')' && str[i] != '(') { 12 | return false; 13 | } 14 | if (str[i] == ')' && --status < 0) { 15 | return false; 16 | } 17 | if (str[i] == '(') { 18 | status++; 19 | } 20 | } 21 | return status == 0; 22 | } 23 | 24 | public static int deep(String s) { 25 | char[] str = s.toCharArray(); 26 | if (!isValid(str)) { 27 | return 0; 28 | } 29 | int count = 0; 30 | int max = 0; 31 | for (int i = 0; i < str.length; i++) { 32 | if (str[i] == '(') { 33 | max = Math.max(max, ++count); 34 | } else { 35 | count--; 36 | } 37 | } 38 | return max; 39 | } 40 | 41 | public static int maxLength(String s) { 42 | if (s == null || s.length() < 2) { 43 | return 0; 44 | } 45 | char[] str = s.toCharArray(); 46 | int[] dp = new int[str.length]; 47 | int pre = 0; 48 | int ans = 0; 49 | // dp[0] = 0; 50 | for (int i = 1; i < str.length; i++) { 51 | if (str[i] == ')') { 52 | pre = i - dp[i - 1] - 1; // 与str[i]配对的左括号的位置 pre 53 | if (pre >= 0 && str[pre] == '(') { 54 | dp[i] = dp[i - 1] + 2 + (pre > 0 ? dp[pre - 1] : 0); 55 | } 56 | } 57 | ans = Math.max(ans, dp[i]); 58 | } 59 | return ans; 60 | } 61 | 62 | public static void main(String[] args) { 63 | String test = "((()))"; 64 | System.out.println(deep(test)); 65 | 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/class01/Code04_ColorLeftRight.java: -------------------------------------------------------------------------------- 1 | package class01; 2 | 3 | public class Code04_ColorLeftRight { 4 | 5 | // RGRGR -> RRRGG 6 | public static int minPaint(String s) { 7 | if (s == null || s.length() < 2) { 8 | return 0; 9 | } 10 | char[] str = s.toCharArray(); 11 | int N = str.length; 12 | int rAll = 0; 13 | for (int i = 0; i < N; i++) { 14 | rAll += str[i] == 'R' ? 1 : 0; 15 | } 16 | int ans = rAll; // 如果数组所有的范围,都是右侧范围,都变成G 17 | int left = 0; 18 | for (int i = 0; i < N - 1; i++) { // 0..i 左侧 n-1..N-1 19 | left += str[i] == 'G' ? 1 : 0; 20 | rAll -= str[i] == 'R' ? 1 : 0; 21 | ans = Math.min(ans, left + rAll); 22 | } 23 | // 0...N-1 左全部 右无 24 | ans = Math.min(ans, left + (str[N - 1] == 'G' ? 1 : 0)); 25 | return ans; 26 | } 27 | 28 | public static void main(String[] args) { 29 | String test = "GGGGGR"; 30 | System.out.println(minPaint(test)); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/class01/Code05_MaxOneBorderSize.java: -------------------------------------------------------------------------------- 1 | package class01; 2 | 3 | public class Code05_MaxOneBorderSize { 4 | 5 | public static void setBorderMap(int[][] m, int[][] right, int[][] down) { 6 | int r = m.length; 7 | int c = m[0].length; 8 | if (m[r - 1][c - 1] == 1) { 9 | right[r - 1][c - 1] = 1; 10 | down[r - 1][c - 1] = 1; 11 | } 12 | for (int i = r - 2; i != -1; i--) { 13 | if (m[i][c - 1] == 1) { 14 | right[i][c - 1] = 1; 15 | down[i][c - 1] = down[i + 1][c - 1] + 1; 16 | } 17 | } 18 | for (int i = c - 2; i != -1; i--) { 19 | if (m[r - 1][i] == 1) { 20 | right[r - 1][i] = right[r - 1][i + 1] + 1; 21 | down[r - 1][i] = 1; 22 | } 23 | } 24 | for (int i = r - 2; i != -1; i--) { 25 | for (int j = c - 2; j != -1; j--) { 26 | if (m[i][j] == 1) { 27 | right[i][j] = right[i][j + 1] + 1; 28 | down[i][j] = down[i + 1][j] + 1; 29 | } 30 | } 31 | } 32 | } 33 | 34 | public static int getMaxSize(int[][] m) { 35 | int[][] right = new int[m.length][m[0].length]; 36 | int[][] down = new int[m.length][m[0].length]; 37 | setBorderMap(m, right, down); // O(N^2); + 38 | 39 | for (int size = Math.min(m.length, m[0].length); size != 0; size--) { 40 | if (hasSizeOfBorder(size, right, down)) { 41 | return size; 42 | } 43 | } 44 | return 0; 45 | } 46 | 47 | public static boolean hasSizeOfBorder(int size, int[][] right, int[][] down) { 48 | for (int i = 0; i != right.length - size + 1; i++) { 49 | for (int j = 0; j != right[0].length - size + 1; j++) { 50 | if (right[i][j] >= size && down[i][j] >= size 51 | && right[i + size - 1][j] >= size 52 | && down[i][j + size - 1] >= size) { 53 | return true; 54 | } 55 | } 56 | } 57 | return false; 58 | } 59 | 60 | public static int[][] generateRandom01Matrix(int rowSize, int colSize) { 61 | int[][] res = new int[rowSize][colSize]; 62 | for (int i = 0; i != rowSize; i++) { 63 | for (int j = 0; j != colSize; j++) { 64 | res[i][j] = (int) (Math.random() * 2); 65 | } 66 | } 67 | return res; 68 | } 69 | 70 | public static void printMatrix(int[][] matrix) { 71 | for (int i = 0; i != matrix.length; i++) { 72 | for (int j = 0; j != matrix[0].length; j++) { 73 | System.out.print(matrix[i][j] + " "); 74 | } 75 | System.out.println(); 76 | } 77 | } 78 | 79 | public static void main(String[] args) { 80 | int[][] matrix = generateRandom01Matrix(7, 8); 81 | printMatrix(matrix); 82 | System.out.println(getMaxSize(matrix)); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/class01/Code06_MakeNo.java: -------------------------------------------------------------------------------- 1 | package class01; 2 | 3 | public class Code06_MakeNo { 4 | 5 | // 生成长度为size的达标数组 6 | // 达标:对于任意的 i 等长奇数达标来 19 | // base -> 等长偶数达标来 20 | int[] ans = new int[size]; 21 | int index = 0; 22 | for(; index < halfSize;index++) { 23 | ans[index] = base[index] * 2 - 1; 24 | } 25 | for(int i = 0 ;index < size;index++,i++) { 26 | ans[index] = base[i] * 2; 27 | } 28 | return ans; 29 | } 30 | 31 | 32 | // 检验函数 33 | public static boolean isValid(int[] arr) { 34 | int N = arr.length; 35 | for (int i = 0; i < N; i++) { 36 | for (int k = i + 1; k < N; k++) { 37 | for (int j = k + 1; j < N; j++) { 38 | 39 | 40 | if (arr[i] + arr[j] == 2 * arr[k]) { 41 | return false; 42 | } 43 | } 44 | } 45 | } 46 | return true; 47 | } 48 | 49 | public static void main(String[] args) { 50 | System.out.println("test begin"); 51 | for (int N = 1; N < 1000; N++) { 52 | int[] arr = makeNo(N); 53 | if (!isValid(arr)) { 54 | System.out.println("Oops!"); 55 | } 56 | } 57 | System.out.println("test end"); 58 | 59 | System.out.println(isValid(makeNo(1042))); 60 | System.out.println(isValid(makeNo(2981))); 61 | 62 | 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/class01/Code07_MaxSumInTree.java: -------------------------------------------------------------------------------- 1 | package class01; 2 | 3 | public class Code07_MaxSumInTree { 4 | 5 | public static class Node { 6 | public int value; 7 | public Node left; 8 | public Node right; 9 | 10 | public Node(int val) { 11 | value = val; 12 | } 13 | } 14 | 15 | public static int maxSum = Integer.MIN_VALUE; 16 | 17 | public static int maxPath(Node head) { 18 | maxSum = Integer.MIN_VALUE; 19 | p(head, 0); 20 | return maxSum; 21 | } 22 | 23 | // 之前的路径和,为pre 24 | public static void p(Node x, int pre) { 25 | if (x.left == null && x.right == null) { 26 | maxSum = Math.max(maxSum, pre + x.value); 27 | } 28 | if (x.left != null) { 29 | p(x.left, pre + x.value); 30 | } 31 | if (x.right != null) { 32 | p(x.right, pre + x.value); 33 | } 34 | } 35 | 36 | public static int maxDis(Node head) { 37 | if (head == null) { 38 | return 0; 39 | } 40 | return process2(head); 41 | } 42 | 43 | // x为头的整棵树上,最大路径和是多少,返回。 44 | // 路径要求,一定从x出发,到叶节点,算做一个路径 45 | public static int process2(Node x) { 46 | if (x.left == null && x.right == null) { 47 | return x.value; 48 | } 49 | int next = Integer.MIN_VALUE; 50 | if (x.left != null) { 51 | next = process2(x.left); 52 | } 53 | if (x.right != null) { 54 | next = Math.max(next, process2(x.right)); 55 | } 56 | return x.value + next; 57 | } 58 | 59 | public static int maxSum2(Node head) { 60 | if (head == null) { 61 | return 0; 62 | } 63 | return f2(head).allTreeMaxSum; 64 | } 65 | 66 | public static class Info { 67 | public int allTreeMaxSum; 68 | public int fromHeadMaxSum; 69 | 70 | public Info(int all, int from) { 71 | allTreeMaxSum = all; 72 | fromHeadMaxSum = from; 73 | } 74 | } 75 | 76 | // 1)X无关的时候, 1, 左树上的整体最大路径和 2, 右树上的整体最大路径和 77 | // 2) X有关的时候 3, x自己 4, x往左走 5,x往右走 78 | public static Info f2(Node x) { 79 | if (x == null) { 80 | return null; 81 | } 82 | Info leftInfo = f2(x.left); 83 | Info rightInfo = f2(x.right); 84 | int p1 = Integer.MIN_VALUE; 85 | if (leftInfo != null) { 86 | p1 = leftInfo.allTreeMaxSum; 87 | } 88 | int p2 = Integer.MIN_VALUE; 89 | if (rightInfo != null) { 90 | p2 = rightInfo.allTreeMaxSum; 91 | } 92 | int p3 = x.value; 93 | int p4 = Integer.MIN_VALUE; 94 | if (leftInfo != null) { 95 | p4 = x.value + leftInfo.fromHeadMaxSum; 96 | } 97 | int p5 = Integer.MIN_VALUE; 98 | if (rightInfo != null) { 99 | p5 = x.value + rightInfo.fromHeadMaxSum; 100 | } 101 | int allTreeMaxSum = Math.max(Math.max(Math.max(p1, p2), p3), Math.max(p4, p5)); 102 | int fromHeadMaxSum = Math.max(Math.max(p3, p4), p5); 103 | return new Info(allTreeMaxSum, fromHeadMaxSum); 104 | } 105 | 106 | // 1)X无关的时候, 1, 左树上的整体最大路径和 2, 右树上的整体最大路径和 107 | // 2) X有关的时候 3, x自己 4, x往左走 5,x往右走 6, 既往左,又往右 108 | public static Info f3(Node x) { 109 | if (x == null) { 110 | return null; 111 | } 112 | Info leftInfo = f3(x.left); 113 | Info rightInfo = f3(x.right); 114 | int p1 = Integer.MIN_VALUE; 115 | if (leftInfo != null) { 116 | p1 = leftInfo.allTreeMaxSum; 117 | } 118 | int p2 = Integer.MIN_VALUE; 119 | if (rightInfo != null) { 120 | p2 = rightInfo.allTreeMaxSum; 121 | } 122 | int p3 = x.value; 123 | int p4 = Integer.MIN_VALUE; 124 | if (leftInfo != null) { 125 | p4 = x.value + leftInfo.fromHeadMaxSum; 126 | } 127 | int p5 = Integer.MIN_VALUE; 128 | if (rightInfo != null) { 129 | p5 = x.value + rightInfo.fromHeadMaxSum; 130 | } 131 | 132 | int p6 = Integer.MIN_VALUE; 133 | if (leftInfo != null && rightInfo != null) { 134 | p6 = x.value + leftInfo.fromHeadMaxSum + rightInfo.fromHeadMaxSum; 135 | } 136 | 137 | int allTreeMaxSum = Math.max(Math.max(Math.max(p1, p2), p3), Math.max(Math.max(p4, p5), p6)); 138 | int fromHeadMaxSum = Math.max(Math.max(p3, p4), p5); 139 | return new Info(allTreeMaxSum, fromHeadMaxSum); 140 | } 141 | 142 | public static int max = Integer.MIN_VALUE; 143 | 144 | public static int bigShuai(Node head) { 145 | if (head.left == null && head.right == null) { 146 | max = Math.max(max, head.value); 147 | return head.value; 148 | } 149 | int nextMax = 0; 150 | if (head.left != null) { 151 | nextMax = bigShuai(head.left); 152 | } 153 | if (head.right != null) { 154 | nextMax = Math.max(nextMax, bigShuai(head.right)); 155 | } 156 | int ans = head.value + nextMax; 157 | max = Math.max(max, ans); 158 | return ans; 159 | } 160 | 161 | } 162 | -------------------------------------------------------------------------------- /src/class02/Code01_FindNumInSortedMatrix.java: -------------------------------------------------------------------------------- 1 | package class02; 2 | 3 | public class Code01_FindNumInSortedMatrix { 4 | 5 | public static boolean isContains(int[][] matrix, int K) { 6 | int row = 0; 7 | int col = matrix[0].length - 1; 8 | while (row < matrix.length && col > -1) { 9 | if (matrix[row][col] == K) { 10 | return true; 11 | } else if (matrix[row][col] > K) { 12 | col--; 13 | } else { 14 | row++; 15 | } 16 | } 17 | return false; 18 | } 19 | 20 | public static void main(String[] args) { 21 | int[][] matrix = new int[][] { { 0, 1, 2, 3, 4, 5, 6 },// 0 22 | { 10, 12, 13, 15, 16, 17, 18 },// 1 23 | { 23, 24, 25, 26, 27, 28, 29 },// 2 24 | { 44, 45, 46, 47, 48, 49, 50 },// 3 25 | { 65, 66, 67, 68, 69, 70, 71 },// 4 26 | { 96, 97, 98, 99, 100, 111, 122 },// 5 27 | { 166, 176, 186, 187, 190, 195, 200 },// 6 28 | { 233, 243, 321, 341, 356, 370, 380 } // 7 29 | }; 30 | int K = 233; 31 | System.out.println(isContains(matrix, K)); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/class02/Code02_PackingMachine.java: -------------------------------------------------------------------------------- 1 | package class02; 2 | 3 | public class Code02_PackingMachine { 4 | 5 | public static int MinOps(int[] arr) { 6 | if (arr == null || arr.length == 0) { 7 | return 0; 8 | } 9 | int size = arr.length; 10 | int sum = 0; 11 | for (int i = 0; i < size; i++) { 12 | sum += arr[i]; 13 | } 14 | if (sum % size != 0) { 15 | return -1; 16 | } 17 | int avg = sum / size; 18 | int leftSum = 0; 19 | int ans = 0; 20 | // 每个位置都求各自的 21 | for (int i = 0; i < arr.length; i++) { 22 | // i号机器,是中间机器,左(0~i-1) i 右(i+1~N-1) 23 | // 负 需要输入 正需要输出 24 | int leftRest = leftSum - i * avg; // a-b 25 | // 负 需要输入 正需要输出 26 | // c - d 27 | int rightRest = (sum - leftSum - arr[i]) - (size - i - 1) * avg; 28 | if (leftRest < 0 && rightRest < 0) { 29 | ans = Math.max(ans, Math.abs(leftRest) + Math.abs(rightRest)); 30 | } else { 31 | ans = Math.max(ans, Math.max(Math.abs(leftRest), Math.abs(rightRest))); 32 | } 33 | leftSum += arr[i]; 34 | } 35 | return ans; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/class02/Code03_MaxABSBetweenLeftAndRight.java: -------------------------------------------------------------------------------- 1 | package class02; 2 | 3 | public class Code03_MaxABSBetweenLeftAndRight { 4 | 5 | public static int maxABS1(int[] arr) { 6 | int res = Integer.MIN_VALUE; 7 | int maxLeft = 0; 8 | int maxRight = 0; 9 | for (int i = 0; i != arr.length - 1; i++) { 10 | maxLeft = Integer.MIN_VALUE; 11 | for (int j = 0; j != i + 1; j++) { 12 | maxLeft = Math.max(arr[j], maxLeft); 13 | } 14 | maxRight = Integer.MIN_VALUE; 15 | for (int j = i + 1; j != arr.length; j++) { 16 | maxRight = Math.max(arr[j], maxRight); 17 | } 18 | res = Math.max(Math.abs(maxLeft - maxRight), res); 19 | } 20 | return res; 21 | } 22 | 23 | public static int maxABS2(int[] arr) { 24 | int[] lArr = new int[arr.length]; 25 | int[] rArr = new int[arr.length]; 26 | lArr[0] = arr[0]; 27 | rArr[arr.length - 1] = arr[arr.length - 1]; 28 | for (int i = 1; i < arr.length; i++) { 29 | lArr[i] = Math.max(lArr[i - 1], arr[i]); 30 | } 31 | for (int i = arr.length - 2; i > -1; i--) { 32 | rArr[i] = Math.max(rArr[i + 1], arr[i]); 33 | } 34 | int max = 0; 35 | for (int i = 0; i < arr.length - 1; i++) { 36 | max = Math.max(max, Math.abs(lArr[i] - rArr[i + 1])); 37 | } 38 | return max; 39 | } 40 | 41 | public static int maxABS3(int[] arr) { 42 | int max = Integer.MIN_VALUE; 43 | for (int i = 0; i < arr.length; i++) { 44 | max = Math.max(arr[i], max); 45 | } 46 | return max - Math.min(arr[0], arr[arr.length - 1]); 47 | } 48 | 49 | public static int[] generateRandomArray(int length) { 50 | int[] arr = new int[length]; 51 | for (int i = 0; i != arr.length; i++) { 52 | arr[i] = (int) (Math.random() * 1000) - 499; 53 | } 54 | return arr; 55 | } 56 | 57 | public static void main(String[] args) { 58 | int[] arr = generateRandomArray(200); 59 | System.out.println(maxABS1(arr)); 60 | System.out.println(maxABS2(arr)); 61 | System.out.println(maxABS3(arr)); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/class02/Code04_TrappingRainWater.java: -------------------------------------------------------------------------------- 1 | package class02; 2 | 3 | public class Code04_TrappingRainWater { 4 | 5 | /* 6 | * 给定一个正整数数组arr,把arr想象成一个直方图。返回这个直方图如果装水,能装下几格水? 7 | * 8 | */ 9 | 10 | public static int water1(int[] arr) { 11 | if (arr == null || arr.length < 2) { 12 | return 0; 13 | } 14 | int N = arr.length; 15 | int water = 0; 16 | for (int i = 1; i < N - 1; i++) { 17 | int leftMax = Integer.MIN_VALUE; 18 | for (int j = 0; j < i; j++) { 19 | leftMax = Math.max(leftMax, arr[j]); 20 | } 21 | int rightMax = Integer.MIN_VALUE; 22 | for (int j = i + 1; j < N; j++) { 23 | rightMax = Math.max(rightMax, arr[j]); 24 | } 25 | water += Math.max(Math.min(leftMax, rightMax) - arr[i], 0); 26 | } 27 | return water; 28 | } 29 | 30 | public static int water2(int[] arr) { 31 | if (arr == null || arr.length < 2) { 32 | return 0; 33 | } 34 | int N = arr.length; 35 | int[] leftMaxs = new int[N]; 36 | leftMaxs[0] = arr[0]; 37 | for (int i = 1; i < N; i++) { 38 | leftMaxs[i] = Math.max(leftMaxs[i - 1], arr[i]); 39 | } 40 | 41 | int[] rightMaxs = new int[N]; 42 | rightMaxs[N - 1] = arr[N - 1]; 43 | for (int i = N - 2; i >= 0; i--) { 44 | rightMaxs[i] = Math.max(rightMaxs[i + 1], arr[i]); 45 | } 46 | int water = 0; 47 | for (int i = 1; i < N - 1; i++) { 48 | water += Math.max(Math.min(leftMaxs[i - 1], rightMaxs[i + 1]) - arr[i], 0); 49 | } 50 | return water; 51 | } 52 | 53 | public static int water3(int[] arr) { 54 | if (arr == null || arr.length < 2) { 55 | return 0; 56 | } 57 | int N = arr.length; 58 | int[] rightMaxs = new int[N]; 59 | rightMaxs[N - 1] = arr[N - 1]; 60 | for (int i = N - 2; i >= 0; i--) { 61 | rightMaxs[i] = Math.max(rightMaxs[i + 1], arr[i]); 62 | } 63 | int water = 0; 64 | int leftMax = arr[0]; 65 | for (int i = 1; i < N - 1; i++) { 66 | water += Math.max(Math.min(leftMax, rightMaxs[i + 1]) - arr[i], 0); 67 | leftMax = Math.max(leftMax, arr[i]); 68 | } 69 | return water; 70 | } 71 | 72 | public static int water4(int[] arr) { 73 | if (arr == null || arr.length < 2) { 74 | return 0; 75 | } 76 | int N = arr.length; 77 | int L = 1; 78 | int leftMax = arr[0]; 79 | int R = N - 2; 80 | int rightMax = arr[N - 1]; 81 | int water = 0; 82 | while (L <= R) { 83 | if (leftMax <= rightMax) { 84 | water += Math.max(0, leftMax - arr[L]); 85 | leftMax = Math.max(leftMax, arr[L++]); 86 | } else { 87 | water += Math.max(0, rightMax - arr[R]); 88 | rightMax = Math.max(rightMax, arr[R--]); 89 | } 90 | } 91 | return water; 92 | } 93 | 94 | // for test 95 | public static int[] generateRandomArray(int len, int value) { 96 | int[] ans = new int[(int) (Math.random() * len) + 1]; 97 | for (int i = 0; i < ans.length; i++) { 98 | ans[i] = (int) (Math.random() * value) + 1; 99 | } 100 | return ans; 101 | } 102 | 103 | public static void main(String[] args) { 104 | int len = 100; 105 | int value = 200; 106 | int testTimes = 100000; 107 | System.out.println("test begin"); 108 | for (int i = 0; i < testTimes; i++) { 109 | int[] arr = generateRandomArray(len, value); 110 | int ans1 = water1(arr); 111 | int ans2 = water2(arr); 112 | int ans3 = water3(arr); 113 | int ans4 = water4(arr); 114 | if (ans1 != ans2 || ans3 != ans4 || ans1 != ans3) { 115 | System.out.println("Oops!"); 116 | } 117 | } 118 | System.out.println("test finish"); 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /src/class02/Code05_TrappingRainWaterII.java: -------------------------------------------------------------------------------- 1 | package class02; 2 | 3 | import java.util.Comparator; 4 | import java.util.PriorityQueue; 5 | 6 | public class Code05_TrappingRainWaterII { 7 | 8 | public static class Node { 9 | public int value; 10 | public int row; 11 | public int col; 12 | 13 | public Node(int v, int r, int c) { 14 | value = v; 15 | row = r; 16 | col = c; 17 | } 18 | 19 | } 20 | 21 | public static class NodeComparator implements Comparator { 22 | 23 | @Override 24 | public int compare(Node o1, Node o2) { 25 | return o1.value - o2.value; 26 | } 27 | 28 | } 29 | 30 | public static int trapRainWater(int[][] heightMap) { 31 | if (heightMap == null || heightMap.length == 0 || heightMap[0] == null || heightMap[0].length == 0) { 32 | return 0; 33 | } 34 | int N = heightMap.length; 35 | int M = heightMap[0].length; 36 | // isEnter[i][j] == true 之前进过 37 | // isEnter[i][j] == false 之前没进过 38 | boolean[][] isEnter = new boolean[N][M]; 39 | // 小根堆 40 | PriorityQueue heap = new PriorityQueue<>(new NodeComparator()); 41 | for (int col = 0; col < M - 1; col++) { 42 | isEnter[0][col] = true; 43 | heap.add(new Node(heightMap[0][col], 0, col)); 44 | } 45 | for (int row = 0; row < N - 1; row++) { 46 | isEnter[row][M - 1] = true; 47 | heap.add(new Node(heightMap[row][M - 1], row, M - 1)); 48 | } 49 | for (int col = M - 1; col > 0; col--) { 50 | isEnter[N - 1][col] = true; 51 | heap.add(new Node(heightMap[N - 1][col], N - 1, col)); 52 | } 53 | for (int row = N - 1; row > 0; row--) { 54 | isEnter[row][0] = true; 55 | heap.add(new Node(heightMap[row][0], row, 0)); 56 | } 57 | 58 | 59 | 60 | 61 | int water = 0; // 每个位置的水量,累加到water上去 62 | int max = 0; // 每个node在弹出的时候,如果value更大,更新max,否则max的值维持不变 63 | while (!heap.isEmpty()) { 64 | Node cur = heap.poll(); 65 | max = Math.max(max, cur.value); 66 | int r = cur.row; 67 | int c = cur.col; 68 | if (r > 0 && !isEnter[r - 1][c]) { // 如果有上面的位置并且上面位置没进过堆 69 | water += Math.max(0, max - heightMap[r - 1][c]); 70 | isEnter[r - 1][c] = true; 71 | heap.add(new Node(heightMap[r - 1][c], r - 1, c)); 72 | } 73 | if (r < N - 1 && !isEnter[r + 1][c]) { 74 | water += Math.max(0, max - heightMap[r + 1][c]); 75 | isEnter[r + 1][c] = true; 76 | heap.add(new Node(heightMap[r + 1][c], r + 1, c)); 77 | } 78 | if (c > 0 && !isEnter[r][c - 1]) { 79 | water += Math.max(0, max - heightMap[r][c - 1]); 80 | isEnter[r][c - 1] = true; 81 | heap.add(new Node(heightMap[r][c - 1], r, c - 1)); 82 | } 83 | if (c < M - 1 && !isEnter[r][c + 1]) { 84 | water += Math.max(0, max - heightMap[r][c + 1]); 85 | isEnter[r][c + 1] = true; 86 | heap.add(new Node(heightMap[r][c + 1], r, c + 1)); 87 | } 88 | } 89 | return water; 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /src/class02/Code06_PrintUniquePairAndTriad.java: -------------------------------------------------------------------------------- 1 | package class02; 2 | 3 | public class Code06_PrintUniquePairAndTriad { 4 | 5 | public static void printUniquePair(int[] arr, int k) { 6 | if (arr == null || arr.length < 2) { 7 | return; 8 | } 9 | int left = 0; 10 | int right = arr.length - 1; 11 | while (left < right) { 12 | if (arr[left] + arr[right] < k) { 13 | left++; 14 | } else if (arr[left] + arr[right] > k) { 15 | right--; 16 | } else { // L + R = aim 17 | if (left == 0 || arr[left - 1] != arr[left]) { 18 | System.out.println(arr[left] + "," + arr[right]); 19 | } 20 | left++; 21 | right--; 22 | } 23 | } 24 | } 25 | 26 | public static void printUniqueTriad(int[] arr, int k) { 27 | if (arr == null || arr.length < 3) { 28 | return; 29 | } 30 | for (int i = 0; i < arr.length - 2; i++) { 31 | if (i == 0 || arr[i] != arr[i - 1]) { 32 | printRest(arr, i, i + 1, arr.length - 1, k - arr[i]); 33 | } 34 | } 35 | } 36 | 37 | public static void printRest(int[] arr, int f, int l, int r, int k) { 38 | while (l < r) { 39 | if (arr[l] + arr[r] < k) { 40 | l++; 41 | } else if (arr[l] + arr[r] > k) { 42 | r--; 43 | } else { 44 | if (l == f + 1 || arr[l - 1] != arr[l]) { 45 | System.out.println(arr[f] + "," + arr[l] + "," + arr[r]); 46 | } 47 | l++; 48 | r--; 49 | } 50 | } 51 | } 52 | 53 | public static void printArray(int[] arr) { 54 | for (int i = 0; i != arr.length; i++) { 55 | System.out.print(arr[i] + " "); 56 | } 57 | System.out.println(); 58 | } 59 | 60 | public static void main(String[] args) { 61 | int sum = 10; 62 | int[] arr1 = { -8, -4, -3, 0, 1, 2, 4, 5, 8, 9 }; 63 | printArray(arr1); 64 | System.out.println("===="); 65 | printUniquePair(arr1, sum); 66 | System.out.println("===="); 67 | printUniqueTriad(arr1, sum); 68 | 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/class02/Code07_KthMinPair.java: -------------------------------------------------------------------------------- 1 | package class02; 2 | 3 | import java.util.Arrays; 4 | import java.util.Comparator; 5 | 6 | public class Code07_KthMinPair { 7 | 8 | public static class Pair { 9 | public int x; 10 | public int y; 11 | 12 | Pair(int x, int y) { 13 | this.x = x; 14 | this.y = y; 15 | } 16 | } 17 | 18 | public static class PairComparator implements Comparator { 19 | 20 | @Override 21 | public int compare(Pair arg0, Pair arg1) { 22 | return arg0.x != arg1.x ? arg0.x - arg1.x : arg0.y - arg1.y; 23 | } 24 | 25 | } 26 | 27 | // O(N^2 * log (N^2))的复杂度,你肯定过不了 28 | // 返回的int[] 长度是2,{3,1} int[2] = [3,1] 29 | public static int[] kthMinPair1(int[] arr, int k) { 30 | int N = arr.length; 31 | if (k > N * N) { 32 | return null; 33 | } 34 | Pair[] pairs = new Pair[N * N]; 35 | int index = 0; 36 | for (int i = 0; i < N; i++) { 37 | for (int j = 0; j < N; j++) { 38 | pairs[index++] = new Pair(arr[i], arr[j]); 39 | } 40 | } 41 | Arrays.sort(pairs, new PairComparator()); 42 | return new int[] { pairs[k - 1].x, pairs[k - 1].y }; 43 | } 44 | 45 | // O(N*logN)的复杂度,你肯定过了 46 | public static int[] kthMinPair2(int[] arr, int k) { 47 | int N = arr.length; 48 | if (k > N * N) { 49 | return null; 50 | } 51 | // O(N*logN) 52 | Arrays.sort(arr); 53 | // 第K小的数值对,第一维数字,是什么 是arr中 54 | int fristNum = arr[(k - 1) / N]; 55 | int lessFristNumSize = 0;// 数出比fristNum小的数有几个 56 | int fristNumSize = 0; // 数出==fristNum的数有几个 57 | // <= fristNum 58 | for (int i = 0; i < N && arr[i] <= fristNum; i++) { 59 | if (arr[i] < fristNum) { 60 | lessFristNumSize++; 61 | } else { 62 | fristNumSize++; 63 | } 64 | } 65 | int rest = k - (lessFristNumSize * N); 66 | return new int[] { fristNum, arr[(rest - 1) / fristNumSize] }; 67 | } 68 | 69 | // O(N)的复杂度,你肯定蒙了 70 | public static int[] kthMinPair3(int[] arr, int k) { 71 | int N = arr.length; 72 | if (k > N * N) { 73 | return null; 74 | } 75 | // 在无序数组中,找到第K小的数,返回值 76 | // 第K小,以1作为开始 77 | int fristNum = getMinKth(arr, (k - 1) / N); 78 | int lessFristNumSize = 0; 79 | int fristNumSize = 0; 80 | for (int i = 0; i < N; i++) { 81 | if (arr[i] < fristNum) { 82 | lessFristNumSize++; 83 | } 84 | if (arr[i] == fristNum) { 85 | fristNumSize++; 86 | } 87 | } 88 | int rest = k - (lessFristNumSize * N); 89 | return new int[] { fristNum, getMinKth(arr, (rest - 1) / fristNumSize) }; 90 | } 91 | 92 | // 改写快排,时间复杂度O(N) 93 | // 在无序数组arr中,找到,如果排序的话,arr[index]的数是什么? 94 | public static int getMinKth(int[] arr, int index) { 95 | int L = 0; 96 | int R = arr.length - 1; 97 | int pivot = 0; 98 | int[] range = null; 99 | while (L < R) { 100 | pivot = arr[L + (int) (Math.random() * (R - L + 1))]; 101 | range = partition(arr, L, R, pivot); 102 | if (index < range[0]) { 103 | R = range[0] - 1; 104 | } else if (index > range[1]) { 105 | L = range[1] + 1; 106 | } else { 107 | return pivot; 108 | } 109 | } 110 | return arr[L]; 111 | } 112 | 113 | public static int[] partition(int[] arr, int L, int R, int pivot) { 114 | int less = L - 1; 115 | int more = R + 1; 116 | int cur = L; 117 | while (cur < more) { 118 | if (arr[cur] < pivot) { 119 | swap(arr, ++less, cur++); 120 | } else if (arr[cur] > pivot) { 121 | swap(arr, cur, --more); 122 | } else { 123 | cur++; 124 | } 125 | } 126 | return new int[] { less + 1, more - 1 }; 127 | } 128 | 129 | public static void swap(int[] arr, int i, int j) { 130 | int tmp = arr[i]; 131 | arr[i] = arr[j]; 132 | arr[j] = tmp; 133 | } 134 | 135 | // 为了测试,生成值也随机,长度也随机的随机数组 136 | public static int[] getRandomArray(int max, int len) { 137 | int[] arr = new int[(int) (Math.random() * len) + 1]; 138 | for (int i = 0; i < arr.length; i++) { 139 | arr[i] = (int) (Math.random() * max) - (int) (Math.random() * max); 140 | } 141 | return arr; 142 | } 143 | 144 | // 为了测试 145 | public static int[] copyArray(int[] arr) { 146 | if (arr == null) { 147 | return null; 148 | } 149 | int[] res = new int[arr.length]; 150 | for (int i = 0; i < arr.length; i++) { 151 | res[i] = arr[i]; 152 | } 153 | return res; 154 | } 155 | 156 | // 随机测试了百万组,保证三种方法都是对的 157 | public static void main(String[] args) { 158 | int max = 100; 159 | int len = 30; 160 | int testTimes = 100000; 161 | System.out.println("test bagin, test times : " + testTimes); 162 | for (int i = 0; i < testTimes; i++) { 163 | int[] arr = getRandomArray(max, len); 164 | int[] arr1 = copyArray(arr); 165 | int[] arr2 = copyArray(arr); 166 | int[] arr3 = copyArray(arr); 167 | int N = arr.length * arr.length; 168 | int k = (int) (Math.random() * N) + 1; 169 | int[] ans1 = kthMinPair1(arr1, k); 170 | int[] ans2 = kthMinPair2(arr2, k); 171 | int[] ans3 = kthMinPair3(arr3, k); 172 | if (ans1[0] != ans2[0] || ans2[0] != ans3[0] || ans1[1] != ans2[1] || ans2[1] != ans3[1]) { 173 | System.out.println("Oops!"); 174 | } 175 | } 176 | System.out.println("test finish"); 177 | } 178 | 179 | } 180 | -------------------------------------------------------------------------------- /src/class03/Code01_ChooseWork.java: -------------------------------------------------------------------------------- 1 | package class03; 2 | 3 | import java.util.Arrays; 4 | import java.util.Comparator; 5 | import java.util.TreeMap; 6 | 7 | public class Code01_ChooseWork { 8 | 9 | public static class Job { 10 | public int money; 11 | public int hard; 12 | 13 | public Job(int money, int hard) { 14 | this.money = money; 15 | this.hard = hard; 16 | } 17 | } 18 | 19 | public static class JobComparator implements Comparator { 20 | @Override 21 | public int compare(Job o1, Job o2) { 22 | return o1.hard != o2.hard ? (o1.hard - o2.hard) : (o2.money - o1.money); 23 | } 24 | } 25 | 26 | public static int[] getMoneys(Job[] job, int[] ability) { 27 | Arrays.sort(job, new JobComparator()); 28 | // 难度为key的工作,最优钱数是多少,有序表 29 | TreeMap map = new TreeMap<>(); 30 | map.put(job[0].hard, job[0].money); 31 | Job pre = job[0]; // pre 之前组的组长 32 | for (int i = 1; i < job.length; i++) { 33 | if (job[i].hard != pre.hard && job[i].money > pre.money) { 34 | pre = job[i]; 35 | map.put(pre.hard, pre.money); 36 | } 37 | } 38 | int[] ans = new int[ability.length]; 39 | for (int i = 0; i < ability.length; i++) { 40 | Integer key = map.floorKey(ability[i]); 41 | ans[i] = key != null ? map.get(key) : 0; 42 | } 43 | return ans; 44 | } 45 | 46 | public static void main(String[] args) { 47 | // java中有序表是红黑树 48 | // 有序表可以被:红黑树、avl树、跳表、size-balanced-tree(SB树)实现 49 | // 不同的实现有什么区别:在使用层次上和性能上看,没区别。只有常数时间的区别。 50 | // 所有接口的性能O(logN) 51 | // 设计细节:扩展班最后一节 52 | // 有序表和哈希表的区别: 53 | // 哈希表的所有功能有序表一定有,哈希表的key(散乱组织,哈希函数) 54 | // 有序表所有的key有序组织,比哈希表的功能多。 55 | // 哈希表所有操作,使用时认为时间复杂度O(1),有序表所有接口的性能O(logN) 56 | TreeMap map = new TreeMap<>(); 57 | map.put(7, "我是7"); // (key,value) 所有的key按顺序组织 58 | map.put(3, "我是3"); 59 | map.put(9, "我是9"); 60 | map.put(2, "我是2"); 61 | map.put(8, "我是8"); 62 | map.put(5, "我是5"); 63 | 64 | map.put(5, "我还是5");// (5, 我还是5) 65 | 66 | 67 | System.out.println(map.containsKey(2)); 68 | System.out.println(map.get(7)); 69 | map.remove(9); 70 | 71 | 72 | 73 | 74 | System.out.println(map.firstKey()); 75 | System.out.println(map.lastKey()); 76 | // <= num 离num最近的key 77 | System.out.println(map.floorKey(6)); 78 | System.out.println(map.floorKey(-2)); 79 | // >= num 离num最近的东西 80 | System.out.println(map.ceilingKey(6)); 81 | System.out.println(map.ceilingKey(100)); 82 | 83 | // 时间复杂度全是O(logN)级别 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/class03/Code02_SnacksWays.java: -------------------------------------------------------------------------------- 1 | package class03; 2 | 3 | public class Code02_SnacksWays { 4 | 5 | public static int ways1(int[] arr, int w) { 6 | // arr[0...] 7 | return process(arr, 0, w); 8 | } 9 | 10 | // 从左往右的经典模型 11 | // 还剩的容量是rest,arr[index...]自由选择, 12 | // 返回选择方案 13 | // index : 0~N 14 | // rest : 0~w 15 | public static int process(int[] arr, int index, int rest) { 16 | if (rest < 0) { // 没有容量了 17 | // -1 无方案的意思 18 | return -1; 19 | } 20 | // rest>=0, 21 | if (index == arr.length) { // 无零食可选 22 | return 1; 23 | } 24 | // rest >=0 25 | // 有零食index 26 | // index号零食,要 or 不要 27 | // index, rest 28 | // (index+1, rest) 29 | // (index+1, rest-arr[i]) 30 | int next1 = process(arr, index + 1, rest); // 不要 31 | int next2 = process(arr, index + 1, rest - arr[index]); // 要 32 | return next1 + (next2 == -1 ? 0 : next2); 33 | } 34 | 35 | public static int ways2(int[] arr, int w) { 36 | int N = arr.length; 37 | int[][] dp = new int[N + 1][w + 1]; 38 | for (int j = 0; j <= w; j++) { 39 | dp[N][j] = 1; 40 | } 41 | for (int i = N - 1; i >= 0; i--) { 42 | for (int j = 0; j <= w; j++) { 43 | dp[i][j] = dp[i + 1][j] + ((j - arr[i] >= 0) ? dp[i + 1][j - arr[i]] : 0); 44 | } 45 | } 46 | return dp[0][w]; 47 | } 48 | 49 | public static int ways3(int[] arr, int w) { 50 | int N = arr.length; 51 | int[][] dp = new int[N][w + 1]; 52 | for (int i = 0; i < N; i++) { 53 | dp[i][0] = 1; 54 | } 55 | if (arr[0] <= w) { 56 | dp[0][arr[0]] = 1; 57 | } 58 | for (int i = 1; i < N; i++) { 59 | for (int j = 1; j <= w; j++) { 60 | dp[i][j] = dp[i - 1][j] + ((j - arr[i]) >= 0 ? dp[i - 1][j - arr[i]] : 0); 61 | } 62 | } 63 | int ans = 0; 64 | for (int j = 0; j <= w; j++) { 65 | ans += dp[N - 1][j]; 66 | } 67 | return ans; 68 | } 69 | 70 | public static void main(String[] args) { 71 | int[] arr = { 4, 3, 2, 9 }; 72 | int w = 8; 73 | System.out.println(ways1(arr, w)); 74 | System.out.println(ways2(arr, w)); 75 | System.out.println(ways3(arr, w)); 76 | 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/class03/Code03_MinPathSum.java: -------------------------------------------------------------------------------- 1 | package class03; 2 | 3 | public class Code03_MinPathSum { 4 | 5 | public static int minPathSum1(int[][] m) { 6 | if (m == null || m.length == 0 || m[0] == null || m[0].length == 0) { 7 | return 0; 8 | } 9 | int row = m.length; 10 | int col = m[0].length; 11 | int[][] dp = new int[row][col]; 12 | dp[0][0] = m[0][0]; 13 | for (int i = 1; i < row; i++) { 14 | dp[i][0] = dp[i - 1][0] + m[i][0]; 15 | } 16 | for (int j = 1; j < col; j++) { 17 | dp[0][j] = dp[0][j - 1] + m[0][j]; 18 | } 19 | for (int i = 1; i < row; i++) { 20 | for (int j = 1; j < col; j++) { 21 | dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + m[i][j]; 22 | } 23 | } 24 | return dp[row - 1][col - 1]; 25 | } 26 | 27 | public static int minPathSum2(int[][] m) { 28 | if (m == null || m.length == 0 || m[0] == null || m[0].length == 0) { 29 | return 0; 30 | } 31 | int more = Math.max(m.length, m[0].length); 32 | int less = Math.min(m.length, m[0].length); 33 | boolean rowmore = more == m.length; 34 | int[] arr = new int[less]; 35 | arr[0] = m[0][0]; 36 | for (int i = 1; i < less; i++) { 37 | arr[i] = arr[i - 1] + (rowmore ? m[0][i] : m[i][0]); 38 | } 39 | for (int i = 1; i < more; i++) { 40 | arr[0] = arr[0] + (rowmore ? m[i][0] : m[0][i]); 41 | for (int j = 1; j < less; j++) { 42 | arr[j] = Math.min(arr[j - 1], arr[j]) 43 | + (rowmore ? m[i][j] : m[j][i]); 44 | } 45 | } 46 | return arr[less - 1]; 47 | } 48 | 49 | 50 | public static int minPathSum3(int[][] m) { 51 | if (m == null || m.length == 0 || m[0] == null || m[0].length == 0) { 52 | return 0; 53 | } 54 | int[] dp = new int[m[0].length]; 55 | int N = m.length; 56 | int M = m[0].length; 57 | dp[0] = m[0][0]; 58 | for(int col = 1; col = 0) { 77 | if (n > 0 && dp[m][n] == dp[m][n - 1]) { 78 | n--; 79 | } else if (m > 0 && dp[m][n] == dp[m - 1][n]) { 80 | m--; 81 | } else { 82 | res[index--] = chs1[m]; 83 | m--; 84 | n--; 85 | } 86 | } 87 | return String.valueOf(res); 88 | } 89 | 90 | public static int[][] getdp(char[] str1, char[] str2) { 91 | int[][] dp = new int[str1.length][str2.length]; 92 | dp[0][0] = str1[0] == str2[0] ? 1 : 0; 93 | for (int i = 1; i < str1.length; i++) { 94 | dp[i][0] = Math.max(dp[i - 1][0], str1[i] == str2[0] ? 1 : 0); 95 | } 96 | for (int j = 1; j < str2.length; j++) { 97 | dp[0][j] = Math.max(dp[0][j - 1], str1[0] == str2[j] ? 1 : 0); 98 | } 99 | for (int i = 1; i < str1.length; i++) { 100 | for (int j = 1; j < str2.length; j++) { 101 | dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); 102 | if (str1[i] == str2[j]) { 103 | dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - 1] + 1); 104 | } 105 | } 106 | } 107 | return dp; 108 | } 109 | 110 | public static void main(String[] args) { 111 | String str1 = "A1BC23Z4"; 112 | String str2 = "12O3YU4P"; 113 | // System.out.println(lcse(str1, str2)); 114 | 115 | System.out.println(lcs(str1, str2)); 116 | System.out.println(dp(str1, str2)); 117 | 118 | } 119 | } -------------------------------------------------------------------------------- /src/class03/Code05_LCSubstring.java: -------------------------------------------------------------------------------- 1 | package class03; 2 | 3 | public class Code05_LCSubstring { 4 | 5 | public static String lcst1(String str1, String str2) { 6 | if (str1 == null || str2 == null || str1.equals("") || str2.equals("")) { 7 | return ""; 8 | } 9 | char[] chs1 = str1.toCharArray(); 10 | char[] chs2 = str2.toCharArray(); 11 | int[][] dp = getdp(chs1, chs2); 12 | int end = 0; 13 | int max = 0; 14 | for (int i = 0; i < chs1.length; i++) { 15 | for (int j = 0; j < chs2.length; j++) { 16 | if (dp[i][j] > max) { 17 | end = i; 18 | max = dp[i][j]; 19 | } 20 | } 21 | } 22 | return str1.substring(end - max + 1, end + 1); 23 | } 24 | 25 | public static int[][] getdp(char[] str1, char[] str2) { 26 | int[][] dp = new int[str1.length][str2.length]; 27 | for (int i = 0; i < str1.length; i++) { 28 | if (str1[i] == str2[0]) { 29 | dp[i][0] = 1; 30 | } 31 | } 32 | for (int j = 1; j < str2.length; j++) { 33 | if (str1[0] == str2[j]) { 34 | dp[0][j] = 1; 35 | } 36 | } 37 | for (int i = 1; i < str1.length; i++) { 38 | for (int j = 1; j < str2.length; j++) { 39 | if (str1[i] == str2[j]) { 40 | dp[i][j] = dp[i - 1][j - 1] + 1; 41 | } 42 | } 43 | } 44 | return dp; 45 | } 46 | 47 | public static String lcst2(String s1, String s2) { 48 | if (s1 == null || s2 == null || s1.equals("") || s2.equals("")) { 49 | return ""; 50 | } 51 | char[] str1 = s1.toCharArray(); 52 | char[] str2 = s2.toCharArray(); 53 | int row = 0; // 出发点的行号 54 | int col = str2.length - 1; // 出发点的列号 55 | int max = 0; 56 | int end = 0; 57 | while (row < str1.length) { 58 | int i = row; 59 | int j = col; 60 | int len = 0; 61 | // 向右下方移动的这一轮 62 | while (i < str1.length && j < str2.length) { 63 | if (str1[i] != str2[j]) { 64 | len = 0; 65 | } else { 66 | len++; 67 | } 68 | // len 69 | if (len > max) { 70 | end = i; 71 | max = len; 72 | } 73 | i++; 74 | j++; 75 | } 76 | if (col > 0) { 77 | col--; 78 | } else { 79 | row++; 80 | } 81 | } 82 | return s1.substring(end - max + 1, end + 1); 83 | } 84 | 85 | public static void main(String[] args) { 86 | String str1 = "ABC1234567DEFG"; 87 | String str2 = "HIJKL1234567MNOP"; 88 | System.out.println(lcst1(str1, str2)); 89 | System.out.println(lcst2(str1, str2)); 90 | 91 | } 92 | 93 | } -------------------------------------------------------------------------------- /src/class03/Code06_TopKTimes.java: -------------------------------------------------------------------------------- 1 | package class03; 2 | 3 | import java.util.Comparator; 4 | import java.util.HashMap; 5 | import java.util.Map.Entry; 6 | import java.util.PriorityQueue; 7 | 8 | public class Code06_TopKTimes { 9 | 10 | public static class Node { 11 | public String str; 12 | public int times; 13 | 14 | public Node(String s, int t) { 15 | str = s; 16 | times = t; 17 | } 18 | } 19 | 20 | public static class NodeComparator implements Comparator { 21 | 22 | @Override 23 | public int compare(Node o1, Node o2) { 24 | return o1.times - o2.times; 25 | } 26 | 27 | } 28 | 29 | public static void printTopKAndRank(String[] arr, int topK) { 30 | if (arr == null || arr.length == 0 || topK < 1 || topK > arr.length) { 31 | return; 32 | } 33 | HashMap map = new HashMap<>(); 34 | for (String str : arr) { 35 | if (!map.containsKey(str)) { 36 | map.put(str, 1); 37 | } else { 38 | map.put(str, map.get(str) + 1); 39 | } 40 | } 41 | topK = Math.min(arr.length, topK); 42 | PriorityQueue heap = new PriorityQueue<>(new NodeComparator()); 43 | for (Entry entry : map.entrySet()) { 44 | Node cur = new Node(entry.getKey(), entry.getValue()); 45 | if (heap.size() < topK) { 46 | heap.add(cur); 47 | } else { 48 | if (heap.peek().times < cur.times) { 49 | heap.poll(); 50 | heap.add(cur); 51 | } 52 | } 53 | } 54 | while (!heap.isEmpty()) { 55 | System.out.println(heap.poll().str); 56 | } 57 | } 58 | 59 | public static String[] generateRandomArray(int len, int max) { 60 | String[] res = new String[len]; 61 | for (int i = 0; i != len; i++) { 62 | res[i] = String.valueOf((int) (Math.random() * (max + 1))); 63 | } 64 | return res; 65 | } 66 | 67 | public static void printArray(String[] arr) { 68 | for (int i = 0; i != arr.length; i++) { 69 | System.out.print(arr[i] + " "); 70 | } 71 | System.out.println(); 72 | } 73 | 74 | public static void main(String[] args) { 75 | String[] arr1 = { "A", "B", "A", "C", "A", "C", "B", "B", "K" }; 76 | printTopKAndRank(arr1, 2); 77 | 78 | String[] arr2 = generateRandomArray(50, 10); 79 | int topK = 3; 80 | printArray(arr2); 81 | printTopKAndRank(arr2, topK); 82 | 83 | } 84 | } -------------------------------------------------------------------------------- /src/class03/Code07_TopKTimesRealTime.java: -------------------------------------------------------------------------------- 1 | package class03; 2 | 3 | import java.util.HashMap; 4 | 5 | public class Code07_TopKTimesRealTime { 6 | 7 | public static class Node { 8 | public String str; 9 | public int times; 10 | 11 | public Node(String s, int t) { 12 | str = s; 13 | times = t; 14 | } 15 | } 16 | 17 | public static class TopKRecord { 18 | private Node[] heap; 19 | private int heapSize; 20 | // string -> Node(times) 21 | private HashMap strNodeMap; 22 | private HashMap nodeIndexMap; 23 | 24 | public TopKRecord(int K) { 25 | heap = new Node[K]; 26 | heapSize = 0; 27 | strNodeMap = new HashMap(); 28 | nodeIndexMap = new HashMap(); 29 | } 30 | 31 | // str用户现在给我的 32 | public void add(String str) { 33 | Node curNode = null; 34 | int preIndex = -1; // str之前在堆上的位置 35 | // 查词频表,看看有没有关于这个str的记录 36 | if (!strNodeMap.containsKey(str)) { // str之前没进来过 37 | curNode = new Node(str, 1); 38 | strNodeMap.put(str, curNode); 39 | nodeIndexMap.put(curNode, -1); 40 | } else { // str之前进来过 41 | curNode = strNodeMap.get(str); 42 | curNode.times++; 43 | preIndex = nodeIndexMap.get(curNode); 44 | } 45 | 46 | // 词频表修改完毕, 47 | if (preIndex == -1) { // 不在堆上 48 | if (heapSize == heap.length) { // 堆满了 49 | if (heap[0].times < curNode.times) { 50 | nodeIndexMap.put(heap[0], -1); 51 | nodeIndexMap.put(curNode, 0); 52 | heap[0] = curNode; 53 | heapify(0, heapSize); 54 | } 55 | } else {// 堆没有满 56 | nodeIndexMap.put(curNode, heapSize); 57 | heap[heapSize] = curNode; 58 | heapInsert(heapSize++); 59 | } 60 | } else { // str已经在堆上了 61 | heapify(preIndex, heapSize); 62 | } 63 | } 64 | 65 | public void printTopK() { 66 | System.out.println("TOP: "); 67 | for (int i = 0; i != heap.length; i++) { 68 | if (heap[i] == null) { 69 | break; 70 | } 71 | System.out.print("Str: " + heap[i].str); 72 | System.out.println(" Times: " + heap[i].times); 73 | } 74 | } 75 | 76 | private void heapInsert(int index) { 77 | while (index != 0) { 78 | int parent = (index - 1) / 2; 79 | if (heap[index].times < heap[parent].times) { 80 | swap(parent, index); 81 | index = parent; 82 | } else { 83 | break; 84 | } 85 | } 86 | } 87 | 88 | private void heapify(int index, int heapSize) { 89 | int l = index * 2 + 1; 90 | int r = index * 2 + 2; 91 | int smallest = index; 92 | while (l < heapSize) { 93 | if (heap[l].times < heap[index].times) { 94 | smallest = l; 95 | } 96 | if (r < heapSize && heap[r].times < heap[smallest].times) { 97 | smallest = r; 98 | } 99 | if (smallest != index) { 100 | swap(smallest, index); 101 | } else { 102 | break; 103 | } 104 | index = smallest; 105 | l = index * 2 + 1; 106 | r = index * 2 + 2; 107 | } 108 | } 109 | 110 | private void swap(int index1, int index2) { 111 | nodeIndexMap.put(heap[index1], index2); 112 | nodeIndexMap.put(heap[index2], index1); 113 | Node tmp = heap[index1]; 114 | heap[index1] = heap[index2]; 115 | heap[index2] = tmp; 116 | } 117 | 118 | } 119 | 120 | public static String[] generateRandomArray(int len, int max) { 121 | String[] res = new String[len]; 122 | for (int i = 0; i != len; i++) { 123 | res[i] = String.valueOf((int) (Math.random() * (max + 1))); 124 | } 125 | return res; 126 | } 127 | 128 | public static void printArray(String[] arr) { 129 | for (int i = 0; i != arr.length; i++) { 130 | System.out.print(arr[i] + " "); 131 | } 132 | System.out.println(); 133 | } 134 | 135 | public static void main(String[] args) { 136 | TopKRecord record = new TopKRecord(2); 137 | record.add("zuo"); 138 | record.printTopK(); 139 | record.add("cheng"); 140 | record.add("cheng"); 141 | record.printTopK(); 142 | record.add("Yun"); 143 | record.add("Yun"); 144 | record.printTopK(); 145 | 146 | } 147 | } -------------------------------------------------------------------------------- /src/class03/Main.java: -------------------------------------------------------------------------------- 1 | //不要拷贝包信息的内容 2 | package class03; 3 | 4 | //本文件是Code02_SnacksWays问题的牛客题目解答 5 | //但是用的分治的方法 6 | //这是牛客的测试链接: 7 | //https://www.nowcoder.com/questionTerminal/d94bb2fa461d42bcb4c0f2b94f5d4281 8 | //把如下的全部代码拷贝进编辑器(java) 9 | //可以直接通过 10 | import java.util.Map.Entry; 11 | import java.util.Scanner; 12 | import java.util.TreeMap; 13 | 14 | public class Main { 15 | 16 | public static void main(String[] args) { 17 | Scanner sc = new Scanner(System.in); 18 | int N = sc.nextInt(); 19 | int bag = sc.nextInt(); 20 | int[] arr = new int[N]; 21 | for (int i = 0; i < arr.length; i++) { 22 | arr[i] = sc.nextInt(); 23 | } 24 | long ways = ways(arr, bag); 25 | System.out.println(ways); 26 | sc.close(); 27 | } 28 | 29 | public static long ways(int[] arr, int bag) { 30 | if (arr == null || arr.length == 0) { 31 | return 0; 32 | } 33 | if (arr.length == 1) { 34 | return arr[0] <= bag ? 2 : 1; 35 | } 36 | int mid = (arr.length - 1) >> 1; 37 | TreeMap lmap = new TreeMap<>(); 38 | long ways = process(arr, 0, 0, mid, bag, lmap); 39 | TreeMap rmap = new TreeMap<>(); 40 | ways += process(arr, mid + 1, 0, arr.length - 1, bag, rmap); 41 | TreeMap rpre = new TreeMap<>(); 42 | long pre = 0; 43 | for (Entry entry : rmap.entrySet()) { 44 | pre += entry.getValue(); 45 | rpre.put(entry.getKey(), pre); 46 | } 47 | for (Entry entry : lmap.entrySet()) { 48 | long lweight = entry.getKey(); 49 | long lways = entry.getValue(); 50 | Long floor = rpre.floorKey(bag - lweight); 51 | if (floor != null) { 52 | long rways = rpre.get(floor); 53 | ways += lways * rways; 54 | } 55 | } 56 | return ways + 1; 57 | } 58 | 59 | public static long process(int[] arr, int index, long w, int end, int bag, TreeMap map) { 60 | if (w > bag) { 61 | return 0; 62 | } 63 | if (index > end) { 64 | if (w != 0) { 65 | if (!map.containsKey(w)) { 66 | map.put(w, 1L); 67 | } else { 68 | map.put(w, map.get(w) + 1); 69 | } 70 | return 1; 71 | } else { 72 | return 0; 73 | } 74 | } else { 75 | long ways = process(arr, index + 1, w, end, bag, map); 76 | ways += process(arr, index + 1, w + arr[index], end, bag, map); 77 | return ways; 78 | } 79 | } 80 | 81 | } -------------------------------------------------------------------------------- /src/class03/TopK.java: -------------------------------------------------------------------------------- 1 | package class03; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Comparator; 5 | import java.util.HashMap; 6 | import java.util.List; 7 | import java.util.TreeSet; 8 | 9 | // 本文件是Code07_TopKTimesRealTime的线上测试 10 | // 测试链接:https://www.lintcode.com/problem/top-k-frequent-words-ii/description 11 | // 把以下的代码粘贴进java环境编辑器 12 | // 以上的代码不要粘贴 13 | // 可以直接通过 14 | public class TopK { 15 | 16 | public static class Node { 17 | public String str; 18 | public int times; 19 | 20 | public Node(String s, int t) { 21 | str = s; 22 | times = t; 23 | } 24 | } 25 | 26 | public static class NodeHeapComp implements Comparator { 27 | 28 | @Override 29 | public int compare(Node o1, Node o2) { 30 | return o1.times != o2.times ? (o1.times - o2.times) : (o2.str.compareTo(o1.str)); 31 | } 32 | 33 | } 34 | 35 | public static class NodeTreeSetComp implements Comparator { 36 | 37 | @Override 38 | public int compare(Node o1, Node o2) { 39 | return o1.times != o2.times ? (o2.times - o1.times) : (o1.str.compareTo(o2.str)); 40 | } 41 | 42 | } 43 | 44 | private Node[] heap; 45 | private int heapSize; 46 | private HashMap strNodeMap; 47 | private HashMap nodeIndexMap; 48 | private NodeHeapComp comp; 49 | private TreeSet treeSet; 50 | 51 | public TopK(int K) { 52 | heap = new Node[K]; 53 | heapSize = 0; 54 | strNodeMap = new HashMap(); 55 | nodeIndexMap = new HashMap(); 56 | comp = new NodeHeapComp(); 57 | treeSet = new TreeSet<>(new NodeTreeSetComp()); 58 | } 59 | 60 | public void add(String str) { 61 | if (heap.length == 0) { 62 | return; 63 | } 64 | Node curNode = null; 65 | int preIndex = -1; 66 | if (!strNodeMap.containsKey(str)) { 67 | curNode = new Node(str, 1); 68 | strNodeMap.put(str, curNode); 69 | nodeIndexMap.put(curNode, -1); 70 | } else { 71 | curNode = strNodeMap.get(str); 72 | // 要在time++之前,先在treeSet中删掉 73 | // 原因是因为一但times++,curNode在treeSet中的排序就失效了 74 | // 这种失效会导致整棵treeSet出现问题 75 | if (treeSet.contains(curNode)) { 76 | treeSet.remove(curNode); 77 | } 78 | curNode.times++; 79 | preIndex = nodeIndexMap.get(curNode); 80 | } 81 | if (preIndex == -1) { 82 | if (heapSize == heap.length) { 83 | if (comp.compare(heap[0], curNode) < 0) { 84 | treeSet.remove(heap[0]); 85 | treeSet.add(curNode); 86 | nodeIndexMap.put(heap[0], -1); 87 | nodeIndexMap.put(curNode, 0); 88 | heap[0] = curNode; 89 | heapify(0, heapSize); 90 | } 91 | } else { 92 | treeSet.add(curNode); 93 | nodeIndexMap.put(curNode, heapSize); 94 | heap[heapSize] = curNode; 95 | heapInsert(heapSize++); 96 | } 97 | } else { 98 | treeSet.add(curNode); 99 | heapify(preIndex, heapSize); 100 | } 101 | } 102 | 103 | public List topk() { 104 | ArrayList ans = new ArrayList<>(); 105 | for (Node node : treeSet) { 106 | ans.add(node.str); 107 | } 108 | return ans; 109 | } 110 | 111 | private void heapInsert(int index) { 112 | while (index != 0) { 113 | int parent = (index - 1) / 2; 114 | if (comp.compare(heap[index], heap[parent]) < 0) { 115 | swap(parent, index); 116 | index = parent; 117 | } else { 118 | break; 119 | } 120 | } 121 | } 122 | 123 | private void heapify(int index, int heapSize) { 124 | int l = index * 2 + 1; 125 | int r = index * 2 + 2; 126 | int smallest = index; 127 | while (l < heapSize) { 128 | if (comp.compare(heap[l], heap[index]) < 0) { 129 | smallest = l; 130 | } 131 | if (r < heapSize && comp.compare(heap[r], heap[smallest]) < 0) { 132 | smallest = r; 133 | } 134 | if (smallest != index) { 135 | swap(smallest, index); 136 | } else { 137 | break; 138 | } 139 | index = smallest; 140 | l = index * 2 + 1; 141 | r = index * 2 + 2; 142 | } 143 | } 144 | 145 | private void swap(int index1, int index2) { 146 | nodeIndexMap.put(heap[index1], index2); 147 | nodeIndexMap.put(heap[index2], index1); 148 | Node tmp = heap[index1]; 149 | heap[index1] = heap[index2]; 150 | heap[index2] = tmp; 151 | } 152 | 153 | } -------------------------------------------------------------------------------- /src/class04/Code01_GetFolderTree.java: -------------------------------------------------------------------------------- 1 | package class04; 2 | 3 | import java.util.TreeMap; 4 | 5 | public class Code01_GetFolderTree { 6 | 7 | public static class Node { 8 | // 上一个节点是通过哪条路,到我的 9 | public String path; 10 | // key : node下级的路 value:node在key这条路上对应的节点是什么 11 | public TreeMap nextMap; 12 | 13 | public Node(String p) { 14 | this.path = p; 15 | nextMap = new TreeMap<>(); 16 | } 17 | } 18 | 19 | // folderPaths -> [ "a\b\c","a\b\s" , "a\d\e" ,"e\f\sty" ] 20 | public static void print(String[] folderPaths) { 21 | if (folderPaths == null || folderPaths.length == 0) { 22 | return; 23 | } 24 | // 根据所有字符串,把前缀树建立好,头节点为head 25 | Node head = generateFolderTree(folderPaths); 26 | 27 | // 打印 28 | printProcess(head, 0); 29 | } 30 | 31 | public static Node generateFolderTree(String[] folderPaths) { 32 | Node head = new Node(""); // 系统根目录, 前缀树头节点 33 | for (String foldPath : folderPaths) { // 拿出每一个绝对路径 34 | String[] paths = foldPath.split("\\\\"); // java 特性,用一个"\"做分割的意思 35 | Node cur = head; 36 | for (int i = 0; i < paths.length; i++) { // "a" , "b" ,"c" 37 | if (!cur.nextMap.containsKey(paths[i])) { 38 | cur.nextMap.put(paths[i], new Node(paths[i])); 39 | } 40 | cur = cur.nextMap.get(paths[i]); 41 | } 42 | } 43 | return head; 44 | } 45 | 46 | // head节点,当前在level层 47 | public static void printProcess(Node node, int level) { 48 | if (level != 0) { 49 | // 2 * (level - 1) 50 | System.out.println(get4nSpace(level) + node.path); 51 | } 52 | for (Node next : node.nextMap.values()) { 53 | printProcess(next, level + 1); 54 | } 55 | } 56 | 57 | public static String get4nSpace(int n) { 58 | String res = ""; 59 | for (int i = 1; i < n; i++) { 60 | res += " "; 61 | } 62 | return res; 63 | } 64 | 65 | public static void main(String[] args) { 66 | 67 | // "a\b\c" '\' a,b,c 68 | String test = "a\\b\\cd"; 69 | 70 | 71 | 72 | 73 | 74 | // "a\b\c" "\" a,b,c 75 | String[] arr = test.split("\\\\"); // \\\\ \\ \ 76 | for(String str : arr) { 77 | System.out.println(str); 78 | } 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/class04/Code02_BSTtoDoubleLinkedList.java: -------------------------------------------------------------------------------- 1 | package class04; 2 | 3 | import java.util.LinkedList; 4 | import java.util.Queue; 5 | 6 | public class Code02_BSTtoDoubleLinkedList { 7 | 8 | public static class Node { 9 | public int value; 10 | public Node left; 11 | public Node right; 12 | 13 | public Node(int data) { 14 | this.value = data; 15 | } 16 | } 17 | 18 | public static Node convert1(Node head) { 19 | Queue queue = new LinkedList(); 20 | inOrderToQueue(head, queue); 21 | if (queue.isEmpty()) { 22 | return head; 23 | } 24 | head = queue.poll(); 25 | Node pre = head; 26 | pre.left = null; 27 | Node cur = null; 28 | while (!queue.isEmpty()) { 29 | cur = queue.poll(); 30 | pre.right = cur; 31 | cur.left = pre; 32 | pre = cur; 33 | } 34 | pre.right = null; 35 | return head; 36 | } 37 | 38 | public static void inOrderToQueue(Node head, Queue queue) { 39 | if (head == null) { 40 | return; 41 | } 42 | inOrderToQueue(head.left, queue); 43 | queue.offer(head); 44 | inOrderToQueue(head.right, queue); 45 | } 46 | 47 | 48 | 49 | public static Node convert2(Node head) { 50 | if (head == null) { 51 | return null; 52 | } 53 | return process(head).start; 54 | } 55 | 56 | // 整棵树,串成双向链表,返回头、尾 57 | public static class Info { 58 | public Node start; 59 | public Node end; 60 | 61 | public Info(Node start, Node end) { 62 | this.start = start; 63 | this.end = end; 64 | } 65 | } 66 | 67 | // 以x为头的整棵搜索二叉树,请全部以有序双向链表的方式,连好 68 | // 并且返回,整个有序双向链表的头节点和尾节点 69 | public static Info process(Node X) { 70 | if (X == null) { 71 | return new Info(null, null); 72 | } 73 | Info leftInfo = process(X.left); 74 | Info rightInfo = process(X.right); 75 | if (leftInfo.end != null) { 76 | leftInfo.end.right = X; 77 | } 78 | X.left = leftInfo.end; 79 | X.right = rightInfo.start; 80 | if (rightInfo.start != null) { 81 | rightInfo.start.left = X; 82 | } 83 | return new Info( 84 | // 整棵树的头, 85 | leftInfo.start != null ? leftInfo.start : X 86 | , 87 | // 整棵树的尾 88 | rightInfo.end != null ? rightInfo.end : X); 89 | } 90 | 91 | public static void printBSTInOrder(Node head) { 92 | System.out.print("BST in-order: "); 93 | if (head != null) { 94 | inOrderPrint(head); 95 | } 96 | System.out.println(); 97 | } 98 | 99 | public static void inOrderPrint(Node head) { 100 | if (head == null) { 101 | return; 102 | } 103 | inOrderPrint(head.left); 104 | System.out.print(head.value + " "); 105 | inOrderPrint(head.right); 106 | } 107 | 108 | public static void printDoubleLinkedList(Node head) { 109 | System.out.print("Double Linked List: "); 110 | Node end = null; 111 | while (head != null) { 112 | System.out.print(head.value + " "); 113 | end = head; 114 | head = head.right; 115 | } 116 | System.out.print("| "); 117 | while (end != null) { 118 | System.out.print(end.value + " "); 119 | end = end.left; 120 | } 121 | System.out.println(); 122 | } 123 | 124 | public static void main(String[] args) { 125 | Node head = new Node(5); 126 | head.left = new Node(2); 127 | head.right = new Node(9); 128 | head.left.left = new Node(1); 129 | head.left.right = new Node(3); 130 | head.left.right.right = new Node(4); 131 | head.right.left = new Node(7); 132 | head.right.right = new Node(10); 133 | head.left.left = new Node(1); 134 | head.right.left.left = new Node(6); 135 | head.right.left.right = new Node(8); 136 | 137 | printBSTInOrder(head); 138 | head = convert1(head); 139 | printDoubleLinkedList(head); 140 | 141 | head = new Node(5); 142 | head.left = new Node(2); 143 | head.right = new Node(9); 144 | head.left.left = new Node(1); 145 | head.left.right = new Node(3); 146 | head.left.right.right = new Node(4); 147 | head.right.left = new Node(7); 148 | head.right.right = new Node(10); 149 | head.left.left = new Node(1); 150 | head.right.left.left = new Node(6); 151 | head.right.left.right = new Node(8); 152 | 153 | printBSTInOrder(head); 154 | head = convert2(head); 155 | printDoubleLinkedList(head); 156 | 157 | } 158 | 159 | } -------------------------------------------------------------------------------- /src/class04/Code03_PreAndInArrayToPosArray.java: -------------------------------------------------------------------------------- 1 | package class04; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.HashSet; 6 | 7 | public class Code03_PreAndInArrayToPosArray { 8 | 9 | public static class Node { 10 | public int value; 11 | public Node left; 12 | public Node right; 13 | 14 | public Node(int v) { 15 | value = v; 16 | } 17 | } 18 | 19 | public static int[] preInToPos1(int[] pre, int[] in) { 20 | if (pre == null || in == null || pre.length != in.length) { 21 | return null; 22 | } 23 | int N = pre.length; 24 | int[] pos = new int[N]; 25 | process1(pre, 0, N - 1, in, 0, N - 1, pos, 0, N - 1); 26 | return pos; 27 | } 28 | 29 | // L1...R1 L2...R2 L3...R3 30 | public static void process1( 31 | int[] pre, int L1, int R1, 32 | int[] in, int L2, int R2, 33 | int[] pos, int L3, int R3) { 34 | if (L1 > R1) { 35 | return; 36 | } 37 | if (L1 == R1) { 38 | pos[L3] = pre[L1]; 39 | return; 40 | } 41 | pos[R3] = pre[L1]; 42 | int mid = L2; 43 | for (; mid <= R2; mid++) { 44 | if (in[mid] == pre[L1]) { 45 | break; 46 | } 47 | } 48 | int leftSize = mid - L2; 49 | process1(pre, L1 + 1, L1 + leftSize, in, L2, mid - 1, pos, L3, L3 + leftSize - 1); 50 | process1(pre, L1 + leftSize + 1, R1, in, mid + 1, R2, pos, L3 + leftSize, R3 - 1); 51 | } 52 | 53 | public static int[] preInToPos2(int[] pre, int[] in) { 54 | if (pre == null || in == null || pre.length != in.length) { 55 | return null; 56 | } 57 | int N = pre.length; 58 | HashMap inMap = new HashMap<>(); 59 | for (int i = 0; i < N; i++) { 60 | inMap.put(in[i], i); 61 | } 62 | int[] pos = new int[N]; 63 | process2(pre, 0, N - 1, in, 0, N - 1, pos, 0, N - 1, inMap); 64 | return pos; 65 | } 66 | 67 | public static void process2(int[] pre, int L1, int R1, int[] in, int L2, int R2, int[] pos, int L3, int R3, 68 | HashMap inMap) { 69 | if (L1 > R1) { 70 | return; 71 | } 72 | if (L1 == R1) { 73 | pos[L3] = pre[L1]; 74 | return; 75 | } 76 | pos[R3] = pre[L1]; 77 | int mid = inMap.get(pre[L1]); 78 | int leftSize = mid - L2; 79 | process2(pre, L1 + 1, L1 + leftSize, in, L2, mid - 1, pos, L3, L3 + leftSize - 1, inMap); 80 | process2(pre, L1 + leftSize + 1, R1, in, mid + 1, R2, pos, L3 + leftSize, R3 - 1, inMap); 81 | } 82 | 83 | // for test 84 | public static int[] getPreArray(Node head) { 85 | ArrayList arr = new ArrayList<>(); 86 | fillPreArray(head, arr); 87 | int[] ans = new int[arr.size()]; 88 | for (int i = 0; i < ans.length; i++) { 89 | ans[i] = arr.get(i); 90 | } 91 | return ans; 92 | } 93 | 94 | // for test 95 | public static void fillPreArray(Node head, ArrayList arr) { 96 | if (head == null) { 97 | return; 98 | } 99 | arr.add(head.value); 100 | fillPreArray(head.left, arr); 101 | fillPreArray(head.right, arr); 102 | } 103 | 104 | // for test 105 | public static int[] getInArray(Node head) { 106 | ArrayList arr = new ArrayList<>(); 107 | fillInArray(head, arr); 108 | int[] ans = new int[arr.size()]; 109 | for (int i = 0; i < ans.length; i++) { 110 | ans[i] = arr.get(i); 111 | } 112 | return ans; 113 | } 114 | 115 | // for test 116 | public static void fillInArray(Node head, ArrayList arr) { 117 | if (head == null) { 118 | return; 119 | } 120 | fillInArray(head.left, arr); 121 | arr.add(head.value); 122 | fillInArray(head.right, arr); 123 | } 124 | 125 | // for test 126 | public static int[] getPosArray(Node head) { 127 | ArrayList arr = new ArrayList<>(); 128 | fillPostArray(head, arr); 129 | int[] ans = new int[arr.size()]; 130 | for (int i = 0; i < ans.length; i++) { 131 | ans[i] = arr.get(i); 132 | } 133 | return ans; 134 | } 135 | 136 | // for test 137 | public static void fillPostArray(Node head, ArrayList arr) { 138 | if (head == null) { 139 | return; 140 | } 141 | fillPostArray(head.left, arr); 142 | fillPostArray(head.right, arr); 143 | arr.add(head.value); 144 | } 145 | 146 | // for test 147 | public static Node generateRandomTree(int value, int N) { 148 | HashSet hasValue = new HashSet(); 149 | return createTree(value, 1, N, hasValue); 150 | } 151 | 152 | // for test 153 | public static Node createTree(int value, int level, int N, HashSet hasValue) { 154 | if (level > N) { 155 | return null; 156 | } 157 | int cur = 0; 158 | do { 159 | cur = (int) (Math.random() * value) + 1; 160 | } while (hasValue.contains(cur)); 161 | hasValue.add(cur); 162 | Node head = new Node(cur); 163 | head.left = createTree(value, level + 1, N, hasValue); 164 | head.right = createTree(value, level + 1, N, hasValue); 165 | return head; 166 | } 167 | 168 | // for test 169 | public static boolean isEqual(int[] arr1, int[] arr2) { 170 | if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) { 171 | return false; 172 | } 173 | if (arr1 == null && arr2 == null) { 174 | return true; 175 | } 176 | if (arr1.length != arr2.length) { 177 | return false; 178 | } 179 | for (int i = 0; i < arr1.length; i++) { 180 | if (arr1[i] != arr2[i]) { 181 | return false; 182 | } 183 | } 184 | return true; 185 | } 186 | 187 | public static void main(String[] args) { 188 | System.out.println("test begin"); 189 | int N = 5; 190 | int value = 1000; 191 | int testTime = 100000; 192 | for (int i = 0; i < testTime; i++) { 193 | Node head = generateRandomTree(value, N); 194 | int[] pre = getPreArray(head); 195 | int[] in = getInArray(head); 196 | int[] pos = getPosArray(head); 197 | int[] ans1 = preInToPos1(pre, in); 198 | int[] ans2 = preInToPos2(pre, in); 199 | if (!isEqual(pos, ans1) || !isEqual(ans1, ans2)) { 200 | System.out.println("Oops!"); 201 | } 202 | } 203 | System.out.println("test end"); 204 | 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /src/class04/Code04_LIS.java: -------------------------------------------------------------------------------- 1 | package class04; 2 | 3 | public class Code04_LIS { 4 | 5 | public static int[] lis1(int[] arr) { 6 | if (arr == null || arr.length == 0) { 7 | return null; 8 | } 9 | int[] dp = getdp1(arr); 10 | return generateLIS(arr, dp); 11 | } 12 | 13 | public static int[] getdp1(int[] arr) { 14 | int[] dp = new int[arr.length]; 15 | for (int i = 0; i < arr.length; i++) { 16 | dp[i] = 1; 17 | for (int j = 0; j < i; j++) { 18 | if (arr[i] > arr[j]) { 19 | dp[i] = Math.max(dp[i], dp[j] + 1); 20 | } 21 | } 22 | } 23 | return dp; 24 | } 25 | 26 | public static int[] generateLIS(int[] arr, int[] dp) { 27 | int len = 0; 28 | int index = 0; 29 | for (int i = 0; i < dp.length; i++) { 30 | if (dp[i] > len) { 31 | len = dp[i]; 32 | index = i; 33 | } 34 | } 35 | int[] lis = new int[len]; 36 | lis[--len] = arr[index]; 37 | for (int i = index; i >= 0; i--) { 38 | if (arr[i] < arr[index] && dp[i] == dp[index] - 1) { 39 | lis[--len] = arr[i]; 40 | index = i; 41 | } 42 | } 43 | return lis; 44 | } 45 | 46 | public static int[] lis2(int[] arr) { 47 | if (arr == null || arr.length == 0) { 48 | return null; 49 | } 50 | int[] dp = getdp2(arr); 51 | return generateLIS(arr, dp); 52 | } 53 | 54 | public static int[] getdp2(int[] arr) { 55 | int[] dp = new int[arr.length]; 56 | int[] ends = new int[arr.length]; 57 | ends[0] = arr[0]; 58 | dp[0] = 1; 59 | int right = 0; // 0....right right往右无效 60 | int l = 0; 61 | int r = 0; 62 | int m = 0; 63 | for (int i = 1; i < arr.length; i++) { 64 | l = 0; 65 | r = right; 66 | while (l <= r) { 67 | m = (l + r) / 2; 68 | if (arr[i] > ends[m]) { 69 | l = m + 1; 70 | } else { 71 | r = m - 1; 72 | } 73 | } 74 | // l -> right+1 75 | right = Math.max(right, l); 76 | ends[l] = arr[i]; 77 | dp[i] = l + 1; 78 | } 79 | return dp; 80 | } 81 | 82 | // for test 83 | public static void printArray(int[] arr) { 84 | for (int i = 0; i != arr.length; i++) { 85 | System.out.print(arr[i] + " "); 86 | } 87 | System.out.println(); 88 | } 89 | 90 | public static void main(String[] args) { 91 | int[] arr = { 2, 1, 5, 3, 6, 4, 8, 9, 7 }; 92 | printArray(arr); 93 | printArray(lis1(arr)); 94 | printArray(lis2(arr)); 95 | 96 | } 97 | } -------------------------------------------------------------------------------- /src/class04/Code05_EnvelopesProblem.java: -------------------------------------------------------------------------------- 1 | package class04; 2 | 3 | import java.util.Arrays; 4 | import java.util.Comparator; 5 | 6 | public class Code05_EnvelopesProblem { 7 | 8 | public static class Envelope { 9 | public int l; 10 | public int h; 11 | 12 | public Envelope(int weight, int hight) { 13 | l = weight; 14 | h = hight; 15 | } 16 | } 17 | 18 | public static class EnvelopeComparator implements Comparator { 19 | @Override 20 | public int compare(Envelope o1, Envelope o2) { 21 | return o1.l != o2.l ? o1.l - o2.l : o2.h - o1.h; 22 | } 23 | } 24 | 25 | public static Envelope[] getSortedEnvelopes(int[][] matrix) { 26 | Envelope[] res = new Envelope[matrix.length]; 27 | for (int i = 0; i < matrix.length; i++) { 28 | res[i] = new Envelope(matrix[i][0], matrix[i][1]); 29 | } 30 | Arrays.sort(res, new EnvelopeComparator()); 31 | return res; 32 | } 33 | 34 | public static int maxEnvelopes(int[][] matrix) { 35 | Envelope[] envelopes = getSortedEnvelopes(matrix); 36 | int[] ends = new int[matrix.length]; 37 | ends[0] = envelopes[0].h; 38 | int right = 0; 39 | int l = 0; 40 | int r = 0; 41 | int m = 0; 42 | for (int i = 1; i < envelopes.length; i++) { 43 | l = 0; 44 | r = right; 45 | while (l <= r) { 46 | m = (l + r) / 2; 47 | if (envelopes[i].h > ends[m]) { 48 | l = m + 1; 49 | } else { 50 | r = m - 1; 51 | } 52 | } 53 | right = Math.max(right, l); 54 | ends[l] = envelopes[i].h; 55 | } 56 | return right + 1; 57 | } 58 | 59 | public static void main(String[] args) { 60 | int[][] test = { { 3, 4 }, { 2, 3 }, { 4, 5 }, { 1, 3 }, { 2, 2 }, { 3, 6 }, { 1, 2 }, { 3, 2 }, { 2, 4 } }; 61 | System.out.println(maxEnvelopes(test)); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/class04/Code06_SubArrayMaxSum.java: -------------------------------------------------------------------------------- 1 | package class04; 2 | 3 | public class Code06_SubArrayMaxSum { 4 | 5 | public static int maxSum(int[] arr) { 6 | if (arr == null || arr.length == 0) { 7 | return 0; 8 | } 9 | int max = Integer.MIN_VALUE; 10 | int cur = 0; 11 | for (int i = 0; i < arr.length; i++) { 12 | cur += arr[i]; 13 | max = Math.max(max, cur); 14 | cur = cur < 0 ? 0 : cur; 15 | } 16 | return max; 17 | } 18 | 19 | public static void printArray(int[] arr) { 20 | for (int i = 0; i != arr.length; i++) { 21 | System.out.print(arr[i] + " "); 22 | } 23 | System.out.println(); 24 | } 25 | 26 | public static void main(String[] args) { 27 | int[] arr1 = { -2, -3, -5, 40, -10, -10, 100, 1 }; 28 | System.out.println(maxSum(arr1)); 29 | 30 | int[] arr2 = { -2, -3, -5, 0, 1, 2, -1 }; 31 | System.out.println(maxSum(arr2)); 32 | 33 | int[] arr3 = { -2, -3, -5, -1 }; 34 | System.out.println(maxSum(arr3)); 35 | 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/class04/Code07_SubMatrixMaxSum.java: -------------------------------------------------------------------------------- 1 | package class04; 2 | 3 | public class Code07_SubMatrixMaxSum { 4 | 5 | public static int maxSum(int[][] m) { 6 | if (m == null || m.length == 0 || m[0].length == 0) { 7 | return 0; 8 | } 9 | int max = Integer.MIN_VALUE; 10 | int cur = 0; 11 | int[] s = null; 12 | for (int i = 0; i != m.length; i++) { // 开始的行号i 13 | s = new int[m[0].length]; // 14 | for (int j = i; j != m.length; j++) { // 结束的行号j,i~j行是我讨论的范围 15 | cur = 0; 16 | for (int k = 0; k != s.length; k++) { 17 | s[k] += m[j][k]; 18 | cur += s[k]; 19 | max = Math.max(max, cur); 20 | cur = cur < 0 ? 0 : cur; 21 | } 22 | } 23 | } 24 | return max; 25 | } 26 | 27 | public static void main(String[] args) { 28 | int[][] matrix = { { -90, 48, 78 }, { 64, -40, 64 }, { -81, -7, 66 } }; 29 | System.out.println(maxSum(matrix)); 30 | 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/class05/Code01_DeleteMinCost.java: -------------------------------------------------------------------------------- 1 | package class05; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Comparator; 5 | import java.util.HashMap; 6 | import java.util.List; 7 | 8 | public class Code01_DeleteMinCost { 9 | 10 | // 题目: 11 | // 给定两个字符串s1和s2,问s2最少删除多少字符可以成为s1的子串? 12 | // 比如 s1 = "abcde",s2 = "axbc" 13 | // 返回 1 14 | 15 | // 解法一,来自群里的解法: 16 | // 求出str2所有的子序列,然后按照长度排序,长度大的排在前面。 17 | // 然后考察哪个子序列字符串和s1的某个子串相等(KMP),答案就出来了。 18 | // 分析: 19 | // 因为题目原本的样本数据中,有特别说明s2的长度很小。所以这么做也没有太大问题,也几乎不会超时。 20 | // 但是如果某一次考试给定的s2长度远大于s1,这么做就不合适了。 21 | public static int minCost1(String s1, String s2) { 22 | List s2Subs = new ArrayList<>(); 23 | process(s2.toCharArray(), 0, "", s2Subs); 24 | s2Subs.sort(new LenComp()); 25 | for (String str : s2Subs) { 26 | if (s1.indexOf(str) != -1) { // indexOf底层和KMP算法代价几乎一样,也可以用KMP代替 27 | return s2.length() - str.length(); 28 | } 29 | } 30 | return s2.length(); 31 | } 32 | 33 | public static void process(char[] str2, int index, String path, List list) { 34 | if (index == str2.length) { 35 | list.add(path); 36 | return; 37 | } 38 | process(str2, index + 1, path, list); 39 | process(str2, index + 1, path + str2[index], list); 40 | } 41 | 42 | public static class LenComp implements Comparator { 43 | 44 | @Override 45 | public int compare(String o1, String o2) { 46 | return o2.length() - o1.length(); 47 | } 48 | 49 | } 50 | 51 | // 解法二 52 | // 我的方法,看的时间比较短,希望同学们积极反馈 53 | // 生成所有s1的子串 54 | // 然后考察每个子串和s2的编辑距离(假设编辑距离只有删除动作且删除一个字符的代价为1) 55 | // 如果s1的长度较小,s2长度较大,这个方法比较合适 56 | public static int minCost2(String s1, String s2) { 57 | if (s1.length() == 0 || s2.length() == 0) { 58 | return s2.length(); 59 | } 60 | int ans = Integer.MAX_VALUE; 61 | char[] str2 = s2.toCharArray(); 62 | for (int start = 0; start < s1.length(); start++) { 63 | for (int end = start + 1; end <= s1.length(); end++) { 64 | // str1[start....end] 65 | // substring -> [ 0,1 ) 66 | ans = Math.min(ans, distance(str2, s1.substring(start, end).toCharArray())); 67 | } 68 | } 69 | return ans == Integer.MAX_VALUE ? s2.length() : ans; 70 | } 71 | 72 | // 求str2到s1sub的编辑距离 73 | // 假设编辑距离只有删除动作且删除一个字符的代价为1 74 | public static int distance(char[] str2, char[] s1sub) { 75 | int row = str2.length; 76 | int col = s1sub.length; 77 | int[][] dp = new int[row][col]; 78 | // dp[i][j]的含义: 79 | // str2[0..i]仅通过删除行为变成s1sub[0..j]的最小代价 80 | // 可能性一: 81 | // str2[0..i]变的过程中,不保留最后一个字符(str2[i]), 82 | // 那么就是通过str2[0..i-1]变成s1sub[0..j]之后,再最后删掉str2[i]即可 -> dp[i][j] = dp[i-1][j] + 1 83 | // 可能性二: 84 | // str2[0..i]变的过程中,想保留最后一个字符(str2[i]),然后变成s1sub[0..j], 85 | // 这要求str2[i] == s1sub[j]才有这种可能, 然后str2[0..i-1]变成s1sub[0..j-1]即可 86 | // 也就是str2[i] == s1sub[j] 的条件下,dp[i][j] = dp[i-1][j-1] 87 | dp[0][0] = str2[0] == s1sub[0] ? 0 : Integer.MAX_VALUE; 88 | for (int j = 1; j < col; j++) { 89 | dp[0][j] = Integer.MAX_VALUE; 90 | } 91 | for (int i = 1; i < row; i++) { 92 | dp[i][0] = (dp[i - 1][0] != Integer.MAX_VALUE || str2[i] == s1sub[0]) ? i : Integer.MAX_VALUE; 93 | } 94 | for (int i = 1; i < row; i++) { 95 | for (int j = 1; j < col; j++) { 96 | dp[i][j] = Integer.MAX_VALUE; 97 | if (dp[i - 1][j] != Integer.MAX_VALUE) { 98 | dp[i][j] = dp[i - 1][j] + 1; 99 | } 100 | if (str2[i] == s1sub[j] && dp[i - 1][j - 1] != Integer.MAX_VALUE) { 101 | dp[i][j] = Math.min(dp[i][j], dp[i - 1][j - 1]); 102 | } 103 | 104 | } 105 | } 106 | return dp[row - 1][col - 1]; 107 | } 108 | 109 | // 解法二的优化 110 | public static int minCost3(String s1, String s2) { 111 | if (s1.length() == 0 || s2.length() == 0) { 112 | return s2.length(); 113 | } 114 | char[] str2 = s2.toCharArray(); 115 | char[] str1 = s1.toCharArray(); 116 | int M = str2.length; 117 | int N = str1.length; 118 | int[][] dp = new int[M][N]; 119 | int ans = M; 120 | for (int start = 0; start < N; start++) { // 开始的列数 121 | dp[0][start] = str2[0] == str1[start] ? 0 : M; 122 | for (int row = 1; row < M; row++) { 123 | dp[row][start] = (str2[row] == str1[start] || dp[row - 1][start] != M) ? row : M; 124 | } 125 | ans = Math.min(ans, dp[M - 1][start]); 126 | // 以上已经把start列,填好 127 | // 以下要把dp[...][start+1....N-1]的信息填好 128 | // start...end end - start +2 129 | for (int end = start + 1; end < N && end - start < M; end++) { 130 | // 0... first-1 行 不用管 131 | int first = end - start; 132 | dp[first][end] = (str2[first] == str1[end] && dp[first - 1][end - 1] == 0) ? 0 : M; 133 | for (int row = first + 1; row < M; row++) { 134 | dp[row][end] = M; 135 | if (dp[row - 1][end] != M) { 136 | dp[row][end] = dp[row - 1][end] + 1; 137 | } 138 | if (dp[row - 1][end - 1] != M && str2[row] == str1[end]) { 139 | dp[row][end] = Math.min(dp[row][end], dp[row - 1][end - 1]); 140 | } 141 | } 142 | ans = Math.min(ans, dp[M - 1][end]); 143 | } 144 | } 145 | return ans; 146 | } 147 | 148 | // 来自学生的做法,时间复杂度O(N * M平方) 149 | // 复杂度和方法三一样,但是思路截然不同 150 | public static int minCost4(String s1, String s2) { 151 | char[] str1 = s1.toCharArray(); 152 | char[] str2 = s2.toCharArray(); 153 | HashMap> map1 = new HashMap<>(); 154 | for (int i = 0; i < str1.length; i++) { 155 | ArrayList list = map1.getOrDefault(str1[i], new ArrayList()); 156 | list.add(i); 157 | map1.put(str1[i], list); 158 | } 159 | int ans = 0; 160 | // 假设删除后的str2必以i位置开头 161 | // 那么查找i位置在str1上一共有几个,并对str1上的每个位置开始遍历 162 | // 再次遍历str2一次,看存在对应str1中i后续连续子串可容纳的最长长度 163 | for (int i = 0; i < str2.length; i++) { 164 | if (map1.containsKey(str2[i])) { 165 | ArrayList keyList = map1.get(str2[i]); 166 | for (int j = 0; j < keyList.size(); j++) { 167 | int cur1 = keyList.get(j) + 1; 168 | int cur2 = i + 1; 169 | int count = 1; 170 | for (int k = cur2; k < str2.length && cur1 < str1.length; k++) { 171 | if (str2[k] == str1[cur1]) { 172 | cur1++; 173 | count++; 174 | } 175 | } 176 | ans = Math.max(ans, count); 177 | } 178 | } 179 | } 180 | return s2.length() - ans; 181 | } 182 | 183 | public static String generateRandomString(int l, int v) { 184 | int len = (int) (Math.random() * l); 185 | char[] str = new char[len]; 186 | for (int i = 0; i < len; i++) { 187 | str[i] = (char) ('a' + (int) (Math.random() * v)); 188 | } 189 | return String.valueOf(str); 190 | } 191 | 192 | public static void main(String[] args) { 193 | int str1Len = 20; 194 | int str2Len = 10; 195 | int v = 5; 196 | int testTime = 10000; 197 | boolean pass = true; 198 | System.out.println("test begin"); 199 | for (int i = 0; i < testTime; i++) { 200 | String str1 = generateRandomString(str1Len, v); 201 | String str2 = generateRandomString(str2Len, v); 202 | int ans1 = minCost1(str1, str2); 203 | int ans2 = minCost2(str1, str2); 204 | int ans3 = minCost3(str1, str2); 205 | int ans4 = minCost4(str1, str2); 206 | if (ans1 != ans2 || ans3 != ans4 || ans1 != ans3) { 207 | pass = false; 208 | System.out.println(str1); 209 | System.out.println(str2); 210 | System.out.println(ans1); 211 | System.out.println(ans2); 212 | System.out.println(ans3); 213 | System.out.println(ans4); 214 | break; 215 | } 216 | } 217 | System.out.println("test pass : " + pass); 218 | } 219 | 220 | } 221 | -------------------------------------------------------------------------------- /src/class05/Code02_EditCost.java: -------------------------------------------------------------------------------- 1 | package class05; 2 | 3 | public class Code02_EditCost { 4 | 5 | public static int minCost1(String s1, String s2, int ic, int dc, int rc) { 6 | if (s1 == null || s2 == null) { 7 | return 0; 8 | } 9 | char[] str1 = s1.toCharArray(); 10 | char[] str2 = s2.toCharArray(); 11 | int N = str1.length + 1; 12 | int M = str2.length + 1; 13 | int[][] dp = new int[N][M]; 14 | // dp[0][0] = 0 15 | for (int i = 1; i < N; i++) { 16 | dp[i][0] = dc * i; 17 | } 18 | for (int j = 1; j < M; j++) { 19 | dp[0][j] = ic * j; 20 | } 21 | for (int i = 1; i < N; i++) { 22 | for (int j = 1; j < M; j++) { 23 | if (str1[i - 1] == str2[j - 1]) { 24 | dp[i][j] = dp[i - 1][j - 1]; 25 | } else { 26 | dp[i][j] = dp[i - 1][j - 1] + rc; 27 | } 28 | dp[i][j] = Math.min(dp[i][j], dp[i][j - 1] + ic); 29 | dp[i][j] = Math.min(dp[i][j], dp[i - 1][j] + dc); 30 | } 31 | } 32 | return dp[N - 1][M - 1]; 33 | } 34 | 35 | public static int minCost2(String str1, String str2, int ic, int dc, int rc) { 36 | if (str1 == null || str2 == null) { 37 | return 0; 38 | } 39 | char[] chs1 = str1.toCharArray(); 40 | char[] chs2 = str2.toCharArray(); 41 | char[] longs = chs1.length >= chs2.length ? chs1 : chs2; 42 | char[] shorts = chs1.length < chs2.length ? chs1 : chs2; 43 | if (chs1.length < chs2.length) { 44 | int tmp = ic; 45 | ic = dc; 46 | dc = tmp; 47 | } 48 | int[] dp = new int[shorts.length + 1]; 49 | for (int i = 1; i <= shorts.length; i++) { 50 | dp[i] = ic * i; 51 | } 52 | for (int i = 1; i <= longs.length; i++) { 53 | int pre = dp[0]; 54 | dp[0] = dc * i; 55 | for (int j = 1; j <= shorts.length; j++) { 56 | int tmp = dp[j]; 57 | if (longs[i - 1] == shorts[j - 1]) { 58 | dp[j] = pre; 59 | } else { 60 | dp[j] = pre + rc; 61 | } 62 | dp[j] = Math.min(dp[j], dp[j - 1] + ic); 63 | dp[j] = Math.min(dp[j], tmp + dc); 64 | pre = tmp; 65 | } 66 | } 67 | return dp[shorts.length]; 68 | } 69 | 70 | public static void main(String[] args) { 71 | String str1 = "ab12cd3"; 72 | String str2 = "abcdf"; 73 | System.out.println(minCost1(str1, str2, 5, 3, 2)); 74 | System.out.println(minCost2(str1, str2, 5, 3, 2)); 75 | 76 | str1 = "abcdf"; 77 | str2 = "ab12cd3"; 78 | System.out.println(minCost1(str1, str2, 3, 2, 4)); 79 | System.out.println(minCost2(str1, str2, 3, 2, 4)); 80 | 81 | str1 = ""; 82 | str2 = "ab12cd3"; 83 | System.out.println(minCost1(str1, str2, 1, 7, 5)); 84 | System.out.println(minCost2(str1, str2, 1, 7, 5)); 85 | 86 | str1 = "abcdf"; 87 | str2 = ""; 88 | System.out.println(minCost1(str1, str2, 2, 9, 8)); 89 | System.out.println(minCost2(str1, str2, 2, 9, 8)); 90 | 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/class05/Code03_CompleteTreeNodeNumber.java: -------------------------------------------------------------------------------- 1 | package class05; 2 | 3 | public class Code03_CompleteTreeNodeNumber { 4 | 5 | public static class Node { 6 | public int value; 7 | public Node left; 8 | public Node right; 9 | 10 | public Node(int data) { 11 | this.value = data; 12 | } 13 | } 14 | 15 | // 请保证head为头的树,是完全二叉树 16 | public static int nodeNum(Node head) { 17 | if (head == null) { 18 | return 0; 19 | } 20 | return bs(head, 1, mostLeftLevel(head, 1)); 21 | } 22 | 23 | // node在第level层,h是总的深度(h永远不变,全局变量 24 | // 以node为头的完全二叉树,节点个数是多少 25 | public static int bs(Node node, int Level, int h) { 26 | if (Level == h) { 27 | return 1; 28 | } 29 | if (mostLeftLevel(node.right, Level + 1) == h) { 30 | return (1 << (h - Level)) + bs(node.right, Level + 1, h); 31 | } else { 32 | return (1 << (h - Level - 1)) + bs(node.left, Level + 1, h); 33 | } 34 | } 35 | 36 | // 如果node在第level层, 37 | // 求以node为头的子树,最大深度是多少 38 | // node为头的子树,一定是完全二叉树 39 | public static int mostLeftLevel(Node node, int level) { 40 | while (node != null) { 41 | level++; 42 | node = node.left; 43 | } 44 | return level - 1; 45 | } 46 | 47 | public static void main(String[] args) { 48 | Node head = new Node(1); 49 | head.left = new Node(2); 50 | head.right = new Node(3); 51 | head.left.left = new Node(4); 52 | head.left.right = new Node(5); 53 | head.right.left = new Node(6); 54 | System.out.println(nodeNum(head)); 55 | 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/class05/Code04_LeastRecentlyUsedCache.java: -------------------------------------------------------------------------------- 1 | package class05; 2 | 3 | import java.util.HashMap; 4 | 5 | public class Code04_LeastRecentlyUsedCache { 6 | 7 | public static class Node { 8 | public K key; 9 | public V value; 10 | public Node last; 11 | public Node next; 12 | 13 | public Node(K key, V value) { 14 | this.key = key; 15 | this.value = value; 16 | } 17 | } 18 | 19 | // 双向链表 20 | // 从head到tail所有节点都是串好的 21 | public static class NodeDoubleLinkedList { 22 | private Node head; 23 | private Node tail; 24 | 25 | public NodeDoubleLinkedList() { 26 | head = null; 27 | tail = null; 28 | } 29 | 30 | // 如果一个新的节点加入,放到尾巴上去 31 | public void addNode(Node newNode) { 32 | if (newNode == null) { 33 | return; 34 | } 35 | // newNode != null 36 | if (head == null) { // 双向链表中一个节点也没有 37 | head = newNode; 38 | tail = newNode; 39 | } else { // 双向链表中之前有节点,tail(非null) 40 | tail.next = newNode; 41 | newNode.last = tail; 42 | tail = newNode; 43 | } 44 | } 45 | 46 | // 潜台词 : 双向链表上一定有这个node 47 | // node分离出,但是node前后环境重新连接 48 | // node放到尾巴上去 49 | public void moveNodeToTail(Node node) { 50 | if (this.tail == node) { 51 | return; 52 | } 53 | if (this.head == node) { // 当前node是老头部 54 | this.head = node.next; 55 | this.head.last = null; 56 | } else { // 当前node是中间的一个节点 57 | node.last.next = node.next; 58 | node.next.last = node.last; 59 | } 60 | node.last = this.tail; 61 | node.next = null; 62 | this.tail.next = node; 63 | this.tail = node; 64 | } 65 | 66 | // 把头节点删掉并返回 67 | public Node removeHead() { 68 | if (this.head == null) { 69 | return null; 70 | } 71 | Node res = this.head; 72 | if (this.head == this.tail) { // 链表中只有一个节点的时候 73 | this.head = null; 74 | this.tail = null; 75 | } else { 76 | this.head = res.next; 77 | res.next = null; 78 | this.head.last = null; 79 | } 80 | return res; 81 | } 82 | 83 | } 84 | 85 | public static class MyCache { 86 | private HashMap> keyNodeMap; 87 | private NodeDoubleLinkedList nodeList; 88 | private final int capacity; 89 | 90 | public MyCache(int cap) { 91 | if (cap < 1) { 92 | throw new RuntimeException("should be more than 0."); 93 | } 94 | keyNodeMap = new HashMap>(); 95 | nodeList = new NodeDoubleLinkedList(); 96 | capacity = cap; 97 | } 98 | 99 | public V get(K key) { 100 | if (keyNodeMap.containsKey(key)) { 101 | Node res = keyNodeMap.get(key); 102 | nodeList.moveNodeToTail(res); 103 | return res.value; 104 | } 105 | return null; 106 | } 107 | 108 | public void set(K key, V value) { 109 | if (keyNodeMap.containsKey(key)) { 110 | Node node = keyNodeMap.get(key); 111 | node.value = value; 112 | nodeList.moveNodeToTail(node); 113 | } else { // 这是一个新加的记录,有可能出现替换 114 | if (keyNodeMap.size() == capacity) { 115 | removeMostUnusedCache(); 116 | } 117 | Node newNode = new Node(key, value); 118 | keyNodeMap.put(key, newNode); 119 | nodeList.addNode(newNode); 120 | } 121 | } 122 | 123 | private void removeMostUnusedCache() { 124 | Node removeNode = nodeList.removeHead(); 125 | keyNodeMap.remove(removeNode.key); 126 | } 127 | 128 | } 129 | 130 | public static void main(String[] args) { 131 | MyCache testCache = new MyCache(3); 132 | testCache.set("A", 1); 133 | testCache.set("B", 2); 134 | testCache.set("C", 3); 135 | System.out.println(testCache.get("B")); 136 | System.out.println(testCache.get("A")); 137 | testCache.set("D", 4); 138 | System.out.println(testCache.get("D")); 139 | System.out.println(testCache.get("C")); 140 | 141 | } 142 | 143 | } 144 | -------------------------------------------------------------------------------- /src/class05/Code05_WordMinPaths.java: -------------------------------------------------------------------------------- 1 | package class05; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.HashSet; 6 | import java.util.LinkedList; 7 | import java.util.List; 8 | import java.util.Queue; 9 | import java.util.Set; 10 | 11 | public class Code05_WordMinPaths { 12 | 13 | public static List> findMinPaths( 14 | String start, 15 | String end, 16 | List list) { 17 | list.add(start); 18 | HashMap> nexts = getNexts(list); 19 | HashMap distances = getDistances(start, nexts); 20 | 21 | 22 | 23 | 24 | LinkedList pathList = new LinkedList<>(); 25 | List> res = new ArrayList<>(); 26 | getShortestPaths(start, end, nexts, distances, pathList, res); 27 | return res; 28 | } 29 | 30 | public static HashMap> getNexts(List words) { 31 | Set dict = new HashSet<>(words); // List 所有东西放入 set 32 | HashMap> nexts = new HashMap<>(); 33 | for (int i = 0; i < words.size(); i++) { 34 | nexts.put(words.get(i), getNext(words.get(i), dict)); 35 | } 36 | return nexts; 37 | } 38 | 39 | private static ArrayList getNext(String word, Set dict) { 40 | ArrayList res = new ArrayList(); 41 | char[] chs = word.toCharArray(); 42 | for (char cur = 'a'; cur <= 'z'; cur++) { 43 | for (int i = 0; i < chs.length; i++) { 44 | if (chs[i] != cur) { 45 | char tmp = chs[i]; 46 | chs[i] = cur; 47 | if (dict.contains(String.valueOf(chs))) { 48 | res.add(String.valueOf(chs)); 49 | } 50 | chs[i] = tmp; 51 | } 52 | } 53 | } 54 | return res; 55 | } 56 | 57 | public static HashMap getDistances(String start, 58 | HashMap> nexts) { 59 | HashMap distances = new HashMap<>(); 60 | distances.put(start, 0); 61 | Queue queue = new LinkedList(); 62 | queue.add(start); 63 | HashSet set = new HashSet(); 64 | set.add(start); 65 | while (!queue.isEmpty()) { 66 | String cur = queue.poll(); 67 | for (String next : nexts.get(cur)) { 68 | if (!set.contains(next)) { 69 | distances.put(next, distances.get(cur) + 1); 70 | queue.add(next); 71 | set.add(next); 72 | } 73 | } 74 | } 75 | return distances; 76 | } 77 | 78 | // 现在来到了什么:cur 79 | // 目的地:end 80 | // 邻居表:nexts 81 | // 最短距离表:distances 82 | // 沿途走过的路径:path上{....} 83 | // 答案往res里放,收集所有的最短路径 84 | private static void getShortestPaths( 85 | String cur, String to, 86 | HashMap> nexts, 87 | HashMap distances, 88 | LinkedList path, 89 | List> res) { 90 | path.add(cur); 91 | if (to.equals(cur)) { 92 | res.add(new LinkedList(path)); 93 | } else { 94 | for (String next : nexts.get(cur)) { 95 | if (distances.get(next) == distances.get(cur) + 1) { 96 | getShortestPaths(next, to, nexts, distances, path, res); 97 | } 98 | } 99 | } 100 | path.pollLast(); 101 | } 102 | 103 | public static void main(String[] args) { 104 | String start = "abc"; 105 | String end = "cab"; 106 | String[] test = { "abc", "cab", "acc", "cbc", "ccc", "cac", "cbb", 107 | "aab", "abb" }; 108 | ArrayList list = new ArrayList<>(); 109 | for (int i = 0; i < test.length; i++) { 110 | list.add(test[i]); 111 | } 112 | List> res = findMinPaths(start, end, list); 113 | for (List obj : res) { 114 | for (String str : obj) { 115 | System.out.print(str + " -> "); 116 | } 117 | System.out.println(); 118 | } 119 | 120 | } 121 | 122 | } 123 | -------------------------------------------------------------------------------- /src/class05/Code06_MaxRevenue.java: -------------------------------------------------------------------------------- 1 | package class05; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.LinkedList; 6 | import java.util.Map.Entry; 7 | import java.util.TreeMap; 8 | 9 | public class Code06_MaxRevenue { 10 | 11 | // 请保证只有唯一的最后节点, 没有环 12 | // dependents[i][j] == 0 认为i项目和j项目没关系,不直接相连 13 | // dependents[i][j] == 1 认为j项目是i项目的其中一个后续 14 | public static int[] maxRevenue(int allTime, int[] revenue, int[] times, 15 | int[][] dependents) { 16 | int size = revenue.length; 17 | HashMap> parents = new HashMap<>(); 18 | for (int i = 0; i < size; i++) { 19 | parents.put(i, new ArrayList<>()); 20 | } 21 | int end = -1; 22 | for (int i = 0; i < dependents.length; i++) { 23 | boolean allZero = true; 24 | for (int j = 0; j < dependents[0].length; j++) { 25 | if (dependents[i][j] != 0) { 26 | parents.get(j).add(i); 27 | allZero = false; 28 | } 29 | } 30 | if (allZero) { 31 | end = i; 32 | } 33 | } 34 | HashMap> nodeCostRevenueMap = new HashMap<>(); 35 | for (int i = 0; i < size; i++) { 36 | nodeCostRevenueMap.put(i, new TreeMap<>()); 37 | } 38 | nodeCostRevenueMap.get(end).put(times[end], revenue[end]); 39 | LinkedList queue = new LinkedList<>(); 40 | queue.add(end); 41 | while (!queue.isEmpty()) { 42 | int cur = queue.poll(); 43 | for (int last : parents.get(cur)) { // 枚举当前项目,所有的父亲 44 | for (Entry entry 45 | : nodeCostRevenueMap.get(cur).entrySet()) { 46 | int lastCost = entry.getKey() + times[last]; 47 | int lastRevenue = entry.getValue() + revenue[last]; 48 | TreeMap lastMap = nodeCostRevenueMap.get(last); 49 | if (lastMap.floorKey(lastCost) == null 50 | || lastMap.get(lastMap.floorKey(lastCost)) < lastRevenue) 51 | { 52 | lastMap.put(lastCost, lastRevenue); 53 | } 54 | } 55 | queue.add(last); 56 | } 57 | } 58 | TreeMap allMap = new TreeMap<>(); 59 | for (TreeMap curMap : nodeCostRevenueMap.values()) { 60 | for (Entry entry : curMap.entrySet()) { 61 | int cost = entry.getKey(); 62 | int reven = entry.getValue(); 63 | if (allMap.floorKey(cost) == null || allMap.get(allMap.floorKey(cost)) < reven) { 64 | allMap.put(cost, reven); 65 | } 66 | } 67 | } 68 | // 有序表最后要过一下,删除一些记录 69 | // allTime 70 | if(allMap.floorKey(allTime) == null) { 71 | // 不能做任何一个活动 72 | } 73 | 74 | return new int[] { allMap.floorKey(allTime), allMap.get(allMap.floorKey(allTime)) }; 75 | } 76 | 77 | public static void main(String[] args) { 78 | int allTime = 10; 79 | int[] revenue = { 2000, 4000, 2500, 1600, 3800, 2600, 4000, 3500 }; 80 | int[] times = { 3, 3, 2, 1, 4, 2, 4, 3 }; 81 | int[][] dependents = { 82 | { 0, 1, 1, 0, 0, 0, 0, 0 }, 83 | { 0, 0, 0, 1, 1, 0, 0, 0 }, 84 | { 0, 0, 0, 1, 0, 0, 0, 0 }, 85 | { 0, 0, 0, 0, 1, 1, 1, 0 }, 86 | { 0, 0, 0, 0, 0, 0, 0, 1 }, 87 | { 0, 0, 0, 0, 0, 0, 0, 1 }, 88 | { 0, 0, 0, 0, 0, 0, 0, 1 }, 89 | { 0, 0, 0, 0, 0, 0, 0, 0 } }; 90 | 91 | 92 | int[] res = maxRevenue(allTime, revenue, times, dependents); 93 | System.out.println(res[0] + " , " + res[1]); 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /src/class06/Code01_MaxEOR.java: -------------------------------------------------------------------------------- 1 | package class06; 2 | 3 | public class Code01_MaxEOR { 4 | 5 | // O(N^2) 6 | public static int maxXorSubarray1(int[] arr) { 7 | if (arr == null || arr.length == 0) { 8 | return 0; 9 | } 10 | // 准备一个前缀异或和数组eor 11 | // eor[i] = arr[0...i]的异或结果 12 | int[] eor = new int[arr.length]; 13 | eor[0] = arr[0]; 14 | // 生成eor数组,eor[i]代表arr[0..i]的异或和 15 | for (int i = 1; i < arr.length; i++) { 16 | eor[i] = eor[i - 1] ^ arr[i]; 17 | } 18 | int max = Integer.MIN_VALUE; 19 | for (int j = 0; j < arr.length; j++) { 20 | for (int i = 0; i <= j; i++) { // 依次尝试arr[0..j]、arr[1..j]..arr[i..j]..arr[j..j] 21 | max = Math.max(max, i == 0 ? eor[j] : eor[j] ^ eor[i - 1]); 22 | } 23 | } 24 | return max; 25 | } 26 | 27 | // 前缀树的节点类型,每个节点向下只可能有走向0或1的路 28 | // node.nexts[0] == null 0方向没路 29 | // node.nexts[0] != null 0方向有路 30 | public static class Node { 31 | public Node[] nexts = new Node[2]; 32 | } 33 | 34 | // 基于本题,定制前缀树的实现 35 | public static class NumTrie { 36 | // 头节点 37 | public Node head = new Node(); 38 | 39 | // 把某个数字newNum加入到这棵前缀树里 40 | // num是一个32位的整数,所以加入的过程一共走32步 41 | public void add(int newNum) { 42 | Node cur = head; 43 | for (int move = 31; move >= 0; move--) { 44 | // 从高位到低位,取出每一位的状态,如果当前状态是0, 45 | // path(int) = 0 46 | // ,如果当前状态是1 47 | // path(int) = 1 48 | int path = ((newNum >> move) & 1); 49 | // 无路新建、有路复用 50 | cur.nexts[path] = cur.nexts[path] == null ? new Node() : cur.nexts[path]; 51 | cur = cur.nexts[path]; 52 | } 53 | } 54 | 55 | // 该结构之前收集了一票数字,并且建好了前缀树 56 | // sum,和 谁 ^ 最大的结果(把结果返回) 57 | public int maxXor(int sum) { 58 | Node cur = head; 59 | int res = 0; 60 | for (int move = 31; move >= 0; move--) { 61 | int path = (sum >> move) & 1; 62 | // 期待的路 63 | int best = move == 31 ? path : (path ^ 1); 64 | // 实际走的路 65 | best = cur.nexts[best] != null ? best : (best ^ 1); 66 | // (path ^ best) 当前位位异或完的结果 67 | res |= (path ^ best) << move; 68 | cur = cur.nexts[best]; 69 | } 70 | return res; 71 | } 72 | } 73 | 74 | public static int maxXorSubarray2(int[] arr) { 75 | if (arr == null || arr.length == 0) { 76 | return 0; 77 | } 78 | int max = Integer.MIN_VALUE; 79 | int eor = 0; // 0..i 异或和 80 | // 前缀树 -> numTrie 81 | NumTrie numTrie = new NumTrie(); 82 | numTrie.add(0); // 一个数也没有的时候,异或和是0 83 | for (int i = 0; i < arr.length; i++) { 84 | eor ^= arr[i]; // eor -> 0..i异或和 85 | // X, 0~0 , 0~1, .., 0~i-1 86 | max = Math.max(max, numTrie.maxXor(eor)); 87 | numTrie.add(eor); 88 | } 89 | return max; 90 | } 91 | 92 | // for test 93 | public static int[] generateRandomArray(int maxSize, int maxValue) { 94 | int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; 95 | for (int i = 0; i < arr.length; i++) { 96 | arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); 97 | } 98 | return arr; 99 | } 100 | 101 | // for test 102 | public static void printArray(int[] arr) { 103 | if (arr == null) { 104 | return; 105 | } 106 | for (int i = 0; i < arr.length; i++) { 107 | System.out.print(arr[i] + " "); 108 | } 109 | System.out.println(); 110 | } 111 | 112 | // for test 113 | public static void main(String[] args) { 114 | int testTime = 500000; 115 | int maxSize = 30; 116 | int maxValue = 50; 117 | boolean succeed = true; 118 | for (int i = 0; i < testTime; i++) { 119 | int[] arr = generateRandomArray(maxSize, maxValue); 120 | int comp = maxXorSubarray1(arr); 121 | int res = maxXorSubarray2(arr); 122 | if (res != comp) { 123 | succeed = false; 124 | printArray(arr); 125 | System.out.println(res); 126 | System.out.println(comp); 127 | break; 128 | } 129 | } 130 | System.out.println(succeed ? "Nice!" : "Fucking fucked!"); 131 | // 132 | // // int[] arr = generateRandomArray(6, maxValue); 133 | // int[] arr = { 3, -28, -29, 2}; 134 | // 135 | // for (int i = 0; i < arr.length; i++) { 136 | // System.out.println(arr[i] + " "); 137 | // } 138 | // System.out.println("========="); 139 | // System.out.println(maxXorSubarray(arr)); 140 | // System.out.println((int) (-28 ^ -29)); 141 | 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/class06/Code02_ExpressionNumber.java: -------------------------------------------------------------------------------- 1 | package class06; 2 | 3 | public class Code02_ExpressionNumber { 4 | 5 | public static boolean isValid(char[] exp) { 6 | if ((exp.length & 1) == 0) { 7 | return false; 8 | } 9 | for (int i = 0; i < exp.length; i = i + 2) { 10 | if ((exp[i] != '1') && (exp[i] != '0')) { 11 | return false; 12 | } 13 | } 14 | for (int i = 1; i < exp.length; i = i + 2) { 15 | if ((exp[i] != '&') && (exp[i] != '|') && (exp[i] != '^')) { 16 | return false; 17 | } 18 | } 19 | return true; 20 | } 21 | 22 | public static int num1(String express, boolean desired) { 23 | if (express == null || express.equals("")) { 24 | return 0; 25 | } 26 | char[] exp = express.toCharArray(); 27 | if (!isValid(exp)) { 28 | return 0; 29 | } 30 | return f(exp, desired, 0, exp.length - 1); 31 | } 32 | 33 | // str[L..R] 返回期待为desired的方法数 34 | // 潜台词:L R 必须是偶数位置 35 | public static int f(char[] str, boolean desired, int L, int R) { 36 | if (L == R) { // base case 1 37 | if (str[L] == '1') { 38 | return desired ? 1 : 0; 39 | } else { // '0' 40 | return desired ? 0 : 1; 41 | } 42 | } 43 | 44 | // L..R 45 | int res = 0; 46 | if (desired) { // 期待为true 47 | // i位置尝试L..R范围上的每一个逻辑符号,都是最后结合的 48 | for (int i = L + 1; i < R; i += 2) { 49 | // exp[i] 一定压中逻辑符号 50 | switch (str[i]) { 51 | case '&': 52 | res += f(str, true, L, i - 1) * f(str, true, i + 1, R); 53 | break; 54 | case '|': 55 | res += f(str, true, L, i - 1) * f(str, false, i + 1, R); 56 | res += f(str, false, L, i - 1) * f(str, true, i + 1, R); 57 | res += f(str, true, L, i - 1) * f(str, true, i + 1, R); 58 | break; 59 | case '^': 60 | res += f(str, true, L, i - 1) * f(str, false, i + 1, R); 61 | res += f(str, false, L, i - 1) * f(str, true, i + 1, R); 62 | break; 63 | } 64 | } 65 | } else { // 期待为false 66 | for (int i = L + 1; i < R; i += 2) { 67 | switch (str[i]) { 68 | case '&': 69 | res += f(str, false, L, i - 1) * f(str, true, i + 1, R); 70 | res += f(str, true, L, i - 1) * f(str, false, i + 1, R); 71 | res += f(str, false, L, i - 1) * f(str, false, i + 1, R); 72 | break; 73 | case '|': 74 | res += f(str, false, L, i - 1) * f(str, false, i + 1, R); 75 | break; 76 | case '^': 77 | res += f(str, true, L, i - 1) * f(str, true, i + 1, R); 78 | res += f(str, false, L, i - 1) * f(str, false, i + 1, R); 79 | break; 80 | } 81 | } 82 | } 83 | return res; 84 | } 85 | 86 | public static int dpLive(String express, boolean desired) { 87 | char[] str = express.toCharArray(); 88 | int N = str.length; 89 | int[][] tMap = new int[N][N]; 90 | int[][] fMap = new int[N][N]; 91 | for (int i = 0; i < N; i += 2) { 92 | tMap[i][i] = str[i] == '1' ? 1 : 0; 93 | fMap[i][i] = str[i] == '0' ? 1 : 0; 94 | } 95 | for (int row = N - 3; row >= 0; row -= 2) { 96 | for (int col = row + 2; col < N; col += 2) { 97 | // row..col tMap fMap 98 | for (int i = row + 1; i < col; i += 2) { 99 | switch (str[i]) { 100 | case '&': 101 | tMap[row][col] += tMap[row][i - 1] * tMap[i + 1][col]; 102 | break; 103 | case '|': 104 | tMap[row][col] += tMap[row][i - 1] * fMap[i + 1][col]; 105 | tMap[row][col] += fMap[row][i - 1] * tMap[i + 1][col]; 106 | tMap[row][col] += tMap[row][i - 1] * tMap[i + 1][col]; 107 | break; 108 | case '^': 109 | tMap[row][col] += tMap[row][i - 1] * fMap[i + 1][col]; 110 | tMap[row][col] += fMap[row][i - 1] * tMap[i + 1][col]; 111 | break; 112 | } 113 | switch (str[i]) { 114 | case '&': 115 | fMap[row][col] += fMap[row][i - 1] * tMap[i + 1][col]; 116 | fMap[row][col] += tMap[row][i - 1] * fMap[i + 1][col]; 117 | fMap[row][col] += fMap[row][i - 1] * fMap[i + 1][col]; 118 | break; 119 | case '|': 120 | fMap[row][col] += fMap[row][i - 1] * fMap[i + 1][col]; 121 | break; 122 | case '^': 123 | fMap[row][col] += tMap[row][i - 1] * tMap[i + 1][col]; 124 | fMap[row][col] += fMap[row][i - 1] * fMap[i + 1][col]; 125 | break; 126 | } 127 | } 128 | } 129 | } 130 | return desired ? tMap[0][N-1] : fMap[0][N-1]; 131 | } 132 | 133 | public static int dp(String s, boolean d) { 134 | char[] str = s.toCharArray(); 135 | int N = str.length; 136 | int[][] tMap = new int[N][N]; 137 | int[][] fMap = new int[N][N]; 138 | for (int i = 0; i < N; i += 2) { 139 | tMap[i][i] = str[i] == '1' ? 1 : 0; 140 | fMap[i][i] = str[i] == '0' ? 1 : 0; 141 | } 142 | for (int row = N - 3; row >= 0; row = row - 2) { 143 | for (int col = row + 2; col < N; col = col + 2) { 144 | // row..col tMap fMap 145 | for (int i = row + 1; i < col; i += 2) { 146 | switch (str[i]) { 147 | case '&': 148 | tMap[row][col] += tMap[row][i - 1] * tMap[i + 1][col]; 149 | break; 150 | case '|': 151 | tMap[row][col] += tMap[row][i - 1] * fMap[i + 1][col]; 152 | tMap[row][col] += fMap[row][i - 1] * tMap[i + 1][col]; 153 | tMap[row][col] += tMap[row][i - 1] * tMap[i + 1][col]; 154 | break; 155 | case '^': 156 | tMap[row][col] += tMap[row][i - 1] * fMap[i + 1][col]; 157 | tMap[row][col] += fMap[row][i - 1] * tMap[i + 1][col]; 158 | break; 159 | } 160 | switch (str[i]) { 161 | case '&': 162 | fMap[row][col] += fMap[row][i - 1] * tMap[i + 1][col]; 163 | fMap[row][col] += tMap[row][i - 1] * fMap[i + 1][col]; 164 | fMap[row][col] += fMap[row][i - 1] * fMap[i + 1][col]; 165 | break; 166 | case '|': 167 | fMap[row][col] += fMap[row][i - 1] * fMap[i + 1][col]; 168 | break; 169 | case '^': 170 | fMap[row][col] += tMap[row][i - 1] * tMap[i + 1][col]; 171 | fMap[row][col] += fMap[row][i - 1] * fMap[i + 1][col]; 172 | break; 173 | } 174 | } 175 | } 176 | } 177 | return d ? tMap[0][N - 1] : fMap[0][N - 1]; 178 | } 179 | 180 | public static int num2(String express, boolean desired) { 181 | if (express == null || express.equals("")) { 182 | return 0; 183 | } 184 | char[] exp = express.toCharArray(); 185 | if (!isValid(exp)) { 186 | return 0; 187 | } 188 | int[][] t = new int[exp.length][exp.length]; 189 | int[][] f = new int[exp.length][exp.length]; 190 | t[0][0] = exp[0] == '0' ? 0 : 1; 191 | f[0][0] = exp[0] == '1' ? 0 : 1; 192 | for (int i = 2; i < exp.length; i += 2) { 193 | t[i][i] = exp[i] == '0' ? 0 : 1; 194 | f[i][i] = exp[i] == '1' ? 0 : 1; 195 | for (int j = i - 2; j >= 0; j -= 2) { 196 | for (int k = j; k < i; k += 2) { 197 | if (exp[k + 1] == '&') { 198 | t[j][i] += t[j][k] * t[k + 2][i]; 199 | f[j][i] += (f[j][k] + t[j][k]) * f[k + 2][i] + f[j][k] * t[k + 2][i]; 200 | } else if (exp[k + 1] == '|') { 201 | t[j][i] += (f[j][k] + t[j][k]) * t[k + 2][i] + t[j][k] * f[k + 2][i]; 202 | f[j][i] += f[j][k] * f[k + 2][i]; 203 | } else { 204 | t[j][i] += f[j][k] * t[k + 2][i] + t[j][k] * f[k + 2][i]; 205 | f[j][i] += f[j][k] * f[k + 2][i] + t[j][k] * t[k + 2][i]; 206 | } 207 | } 208 | } 209 | } 210 | return desired ? t[0][t.length - 1] : f[0][f.length - 1]; 211 | } 212 | 213 | public static void main(String[] args) { 214 | String express = "1^0&0|1&1^0&0^1|0|1&1"; 215 | boolean desired = true; 216 | System.out.println(num1(express, desired)); 217 | System.out.println(num2(express, desired)); 218 | System.out.println(dp(express, desired)); 219 | System.out.println(dpLive(express, desired)); 220 | } 221 | 222 | } 223 | -------------------------------------------------------------------------------- /src/class06/Code02_MostEOR.java: -------------------------------------------------------------------------------- 1 | package class06; 2 | 3 | import java.util.HashMap; 4 | 5 | public class Code02_MostEOR { 6 | 7 | public static int mostEOR(int[] arr) { 8 | if (arr == null || arr.length == 0) { 9 | return 0; 10 | } 11 | int N = arr.length; 12 | int[] dp = new int[N]; // dp[i] = 0 13 | HashMap map = new HashMap<>(); 14 | map.put(0, -1); 15 | int sum = 0; 16 | for (int i = 0; i < arr.length; i++) { 17 | sum ^= arr[i]; 18 | if (map.containsKey(sum)) { 19 | int pre = map.get(sum); 20 | dp[i] = pre == -1 ? 1 : (dp[pre] + 1); 21 | } 22 | if (i > 0) { 23 | dp[i] = Math.max(dp[i - 1], dp[i]); 24 | } 25 | map.put(sum, i); 26 | } 27 | return dp[dp.length - 1]; 28 | } 29 | 30 | // for test 31 | public static int comparator(int[] arr) { 32 | if (arr == null || arr.length == 0) { 33 | return 0; 34 | } 35 | int[] eors = new int[arr.length]; 36 | int eor = 0; 37 | for (int i = 0; i < arr.length; i++) { 38 | eor ^= arr[i]; 39 | eors[i] = eor; 40 | } 41 | int[] mosts = new int[arr.length]; 42 | mosts[0] = arr[0] == 0 ? 1 : 0; 43 | for (int i = 1; i < arr.length; i++) { 44 | mosts[i] = eors[i] == 0 ? 1 : 0; 45 | for (int j = 0; j < i; j++) { 46 | if ((eors[i] ^ eors[j]) == 0) { 47 | mosts[i] = Math.max(mosts[i], mosts[j] + 1); 48 | } 49 | } 50 | mosts[i] = Math.max(mosts[i], mosts[i - 1]); 51 | } 52 | return mosts[mosts.length - 1]; 53 | } 54 | 55 | // for test 56 | public static int[] generateRandomArray(int maxSize, int maxValue) { 57 | int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; 58 | for (int i = 0; i < arr.length; i++) { 59 | arr[i] = (int) ((maxValue + 1) * Math.random()); 60 | } 61 | return arr; 62 | } 63 | 64 | // for test 65 | public static void printArray(int[] arr) { 66 | if (arr == null) { 67 | return; 68 | } 69 | for (int i = 0; i < arr.length; i++) { 70 | System.out.print(arr[i] + " "); 71 | } 72 | System.out.println(); 73 | } 74 | 75 | // for test 76 | public static void main(String[] args) { 77 | int testTime = 500000; 78 | int maxSize = 300; 79 | int maxValue = 100; 80 | boolean succeed = true; 81 | for (int i = 0; i < testTime; i++) { 82 | int[] arr = generateRandomArray(maxSize, maxValue); 83 | int res = mostEOR(arr); 84 | int comp = comparator(arr); 85 | if (res != comp) { 86 | succeed = false; 87 | printArray(arr); 88 | System.out.println(res); 89 | System.out.println(comp); 90 | break; 91 | } 92 | } 93 | System.out.println(succeed ? "Nice!" : "Fucking fucked!"); 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /src/class06/Code03_JumpGame.java: -------------------------------------------------------------------------------- 1 | package class06; 2 | 3 | public class Code03_JumpGame { 4 | 5 | public static int jump(int[] arr) { 6 | if (arr == null || arr.length == 0) { 7 | return 0; 8 | } 9 | int step = 0; // 跳了多少步 10 | int cur = 0; // step步内,右边界 11 | int next = 0;// step+1步内,右边界 12 | for (int i = 0; i < arr.length; i++) { 13 | if (cur < i) { 14 | step++; 15 | cur = next; 16 | } 17 | next = Math.max(next, i + arr[i]); 18 | } 19 | return step; 20 | } 21 | 22 | public static void main(String[] args) { 23 | int[] arr = { 3, 2, 3, 1, 1, 4 }; 24 | System.out.println(jump(arr)); 25 | 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/class06/Code04_TopKSumCrossTwoArrays.java: -------------------------------------------------------------------------------- 1 | package class06; 2 | 3 | import java.util.Arrays; 4 | import java.util.Comparator; 5 | import java.util.PriorityQueue; 6 | 7 | public class Code04_TopKSumCrossTwoArrays { 8 | 9 | // 放入大根堆中的结构 10 | public static class Node { 11 | public int index1;// arr1中的位置 12 | public int index2;// arr2中的位置 13 | public int sum;// arr1[index1] + arr2[index2]的值 14 | 15 | public Node(int i1, int i2, int s) { 16 | index1 = i1; 17 | index2 = i2; 18 | sum = s; 19 | } 20 | } 21 | 22 | // 生成大根堆的比较器 23 | public static class MaxHeapComp implements Comparator { 24 | @Override 25 | public int compare(Node o1, Node o2) { 26 | return o2.sum - o1.sum; 27 | } 28 | } 29 | 30 | public static int[] topKSum(int[] arr1, int[] arr2, int topK) { 31 | if (arr1 == null || arr2 == null || topK < 1) { 32 | return null; 33 | } 34 | // arr1 50 arr2 20 1000 topk 100万 35 | topK = Math.min(topK, arr1.length * arr2.length); 36 | 37 | int[] res = new int[topK]; 38 | int resIndex = 0; 39 | 40 | PriorityQueue maxHeap = new PriorityQueue<>(new MaxHeapComp()); 41 | 42 | // set[i][j] == false, arr1[i] arr2[j] 之前,没进过 43 | // set[i][j] == true; arr1[i] arr2[j] 之前,进过 44 | boolean[][] set = new boolean[arr1.length][arr2.length]; 45 | int i1 = arr1.length - 1; 46 | int i2 = arr2.length - 1; 47 | maxHeap.add(new Node(i1, i2, arr1[i1] + arr2[i2])); 48 | set[i1][i2] = true; 49 | while (resIndex != topK) { 50 | Node curNode = maxHeap.poll(); 51 | res[resIndex++] = curNode.sum; 52 | i1 = curNode.index1; 53 | i2 = curNode.index2; 54 | if (i1 - 1 >= 0 && !set[i1 - 1][i2]) { 55 | set[i1 - 1][i2] = true; 56 | maxHeap.add(new Node(i1 - 1, i2, arr1[i1 - 1] + arr2[i2])); 57 | } 58 | if (i2 - 1 >= 0 && !set[i1][i2 - 1]) { 59 | set[i1][i2 - 1] = true; 60 | maxHeap.add(new Node(i1, i2 - 1, arr1[i1] + arr2[i2 - 1])); 61 | } 62 | } 63 | return res; 64 | } 65 | 66 | // For test, this method is inefficient but absolutely right 67 | public static int[] topKSumTest(int[] arr1, int[] arr2, int topK) { 68 | int[] all = new int[arr1.length * arr2.length]; 69 | int index = 0; 70 | for (int i = 0; i != arr1.length; i++) { 71 | for (int j = 0; j != arr2.length; j++) { 72 | all[index++] = arr1[i] + arr2[j]; 73 | } 74 | } 75 | Arrays.sort(all); 76 | int[] res = new int[Math.min(topK, all.length)]; 77 | index = all.length - 1; 78 | for (int i = 0; i != res.length; i++) { 79 | res[i] = all[index--]; 80 | } 81 | return res; 82 | } 83 | 84 | public static int[] generateRandomSortArray(int len) { 85 | int[] res = new int[len]; 86 | for (int i = 0; i != res.length; i++) { 87 | res[i] = (int) (Math.random() * 50000) + 1; 88 | } 89 | Arrays.sort(res); 90 | return res; 91 | } 92 | 93 | public static void printArray(int[] arr) { 94 | for (int i = 0; i != arr.length; i++) { 95 | System.out.print(arr[i] + " "); 96 | } 97 | System.out.println(); 98 | } 99 | 100 | public static boolean isEqual(int[] arr1, int[] arr2) { 101 | if (arr1 == null || arr2 == null || arr1.length != arr2.length) { 102 | return false; 103 | } 104 | for (int i = 0; i != arr1.length; i++) { 105 | if (arr1[i] != arr2[i]) { 106 | return false; 107 | } 108 | } 109 | return true; 110 | } 111 | 112 | public static void main(String[] args) { 113 | int a1Len = 5000; 114 | int a2Len = 4000; 115 | int k = 20000000; 116 | int[] arr1 = generateRandomSortArray(a1Len); 117 | int[] arr2 = generateRandomSortArray(a2Len); 118 | long start = System.currentTimeMillis(); 119 | int[] res = topKSum(arr1, arr2, k); 120 | long end = System.currentTimeMillis(); 121 | System.out.println(end - start + " ms"); 122 | 123 | start = System.currentTimeMillis(); 124 | int[] absolutelyRight = topKSumTest(arr1, arr2, k); 125 | end = System.currentTimeMillis(); 126 | System.out.println(end - start + " ms"); 127 | 128 | System.out.println(isEqual(res, absolutelyRight)); 129 | 130 | } 131 | 132 | } 133 | -------------------------------------------------------------------------------- /src/class06/Code05_Split4Parts.java: -------------------------------------------------------------------------------- 1 | package class06; 2 | 3 | import java.util.HashMap; 4 | import java.util.HashSet; 5 | 6 | public class Code05_Split4Parts { 7 | 8 | public static boolean canSplits1(int[] arr) { 9 | if (arr == null || arr.length < 7) { 10 | return false; 11 | } 12 | HashSet set = new HashSet(); 13 | int sum = 0; 14 | for (int i = 0; i < arr.length; i++) { 15 | sum += arr[i]; 16 | } 17 | int leftSum = arr[0]; 18 | for (int i = 1; i < arr.length - 1; i++) { 19 | set.add(String.valueOf(leftSum) + "_" + String.valueOf(sum - leftSum - arr[i])); 20 | leftSum += arr[i]; 21 | } 22 | int l = 1; 23 | int lsum = arr[0]; 24 | int r = arr.length - 2; 25 | int rsum = arr[arr.length - 1]; 26 | while (l < r - 3) { 27 | if (lsum == rsum) { 28 | String lkey = String.valueOf(lsum * 2 + arr[l]); 29 | String rkey = String.valueOf(rsum * 2 + arr[r]); 30 | if (set.contains(lkey + "_" + rkey)) { 31 | return true; 32 | } 33 | lsum += arr[l++]; 34 | } else if (lsum < rsum) { 35 | lsum += arr[l++]; 36 | } else { 37 | rsum += arr[r--]; 38 | } 39 | } 40 | return false; 41 | } 42 | 43 | public static boolean canSplits2(int[] arr) { 44 | if (arr == null || arr.length < 7) { 45 | return false; 46 | } 47 | // key 某一个累加和, value出现的位置 48 | HashMap map = new HashMap(); 49 | int sum = arr[0]; 50 | for (int i = 1; i < arr.length; i++) { 51 | map.put(sum, i); 52 | sum += arr[i]; 53 | } 54 | int lsum = arr[0]; // 第一刀左侧的累加和 55 | for (int s1 = 1; s1 < arr.length - 5; s1++) { // s1是第一刀的位置 56 | int checkSum = lsum * 2 + arr[s1]; // 100 x 100 100*2 + x 57 | if (map.containsKey(checkSum)) { 58 | int s2 = map.get(checkSum); // j -> y 59 | checkSum += lsum + arr[s2]; 60 | if (map.containsKey(checkSum)) { // 100 * 3 + x + y 61 | int s3 = map.get(checkSum); // k -> z 62 | if (checkSum + arr[s3] + lsum == sum) { 63 | return true; 64 | } 65 | } 66 | } 67 | lsum += arr[s1]; 68 | } 69 | return false; 70 | } 71 | 72 | public static int[] generateRondomArray() { 73 | int[] res = new int[(int) (Math.random() * 10) + 7]; 74 | for (int i = 0; i < res.length; i++) { 75 | res[i] = (int) (Math.random() * 10) + 1; 76 | } 77 | return res; 78 | } 79 | 80 | public static void main(String[] args) { 81 | int testTime = 3000000; 82 | for (int i = 0; i < testTime; i++) { 83 | int[] arr = generateRondomArray(); 84 | if (canSplits1(arr) ^ canSplits2(arr)) { 85 | System.out.println("Error"); 86 | } 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/class06/Code06_StringCross.java: -------------------------------------------------------------------------------- 1 | package class06; 2 | 3 | public class Code06_StringCross { 4 | 5 | public static boolean isCross1(String s1, String s2, String ai) { 6 | if (s1 == null || s2 == null || ai == null) { 7 | return false; 8 | } 9 | char[] str1 = s1.toCharArray(); 10 | char[] str2 = s2.toCharArray(); 11 | char[] aim = ai.toCharArray(); 12 | if (aim.length != str1.length + str2.length) { 13 | return false; 14 | } 15 | boolean[][] dp = new boolean[str1.length + 1][str2.length + 1]; 16 | dp[0][0] = true; 17 | for (int i = 1; i <= str1.length; i++) { 18 | if (str1[i - 1] != aim[i - 1]) { 19 | break; 20 | } 21 | dp[i][0] = true; 22 | } 23 | for (int j = 1; j <= str2.length; j++) { 24 | if (str2[j - 1] != aim[j - 1]) { 25 | break; 26 | } 27 | dp[0][j] = true; 28 | } 29 | for (int i = 1; i <= str1.length; i++) { 30 | for (int j = 1; j <= str2.length; j++) { 31 | 32 | if ( 33 | 34 | (str1[i - 1] == aim[i + j - 1] && dp[i - 1][j]) 35 | 36 | || 37 | 38 | (str2[j - 1] == aim[i + j - 1] && dp[i][j - 1]) 39 | 40 | 41 | ) { 42 | 43 | 44 | dp[i][j] = true; 45 | 46 | 47 | } 48 | 49 | 50 | 51 | } 52 | } 53 | return dp[str1.length][str2.length]; 54 | } 55 | 56 | public static boolean isCross2(String str1, String str2, String aim) { 57 | if (str1 == null || str2 == null || aim == null) { 58 | return false; 59 | } 60 | char[] ch1 = str1.toCharArray(); 61 | char[] ch2 = str2.toCharArray(); 62 | char[] chaim = aim.toCharArray(); 63 | if (chaim.length != ch1.length + ch2.length) { 64 | return false; 65 | } 66 | char[] longs = ch1.length >= ch2.length ? ch1 : ch2; 67 | char[] shorts = ch1.length < ch2.length ? ch1 : ch2; 68 | boolean[] dp = new boolean[shorts.length + 1]; 69 | dp[0] = true; 70 | for (int i = 1; i <= shorts.length; i++) { 71 | if (shorts[i - 1] != chaim[i - 1]) { 72 | break; 73 | } 74 | dp[i] = true; 75 | } 76 | for (int i = 1; i <= longs.length; i++) { 77 | dp[0] = dp[0] && longs[i - 1] == chaim[i - 1]; 78 | for (int j = 1; j <= shorts.length; j++) { 79 | if ((longs[i - 1] == chaim[i + j - 1] && dp[j]) || (shorts[j - 1] == chaim[i + j - 1] && dp[j - 1])) { 80 | dp[j] = true; 81 | } else { 82 | dp[j] = false; 83 | } 84 | } 85 | } 86 | return dp[shorts.length]; 87 | } 88 | 89 | public static void main(String[] args) { 90 | String str1 = "1234"; 91 | String str2 = "abcd"; 92 | String aim = "1a23bcd4"; 93 | System.out.println(isCross1(str1, str2, aim)); 94 | System.out.println(isCross2(str1, str2, aim)); 95 | 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /src/class06/Code07_PMinParts.java: -------------------------------------------------------------------------------- 1 | package class06; 2 | 3 | public class Code07_PMinParts { 4 | 5 | public static int minParts(String s) { 6 | if (s == null || s.length() == 0) { 7 | return 0; 8 | } 9 | if (s.length() == 1) { 10 | return 1; 11 | } 12 | char[] str = s.toCharArray(); 13 | int N = str.length; 14 | boolean[][] isP = new boolean[N][N]; 15 | for (int i = 0; i < N; i++) { 16 | isP[i][i] = true; 17 | } 18 | for (int i = 0; i < N - 1; i++) { 19 | isP[i][i + 1] = str[i] == str[i + 1]; 20 | } 21 | for (int row = N - 3; row >= 0; row--) { 22 | for (int col = row + 2; col < N; col++) { 23 | isP[row][col] = str[row] == str[col] && isP[row + 1][col - 1]; 24 | } 25 | } 26 | int[] dp = new int[N + 1]; 27 | for (int i = 0; i <= N; i++) { 28 | dp[i] = Integer.MAX_VALUE; 29 | } 30 | dp[N] = 0; 31 | for (int i = N - 1; i >= 0; i--) { 32 | for (int end = i; end < N; end++) { 33 | // i..end 34 | if (isP[i][end]) { 35 | dp[i] = Math.min(dp[i], 1 + dp[end + 1]); 36 | } 37 | } 38 | } 39 | return dp[0]; 40 | } 41 | 42 | public static void main(String[] args) { 43 | String test = "aba12321412321TabaKFK"; 44 | System.out.println(minParts(test)); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/class06/Main.java: -------------------------------------------------------------------------------- 1 | package class06; 2 | 3 | // 本文件为Code04_TopKSumCrossTwoArrays的练习题 4 | // 测试链接 : https://www.nowcoder.com/practice/7201cacf73e7495aa5f88b223bbbf6d1 5 | // 不要提交包信息,提交下面的代码可以直接通过 6 | // 因为测试平台会卡空间,所以把set换成了动态加和减的结构 7 | 8 | import java.util.Scanner; 9 | import java.util.Comparator; 10 | import java.util.HashSet; 11 | import java.util.PriorityQueue; 12 | 13 | public class Main { 14 | 15 | public static void main(String[] args) { 16 | Scanner sc = new Scanner(System.in); 17 | int N = sc.nextInt(); 18 | int K = sc.nextInt(); 19 | int[] arr1 = new int[N]; 20 | int[] arr2 = new int[N]; 21 | for (int i = 0; i < N; i++) { 22 | arr1[i] = sc.nextInt(); 23 | } 24 | for (int i = 0; i < N; i++) { 25 | arr2[i] = sc.nextInt(); 26 | } 27 | int[] topK = topKSum(arr1, arr2, K); 28 | for (int i = 0; i < K; i++) { 29 | System.out.print(topK[i] + " "); 30 | } 31 | System.out.println(); 32 | sc.close(); 33 | } 34 | 35 | // 放入大根堆中的结构 36 | public static class Node { 37 | public int index1;// arr1中的位置 38 | public int index2;// arr2中的位置 39 | public int sum;// arr1[index1] + arr2[index2]的值 40 | 41 | public Node(int i1, int i2, int s) { 42 | index1 = i1; 43 | index2 = i2; 44 | sum = s; 45 | } 46 | } 47 | 48 | // 生成大根堆的比较器 49 | public static class MaxHeapComp implements Comparator { 50 | @Override 51 | public int compare(Node o1, Node o2) { 52 | return o2.sum - o1.sum; 53 | } 54 | } 55 | 56 | public static int[] topKSum(int[] arr1, int[] arr2, int topK) { 57 | if (arr1 == null || arr2 == null || topK < 1) { 58 | return null; 59 | } 60 | int N = arr1.length; 61 | int M = arr2.length; 62 | topK = Math.min(topK, N * M); 63 | int[] res = new int[topK]; 64 | int resIndex = 0; 65 | PriorityQueue maxHeap = new PriorityQueue<>(new MaxHeapComp()); 66 | HashSet set = new HashSet<>(); 67 | int i1 = N - 1; 68 | int i2 = M - 1; 69 | maxHeap.add(new Node(i1, i2, arr1[i1] + arr2[i2])); 70 | set.add(x(i1, i2, M)); 71 | while (resIndex != topK) { 72 | Node curNode = maxHeap.poll(); 73 | res[resIndex++] = curNode.sum; 74 | i1 = curNode.index1; 75 | i2 = curNode.index2; 76 | set.remove(x(i1, i2, M)); 77 | if (i1 - 1 >= 0 && !set.contains(x(i1 - 1, i2, M))) { 78 | set.add(x(i1 - 1, i2, M)); 79 | maxHeap.add(new Node(i1 - 1, i2, arr1[i1 - 1] + arr2[i2])); 80 | } 81 | if (i2 - 1 >= 0 && !set.contains(x(i1, i2 - 1, M))) { 82 | set.add(x(i1, i2 - 1, M)); 83 | maxHeap.add(new Node(i1, i2 - 1, arr1[i1] + arr2[i2 - 1])); 84 | } 85 | } 86 | return res; 87 | } 88 | 89 | public static long x(int i1, int i2, int M) { 90 | return (long) i1 * (long) M + (long) i2; 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/class07/Code01_MinLengthForSort.java: -------------------------------------------------------------------------------- 1 | package class07; 2 | 3 | public class Code01_MinLengthForSort { 4 | 5 | public static int getMinLength(int[] arr) { 6 | if (arr == null || arr.length < 2) { 7 | return 0; 8 | } 9 | int min = arr[arr.length - 1]; 10 | int noMinIndex = -1; 11 | for (int i = arr.length - 2; i != -1; i--) { 12 | if (arr[i] > min) { 13 | noMinIndex = i; 14 | } else { 15 | min = Math.min(min, arr[i]); 16 | } 17 | } 18 | if (noMinIndex == -1) { 19 | return 0; 20 | } 21 | int max = arr[0]; 22 | int noMaxIndex = -1; 23 | for (int i = 1; i != arr.length; i++) { 24 | if (arr[i] < max) { 25 | noMaxIndex = i; 26 | } else { 27 | max = Math.max(max, arr[i]); 28 | } 29 | } 30 | return noMaxIndex - noMinIndex + 1; 31 | } 32 | 33 | public static void main(String[] args) { 34 | int[] arr = { 1, 2, 4, 7, 10, 11, 7, 12, 6, 7, 16, 18, 19 }; 35 | System.out.println(getMinLength(arr)); 36 | 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/class07/Code02_SmallestUnFormedSum.java: -------------------------------------------------------------------------------- 1 | package class07; 2 | 3 | import java.util.Arrays; 4 | import java.util.HashSet; 5 | 6 | public class Code02_SmallestUnFormedSum { 7 | 8 | public static int unformedSum1(int[] arr) { 9 | if (arr == null || arr.length == 0) { 10 | return 1; 11 | } 12 | HashSet set = new HashSet(); 13 | process(arr, 0, 0, set); 14 | int min = Integer.MAX_VALUE; 15 | for (int i = 0; i != arr.length; i++) { 16 | min = Math.min(min, arr[i]); 17 | } 18 | for (int i = min + 1; i != Integer.MIN_VALUE; i++) { 19 | if (!set.contains(i)) { 20 | return i; 21 | } 22 | } 23 | return 0; 24 | } 25 | 26 | public static void process(int[] arr, int i, int sum, HashSet set) { 27 | if (i == arr.length) { 28 | set.add(sum); 29 | return; 30 | } 31 | process(arr, i + 1, sum, set); 32 | process(arr, i + 1, sum + arr[i], set); 33 | } 34 | 35 | public static int unformedSum2(int[] arr) { 36 | if (arr == null || arr.length == 0) { 37 | return 1; 38 | } 39 | int sum = 0; 40 | int min = Integer.MAX_VALUE; 41 | for (int i = 0; i != arr.length; i++) { 42 | sum += arr[i]; 43 | min = Math.min(min, arr[i]); 44 | } 45 | // boolean[][] dp ... 46 | int N = arr.length; 47 | boolean[][] dp = new boolean[N][sum + 1]; 48 | for (int i = 0; i < N; i++) {// arr[0..i] 0 49 | dp[i][0] = true; 50 | } 51 | dp[0][arr[0]] = true; 52 | for (int i = 1; i < N; i++) { 53 | for (int j = 1; j <= sum; j++) { 54 | dp[i][j] = dp[i - 1][j] || ((j - arr[i] >= 0) ? dp[i - 1][j - arr[i]] : false); 55 | } 56 | } 57 | for (int j = min; j <= sum; j++) { 58 | if (!dp[N - 1][j]) { 59 | return j; 60 | } 61 | } 62 | return sum + 1; 63 | } 64 | 65 | // 已知arr中肯定有1这个数 66 | public static int unformedSum3(int[] arr) { 67 | if (arr == null || arr.length == 0) { 68 | return 0; 69 | } 70 | Arrays.sort(arr); // O (N * logN) 71 | int range = 1; 72 | // arr[0] == 1 73 | for (int i = 1; i != arr.length; i++) { 74 | if (arr[i] > range + 1) { 75 | return range + 1; 76 | } else { 77 | range += arr[i]; 78 | } 79 | } 80 | return range + 1; 81 | } 82 | 83 | public static int[] generateArray(int len, int maxValue) { 84 | int[] res = new int[len]; 85 | for (int i = 0; i != res.length; i++) { 86 | res[i] = (int) (Math.random() * maxValue) + 1; 87 | } 88 | return res; 89 | } 90 | 91 | public static void printArray(int[] arr) { 92 | for (int i = 0; i != arr.length; i++) { 93 | System.out.print(arr[i] + " "); 94 | } 95 | System.out.println(); 96 | } 97 | 98 | public static void main(String[] args) { 99 | int len = 27; 100 | int max = 30; 101 | int[] arr = generateArray(len, max); 102 | printArray(arr); 103 | long start = System.currentTimeMillis(); 104 | System.out.println(unformedSum1(arr)); 105 | long end = System.currentTimeMillis(); 106 | System.out.println("cost time: " + (end - start) + " ms"); 107 | System.out.println("======================================"); 108 | 109 | start = System.currentTimeMillis(); 110 | System.out.println(unformedSum2(arr)); 111 | end = System.currentTimeMillis(); 112 | System.out.println("cost time: " + (end - start) + " ms"); 113 | System.out.println("======================================"); 114 | 115 | System.out.println("set arr[0] to 1"); 116 | arr[0] = 1; 117 | start = System.currentTimeMillis(); 118 | System.out.println(unformedSum3(arr)); 119 | end = System.currentTimeMillis(); 120 | System.out.println("cost time: " + (end - start) + " ms"); 121 | 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/class07/Code03_MinPatches.java: -------------------------------------------------------------------------------- 1 | package class07; 2 | 3 | import java.util.Arrays; 4 | 5 | public class Code03_MinPatches { 6 | 7 | // arr请保证有序,且正数 8 | public static int minPatches(int[] arr, int aim) { 9 | int patches = 0; // 缺多少个数字 10 | long range = 0; // 已经完成了1 ~ range的目标 11 | Arrays.sort(arr); 12 | for (int i = 0; i != arr.length; i++) { 13 | // 1~range 14 | // 1 ~ arr[i]-1 15 | while (arr[i] - 1 > range) { // arr[i] 1 ~ arr[i]-1 16 | range += range + 1; // range + 1 是缺的数字 17 | patches++; 18 | if (range >= aim) { 19 | return patches; 20 | } 21 | } 22 | range += arr[i]; 23 | if (range >= aim) { 24 | return patches; 25 | } 26 | } 27 | while (aim >= range + 1) { 28 | range += range + 1; 29 | patches++; 30 | } 31 | return patches; 32 | } 33 | 34 | public static int minPatches2(int[] arr, int K) { 35 | int patches = 0; // 缺多少个数字 36 | int range = 0; // 已经完成了1 ~ range的目标 37 | for (int i = 0; i != arr.length; i++) { 38 | // 1~range 39 | // 1 ~ arr[i]-1 40 | while (arr[i] > range + 1) { // arr[i] 1 ~ arr[i]-1 41 | 42 | if (range > Integer.MAX_VALUE - range - 1) { 43 | return patches + 1; 44 | } 45 | 46 | range += range + 1; // range + 1 是缺的数字 47 | patches++; 48 | if (range >= K) { 49 | return patches; 50 | } 51 | } 52 | if (range > Integer.MAX_VALUE - arr[i]) { 53 | return patches; 54 | } 55 | range += arr[i]; 56 | if (range >= K) { 57 | return patches; 58 | } 59 | } 60 | while (K >= range + 1) { 61 | if (K == range && K == Integer.MAX_VALUE) { 62 | return patches; 63 | } 64 | if (range > Integer.MAX_VALUE - range - 1) { 65 | return patches + 1; 66 | } 67 | range += range + 1; 68 | patches++; 69 | } 70 | return patches; 71 | } 72 | 73 | public static void main(String[] args) { 74 | int[] test = { 1, 2, 31, 33 }; 75 | int n = 2147483647; 76 | System.out.println(minPatches(test, n)); 77 | 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/class07/Code04_LargestComponentSizebyCommonFactor.java: -------------------------------------------------------------------------------- 1 | package class07; 2 | 3 | import java.util.HashMap; 4 | 5 | // 本题为leetcode原题 6 | // 测试链接:https://leetcode.com/problems/largest-component-size-by-common-factor/ 7 | // 方法1会超时,但是方法2直接通过 8 | public class Code04_LargestComponentSizebyCommonFactor { 9 | 10 | public static int largestComponentSize1(int[] arr) { 11 | int N = arr.length; 12 | UnionFind set = new UnionFind(N); 13 | for (int i = 0; i < N; i++) { 14 | for (int j = i + 1; j < N; j++) { 15 | if (gcd(arr[i], arr[j]) != 1) { 16 | set.union(i, j); 17 | } 18 | } 19 | } 20 | return set.maxSize(); 21 | } 22 | 23 | public static int largestComponentSize2(int[] arr) { 24 | int N = arr.length; 25 | UnionFind unionFind = new UnionFind(N); 26 | HashMap fatorsMap = new HashMap<>(); 27 | for (int i = 0; i < N; i++) { 28 | int num = arr[i]; 29 | int limit = (int) Math.sqrt(num); 30 | for (int j = 1; j <= limit; j++) { 31 | if (num % j == 0) { 32 | if (j != 1) { 33 | if (!fatorsMap.containsKey(j)) { 34 | fatorsMap.put(j, i); 35 | } else { 36 | unionFind.union(fatorsMap.get(j), i); 37 | } 38 | } 39 | int other = num / j; 40 | if (other != 1) { 41 | if (!fatorsMap.containsKey(other)) { 42 | fatorsMap.put(other, i); 43 | } else { 44 | unionFind.union(fatorsMap.get(other), i); 45 | } 46 | } 47 | } 48 | } 49 | } 50 | return unionFind.maxSize(); 51 | } 52 | 53 | public static int gcd(int m, int n) { 54 | return n == 0 ? m : gcd(n, m % n); 55 | } 56 | 57 | public static class UnionFind { 58 | private int[] parents; 59 | private int[] sizes; 60 | private int[] help; 61 | 62 | public UnionFind(int N) { 63 | parents = new int[N]; 64 | sizes = new int[N]; 65 | help = new int[N]; 66 | for (int i = 0; i < N; i++) { 67 | parents[i] = i; 68 | sizes[i] = 1; 69 | } 70 | } 71 | 72 | public int maxSize() { 73 | int ans = 0; 74 | for (int size : sizes) { 75 | ans = Math.max(ans, size); 76 | } 77 | return ans; 78 | } 79 | 80 | private int find(int i) { 81 | int hi = 0; 82 | while (i != parents[i]) { 83 | help[hi++] = i; 84 | i = parents[i]; 85 | } 86 | for (hi--; hi >= 0; hi--) { 87 | parents[help[hi]] = i; 88 | } 89 | return i; 90 | } 91 | 92 | public void union(int i, int j) { 93 | int f1 = find(i); 94 | int f2 = find(j); 95 | if (f1 != f2) { 96 | int big = sizes[f1] >= sizes[f2] ? f1 : f1; 97 | int small = big == f1 ? f2 : f1; 98 | parents[small] = big; 99 | sizes[big] = sizes[f1] + sizes[f2]; 100 | } 101 | } 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /src/class07/Code05_RemoveDuplicateLettersLessLexi.java: -------------------------------------------------------------------------------- 1 | package class07; 2 | 3 | public class Code05_RemoveDuplicateLettersLessLexi { 4 | 5 | // 在str中,每种字符都要保留一个,让最后的结果,字典序最小 ,并返回 6 | public static String removeDuplicateLetters1(String str) { 7 | if (str == null || str.length() < 2) { 8 | return str; 9 | } 10 | int[] map = new int[256]; 11 | for (int i = 0; i < str.length(); i++) { 12 | map[str.charAt(i)]++; 13 | } 14 | int minACSIndex = 0; 15 | for (int i = 0; i < str.length(); i++) { 16 | minACSIndex = str.charAt(minACSIndex) > str.charAt(i) ? i : minACSIndex; 17 | if (--map[str.charAt(i)] == 0) { 18 | break; 19 | } 20 | } 21 | return String.valueOf(str.charAt(minACSIndex)) + removeDuplicateLetters1( 22 | str.substring(minACSIndex + 1).replaceAll(String.valueOf(str.charAt(minACSIndex)), "")); 23 | } 24 | 25 | public static String removeDuplicateLetters2(String s) { 26 | char[] str = s.toCharArray(); 27 | // 小写字母ascii码值范围[97~122],所以用长度为26的数组做次数统计 28 | // 如果map[i] > -1,则代表ascii码值为i的字符的出现次数 29 | // 如果map[i] == -1,则代表ascii码值为i的字符不再考虑 30 | int[] map = new int[26]; 31 | for (int i = 0; i < str.length; i++) { 32 | map[str[i] - 'a']++; 33 | } 34 | char[] res = new char[26]; 35 | int index = 0; 36 | int L = 0; 37 | int R = 0; 38 | while (R != str.length) { 39 | // 如果当前字符是不再考虑的,直接跳过 40 | // 如果当前字符的出现次数减1之后,后面还能出现,直接跳过 41 | if (map[str[R] - 'a'] == -1 || --map[str[R] - 'a'] > 0) { 42 | R++; 43 | } else { // 当前字符需要考虑并且之后不会再出现了 44 | // 在str[L..R]上所有需要考虑的字符中,找到ascii码最小字符的位置 45 | int pick = -1; 46 | for (int i = L; i <= R; i++) { 47 | if (map[str[i] - 'a'] != -1 && (pick == -1 || str[i] < str[pick])) { 48 | pick = i; 49 | } 50 | } 51 | // 把ascii码最小的字符放到挑选结果中 52 | res[index++] = str[pick]; 53 | // 在上一个的for循环中,str[L..R]范围上每种字符的出现次数都减少了 54 | // 需要把str[pick + 1..R]上每种字符的出现次数加回来 55 | for (int i = pick + 1; i <= R; i++) { 56 | if (map[str[i] - 'a'] != -1) { // 只增加以后需要考虑字符的次数 57 | map[str[i] - 'a']++; 58 | } 59 | } 60 | // 选出的ascii码最小的字符,以后不再考虑了 61 | map[str[pick] - 'a'] = -1; 62 | // 继续在str[pick + 1......]上重复这个过程 63 | L = pick + 1; 64 | R = L; 65 | } 66 | } 67 | return String.valueOf(res, 0, index); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/class07/Code06_LongestNoRepeatSubstring.java: -------------------------------------------------------------------------------- 1 | package class07; 2 | 3 | public class Code06_LongestNoRepeatSubstring { 4 | 5 | public static int maxUnique(String str) { 6 | if (str == null || str.equals("")) { 7 | return 0; 8 | } 9 | char[] chas = str.toCharArray(); 10 | // map 替代了哈希表 假设字符的码是0~255 11 | int[] map = new int[256]; 12 | for (int i = 0; i < 256; i++) { 13 | map[i] = -1; 14 | } 15 | int len = 0; 16 | int pre = -1; 17 | int cur = 0; 18 | for (int i = 0; i != chas.length; i++) { 19 | pre = Math.max(pre, map[chas[i]]); 20 | cur = i - pre; 21 | len = Math.max(len, cur); 22 | map[chas[i]] = i; 23 | } 24 | return len; 25 | } 26 | 27 | // for test 28 | public static String getRandomString(int len) { 29 | char[] str = new char[len]; 30 | int base = 'a'; 31 | int range = 'z' - 'a' + 1; 32 | for (int i = 0; i != len; i++) { 33 | str[i] = (char) ((int) (Math.random() * range) + base); 34 | } 35 | return String.valueOf(str); 36 | } 37 | 38 | // for test 39 | public static String maxUniqueString(String str) { 40 | if (str == null || str.equals("")) { 41 | return str; 42 | } 43 | char[] chas = str.toCharArray(); 44 | int[] map = new int[256]; 45 | for (int i = 0; i < 256; i++) { 46 | map[i] = -1; 47 | } 48 | int len = -1; 49 | int pre = -1; 50 | int cur = 0; 51 | int end = -1; 52 | for (int i = 0; i != chas.length; i++) { 53 | pre = Math.max(pre, map[chas[i]]); 54 | cur = i - pre; 55 | if (cur > len) { 56 | len = cur; 57 | end = i; 58 | } 59 | map[chas[i]] = i; 60 | } 61 | return str.substring(end - len + 1, end + 1); 62 | } 63 | 64 | public static void main(String[] args) { 65 | String str = getRandomString(20); 66 | System.out.println(str); 67 | System.out.println(maxUnique(str)); 68 | System.out.println(maxUniqueString(str)); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/class07/Code07_MaxPointsOneLine.java: -------------------------------------------------------------------------------- 1 | package class07; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public class Code07_MaxPointsOneLine { 7 | 8 | public static class Point { 9 | public int x; 10 | public int y; 11 | 12 | Point() { 13 | x = 0; 14 | y = 0; 15 | } 16 | 17 | Point(int a, int b) { 18 | x = a; 19 | y = b; 20 | } 21 | } 22 | 23 | public static int maxPoints(Point[] points) { 24 | if (points == null) { 25 | return 0; 26 | } 27 | if (points.length <= 2) { 28 | return points.length; 29 | } 30 | // key : 分子 value : 分母表 31 | Map> map = new HashMap>(); 32 | int result = 0; 33 | for (int i = 0; i < points.length; i++) { 34 | map.clear(); 35 | int samePosition = 1; 36 | int sameX = 0; 37 | int sameY = 0; 38 | int line = 0; 39 | for (int j = i + 1; j < points.length; j++) { 40 | int x = points[j].x - points[i].x; 41 | int y = points[j].y - points[i].y; 42 | if (x == 0 && y == 0) { 43 | samePosition++; 44 | } else if (x == 0) { 45 | sameX++; 46 | } else if (y == 0) { 47 | sameY++; 48 | } else { 49 | int gcd = gcd(x, y); 50 | x /= gcd; 51 | y /= gcd; 52 | if (!map.containsKey(x)) { 53 | map.put(x, new HashMap()); 54 | } 55 | if (!map.get(x).containsKey(y)) { 56 | map.get(x).put(y, 0); 57 | } 58 | map.get(x).put(y, map.get(x).get(y) + 1); 59 | line = Math.max(line, map.get(x).get(y)); 60 | } 61 | } 62 | result = Math.max(result, Math.max(Math.max(sameX, sameY), line) + samePosition); 63 | } 64 | return result; 65 | } 66 | 67 | // 保证初始调用的时候,a和b不等于0 68 | public static int gcd(int a, int b) { 69 | return b == 0 ? a : gcd(b, a % b); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/class08/Code01_ReceiveAndPrintOrderLine.java: -------------------------------------------------------------------------------- 1 | package class08; 2 | 3 | import java.util.HashMap; 4 | 5 | public class Code01_ReceiveAndPrintOrderLine { 6 | 7 | public static class Node { 8 | public String info; 9 | public Node next; 10 | 11 | public Node(String str) { 12 | info = str; 13 | } 14 | } 15 | 16 | public static class MessageBox { 17 | private HashMap headMap; 18 | private HashMap tailMap; 19 | private int waitPoint; 20 | 21 | public MessageBox() { 22 | headMap = new HashMap(); 23 | tailMap = new HashMap(); 24 | waitPoint = 1; 25 | } 26 | 27 | // 消息的编号,info消息的内容, 消息一定从1开始 28 | public void receive(int num, String info) { 29 | if (num < 1) { 30 | return; 31 | } 32 | Node cur = new Node(info); 33 | // num~num 34 | headMap.put(num, cur); 35 | tailMap.put(num, cur); 36 | // 建立了num~num这个连续区间的头和尾 37 | // 查询有没有某个连续区间以num-1结尾 38 | if (tailMap.containsKey(num - 1)) { 39 | tailMap.get(num - 1).next = cur; 40 | tailMap.remove(num - 1); 41 | headMap.remove(num); 42 | } 43 | // 查询有没有某个连续区间以num+1开头的 44 | if (headMap.containsKey(num + 1)) { 45 | cur.next = headMap.get(num + 1); 46 | tailMap.remove(num); 47 | headMap.remove(num + 1); 48 | } 49 | if (num == waitPoint) { 50 | print(); 51 | } 52 | } 53 | 54 | private void print() { 55 | Node node = headMap.get(waitPoint); 56 | headMap.remove(waitPoint); 57 | while (node != null) { 58 | System.out.print(node.info + " "); 59 | node = node.next; 60 | waitPoint++; 61 | } 62 | tailMap.remove(waitPoint-1); 63 | System.out.println(); 64 | } 65 | 66 | } 67 | 68 | public static void main(String[] args) { 69 | // MessageBox only receive 1~N 70 | MessageBox box = new MessageBox(); 71 | 72 | box.receive(2,"B"); // - 2" 73 | box.receive(1,"A"); // 1 2 -> print, trigger is 1 74 | 75 | box.receive(4,"D"); // - 4 76 | box.receive(5,"E"); // - 4 5 77 | box.receive(7,"G"); // - 4 5 - 7 78 | box.receive(8,"H"); // - 4 5 - 7 8 79 | box.receive(6,"F"); // - 4 5 6 7 8 80 | box.receive(3,"C"); // 3 4 5 6 7 8 -> print, trigger is 3 81 | 82 | box.receive(9,"I"); // 9 -> print, trigger is 9 83 | 84 | box.receive(10,"J"); // 10 -> print, trigger is 10 85 | 86 | box.receive(12,"L"); // - 12 87 | box.receive(13,"M"); // - 12 13 88 | box.receive(11,"K"); // 11 12 13 -> print, trigger is 11 89 | 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/class08/Code02_MoneyWays.java: -------------------------------------------------------------------------------- 1 | package class08; 2 | 3 | public class Code02_MoneyWays { 4 | 5 | public static int moneyWays(int[] arbitrary, int[] onlyone, int money) { 6 | if (money < 0) { 7 | return 0; 8 | } 9 | if ((arbitrary == null || arbitrary.length == 0) && (onlyone == null || onlyone.length == 0)) { 10 | return money == 0 ? 1 : 0; 11 | } 12 | // 任意张 的数组, 一张的数组,不可能都没有 13 | int[][] dparb = getDpArb(arbitrary, money); 14 | int[][] dpone = getDpOne(onlyone, money); 15 | if (dparb == null) { // 任意张的数组没有,一张的数组有 16 | return dpone[dpone.length - 1][money]; 17 | } 18 | if (dpone == null) { // 任意张的数组有,一张的数组没有 19 | return dparb[dparb.length - 1][money]; 20 | } 21 | int res = 0; 22 | for (int i = 0; i <= money; i++) { 23 | res += dparb[dparb.length - 1][i] * dpone[dpone.length - 1][money - i]; 24 | } 25 | return res; 26 | } 27 | 28 | public static int[][] getDpArb(int[] arr, int money) { 29 | if (arr == null || arr.length == 0) { 30 | return null; 31 | } 32 | int[][] dp = new int[arr.length][money + 1]; 33 | // dp[i][j] 0..i券 自由选择张数, 搞定j元, 有多少方法? 34 | 35 | for (int i = 0; i < arr.length; i++) { 36 | dp[i][0] = 1; 37 | } 38 | // [0] 5元 0元 5元 10元 15元 20元 39 | for (int j = 1; arr[0] * j <= money; j++) { 40 | dp[0][arr[0] * j] = 1; 41 | } 42 | // 0行 0列 填完了 43 | for (int i = 1; i < arr.length; i++) { 44 | for (int j = 1; j <= money; j++) { 45 | dp[i][j] = dp[i - 1][j]; 46 | dp[i][j] += j - arr[i] >= 0 ? dp[i][j - arr[i]] : 0; 47 | } 48 | } 49 | return dp; 50 | } 51 | 52 | public static int[][] getDpOne(int[] arr, int money) { 53 | if (arr == null || arr.length == 0) { 54 | return null; 55 | } 56 | int[][] dp = new int[arr.length][money + 1]; 57 | for (int i = 0; i < arr.length; i++) { 58 | dp[i][0] = 1; 59 | } 60 | if (arr[0] <= money) { 61 | dp[0][arr[0]] = 1; 62 | } 63 | for (int i = 1; i < arr.length; i++) { 64 | for (int j = 1; j <= money; j++) { 65 | dp[i][j] = dp[i - 1][j]; 66 | dp[i][j] += j - arr[i] >= 0 ? dp[i - 1][j - arr[i]] : 0; 67 | } 68 | } 69 | return dp; 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/class08/Code03_OneNumber.java: -------------------------------------------------------------------------------- 1 | package class08; 2 | 3 | public class Code03_OneNumber { 4 | 5 | public static int solution1(int num) { 6 | if (num < 1) { 7 | return 0; 8 | } 9 | int count = 0; 10 | for (int i = 1; i != num + 1; i++) { 11 | count += get1Nums(i); 12 | } 13 | return count; 14 | } 15 | 16 | public static int get1Nums(int num) { 17 | int res = 0; 18 | while (num != 0) { 19 | if (num % 10 == 1) { 20 | res++; 21 | } 22 | num /= 10; 23 | } 24 | return res; 25 | } 26 | 27 | public static int solution2(int num) { 28 | if (num < 1) { 29 | return 0; 30 | } 31 | // num -> 13625 32 | // len = 5位数 33 | int len = getLenOfNum(num); 34 | if (len == 1) { 35 | return 1; 36 | } 37 | // num 13625 38 | // tmp1 10000 39 | // num 7872328738273 40 | // tmp1 1000000000000 41 | int tmp1 = powerBaseOf10(len - 1); 42 | // num最高位 num / tmp1 43 | int first = num / tmp1; 44 | // 最高1 N % tmp1 + 1 45 | // 最高位first tmp1 46 | int firstOneNum = first == 1 ? num % tmp1 + 1 : tmp1; 47 | // 除去最高位之外,剩下1的数量 48 | // 最高位1 10(k-2次方) * (k-1) * 1 49 | // 最高位first 10(k-2次方) * (k-1) * first 50 | int otherOneNum = first * (len - 1) * (tmp1 / 10); 51 | return firstOneNum + otherOneNum + solution2(num % tmp1); 52 | } 53 | 54 | public static int getLenOfNum(int num) { 55 | int len = 0; 56 | while (num != 0) { 57 | len++; 58 | num /= 10; 59 | } 60 | return len; 61 | } 62 | 63 | public static int powerBaseOf10(int base) { 64 | return (int) Math.pow(10, base); 65 | } 66 | 67 | public static void main(String[] args) { 68 | int num = 50000000; 69 | long start1 = System.currentTimeMillis(); 70 | System.out.println(solution1(num)); 71 | long end1 = System.currentTimeMillis(); 72 | System.out.println("cost time: " + (end1 - start1) + " ms"); 73 | 74 | long start2 = System.currentTimeMillis(); 75 | System.out.println(solution2(num)); 76 | long end2 = System.currentTimeMillis(); 77 | System.out.println("cost time: " + (end2 - start2) + " ms"); 78 | 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/class08/Code04_MoneyProblem.java: -------------------------------------------------------------------------------- 1 | package class08; 2 | 3 | public class Code04_MoneyProblem { 4 | 5 | // int[] d d[i]:i号怪兽的武力 6 | // int[] p p[i]:i号怪兽要求的钱 7 | // ability 当前你所具有的能力 8 | // index 来到了第index个怪兽的面前 9 | 10 | // 目前,你的能力是ability,你来到了index号怪兽的面前,如果要通过后续所有的怪兽, 11 | // 请返回需要花的最少钱数 12 | public static long process(int[] d, int[] p, int ability, int index) { 13 | if (index == d.length) { 14 | return 0; 15 | } 16 | if (ability < d[index]) { 17 | return p[index] + process(d, p, ability + d[index], index + 1); 18 | } else { // 可以贿赂,也可以不贿赂 19 | return 20 | Math.min( 21 | p[index] + process(d, p, ability + d[index], index + 1), 22 | process(d, p, ability, index + 1) 23 | ); 24 | } 25 | } 26 | 27 | public static long func1(int[] d, int[] p) { 28 | return process(d, p, 0, 0); 29 | } 30 | 31 | public static long func2(int[] d, int[] p) { 32 | int sum = 0; 33 | for (int num : d) { 34 | sum += num; 35 | } 36 | long[][] dp = new long[d.length + 1][sum + 1]; 37 | for (int cur = d.length - 1; cur >= 0; cur--) { 38 | for (int hp = 0; hp <= sum; hp++) { 39 | // 如果这种情况发生,那么这个hp必然是递归过程中不会出现的状态 40 | // 既然动态规划是尝试过程的优化,尝试过程碰不到的状态,不必计算 41 | if (hp + d[cur] > sum) { 42 | continue; 43 | } 44 | if (hp < d[cur]) { 45 | dp[cur][hp] = p[cur] + dp[cur + 1][hp + d[cur]]; 46 | } else { 47 | dp[cur][hp] = Math.min(p[cur] + dp[cur + 1][hp + d[cur]], dp[cur + 1][hp]); 48 | } 49 | } 50 | } 51 | return dp[0][0]; 52 | } 53 | 54 | public static long func3(int[] d, int[] p) { 55 | int sum = 0; 56 | for (int num : p) { 57 | sum += num; 58 | } 59 | // dp[i][j]含义: 60 | // 能经过0~i的怪兽,且花钱为j(花钱的严格等于j)时的武力值最大是多少? 61 | // 如果dp[i][j]==-1,表示经过0~i的怪兽,花钱为j是无法通过的,或者之前的钱怎么组合也得不到正好为j的钱数 62 | int[][] dp = new int[d.length][sum + 1]; 63 | for (int i = 0; i < dp.length; i++) { 64 | for (int j = 0; j <= sum; j++) { 65 | dp[i][j] = -1; 66 | } 67 | } 68 | // 经过0~i的怪兽,花钱数一定为p[0],达到武力值d[0]的地步。其他第0行的状态一律是无效的 69 | dp[0][p[0]] = d[0]; 70 | for (int i = 1; i < d.length; i++) { 71 | for (int j = 0; j <= sum; j++) { 72 | // 可能性一,为当前怪兽花钱 73 | // 存在条件: 74 | // j - p[i]要不越界,并且在钱数为j - p[i]时,要能通过0~i-1的怪兽,并且钱数组合是有效的。 75 | if (j >= p[i] && dp[i - 1][j - p[i]] != -1) { 76 | dp[i][j] = dp[i - 1][j - p[i]] + d[i]; 77 | } 78 | // 可能性二,不为当前怪兽花钱 79 | // 存在条件: 80 | // 0~i-1怪兽在花钱为j的情况下,能保证通过当前i位置的怪兽 81 | if (dp[i - 1][j] >= d[i]) { 82 | // 两种可能性中,选武力值最大的 83 | dp[i][j] = Math.max(dp[i][j], dp[i - 1][j]); 84 | } 85 | } 86 | } 87 | int ans = 0; 88 | // dp表最后一行上,dp[N-1][j]代表: 89 | // 能经过0~N-1的怪兽,且花钱为j(花钱的严格等于j)时的武力值最大是多少? 90 | // 那么最后一行上,最左侧的不为-1的列数(j),就是答案 91 | for (int j = 0; j <= sum; j++) { 92 | if (dp[d.length - 1][j] != -1) { 93 | ans = j; 94 | break; 95 | } 96 | } 97 | return ans; 98 | } 99 | 100 | public static int[][] generateTwoRandomArray(int len, int value) { 101 | int size = (int) (Math.random() * len) + 1; 102 | int[][] arrs = new int[2][size]; 103 | for (int i = 0; i < size; i++) { 104 | arrs[0][i] = (int) (Math.random() * value) + 1; 105 | arrs[1][i] = (int) (Math.random() * value) + 1; 106 | } 107 | return arrs; 108 | } 109 | 110 | public static void main(String[] args) { 111 | int len = 10; 112 | int value = 20; 113 | int testTimes = 1000000; 114 | for (int i = 0; i < testTimes; i++) { 115 | int[][] arrs = generateTwoRandomArray(len, value); 116 | int[] d = arrs[0]; 117 | int[] p = arrs[1]; 118 | long ans1 = func1(d, p); 119 | long ans2 = func2(d, p); 120 | long ans3 = func3(d, p); 121 | if (ans1 != ans2 || ans2 != ans3) { 122 | System.out.println("oops!"); 123 | } 124 | } 125 | 126 | } 127 | 128 | } 129 | -------------------------------------------------------------------------------- /src/class08/Code05_LongestIntegratedLength.java: -------------------------------------------------------------------------------- 1 | package class08; 2 | 3 | import java.util.Arrays; 4 | import java.util.HashSet; 5 | 6 | public class Code05_LongestIntegratedLength { 7 | 8 | public static int getLIL1(int[] arr) { 9 | if (arr == null || arr.length == 0) { 10 | return 0; 11 | } 12 | int len = 0; 13 | // O(N^3 * log N) 14 | for (int start = 0; start < arr.length; start++) { // 子数组所有可能的开头 15 | for (int end = start; end < arr.length; end++) { // 开头为start的情况下,所有可能的结尾 16 | // arr[s ... e] 17 | // O(N * logN) 18 | if (isIntegrated(arr, start, end)) { 19 | len = Math.max(len, end - start + 1); 20 | } 21 | } 22 | } 23 | return len; 24 | } 25 | 26 | public static boolean isIntegrated(int[] arr, int left, int right) { 27 | int[] newArr = Arrays.copyOfRange(arr, left, right + 1); // O(N) 28 | Arrays.sort(newArr); // O(N*logN) 29 | for (int i = 1; i < newArr.length; i++) { 30 | if (newArr[i - 1] != newArr[i] - 1) { 31 | return false; 32 | } 33 | } 34 | return true; 35 | } 36 | 37 | public static int getLIL2(int[] arr) { 38 | if (arr == null || arr.length == 0) { 39 | return 0; 40 | } 41 | int len = 0; 42 | int max = 0; 43 | int min = 0; 44 | HashSet set = new HashSet(); 45 | for (int L = 0; L < arr.length; L++) { // L 左边界 46 | // L ....... 47 | set.clear(); 48 | max = Integer.MIN_VALUE; 49 | min = Integer.MAX_VALUE; 50 | for (int R = L; R < arr.length; R++) { // R 右边界 51 | // arr[L..R]这个子数组在验证 l...R L...r+1 l...r+2 52 | if (set.contains(arr[R])) { 53 | // arr[L..R]上开始 出现重复值了,arr[L..R往后]不需要验证了, 54 | // 一定不是可整合的 55 | break; 56 | } 57 | // arr[L..R]上无重复值 58 | set.add(arr[R]); 59 | max = Math.max(max, arr[R]); 60 | min = Math.min(min, arr[R]); 61 | if (max - min == R - L) { // L..R 是可整合的 62 | len = Math.max(len, R - L + 1); 63 | } 64 | } 65 | } 66 | return len; 67 | } 68 | 69 | public static void main(String[] args) { 70 | int[] arr = { 5, 5, 3, 2, 6, 4, 3 }; 71 | System.out.println(getLIL1(arr)); 72 | System.out.println(getLIL2(arr)); 73 | 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/class08/Code06_PalindromeMinAdd.java: -------------------------------------------------------------------------------- 1 | package class08; 2 | 3 | public class Code06_PalindromeMinAdd { 4 | 5 | public static String getPalindrome1(String str) { 6 | if (str == null || str.length() < 2) { 7 | return str; 8 | } 9 | char[] chas = str.toCharArray(); 10 | int[][] dp = getDP(chas); 11 | char[] res = new char[chas.length + dp[0][chas.length - 1]]; 12 | int i = 0; 13 | int j = chas.length - 1; 14 | int resl = 0; 15 | int resr = res.length - 1; 16 | while (i <= j) { 17 | if (chas[i] == chas[j]) { 18 | res[resl++] = chas[i++]; 19 | res[resr--] = chas[j--]; 20 | } else if (dp[i][j - 1] < dp[i + 1][j]) { 21 | res[resl++] = chas[j]; 22 | res[resr--] = chas[j--]; 23 | } else { 24 | res[resl++] = chas[i]; 25 | res[resr--] = chas[i++]; 26 | } 27 | } 28 | return String.valueOf(res); 29 | } 30 | 31 | public static int[][] getDP(char[] str) { 32 | int[][] dp = new int[str.length][str.length]; 33 | for (int j = 1; j < str.length; j++) { 34 | dp[j - 1][j] = str[j - 1] == str[j] ? 0 : 1; 35 | for (int i = j - 2; i > -1; i--) { 36 | if (str[i] == str[j]) { 37 | dp[i][j] = dp[i + 1][j - 1]; 38 | } else { 39 | dp[i][j] = Math.min(dp[i + 1][j], dp[i][j - 1]) + 1; 40 | } 41 | } 42 | } 43 | return dp; 44 | } 45 | 46 | public static void main(String[] args) { 47 | String str = "AB1CD2EFG3H43IJK2L1MN"; 48 | System.out.println(getPalindrome1(str)); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/class08/Main.java: -------------------------------------------------------------------------------- 1 | package class08; 2 | 3 | // 本题是本节MoneyWays问题的在线测试 4 | // 牛客测试链接 : https://www.nowcoder.com/questionTerminal/93bcd2190da34099b98dfc9a9fb77984 5 | // 提交以下的代码 6 | import java.util.Scanner; 7 | 8 | public class Main { 9 | 10 | public static void main(String[] args) { 11 | Scanner sc = new Scanner(System.in); 12 | int N1 = sc.nextInt(); 13 | int N2 = sc.nextInt(); 14 | int M = sc.nextInt(); 15 | int[] arr1 = new int[N1]; 16 | int[] arr2 = new int[N2]; 17 | for (int i = 0; i < N1; i++) { 18 | arr1[i] = sc.nextInt(); 19 | } 20 | for (int i = 0; i < N2; i++) { 21 | arr2[i] = sc.nextInt(); 22 | } 23 | System.out.println(moneyWays(arr1, arr2, M)); 24 | sc.close(); 25 | } 26 | 27 | public static final long mod = 1000000007; 28 | 29 | public static int moneyWays(int[] arbitrary, int[] onlyone, int money) { 30 | long[][] dparb = getDpArb(arbitrary, money); 31 | long[][] dpone = getDpOne(onlyone, money); 32 | long res = 0; 33 | for (int i = 0; i <= money; i++) { 34 | res = (res + dparb[dparb.length - 1][i] * dpone[dpone.length - 1][money - i]) % mod; 35 | } 36 | return (int) res; 37 | } 38 | 39 | public static long[][] getDpArb(int[] arr, int money) { 40 | long[][] dp = new long[arr.length][money + 1]; 41 | for (int i = 0; i < arr.length; i++) { 42 | dp[i][0] = 1; 43 | } 44 | for (int j = 1; arr[0] * j <= money; j++) { 45 | dp[0][arr[0] * j] = 1; 46 | } 47 | for (int i = 1; i < arr.length; i++) { 48 | for (int j = 1; j <= money; j++) { 49 | dp[i][j] = (dp[i - 1][j] + (j - arr[i] >= 0 ? dp[i][j - arr[i]] : 0)) % mod; 50 | } 51 | } 52 | return dp; 53 | } 54 | 55 | public static long[][] getDpOne(int[] arr, int money) { 56 | long[][] dp = new long[arr.length][money + 1]; 57 | for (int i = 0; i < arr.length; i++) { 58 | dp[i][0] = 1; 59 | } 60 | if (arr[0] <= money) { 61 | dp[0][arr[0]] = 1; 62 | } 63 | for (int i = 1; i < arr.length; i++) { 64 | for (int j = 1; j <= money; j++) { 65 | dp[i][j] = (dp[i - 1][j] + (j - arr[i] >= 0 ? dp[i - 1][j - arr[i]] : 0)) % mod; 66 | } 67 | } 68 | return dp; 69 | } 70 | 71 | } --------------------------------------------------------------------------------