├── .gitignore ├── .vscode └── settings.json ├── A3medium ├── 3. 中级.iml ├── class06 │ ├── C02_BSTtoDoubleLinkedList.java │ ├── C03_BiggestSubBSTInTree.java │ ├── C04_PreAndInArrayToPosArray.java │ ├── C05_Light.java │ ├── C06_SubArrayMaxSum.java │ └── C07_SubMatrixMaxSum.java ├── class07 │ ├── C01_ChineseExpression.java │ ├── C01_EnglishExpression.java │ ├── C02_PrintNoInArray.java │ ├── C03_3times.java │ ├── C04_Kiki.java │ ├── C05_CompleteTreeNodeNumber.java │ └── C06_MaxRevenue.java └── class08 │ ├── C02_ExpressionNumber.java │ ├── C03_StringToKth.java │ ├── C04_LongestNoRepeatSubstring.java │ ├── C05_EditCost.java │ ├── C06_RemoveDuplicateLettersLessLexi.java │ ├── C07_WordMinPaths.java │ └── C08_MostIncreaseSubSequence.java ├── A4high ├── 4. 高级.iml ├── class01 │ ├── C01_MaxGap.java │ ├── C02_MostEOR.java │ ├── C03_MoneyWays.java │ ├── C04_JosephusProblem.java │ └── C05_FindKthMinNumber.java ├── class02 │ ├── C01_BuildingOutline.java │ ├── C02_LongestSumSubArrayLengthInPositiveArray.java │ ├── C03_LongestLessSumSubArrayLength.java │ ├── C04_Nim.java │ └── C05_NumberAndString.java ├── class03 │ ├── C01_MaxPathSumInBT.java │ ├── C02_SnakeGame.java │ ├── C03_ExpressionCompute.java │ ├── C04_LCSubstring.java │ └── C05_LCSubsequence.java ├── class04 │ ├── C01_MinBoat.java │ ├── C02_PalindromeSubsequence.java │ ├── C03_PalindromeMinAdd.java │ ├── C04_PalindromeMinCut.java │ ├── C05_PalindromeWays.java │ ├── C06_BFPRT.java │ └── README.md ├── class05 │ ├── C02_SplitNumer.java │ ├── C03_BiggestBSTTopologyInTree.java │ └── C04_ShuffleProblem.java ├── class06 │ ├── C01_SDEandPM.java │ ├── C02_RecoverBST.java │ ├── C03_VisibleMountains.java │ └── C04_CoverMax.java ├── class07 │ ├── C01_RegularExpressionMatch.java │ ├── C02_MaxEOR.java │ ├── C03_BurstBalloons.java │ └── C04_HanoiProblem.java └── class08 │ ├── C02_MinWindowLength.java │ ├── C03_LFU.java │ └── C04_GasStations.java ├── README.md ├── algo.iml ├── binary_search ├── C01_bs.java ├── C04_BSExist.java ├── C05_BSNearLeft.java └── C08_GetMax.java ├── bit_operation ├── C01_GetMax.java ├── C02_Power.java └── C03_AddMinusMultiDivideByBit.java ├── dp ├── C01_RobotWalk.java ├── C02_CoinsMin.java ├── C03_CardsInLine.java ├── C04_HorseJump.java ├── C05_BobDie.java ├── C06_MinPathSum.java ├── C07_CoinsWay.java ├── C09_UniqueBST.java ├── C10_CoffeeTime.java ├── C11_MinPathSum.java └── C12_CompriseWays.java ├── fibonacci ├── C01_ZeroLeftOneStringNumber.java ├── C02_CowBornNumber.java └── C03_DeleteWood.java ├── force_recursion ├── C01_Hanoi.java ├── C02_CardsInLine.java ├── C03_PrintAllPermutations.java ├── C04_ReverseStackUsingRecursive.java ├── C05_ConvertToLetterString.java ├── C06_Knapsack.java ├── C07_PrintAllSubsquences.java ├── C08_MaxDistanceInTree.java ├── C09_MaxHappy.java └── c10_NQueens.java ├── graph ├── C01_BFS.java ├── C02_DFS.java ├── C03_TopologySort.java ├── C04_Kruskal.java ├── C05_Prim.java ├── C06_Dijkstra.java ├── Edge.java ├── Graph.java ├── GraphGenerator.java └── Node.java ├── greed ├── C02_LowestLexicography.java ├── C03_LessMoneySplitGold.java ├── C04_BestArrange.java ├── C05_IPO.java └── C06_MadianQuick.java ├── hash_function ├── C01_HashMap.java ├── C02_RandomPool.java ├── C03_Islands.java ├── C04_UnionFind.java ├── C05_KMP.java ├── C06_Manacher.java ├── C07_SlidingWindowMaxArray.java ├── C08_MonotonousStack.java ├── C09_AllTimesMinToMax.java └── C10_MaxTarget.java ├── leetcode ├── 306.java ├── 43.java ├── 521.java ├── Solution150.java ├── Solution19.java ├── Solution203.java ├── Solution224.java ├── Solution227.java ├── Solution237.java ├── Solution24.java ├── Solution341.java ├── Solution385.java ├── Solution388.java ├── Solution394.java ├── Solution430.java ├── Solution482.java ├── Solution591.java ├── Solution6.java ├── Solution61.java ├── Solution636.java ├── Solution68.java ├── Solution682.java ├── Solution71.java └── Solution92.java ├── linked_list ├── C01_HashAndTree.java ├── C02_ReverseList.java ├── C03_PrintCommonPart.java ├── C04_IsPalindromeList.java ├── C05_SmallerEqualBigger.java ├── C06_CopyListWithRandom.java └── C07_FindFirstIntersectNode.java ├── macro_scheduling ├── C01_RotateMatrix.java ├── C02_ZigZagPrintMatrix.java └── C03_PrintMatrixSpiralOrder.java ├── others ├── C01_DogCatQueue.java ├── C02_GetMinStack.java ├── C03_StackAndQueueConvert.java ├── C04_MaxABSBetweenLeftAndRight.java ├── C05_IsRotation.java ├── C06_NearMultiple4Times.java ├── C09_ConvertStringToInteger.java └── C12_ChooseWork.java ├── skill ├── C01_CordCoverMaxPoint.java ├── C02_AppleMinBags.java ├── C03_Eat.java ├── C04_ColorLeftRight.java ├── C05_MaxOneBorderSize.java ├── C06_Rand5ToRand7.java ├── C08_NeedParentheses.java ├── C09_SubvalueEqualK.java ├── C10_MagicOp.java ├── C11_ParenthesesDeep.java ├── C12_StackSortStack.java ├── C13_NumToStringWays.java ├── C14_MaxSumInTree.java ├── C15_FindNumInSortedMatrix.java ├── C16_PackingMachine.java ├── C17_SplitNbySM.java ├── C18_TopKTimes.java ├── C18_TopKTimes2.java └── C19_WaterProblem.java ├── sort ├── C01_SelectionSort.java ├── C02_BubbleSort.java ├── C03_InsertionSort.java ├── C07_EvenTimesOddTimes.java ├── C09_FindOneLessValueIndex.java ├── C10_MergeSort.java ├── C11_SmallSum.java ├── C12_HeapSort.java ├── C13_SortArrayDistanceLessK.java ├── C14_NetherlandsFlag.java ├── C15_QuickSort.java ├── C16_CountSort.java ├── C17_RadixSort.java └── C18_Comparator.java ├── tree ├── C01_PreInPosTraversal.java ├── C02_PrintBinaryTree.java ├── C03_TreeMaxWidth.java ├── C04_IsBST.java ├── C05_IsCBT.java ├── C05_isFullBinaryTree.java ├── C06_IsBalancedTree.java ├── C07_LowestCommonAncestor.java ├── C08_SuccessorNode.java ├── C09_SerializeAndReconstructTree.java ├── C10_PaperFolding.java ├── C12_MorrisTraversal.java ├── prefix_tree │ ├── C01_TrieTree.java │ └── C02_GetFolderTree.java └── senior_tree │ ├── AVLTree.java │ ├── AbstractBinarySearchTree.java │ ├── AbstractSelfBalancingBinarySearchTree.java │ ├── BinarySearchTree.java │ ├── C01_SizeBalancedTreeMap.java │ ├── C02_SizeBalancedTreeMap.java │ ├── C03_SkipListMap.java │ └── RedBlackTree.java ├── util ├── Com.java └── Util.java ├── 左神算法笔记.pdf └── 范围上尝试模型.pdf /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | replay_pid* 25 | 26 | .DS_Store -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "java.debug.settings.onBuildFailureProceed": true 3 | } -------------------------------------------------------------------------------- /A3medium/3. 中级.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /A3medium/class06/C04_PreAndInArrayToPosArray.java: -------------------------------------------------------------------------------- 1 | package A3medium.class06; 2 | 3 | import java.util.HashMap; 4 | 5 | // 已知一棵二叉树中没有重复节点,并且给定了这棵树的中序遍历数组和先序遍历数组,返回后序遍历数组。 6 | // 比如给定: 7 | // int[] pre = { 1, 2, 4, 5, 3, 6, 7 }; 8 | // int[] in = { 4, 2, 5, 1, 6, 3, 7 }; 9 | // 返回: {4,5,2,6,7,3,1} 10 | public class C04_PreAndInArrayToPosArray { 11 | 12 | // // 时间复杂度 O(N) 13 | // public static int[] getPosArray(int[] pre, int[] in) { 14 | // if (pre == null || in == null) { 15 | // return null; 16 | // } 17 | // int len = pre.length; 18 | // int[] pos = new int[len]; 19 | // HashMap map = new HashMap(); 20 | // for (int i = 0; i < len; i++) { 21 | // map.put(in[i], i); 22 | // } 23 | // setPos(pre, 0, len - 1, in, 0, len - 1, pos, len - 1, map); 24 | // return pos; 25 | // } 26 | 27 | // public static int setPos(int[] p, int pi, int pj, int[] n, int ni, int nj, 28 | // int[] s, int si, 29 | // HashMap map) { 30 | // if (pi > pj) { 31 | // return si; 32 | // } 33 | // s[si--] = p[pi]; 34 | // // 遍历获取in数组内子树头节点位置,改为了用hashmap预处理缓存 35 | // int i = map.get(p[pi]); 36 | // si = setPos(p, pj - nj + i + 1, pj, n, i + 1, nj, s, si, map); 37 | // return setPos(p, pi + 1, pi + i - ni, n, ni, i - 1, s, si, map); 38 | // } 39 | 40 | public static int[] getPosArray(int[] pre, int[] in) { 41 | if (pre == null || in == null || pre.length != in.length) { 42 | return null; 43 | } 44 | // 缓存中序遍历数组的位置索引 45 | HashMap map = new HashMap<>(); 46 | for (int i = 0; i < in.length; i++) { 47 | map.put(in[i], i); 48 | } 49 | 50 | int[] pos = new int[pre.length]; 51 | process(pre, in, pos, map, 0, pre.length - 1, 0, in.length - 1, 0, pos.length - 1); 52 | return pos; 53 | } 54 | 55 | public static void process(int[] pre, int[] in, int[] pos, HashMap map, int preS, int preE, int inS, 56 | int inE, int posS, int posE) { 57 | if (preS > preE || inS > inE || posS > posE) { 58 | return; 59 | } 60 | // 更改当前子树的头节点 61 | pos[posE] = pre[preS]; 62 | int headIndex = map.get(pre[preS]); 63 | 64 | // int leftCount = headIndex - inS; 65 | // int rightCount = inE - headIndex; 66 | 67 | // // 左侧递归更改值,// preE为preS + 1 +( headIndex - inS) - 1 68 | process(pre, in, pos, map, preS + 1, preS + headIndex - inS, inS, headIndex - 1, posS, posS + headIndex - inS - 1); 69 | // 右侧递归更改值 70 | process(pre, in, pos, map, preS + headIndex - inS + 1, preE, headIndex + 1, inE, posS + headIndex - inS, posE - 1); 71 | } 72 | 73 | // for test 74 | public static void printArray(int[] arr) { 75 | if (arr == null) { 76 | return; 77 | } 78 | for (int i = 0; i != arr.length; i++) { 79 | System.out.print(arr[i] + " "); 80 | } 81 | System.out.println(); 82 | } 83 | 84 | public static void main(String[] args) { 85 | int[] pre = { 1, 2, 4, 5, 3, 6, 7 }; 86 | int[] in = { 4, 2, 5, 1, 6, 3, 7 }; 87 | int[] pos = getPosArray(pre, in); 88 | printArray(pos); // { 4 5 2 6 7 3 1 } 89 | 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /A3medium/class06/C06_SubArrayMaxSum.java: -------------------------------------------------------------------------------- 1 | package A3medium.class06; 2 | 3 | // 为了保证招聘信息的质量问题,公司为每个职位设计了打分系统,打分可以为正数,也可以为负数, 4 | // 正数表示用户认可帖子质量,负数表示用户不认可帖子质量。 5 | // 打分的分数根据评价用户的等级大小不定,比如可以为 -1分,10分,30分,-10分等。 6 | // 假设数组A记录了一条帖子所有打分记录,现在需要找出帖子曾经得到过最高的分数是多少。 7 | // 其中,最高分的定义为: 用户所有打分记录中,连续打分数据之和的最大值即认为是帖子曾经获得的最高分。 8 | // 例 如:帖子10001010近期的打 分记录为[1,1,-1,-10,11,4,-6,9,20,-10,-2], 9 | // 那么该条帖子曾经到达过的最高分数为 11+4+(-6)+9+20=38。 10 | // 请实现一段代码,输入为帖子近期的打分记录,输出为当前帖子 得到的最高分数。 11 | 12 | // 子数组最大和问题 13 | // NOTE: 假设答案法 14 | // 较大子数组之间的分界是:子数组和小于等于0时,因为当和小于等于0时完全可以不要这部分负担 15 | public class C06_SubArrayMaxSum { 16 | // public static int maxSum(int[] arr) { 17 | // if (arr == null || arr.length == 0) { 18 | // return 0; 19 | // } 20 | // int max = Integer.MIN_VALUE; 21 | // int cur = 0; 22 | // for (int i = 0; i != arr.length; i++) { 23 | // cur += arr[i]; 24 | // max = Math.max(max, cur); 25 | // cur = cur < 0 ? 0 : cur; 26 | // } 27 | // return max; 28 | // } 29 | 30 | public static int maxSum(int[] arr) { 31 | if (arr == null || arr.length == 0) { 32 | return 0; 33 | } 34 | 35 | int maxSum = Integer.MIN_VALUE; 36 | int curSum = 0; 37 | for (int i = 0; i < arr.length; i++) { 38 | curSum += arr[i]; 39 | maxSum = Math.max(curSum, maxSum); 40 | if (curSum <= 0) { 41 | curSum = 0; 42 | } 43 | } 44 | return maxSum; 45 | } 46 | 47 | // for test 48 | public static void printArray(int[] arr) { 49 | for (int i = 0; i != arr.length; i++) { 50 | System.out.print(arr[i] + " "); 51 | } 52 | System.out.println(); 53 | } 54 | 55 | public static void main(String[] args) { 56 | int[] arr1 = { -2, -3, -5, 40, -10, -10, 100, 1 }; 57 | System.out.println(maxSum(arr1)); 58 | 59 | int[] arr2 = { -2, -3, -5, 0, 1, 2, -1 }; 60 | System.out.println(maxSum(arr2)); 61 | 62 | int[] arr3 = { -2, -3, -5, -1 }; 63 | System.out.println(maxSum(arr3)); 64 | 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /A3medium/class06/C07_SubMatrixMaxSum.java: -------------------------------------------------------------------------------- 1 | package A3medium.class06; 2 | 3 | // 给定一个整型矩阵,返回子矩阵的最大累计和 4 | public class C07_SubMatrixMaxSum { 5 | 6 | // public static int maxSum(int[][] m) { 7 | // if (m == null || m.length == 0 || m[0].length == 0) { 8 | // return 0; 9 | // } 10 | // int max = Integer.MIN_VALUE; 11 | // int cur = 0; 12 | // int[] s = null; 13 | // for (int i = 0; i != m.length; i++) { 14 | // s = new int[m[0].length]; 15 | // for (int j = i; j != m.length; j++) { 16 | // cur = 0; 17 | // for (int k = 0; k != s.length; k++) { 18 | // s[k] += m[j][k]; 19 | // cur += s[k]; 20 | // max = Math.max(max, cur); 21 | // cur = cur < 0 ? 0 : cur; 22 | // } 23 | // } 24 | // } 25 | // return max; 26 | // } 27 | 28 | public static int maxSum2(int[][] m) { 29 | if (m == null || m.length == 0 || m[0].length == 0) { 30 | return 0; 31 | } 32 | int maxSum = Integer.MIN_VALUE; 33 | int curSum = 0; 34 | int[] cache = new int[m[0].length]; 35 | 36 | for (int i = 0; i < m.length; i++) { 37 | for (int j = i; j < m.length; j++) { 38 | curSum = 0; 39 | for (int k = 0; k < m[0].length; k++) { 40 | cache[k] += m[j][k]; 41 | curSum += cache[k]; 42 | maxSum = Math.max(maxSum, curSum); 43 | if (curSum <= 0) { 44 | curSum = 0; 45 | } 46 | } 47 | 48 | } 49 | 50 | for (int j = 0; j < cache.length; j++) { 51 | cache[j] = 0; 52 | } 53 | } 54 | 55 | return maxSum; 56 | } 57 | 58 | public static void main(String[] args) { 59 | int[][] matrix = { { -90, 48, 78 }, { 64, -40, 64 }, { -81, -7, 66 } }; 60 | // System.out.println(maxSum(matrix)); 61 | System.out.println(maxSum2(matrix)); 62 | 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /A3medium/class07/C01_EnglishExpression.java: -------------------------------------------------------------------------------- 1 | package A3medium.class07; 2 | 3 | // TODO: 4 | public class C01_EnglishExpression { 5 | 6 | public static String num1To19(int num) { 7 | if (num < 1 || num > 19) { 8 | return ""; 9 | } 10 | String[] names = { "One ", "Two ", "Three ", "Four ", "Five ", "Six ", 11 | "Seven ", "Eight ", "Nine ", "Ten ", "Eleven ", "Twelve ", 12 | "Thirteen ", "Fourteen ", "Fifteen ", "Sixteen ", "Sixteen ", 13 | "Eighteen ", "Nineteen " }; 14 | return names[num - 1]; 15 | } 16 | 17 | public static String num1To99(int num) { 18 | if (num < 1 || num > 99) { 19 | return ""; 20 | } 21 | if (num < 20) { 22 | return num1To19(num); 23 | } 24 | int high = num / 10; 25 | String[] tyNames = { "Twenty ", "Thirty ", "Forty ", "Fifty ", 26 | "Sixty ", "Seventy ", "Eighty ", "Ninety " }; 27 | return tyNames[high - 2] + num1To19(num % 10); 28 | } 29 | 30 | public static String num1To999(int num) { 31 | if (num < 1 || num > 999) { 32 | return ""; 33 | } 34 | if (num < 100) { 35 | return num1To99(num); 36 | } 37 | int high = num / 100; 38 | return num1To19(high) + "Hundred " + num1To99(num % 100); 39 | } 40 | 41 | public static String getNumEngExp(int num) { 42 | if (num == 0) { 43 | return "Zero"; 44 | } 45 | String res = ""; 46 | if (num < 0) { 47 | res = "Negative, "; 48 | } 49 | if (num == Integer.MIN_VALUE) { 50 | res += "Two Billion, "; 51 | num %= -2000000000; 52 | } 53 | num = Math.abs(num); 54 | int high = 1000000000; 55 | int highIndex = 0; 56 | String[] names = { "Billion", "Million", "Thousand", "" }; 57 | while (num != 0) { 58 | int cur = num / high; 59 | num %= high; 60 | if (cur != 0) { 61 | res += num1To999(cur); 62 | res += names[highIndex] + (num == 0 ? " " : ", "); 63 | } 64 | high /= 1000; 65 | highIndex++; 66 | } 67 | return res; 68 | } 69 | 70 | public static int generateRandomNum() { 71 | boolean isNeg = Math.random() > 0.5 ? false : true; 72 | int value = (int) (Math.random() * Integer.MIN_VALUE); 73 | return isNeg ? value : -value; 74 | } 75 | 76 | public static void main(String[] args) { 77 | System.out.println(getNumEngExp(0)); 78 | System.out.println(getNumEngExp(Integer.MAX_VALUE)); 79 | System.out.println(getNumEngExp(Integer.MIN_VALUE)); 80 | int num = generateRandomNum(); 81 | System.out.println(num); 82 | System.out.println(getNumEngExp(num)); 83 | 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /A3medium/class07/C02_PrintNoInArray.java: -------------------------------------------------------------------------------- 1 | package A3medium.class07; 2 | 3 | // 给定一个整数数组A,长度为n,有 1 <= A[i] <= n,且对于[1,n]的整数,其中部分整数会重复出现而部分不会出现。 4 | // 实现算法找到[1,n]中所有未出现在A中的整数。 5 | // 提示:尝试实现O(n)的时间复杂度和O(1)的空间复杂度(返回值不计入空间复 杂度)。 6 | // 输入描述: 7 | // 一行数字,全部为整数,空格分隔 8 | // A0 A1 A2 A3... 9 | // 输出描述: 10 | // 一行数字,全部为整数,空格分隔R0 R1 R2 R3... 示例1: 11 | // 输入 12 | // 1343 13 | // 输出 14 | // 2 15 | public class C02_PrintNoInArray { 16 | 17 | // // 请保证arr[0..N-1]上的数字都在[1~n]之间 18 | // public static void printNumberNoInArray(int[] arr) { 19 | // if (arr == null || arr.length == 0) { 20 | // return; 21 | // } 22 | // for (int i = 0; i < arr.length; i++) { 23 | // modify(arr[i], arr); 24 | // } 25 | // for (int i = 0; i < arr.length; i++) { 26 | // if (arr[i] != i + 1) { 27 | // System.out.println(i + 1); 28 | // } 29 | // } 30 | // } 31 | 32 | // public static void modify(int value, int[] arr) { 33 | // while (arr[value - 1] != value) { 34 | // int tmp = arr[value - 1]; 35 | // arr[value - 1] = value; 36 | // value = tmp; 37 | // } 38 | // } 39 | 40 | // 法一 41 | public static void printNumberNoInArray(int[] arr) { 42 | if (arr == null || arr.length == 0) { 43 | return; 44 | } 45 | 46 | for (int i = 0; i < arr.length; i++) { 47 | if (arr[i] != i + 1) { 48 | modify(arr, i); 49 | } 50 | } 51 | 52 | for (int i = 0; i < arr.length; i++) { 53 | if (arr[i] != i + 1) { 54 | System.out.println(i + 1); 55 | } 56 | } 57 | } 58 | 59 | private static void modify(int[] arr, int i) { 60 | int cache; 61 | while (arr[i] != arr[arr[i] - 1]) { 62 | // tem = arr[arr[i] - 1]; 63 | cache = arr[arr[i] - 1]; 64 | arr[arr[i] - 1] = arr[i]; 65 | arr[i] = cache; 66 | } 67 | } 68 | 69 | // 法二 70 | // NOTE: 可以通过改为负数,来标记对应索引的数存在 71 | public static void printNumberNoInArray2(int[] arr) { 72 | if (arr == null || arr.length == 0) { 73 | return; 74 | } 75 | for (int i = 0; i < arr.length; i++) { 76 | if (arr[i] > 0 && arr[arr[i] - 1] > 0) { 77 | arr[arr[i] - 1] = -arr[arr[i] - 1]; 78 | } 79 | } 80 | 81 | for (int i = 0; i < arr.length; i++) { 82 | if (arr[i] > 0) { 83 | System.out.println(i + 1); 84 | } 85 | } 86 | 87 | // 恢复数据 88 | for (int i = 0; i < arr.length; i++) { 89 | if (arr[i] < 0) { 90 | arr[i] = -arr[i]; 91 | } 92 | } 93 | } 94 | 95 | public static void main(String[] args) { 96 | int[] test = { 3, 2, 3, 5, 6, 1, 6 }; 97 | printNumberNoInArray2(test); 98 | System.out.println("---"); 99 | printNumberNoInArray(test); 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /A3medium/class07/C03_3times.java: -------------------------------------------------------------------------------- 1 | package A3medium.class07; 2 | 3 | // 小Q得到一个神奇的数列: 1, 12, 123,...12345678910,1234567891011... 4 | // 并且小Q对于能否被3整除这个性质很感兴趣。 5 | // 小Q现在希望你能帮他计算一下从数列的第l个到第r个(包含端点)有多少个数可以被3整除。 (索引从1开始) 6 | // 输入描述: 7 | // 输入包括两个整数l和r(1 <= l <= r <= 1e9), 表示要求解的区间两端。 8 | // 输出描述: 9 | // 输出一个整数, 表示区间内能被3整除的数字个数。 10 | 11 | // 示例1: 12 | // 输入 25 13 | // 输出 3 14 | 15 | // 解题思路:判断一个数能不能被3整除,等价于一个数的每位之和能否被3整除。刚开始想打表,但发现数据 量是1e9,一维数组最多只能开到1e8.所以就纯暴力判断了,不过数据是有规律的,第一个数是1、第二个数是12,第三个数是123,所以只用判断n*(n+1)/2%3即可。因为数量太大了,所以用long long 16 | public class C03_3times { 17 | 18 | // public static int getNum(int l, int r) { 19 | // int sum = 0; 20 | // for (int i = l; i <= r; i++) { 21 | // long tmp = (long) (i + 1) * (long) i / 2L; 22 | // if (tmp % 3 == 0) { 23 | // sum++; 24 | // } 25 | // } 26 | // return sum; 27 | // } 28 | 29 | // TODO: 求余数,求模的运算性质 30 | // NOTE:10的任意倍数 % 3 都是1 31 | public static int getNum2(int l, int r) { 32 | if (l < 0 || l > r) { 33 | return 0; 34 | } 35 | 36 | int sum = 0; 37 | for (int i = l; i <= r; i++) { 38 | long tem = (long) (i + i * i) / 2; // 等差数列求和 39 | if (tem % 3 == 0) { 40 | sum++; 41 | } 42 | } 43 | return sum; 44 | } 45 | 46 | public static void main(String[] args) { 47 | int l = 100; 48 | int r = 5000; 49 | // System.out.println(getNum(l, r)); 50 | System.out.println(getNum2(l, r)); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /A3medium/class07/C05_CompleteTreeNodeNumber.java: -------------------------------------------------------------------------------- 1 | package A3medium.class07; 2 | 3 | // 求完全二叉树节点的个数 4 | public class C05_CompleteTreeNodeNumber { 5 | 6 | public static class Node { 7 | public int value; 8 | public Node left; 9 | public Node right; 10 | 11 | public Node(int data) { 12 | this.value = data; 13 | } 14 | } 15 | 16 | // 时间复杂度优化 17 | // public static int nodeNum(Node head) { 18 | // if (head == null) { 19 | // return 0; 20 | // } 21 | // return bs(head, 1, mostLeftLevel(head, 1)); 22 | // } 23 | 24 | // public static int bs(Node node, int l, int h) { 25 | // if (l == h) { 26 | // return 1; 27 | // } 28 | // if (mostLeftLevel(node.right, l + 1) == h) { 29 | // return (1 << (h - l)) + bs(node.right, l + 1, h); 30 | // } else { 31 | // return (1 << (h - l - 1)) + bs(node.left, l + 1, h); 32 | // } 33 | // } 34 | 35 | // public static int mostLeftLevel(Node node, int level) { 36 | // while (node != null) { 37 | // level++; 38 | // node = node.left; 39 | // } 40 | // return level - 1; 41 | // } 42 | 43 | // 时间复杂度O(n) 44 | public static int nodeNum(Node head) { 45 | if (head == null) { 46 | return 0; 47 | } 48 | return nodeNum(head.left) + 1 + nodeNum(head.right); 49 | } 50 | 51 | // 时间复杂度优化 52 | public static int nodeNum2(Node head) { 53 | if (head == null) { 54 | return 0; 55 | } 56 | 57 | return process(head, getMostLeftHeight(head)); 58 | } 59 | 60 | private static int process(Node head, int height) { 61 | if (head == null) { 62 | return 0; 63 | } 64 | 65 | int count; 66 | if (getMostLeftHeight(head.right) == height - 1) { // 左子树为满二叉树 67 | count = 1 + (int) Math.pow(2, height - 1) - 1 + process(head.right, height - 1); 68 | } else { // 右子树为满二叉树 69 | count = 1 + (int) Math.pow(2, height - 2) - 1 + process(head.left, height - 1); 70 | } 71 | return count; 72 | } 73 | 74 | private static int getMostLeftHeight(Node head) { 75 | int height = 0; 76 | while (head != null) { 77 | height++; 78 | head = head.left; 79 | } 80 | return height; 81 | } 82 | 83 | public static void main(String[] args) { 84 | Node head = new Node(1); 85 | head.left = new Node(2); 86 | head.right = new Node(3); 87 | head.left.left = new Node(4); 88 | head.left.right = new Node(5); 89 | head.right.left = new Node(6); 90 | head.right.right = new Node(7); 91 | head.left.left.left = new Node(8); 92 | System.out.println(nodeNum(head)); 93 | System.out.println(nodeNum2(head)); 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /A3medium/class08/C03_StringToKth.java: -------------------------------------------------------------------------------- 1 | package A3medium.class08; 2 | 3 | // 在数据加密和数据压缩中常需要对特殊的字符串进行编码。 4 | // 给定的字母表A由26个小写英文字母组成,即 A={a, b...z}。 5 | // 该字母表产生的升序字符串是指定字符串中字母从左到右出现的次序与字母在字母表中出现的次序相同,且每个字符最多出现1次。 6 | // 例如,a,b,ab,bc,xyz等字符串是升序字符串。 7 | // 对字母表A产生的所有长度不超过6的升序字符串按照字典排列编码如下:a(1),b(2),c(3)......,z(26),ab(27), ac(28)...... 8 | // 对于任意长度不超过16的升序字符串,迅速计算出它在上述字典中的编码。 9 | // 输入描述: 输入一个字符串。 10 | // 输出描述: 输出其字符串编码。 11 | // 示例1: 12 | // 输入: ab 13 | // 输出: 27 14 | public class C03_StringToKth { 15 | 16 | // // 第i个字符开头、长度为len的所有字符串中的第一个字符串,是第几个 17 | // public static int f(int i, int len) { 18 | // int sum = 0; 19 | // if (len == 1) { 20 | // return 1; 21 | // } 22 | // for (int j = i + 1; j <= 26; j++) { 23 | // sum += f(j, len - 1); 24 | // } 25 | // return sum; 26 | 27 | // } 28 | 29 | // // 长度为len的字符串有多少个 30 | // public static int g(int len) { 31 | // int sum = 0; 32 | // for (int i = 1; i <= 26; i++) { 33 | // sum += f(i, len); 34 | // } 35 | // return sum; 36 | // } 37 | 38 | // public static int kth(String s) { 39 | // char[] str = s.toCharArray(); 40 | // int sum = 0; 41 | // int len = str.length; 42 | // for (int i = 1; i < len; i++) { 43 | // sum += g(i); 44 | // } 45 | // int first = str[0] - 'a' + 1; 46 | // for (int i = 1; i < first; i++) { 47 | // sum += f(i, len); 48 | // } 49 | // int pre = first; 50 | // for (int i = 1; i < len; i++) { 51 | // int cur = str[i] - 'a' + 1; 52 | // for (int j = pre + 1; j < cur; j++) { 53 | // sum += f(j, len - i); 54 | // } 55 | // pre = cur; 56 | // } 57 | // return sum + 1; 58 | // } 59 | 60 | public static int kth2(String s) { 61 | if (s == null || s.length() == 0) { 62 | return 0; 63 | } 64 | s = s.toLowerCase(); 65 | 66 | int res = 0; 67 | int len = s.length(); 68 | 69 | // 1~n-1长度的字符串数量 70 | for (int i = 1; i < len; i++) { 71 | res += countOnLengthN(i); 72 | } 73 | // 长度为n时 74 | int first = s.charAt(0) - 96; 75 | for (int i = 1; i < first; i++) { 76 | res += startCharCount(i, len); 77 | } 78 | for (int i = 0; i < len - 1; i++) { 79 | int cur = s.charAt(i) - 96; 80 | int next = s.charAt(i + 1) - 96; 81 | for (int j = cur + 1; j < next; j++) { 82 | res += startCharCount(j, len - i - 1); 83 | } 84 | } 85 | 86 | // 加上1就是自己的序号 87 | return res + 1; 88 | } 89 | 90 | // 两个功能函数 91 | // 1:长度为n的字符串的数量 92 | public static int countOnLengthN(int n) { 93 | if (n <= 0) { 94 | return 0; 95 | } 96 | int sum = 0; 97 | // 26个字母用1-26表示 98 | for (int i = 1; i <= 26; i++) { 99 | sum += startCharCount(i, n); 100 | } 101 | return sum; 102 | } 103 | 104 | // 2. 固定长度n,第c字母开头有多少子序列 105 | public static int startCharCount(int startChar, int n) { 106 | // startChar过大,for也不会执行,不需要额外base case 107 | // if (n <= 0) { 108 | // return 0; 109 | // } 110 | if (n == 1) { 111 | return 1; 112 | } 113 | 114 | int sum = 0; 115 | for (int i = startChar + 1; i <= 26; i++) { 116 | sum += startCharCount(i, n - 1); 117 | } 118 | return sum; 119 | } 120 | 121 | public static void main(String[] args) { 122 | String test = "bcfgi"; 123 | // System.out.println(kth(test)); 124 | System.out.println(kth2(test)); 125 | } 126 | 127 | } -------------------------------------------------------------------------------- /A3medium/class08/C04_LongestNoRepeatSubstring.java: -------------------------------------------------------------------------------- 1 | package A3medium.class08; 2 | 3 | // 在一个字符串中找到没有重复字符子串中最长的长度。 4 | // 例如: 5 | // abcabcbb没有重复字符的最长子串是abc,长度为3; 6 | // bbbbb,答案是b,长度为1 7 | // pwwkew,答案是wke,长度是3 8 | // 要求:答案必须是子串,"pwke" 是一个子字符序列但不是一个子字符串。 9 | 10 | // NOTE: 看到子串和子数组的问题,就想想以任意一个位置i结尾时的情况 11 | public class C04_LongestNoRepeatSubstring { 12 | 13 | public static int maxUnique(String str) { 14 | if (str == null || str.equals("")) { 15 | return 0; 16 | } 17 | char[] chas = str.toCharArray(); 18 | int[] map = new int[256]; 19 | for (int i = 0; i < 256; i++) { 20 | map[i] = -1; 21 | } 22 | int len = 0; 23 | int pre = -1; 24 | int cur = 0; 25 | for (int i = 0; i != chas.length; i++) { 26 | pre = Math.max(pre, map[chas[i]]); 27 | cur = i - pre; 28 | len = Math.max(len, cur); 29 | map[chas[i]] = i; 30 | } 31 | return len; 32 | } 33 | 34 | // 法一:考虑使用滑动窗口 35 | // public static int maxUnique2(String str) { 36 | 37 | // } 38 | 39 | // 法二:思考任意一个位置i结尾时的无重复子串长度 40 | public static int maxUnique3(String str) { 41 | if (str == null || str.equals("")) { 42 | return 0; 43 | } 44 | char[] arr = str.toCharArray(); 45 | int[] maxArr = new int[arr.length]; // 可用pre变量代替 46 | 47 | // 关键要有一张map,记录字符上次出现的位置 48 | int[] map = new int[256]; 49 | for (int i = 0; i < map.length; i++) { 50 | map[i] = -1; 51 | } 52 | map[arr[0]] = 0; 53 | 54 | int maxLen = maxArr[0]; 55 | for (int i = 1; i < arr.length; i++) { 56 | maxArr[i] = map[arr[i]] != -1 ? Math.min(maxArr[i - 1] + 1, i - map[arr[i]]) : maxArr[i - 1] + 1; 57 | map[arr[i]] = i; 58 | } 59 | 60 | for (int i = 1; i < maxArr.length; i++) { 61 | maxLen = Math.max(maxArr[i], maxLen); 62 | } 63 | 64 | return maxLen; 65 | } 66 | 67 | // for test 68 | public static String getRandomString(int len) { 69 | char[] str = new char[len]; 70 | int base = 'a'; 71 | int range = 'z' - 'a' + 1; 72 | for (int i = 0; i != len; i++) { 73 | str[i] = (char) ((int) (Math.random() * range) + base); 74 | } 75 | return String.valueOf(str); 76 | } 77 | 78 | // for test 79 | public static String maxUniqueString(String str) { 80 | if (str == null || str.equals("")) { 81 | return str; 82 | } 83 | char[] chas = str.toCharArray(); 84 | int[] map = new int[256]; 85 | for (int i = 0; i < 256; i++) { 86 | map[i] = -1; 87 | } 88 | int len = -1; 89 | int pre = -1; 90 | int cur = 0; 91 | int end = -1; 92 | for (int i = 0; i != chas.length; i++) { 93 | pre = Math.max(pre, map[chas[i]]); 94 | cur = i - pre; 95 | if (cur > len) { 96 | len = cur; 97 | end = i; 98 | } 99 | map[chas[i]] = i; 100 | } 101 | return str.substring(end - len + 1, end + 1); 102 | } 103 | 104 | public static void main(String[] args) { 105 | String str = getRandomString(20); 106 | System.out.println(str); 107 | System.out.println(maxUniqueString(str)); 108 | System.out.println(maxUnique(str)); 109 | System.out.println(maxUnique3(str)); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /A3medium/class08/C06_RemoveDuplicateLettersLessLexi.java: -------------------------------------------------------------------------------- 1 | package A3medium.class08; 2 | 3 | // 给定一个全是小写字母的字符串str,删除多余字符,使得每种字符只保留一个,并让最终结果字符串的字典序最小 4 | // 【举例】 5 | // str = "acbc",删掉第一个'c',得到"abc",是所有结果字符串中字典序最小的。 6 | // str = "dbcacbca",删掉第一个'b'、第一个'c'、第二个'c'、第二个'a',得到"dabc", 是所有结果字符串中字典序最小的。 7 | public class C06_RemoveDuplicateLettersLessLexi { 8 | 9 | public static String removeDuplicateLetters(String s) { 10 | char[] str = s.toCharArray(); 11 | // 小写字母ascii码值范围[97~122],所以用长度为26的数组做次数统计 12 | // 如果map[i] > -1,则代表ascii码值为i的字符的出现次数 13 | // 如果map[i] == -1,则代表ascii码值为i的字符不再考虑 14 | int[] map = new int[26]; 15 | for (int i = 0; i < str.length; i++) { 16 | map[str[i] - 'a']++; 17 | } 18 | char[] res = new char[26]; 19 | int index = 0; 20 | int L = 0; 21 | int R = 0; 22 | while (R != str.length) { 23 | // 如果当前字符是不再考虑的,直接跳过 24 | // 如果当前字符的出现次数减1之后,后面还能出现,直接跳过 25 | if (map[str[R] - 'a'] == -1 || --map[str[R] - 'a'] > 0) { 26 | R++; 27 | } else { // 当前字符需要考虑并且之后不会再出现了 28 | // 在str[L..R]上所有需要考虑的字符中,找到ascii码最小字符的位置 29 | int pick = -1; 30 | for (int i = L; i <= R; i++) { 31 | if (map[str[i] - 'a'] != -1 && (pick == -1 || str[i] < str[pick])) { 32 | pick = i; 33 | } 34 | } 35 | // 把ascii码最小的字符放到挑选结果中 36 | res[index++] = str[pick]; 37 | // 在上一个的for循环中,str[L..R]范围上每种字符的出现次数都减少了 38 | // 需要把str[pick + 1..R]上每种字符的出现次数加回来 39 | for (int i = pick + 1; i <= R; i++) { 40 | if (map[str[i] - 'a'] != -1) { // 只增加以后需要考虑字符的次数 41 | map[str[i] - 'a']++; 42 | } 43 | } 44 | // 选出的ascii码最小的字符,以后不再考虑了 45 | map[str[pick] - 'a'] = -1; 46 | // 继续在str[pick + 1......]上重复这个过程 47 | L = pick + 1; 48 | R = L; 49 | } 50 | } 51 | return String.valueOf(res, 0, index); 52 | } 53 | 54 | public static String removeDuplicateLetters2(String s) { 55 | if (s == null || s.length() <= 1) { 56 | return s; 57 | } 58 | 59 | char[] arr = s.toCharArray(); 60 | 61 | // Map 62 | int[] charCount = new int[26]; 63 | for (int i = 0; i < arr.length; i++) { 64 | charCount[arr[i] - 97]++; 65 | } 66 | 67 | int minCharI = 0; 68 | for (int i = 0; i < arr.length; i++) { 69 | charCount[arr[i] - 97]--; 70 | minCharI = arr[i] <= arr[minCharI] ? i : minCharI; 71 | if (charCount[arr[i] - 97] == 0) { 72 | break; 73 | } 74 | } 75 | return arr[minCharI] 76 | + removeDuplicateLetters2(s.substring(minCharI + 1).replaceAll(String.valueOf(arr[minCharI]), "")); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /A3medium/class08/C08_MostIncreaseSubSequence.java: -------------------------------------------------------------------------------- 1 | package A3medium.class08; 2 | 3 | // 问题: 求最长递增子序列 4 | public class C08_MostIncreaseSubSequence { 5 | 6 | 7 | // 1.dp方法:O(N2) 8 | 9 | // 2. O(N*logN) 10 | 11 | 12 | public static void main(String[] args) { 13 | int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 14 | 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /A4high/4. 高级.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /A4high/class02/C02_LongestSumSubArrayLengthInPositiveArray.java: -------------------------------------------------------------------------------- 1 | package A4high.class02; 2 | 3 | import java.util.HashMap; 4 | 5 | // 问题:给定一个数组arr,该数组无序,但每个值均为正数,再给定一个正数k。 6 | // 求arr的所有子数组中所有元素相加和为k的最长子数组长度。 7 | // 例如,arr=[1,2,1,1,1],k=3。累加和为3的最长子数组为[1,1,1],所以结果返回3。 8 | // 要求:时间复杂度O(N),额外空间复杂度O(1) 9 | 10 | // NOTE: 预处理出前缀和 11 | // 补充问题:数组有正,有负,有零时怎么求和为K的最长子数组长度 12 | 13 | // NOTE: 滑动窗口 14 | public class C02_LongestSumSubArrayLengthInPositiveArray { 15 | 16 | public static int getMaxLength(int[] arr, int k) { 17 | if (arr == null || arr.length == 0 || k <= 0) { 18 | return 0; 19 | } 20 | int left = 0; 21 | int right = 0; 22 | int sum = arr[0]; 23 | int len = 0; 24 | 25 | while (right < arr.length) { 26 | if (sum == k) { 27 | len = Math.max(len, right - left + 1); 28 | sum -= arr[left++]; 29 | } else if (sum < k) { 30 | right++; 31 | if (right == arr.length) { 32 | break; 33 | } 34 | sum += arr[right]; 35 | } else { 36 | sum -= arr[left++]; 37 | } 38 | } 39 | return len; 40 | } 41 | 42 | // 滑动窗口 43 | public static int getMaxLength2(int[] arr, int k) { 44 | if (arr == null || arr.length == 0 || k <= 0) { 45 | return 0; 46 | } 47 | int left = 0; 48 | int right = 0; 49 | int curSum = 0; 50 | int maxLen = 0; 51 | while (right < arr.length || curSum >= k) { // 注意还需 curSum >= k已确保right到最后的索引也能把其子数组全部校验到 52 | if (curSum == k) { 53 | maxLen = Math.max(maxLen, right - left); 54 | curSum -= arr[left]; 55 | left++; 56 | } else if (curSum < k) { 57 | curSum += arr[right]; 58 | right++; 59 | } else { 60 | curSum -= arr[left]; 61 | left++; 62 | } 63 | } 64 | 65 | return maxLen; 66 | } 67 | 68 | // 补充问题:数组有正,有负,有零时怎么求和为K的最长子数组长度 69 | public static int getMaxLengthInAnyRange(int[] arr, int k) { 70 | if (arr == null || arr.length == 0 || k <= 0) { 71 | return 0; 72 | } 73 | 74 | HashMap map = new HashMap<>(); 75 | int sum = 0; 76 | int maxLen = 0; 77 | for (int i = 0; i < arr.length; i++) { 78 | sum += arr[i]; 79 | if (map.containsKey(sum - k)) { 80 | maxLen = Math.max(maxLen, i - map.get(sum - k)); 81 | } 82 | 83 | if (!map.containsKey(sum)) { 84 | map.put(sum, i); 85 | } 86 | } 87 | 88 | return maxLen; 89 | } 90 | 91 | // for test 92 | public static int[] generatePositiveArray(int size) { 93 | int[] result = new int[size]; 94 | for (int i = 0; i != size; i++) { 95 | result[i] = (int) (Math.random() * 10) + 1; 96 | } 97 | return result; 98 | } 99 | 100 | // for test 101 | public static void printArray(int[] arr) { 102 | for (int i = 0; i != arr.length; i++) { 103 | System.out.print(arr[i] + " "); 104 | } 105 | System.out.println(); 106 | } 107 | 108 | public static void main(String[] args) { 109 | int len = 20; 110 | int k = 15; 111 | for (int i = 0; i < 10000; i++) { 112 | int[] arr = generatePositiveArray(len); 113 | // printArray(arr); 114 | // int one = getMaxLength(arr, k); 115 | int two = getMaxLength2(arr, k); 116 | // if (one != two) { 117 | // System.out.println("error"); 118 | printArray(arr); 119 | // System.out.println(one); 120 | System.out.println(two); 121 | // } 122 | } 123 | 124 | // System.out.println(getMaxLength2(new int[] { 2, 3, 1, 9 }, 15)); 125 | ; 126 | } 127 | 128 | } 129 | -------------------------------------------------------------------------------- /A4high/class02/C04_Nim.java: -------------------------------------------------------------------------------- 1 | package A4high.class02; 2 | 3 | // nim博弈问题 4 | 5 | // 给定一个非负数组,每一个值代表该位置上有几个铜板。 6 | // a和b玩游戏,a先手,b后手, 轮到某个人的时候,只能在一个位置上拿任意数量的铜板,但是不能不拿。 7 | // 谁最先把铜板拿完谁赢。假设a和b都极度聪明,请返回获胜者的名字。 8 | public class C04_Nim { 9 | 10 | // 保证arr是正数数组 11 | // public static void printWinner(int[] arr) { 12 | // int eor = 0; 13 | // for (int num : arr) { 14 | // eor ^= num; 15 | // } 16 | // if (eor == 0) { 17 | // System.out.println("后手赢"); 18 | // } else { 19 | // System.out.println("先手赢"); 20 | // } 21 | // } 22 | 23 | // NOTE:https://www.cnblogs.com/jiangjun/archive/2012/11/01/2749937.html 24 | public static void nim(int[] arr) { 25 | int xor = 0; 26 | for (int i = 0; i < arr.length; i++) { 27 | xor ^= arr[i]; 28 | } 29 | 30 | System.out.println(xor == 0 ? "后手赢": "先手赢"); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /A4high/class04/C03_PalindromeMinAdd.java: -------------------------------------------------------------------------------- 1 | package A4high.class04; 2 | 3 | // 给定一个字符串str,如果可以在str的任意位置添加字符,请返回在添加字符最少的情况下,让str整体都是回文字符串的一种结果。 4 | // 【举例】 5 | // str="ABA"。str本身就是回文串,不需要添加字符,所以返回"ABA"。 6 | // str="AB"。可以在'A'之前添加'B',使str整体都是回文串,故可以返回"BAB"。 7 | // 也可以在'B'之后添加'A',使str整体都是回文串,故也可以返回"ABA"。 8 | // 总之,只要添加的字符数最少,返回其中一种结果即可。 9 | 10 | // NOTE:范围上尝试模型 11 | public class C03_PalindromeMinAdd { 12 | 13 | // public static String getPalindrome1(String str) { 14 | // if (str == null || str.length() < 2) { 15 | // return str; 16 | // } 17 | // char[] chas = str.toCharArray(); 18 | // int[][] dp = getDP(chas); 19 | // char[] res = new char[chas.length + dp[0][chas.length - 1]]; 20 | // int i = 0; 21 | // int j = chas.length - 1; 22 | // int resl = 0; 23 | // int resr = res.length - 1; 24 | // while (i <= j) { 25 | // if (chas[i] == chas[j]) { 26 | // res[resl++] = chas[i++]; 27 | // res[resr--] = chas[j--]; 28 | // } else if (dp[i][j - 1] < dp[i + 1][j]) { 29 | // res[resl++] = chas[j]; 30 | // res[resr--] = chas[j--]; 31 | // } else { 32 | // res[resl++] = chas[i]; 33 | // res[resr--] = chas[i++]; 34 | // } 35 | // } 36 | // return String.valueOf(res); 37 | // } 38 | 39 | // public static int[][] getDP(char[] str) { 40 | // int[][] dp = new int[str.length][str.length]; 41 | // for (int j = 1; j < str.length; j++) { 42 | // dp[j - 1][j] = str[j - 1] == str[j] ? 0 : 1; 43 | // for (int i = j - 2; i > -1; i--) { 44 | // if (str[i] == str[j]) { 45 | // dp[i][j] = dp[i + 1][j - 1]; 46 | // } else { 47 | // dp[i][j] = Math.min(dp[i + 1][j], dp[i][j - 1]) + 1; 48 | // } 49 | // } 50 | // } 51 | // return dp; 52 | // } 53 | 54 | public static String getPalindrome2(String str) { 55 | if (str == null || str.length() == 0) { 56 | return ""; 57 | } 58 | 59 | char[] arr = str.toCharArray(); 60 | String[][] dpCache = new String[arr.length][arr.length]; 61 | for (int i = 0; i < dpCache.length - 1; i++) { 62 | dpCache[i][i] = String.valueOf(arr[i]); 63 | dpCache[i][i + 1] = String.valueOf(arr[i] == arr[i + 1] ? new char[] { arr[i], arr[i + 1] } 64 | : new char[] { arr[i], arr[i + 1], arr[i] }); 65 | } 66 | dpCache[arr.length - 1][arr.length - 1] = String.valueOf(arr[arr.length - 1]); 67 | 68 | for (int i = dpCache.length - 3; i >= 0; i--) { 69 | for (int j = i + 2; j < dpCache[0].length; j++) { 70 | // 左侧和下侧 71 | dpCache[i][j] = dpCache[i][j - 1].length() > dpCache[i + 1][j].length() ? arr[i] + dpCache[i + 1][j] + arr[i] 72 | : arr[j] + dpCache[i][j - 1] + arr[j]; 73 | // 对比左下侧 74 | if (arr[i] == arr[j] && dpCache[i + 1][j - 1].length() + 2 < dpCache[i][j].length()) { 75 | dpCache[i][j] = arr[i] + dpCache[i + 1][j - 1] + arr[i]; 76 | } 77 | } 78 | } 79 | 80 | return dpCache[0][arr.length - 1]; 81 | } 82 | 83 | public static void main(String[] args) { 84 | String str = "AB1CD2EFG3H43IJK2L1MMN"; 85 | // System.out.println(getPalindrome1(str)); 86 | // 长度得一样,具体的结果字符串可能有多种,保证为回文字符串即可 87 | System.out.println(getPalindrome2(str)); 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /A4high/class04/README.md: -------------------------------------------------------------------------------- 1 | 参考:https://buptbridgewang.top/blog/22 2 | 3 | 从左往右尝试模型 4 | 5 | 范围上尝试模型:i-j范围上的问题,考虑i的可能性,j的可能性,分类讨论f(i, j)到f(i-1, j)、f(i, j-1)、f(i-1, j-1)的转化函数 6 | 7 | -------------------------------------------------------------------------------- /A4high/class06/C04_CoverMax.java: -------------------------------------------------------------------------------- 1 | package A4high.class06; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.Comparator; 6 | import java.util.List; 7 | import java.util.TreeSet; 8 | 9 | // 平面内有n个矩形, 第i个矩形的左下角坐标为(x1[i], y1[i]), 右上角坐标为(x2[i], y2[i])。 10 | // 如果两个或者多个矩形有公共区域则认为它们是相互重叠的(不考虑边界和角落)。 11 | // 请你计算出平面内重叠矩形数量最多的地方,有多少个矩形相互重叠。 12 | public class C04_CoverMax { 13 | 14 | public static class Rectangle { 15 | public int up; 16 | public int down; 17 | public int left; 18 | public int right; 19 | 20 | public Rectangle(int up, int down, int left, int right) { 21 | this.up = up; 22 | this.down = down; 23 | this.left = left; 24 | this.right = right; 25 | } 26 | 27 | } 28 | 29 | public static class DownComparator implements Comparator { 30 | @Override 31 | public int compare(Rectangle o1, Rectangle o2) { 32 | return o1.down - o2.down; 33 | } 34 | } 35 | 36 | public static class LeftComparator implements Comparator { 37 | @Override 38 | public int compare(Rectangle o1, Rectangle o2) { 39 | return o1.left - o2.left; 40 | } 41 | } 42 | 43 | public static class RightComparator implements Comparator { 44 | @Override 45 | public int compare(Rectangle o1, Rectangle o2) { 46 | return o1.right - o2.right; 47 | } 48 | } 49 | 50 | public static int maxCover(Rectangle[] recs) { 51 | if (recs == null || recs.length == 0) { 52 | return 0; 53 | } 54 | Arrays.sort(recs, new DownComparator()); 55 | TreeSet leftOrdered = new TreeSet<>(new LeftComparator()); 56 | int ans = 0; 57 | for (int i = 0; i < recs.length; i++) { 58 | int curDown = recs[i].down; 59 | int index = i; 60 | while (recs[index].down == curDown) { 61 | leftOrdered.add(recs[index]); 62 | index++; 63 | } 64 | i = index; 65 | removeLowerOnCurDown(leftOrdered, curDown); 66 | TreeSet rightOrdered = new TreeSet<>(new RightComparator()); 67 | for (Rectangle rec : leftOrdered) { 68 | removeLeftOnCurLeft(rightOrdered, rec.left); 69 | rightOrdered.add(rec); 70 | ans = Math.max(ans, rightOrdered.size()); 71 | } 72 | } 73 | return ans; 74 | } 75 | 76 | public static void removeLowerOnCurDown(TreeSet set, int curDown) { 77 | List removes = new ArrayList<>(); 78 | for (Rectangle rec : set) { 79 | if (rec.up <= curDown) { 80 | removes.add(rec); 81 | } 82 | } 83 | for (Rectangle rec : removes) { 84 | set.remove(rec); 85 | } 86 | } 87 | 88 | public static void removeLeftOnCurLeft(TreeSet rightOrdered, int curLeft) { 89 | List removes = new ArrayList<>(); 90 | for (Rectangle rec : rightOrdered) { 91 | if (rec.right > curLeft) { 92 | break; 93 | } 94 | removes.add(rec); 95 | } 96 | for (Rectangle rec : removes) { 97 | rightOrdered.remove(rec); 98 | } 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /A4high/class08/C02_MinWindowLength.java: -------------------------------------------------------------------------------- 1 | package A4high.class08; 2 | 3 | import java.util.HashMap; 4 | 5 | // 给定字符串str1和str2,求str1的子串中含有str2所有字符的最小子串长度 6 | // 【举例】 7 | // str1="abcde",str2="ac" 8 | // 因为"abc"包含str2所有的字符,并且在满足这一条件的str1的所有子串中,"abc"是最短的,返回3。 9 | // str1="12345",str2="344" 最小包含子串不存在,返回0。 10 | // 注意不考虑顺序 11 | 12 | // 滑动窗口+词频表 13 | public class C02_MinWindowLength { 14 | 15 | public static int minLength(String str1, String str2) { 16 | if (str1 == null || str2 == null || str1.length() < str2.length()) { 17 | return 0; 18 | } 19 | char[] chas1 = str1.toCharArray(); 20 | char[] chas2 = str2.toCharArray(); 21 | int[] map = new int[256]; 22 | for (int i = 0; i != chas2.length; i++) { 23 | map[chas2[i]]++; 24 | } 25 | int left = 0; 26 | int right = 0; 27 | int match = chas2.length; 28 | int minLen = Integer.MAX_VALUE; 29 | while (right != chas1.length) { 30 | map[chas1[right]]--; // 不在str2的会减成负数,用于下面判断 31 | if (map[chas1[right]] >= 0) { 32 | match--; 33 | } 34 | if (match == 0) { 35 | while (map[chas1[left]] < 0) { 36 | map[chas1[left++]]++; 37 | } 38 | minLen = Math.min(minLen, right - left + 1); 39 | match++; 40 | map[chas1[left++]]++; 41 | } 42 | right++; 43 | } 44 | return minLen == Integer.MAX_VALUE ? 0 : minLen; 45 | } 46 | 47 | // hashmap方式,还是法一的答案简单 48 | public static int minLength2(String str1, String str2) { 49 | if (str1 == null || str2 == null || str1.length() < str2.length()) { 50 | return 0; 51 | } 52 | char[] arr1 = str1.toCharArray(); 53 | char[] arr2 = str2.toCharArray(); 54 | 55 | // 构建词频表 56 | HashMap map = new HashMap<>(); 57 | for (int i = 0; i < arr2.length; i++) { 58 | if (!map.containsKey(arr2[i])) { 59 | map.put(arr2[i], 0); 60 | } 61 | map.put(arr2[i], map.get(arr2[i]) + 1); 62 | } 63 | 64 | int res = Integer.MAX_VALUE; 65 | int left = -1; 66 | int right = 0; 67 | int needMatch = arr2.length; 68 | while (right != arr1.length) { 69 | // System.out.println(needMatch); 70 | if (map.containsKey(arr1[right])) { 71 | if (map.get(arr1[right]) > 0) { 72 | needMatch--; 73 | } 74 | map.put(arr1[right], map.get(arr1[right]) - 1); 75 | } 76 | if (needMatch == 0) { 77 | left++; 78 | while (true) { 79 | if (map.containsKey(arr1[left])) { 80 | map.put(arr1[left], map.get(arr1[left]) + 1); 81 | if (map.get(arr1[left]) == 1) { // 词频表表示字符i所欠的次数,为负数则表示多余的字符数,应保证每个字符都小于1 82 | needMatch++; 83 | break; 84 | } 85 | } 86 | left++; 87 | } 88 | 89 | res = Math.min(res, right - left + 1); 90 | } 91 | 92 | right++; 93 | } 94 | return res == Integer.MAX_VALUE ? 0 : res; 95 | } 96 | 97 | public static void main(String[] args) { 98 | String str1 = "adabbcq231a"; 99 | String str2 = "acb1a"; 100 | System.out.println(minLength(str1, str2)); 101 | System.out.println(minLength2(str1, str2)); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 左神算法班笔记 2 | 3 | > 可借鉴的笔记及源码解析链接:https://github.com/renyujie518/StrcuctandAlgorithm/tree/master/StructandAlgorithm/src 4 | 5 | > 视频地址:https://www.bilibili.com/video/BV13g41157hK/ 6 | 7 | ### 分支内容 8 | 9 | - main - 自我练习实现 10 | - 左神源码 - 左神算法课程的源码,目测版本不一样,可供参考 11 | 12 | #### 待整理: 13 | 14 | 1. determinant_reasoning:当一个问题除了前几项是 base case 能直接已知结果外,后续的每一项都按照之前值的严格递推表达式来求出的问题,推理结果为`f(n, n-1,... n-m) = f(m,...2,1) * Math.pow(|{x x x} {x x x}{x x x}|, n - m)` 15 | 典例:斐波那契数列的 O(logN)算法 16 | 17 | 2. 假设答案法:假设出最终答案,根据其位置推断出性质,再根据性质设计出简易的代码流程找出答案的位置 18 | 19 | 3. 打表法 20 | 21 | 4. 构造平凡解,舍弃可能性方法(高级班-1) 22 | 23 | 5. 动态规划的斜率优化:当动态规划的状态转移方程中存在枚举行为时,观察临近位置的求值过程是否已经包含了枚举过程的一部分了,存在则可以利用这个位置的值以复用之前位置的枚举结果,减少时间复杂度。 24 | 25 | 6. 递归需保证后效性,既母问题的所有决策都体现在子问题的参数上,而不是保留在母问题里 26 | 27 | 7. 桶排序普遍针对数据量很大,无法一次加载进内存的数据。将数据分桶,要求每个桶的大小能够被内存加载,进行快排,如果某个区间内数据量仍超出内存,则继续拆分。 28 | 29 | 8. 针对无序的字符串序列问题,考虑使用词频表+滑动窗口 30 | 31 | 9. 汉诺塔问题n个盘移动次数为:2的n次方减1 32 | 33 | #### TODO: 34 | 35 | - [x] 补充题目注释 36 | - [x] 总结技巧并添加示例题目链接 37 | - [ ] 修改 main 分支仅保留自己的代码 38 | - [ ] 重学行列式完成 fibonacci 文件夹 39 | - [ ] 补充封装对数器 40 | - [ ] 补充桶排序例题 41 | 42 | #### 思维技巧: 43 | 44 | 1. 察觉已经计算过的部分并重用,或用缓存以重用 45 | 2. 要用费时间换空间,要么费空间换时间,此消彼长 46 | 3. 利用数学思维:分类讨论,数形结合 47 | 4. 链表常用技巧:快慢指针, 48 | 5. 子字符串串、子数组的问题,就考虑以任意一个位置 i 结尾时的情况;子序列的问题,就每个位置考虑是否选择的问题 49 | 6. 对于有单调性的数组(都为正数或负数),考虑滑动窗口方式 50 | 51 | #### 优化方向: 52 | 53 | 1. 自身的数据状况 54 | 2. 所要求解的标准 55 | #### 待强化: 56 | 57 | - [ ] 小根堆,大根堆(例:skill-c18) 58 | - [ ] 二分法(例:skill-c01) 59 | - [ ] 行列式 60 | - [ ] 编辑距离问题(https://leetcode-cn.com/problems/edit-distance/) 61 | - [ ] 字符串相关 62 | 63 | ### 概念整理for leetcode 64 | - [字符串哈希](https://leetcode.cn/problems/shortest-palindrome/) 65 | - [Rabin-Karp算法和KMP算法](https://leetcode.cn/problems/repeated-string-match/) -------------------------------------------------------------------------------- /algo.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /binary_search/C01_bs.java: -------------------------------------------------------------------------------- 1 | package binary_search; 2 | 3 | // TODO: 4 | class C01_BS { 5 | 6 | // // 第一个 >=5 的元素 7 | // public static int firstGE5(int[] arr, int n) { 8 | 9 | // } 10 | 11 | // // 最后一个 <5 的元素 12 | // public static int lastL5(int[] arr, int n) { 13 | 14 | // } 15 | 16 | // // 第一个 >5 的元素 17 | // public static int firstG5(int[] arr, int n) { 18 | 19 | // } 20 | 21 | // // 最后一个 <=5 的元素 22 | // public static int lastLE5(int[] arr, int n) { 23 | 24 | // } 25 | 26 | // 循环二分 27 | public static int binary_search(int[] arr, int target) { 28 | if (arr == null || arr.length == 0) { 29 | return -1; 30 | } 31 | 32 | int left = 0; 33 | int right = arr.length - 1; 34 | int mid; 35 | while (left <= right) { 36 | mid = left + (right - left) / 2; // 为了不溢出 37 | if (arr[mid] == target) { 38 | return mid; 39 | } else if (arr[mid] > target) { 40 | right = mid - 1; 41 | } else { 42 | left = mid + 1; 43 | } 44 | } 45 | return -1; 46 | } 47 | 48 | // 递归二分 49 | public static int binary_search2(int[] arr, int target) { 50 | if (arr == null || arr.length == 0) { 51 | return -1; 52 | } 53 | return process(arr, target, 0, arr.length - 1); 54 | } 55 | 56 | private static int process(int[] arr, int target, int left, int right) { 57 | int mid = left + (right - left) / 2; 58 | if (left > right) { 59 | return -1; 60 | } 61 | if (arr[mid] == target) { 62 | return mid; 63 | } else if (arr[mid] > target) { 64 | return process(arr, target, left, mid - 1); 65 | } else { 66 | return process(arr, target, mid + 1, right); 67 | } 68 | } 69 | 70 | public static void main(String[] args) { 71 | int[] arr = new int[] { 1, 2, 3, 5, 5, 5, 8, 9 }; 72 | System.out.println(binary_search(arr, 5)); 73 | System.out.println(binary_search2(arr, 5)); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /binary_search/C04_BSExist.java: -------------------------------------------------------------------------------- 1 | package binary_search; 2 | 3 | // 一个有序数组中,找某个数是否存在 4 | public class C04_BSExist { 5 | public static boolean exist(int[] sortedArr, int num) { 6 | if (sortedArr == null || sortedArr.length == 0) { 7 | return false; 8 | } 9 | int L = 0; 10 | int R = sortedArr.length - 1; 11 | int mid = 0; 12 | while (L < R) { 13 | mid = L + ((R - L) >> 1); 14 | if (sortedArr[mid] == num) { 15 | return true; 16 | } else if (sortedArr[mid] > num) { 17 | R = mid - 1; 18 | } else { 19 | L = mid + 1; 20 | } 21 | } 22 | return sortedArr[L] == num; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /binary_search/C05_BSNearLeft.java: -------------------------------------------------------------------------------- 1 | package binary_search; 2 | 3 | // 在arr上,找满足>=value的最左位置 4 | public class C05_BSNearLeft { 5 | 6 | public static int nearestIndex(int[] arr, int value) { 7 | int L = 0; 8 | int R = arr.length - 1; 9 | int index = -1; 10 | while (L < R) { 11 | int mid = L + ((R - L) >> 1); 12 | if (arr[mid] >= value) { 13 | index = mid; 14 | R = mid - 1; 15 | } else { 16 | L = mid + 1; 17 | } 18 | } 19 | return index; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /binary_search/C08_GetMax.java: -------------------------------------------------------------------------------- 1 | package binary_search; 2 | 3 | // 二分递归求最大值 4 | public class C08_GetMax { 5 | 6 | public static int getMax(int[] arr) { 7 | return process(arr, 0, arr.length - 1); 8 | } 9 | 10 | // public static int process_answer(int[] arr, int L, int R) { 11 | // if (L == R) { 12 | // return arr[L]; 13 | // } 14 | // int mid = L + ((R - L) >> 1); 15 | // int leftMax = process(arr, L, mid); 16 | // int rightMax = process(arr, mid + 1, R); 17 | // return Math.max(leftMax, rightMax); 18 | // } 19 | 20 | public static int process(int[] arr, int L, int R) { 21 | if (R - L == 1) { 22 | return Math.max(arr[L], arr[R]); 23 | } 24 | 25 | int midIndex = (int) Math.floor(L + (R - L) >> 1); 26 | int leftMax = process(arr, L, midIndex); 27 | int rightMax = process(arr, midIndex + 1, R); 28 | return Math.max(leftMax, rightMax); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /bit_operation/C01_GetMax.java: -------------------------------------------------------------------------------- 1 | package bit_operation; 2 | 3 | // 位运算的题目 4 | // 给定两个有符号32位整数a和b,返回a和b中较大的。 5 | // 【要求】 6 | // 不用做任何比较判断。 7 | public class C01_GetMax { 8 | 9 | // public static int flip(int n) { 10 | // return n ^ 1; 11 | // } 12 | 13 | // public static int sign(int n) { 14 | // return flip((n >> 31) & 1); 15 | // } 16 | // c有溢出问题 17 | // public static int getMax1(int a, int b) { 18 | // int c = a - b; 19 | // int scA = sign(c); 20 | // int scB = flip(scA); 21 | // return a * scA + b * scB; 22 | // } 23 | 24 | // c无溢出问题,因为当c溢出时,就不看c的符号位了,单独有a, b符号位决定 25 | // public static int getMax2(int a, int b) { 26 | // int c = a - b; 27 | // int sa = sign(a); 28 | // int sb = sign(b); 29 | // int sc = sign(c); 30 | // int difSab = sa ^ sb; 31 | // int sameSab = flip(difSab); 32 | // int returnA = difSab * sa + sameSab * sc; 33 | // int returnB = flip(returnA); 34 | // return a * returnA + b * returnB; 35 | // } 36 | public static int getMax1(int a, int b) { 37 | int c = a - b; 38 | // NOTE: 不能这样得出符号位:~((c >>> 31) & 1), 取反会前31为都由0变为1 39 | int isPositive = (c >>> 31) ^ 1; 40 | // System.out.println("negative: " + isPositive); 41 | int isNegative = isPositive ^ 1; 42 | 43 | return isPositive * a + isNegative * b; 44 | } 45 | 46 | public static int getMax2(int a, int b) { 47 | int c = a - b; 48 | int aSign = ((a >> 31) & 1) ^ 1; 49 | // int bSign = ((b >> 31) & 1) ^ 1; 50 | int cSign = ((c >> 31) & 1) ^ 1; 51 | int abDiff = a ^ b; 52 | int abSame = abDiff ^ 1; 53 | int returnA = abDiff * cSign + abSame * aSign; 54 | int returnB = returnA ^ 1; 55 | 56 | return returnA * a + returnB * b; 57 | } 58 | 59 | public static void main(String[] args) { 60 | int a = -16; 61 | int b = 1; 62 | System.out.println(getMax1(a, b)); 63 | System.out.println(getMax2(a, b)); 64 | a = 2147483647; 65 | b = -2147480000; 66 | System.out.println(getMax1(a, b)); // wrong answer because of overflow 67 | System.out.println(getMax2(a, b)); 68 | 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /bit_operation/C02_Power.java: -------------------------------------------------------------------------------- 1 | package bit_operation; 2 | // 判断一个32位正数是不是2的幂、4的幂 3 | public class C02_Power { 4 | 5 | // public static boolean is2Power(int n) { 6 | // return (n & (n - 1)) == 0; 7 | // } 8 | 9 | // public static boolean is4Power(int n) { 10 | // return (n & (n - 1)) == 0 && (n & 0x55555555) != 0; 11 | // } 12 | 13 | public static boolean is2Power(int n) { 14 | return ((~n + 1) & n) == n; 15 | } 16 | 17 | public static boolean is4Power(int n) { 18 | return ((~n + 1) & n) == n && (n &0x55555555) != 0 ; 19 | } 20 | 21 | public static void main(String[] args) { 22 | System.out.println(is2Power(2)); 23 | System.out.println(is2Power(4)); 24 | System.out.println(is2Power(8192)); 25 | System.out.println(is2Power(16)); 26 | System.out.println(is2Power(32)); 27 | System.out.println(is2Power(64)); 28 | System.out.println("-----------------------"); 29 | System.out.println(is4Power(2)); 30 | System.out.println(is4Power(4)); 31 | System.out.println(is4Power(8192)); 32 | System.out.println(is4Power(16)); 33 | System.out.println(is4Power(32)); 34 | System.out.println(is4Power(64)); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /dp/C10_CoffeeTime.java: -------------------------------------------------------------------------------- 1 | package dp; 2 | 3 | // 给定一个数组arr,每个元素表示一台咖啡机冲咖啡的时间 4 | // 给定N,表示有多少人喝咖啡 5 | // 给定a,表示只有一台咖啡杯清洗机器,其洗咖啡杯所需时间 6 | // 给定b,咖啡杯不洗自然挥发自己变干净的时间 7 | // 问所有人喝一杯咖啡到所有杯子都干净至少要多久 8 | // 所有数都是正数 9 | 10 | // TODO: 11 | // P22 12 | public class C10_CoffeeTime { 13 | 14 | public static void main(String[] args) { 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /dp/C11_MinPathSum.java: -------------------------------------------------------------------------------- 1 | package dp; 2 | 3 | // easy, no need todo 4 | // 给你一个二维数组matrix,其中每个数都是正数,要求从左上角走到右下角。 5 | // 每一步只能向右或者向下,沿途经过的数字要累加起来。最后请返回最小的路径和。 6 | 7 | public class C11_MinPathSum { 8 | 9 | public static int minPathSum1(int[][] m) { 10 | if (m == null || m.length == 0 || m[0] == null || m[0].length == 0) { 11 | return 0; 12 | } 13 | int row = m.length; 14 | int col = m[0].length; 15 | int[][] dp = new int[row][col]; 16 | dp[0][0] = m[0][0]; 17 | for (int i = 1; i < row; i++) { 18 | dp[i][0] = dp[i - 1][0] + m[i][0]; 19 | } 20 | for (int j = 1; j < col; j++) { 21 | dp[0][j] = dp[0][j - 1] + m[0][j]; 22 | } 23 | for (int i = 1; i < row; i++) { 24 | for (int j = 1; j < col; j++) { 25 | dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + m[i][j]; 26 | } 27 | } 28 | return dp[row - 1][col - 1]; 29 | } 30 | 31 | public static int minPathSum2(int[][] m) { 32 | if (m == null || m.length == 0 || m[0] == null || m[0].length == 0) { 33 | return 0; 34 | } 35 | int more = Math.max(m.length, m[0].length); 36 | int less = Math.min(m.length, m[0].length); 37 | boolean rowmore = more == m.length; 38 | int[] arr = new int[less]; 39 | arr[0] = m[0][0]; 40 | for (int i = 1; i < less; i++) { 41 | arr[i] = arr[i - 1] + (rowmore ? m[0][i] : m[i][0]); 42 | } 43 | for (int i = 1; i < more; i++) { 44 | arr[0] = arr[0] + (rowmore ? m[i][0] : m[0][i]); 45 | for (int j = 1; j < less; j++) { 46 | arr[j] = Math.min(arr[j - 1], arr[j]) + (rowmore ? m[i][j] : m[j][i]); 47 | } 48 | } 49 | return arr[less - 1]; 50 | } 51 | 52 | // for test 53 | public static int[][] generateRandomMatrix(int rowSize, int colSize) { 54 | if (rowSize < 0 || colSize < 0) { 55 | return null; 56 | } 57 | int[][] result = new int[rowSize][colSize]; 58 | for (int i = 0; i != result.length; i++) { 59 | for (int j = 0; j != result[0].length; j++) { 60 | result[i][j] = (int) (Math.random() * 10); 61 | } 62 | } 63 | return result; 64 | } 65 | 66 | // for test 67 | public static void printMatrix(int[][] matrix) { 68 | for (int i = 0; i != matrix.length; i++) { 69 | for (int j = 0; j != matrix[0].length; j++) { 70 | System.out.print(matrix[i][j] + " "); 71 | } 72 | System.out.println(); 73 | } 74 | } 75 | 76 | public static void main(String[] args) { 77 | // int[][] m = generateRandomMatrix(3, 4); 78 | int[][] m = { { 1, 3, 5, 9 }, { 8, 1, 3, 4 }, { 5, 0, 6, 1 }, { 8, 8, 4, 0 } }; 79 | printMatrix(m); 80 | System.out.println(minPathSum1(m)); 81 | System.out.println(minPathSum2(m)); 82 | 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /fibonacci/C01_ZeroLeftOneStringNumber.java: -------------------------------------------------------------------------------- 1 | package fibonacci; 2 | 3 | // NOTE: 当一个问题除了前几项是base case能直接已知结果外, 4 | // 后续的每一项都按照之前值的严格递推表达式来求出的问题,典例:斐波那契数列的O(logN)算法 5 | // f(n,n-1,...n-m)=f(m,...2,1)*Math.pow(|{x x x}{x x x}{x x x}|,n-m) 6 | 7 | // 题目: 8 | // 字符串只由'0'和'1'两种字符构成,当字符串长度为1时,所有可能的字符串为"0"、"1"; 9 | // 当字符串长度为2时,所有可能的字符串为"00"、"01"、"10"、"11"; 10 | // 当字符串长度为3时,所有可能的字符串为"000"、"001"、"010"、"011"、"100"、 "101"、"110"、"111"... 11 | // 如果某一个字符串中,只要是出现'0'的位置,左边就靠着'1',这样的字符串叫作达标字符串。 12 | // 给定一个正数N,返回所有长度为N的字符串中,达标字符串的数量。 比如,N=3,返回3,因为只有"101"、"110"、"111"达标。 13 | // TODO: 14 | public class C01_ZeroLeftOneStringNumber { 15 | 16 | public static int getNum1(int n) { 17 | if (n < 1) { 18 | return 0; 19 | } 20 | return process(1, n); 21 | } 22 | 23 | public static int process(int i, int n) { 24 | if (i == n - 1) { 25 | return 2; 26 | } 27 | if (i == n) { 28 | return 1; 29 | } 30 | return process(i + 1, n) + process(i + 2, n); 31 | } 32 | 33 | public static int getNum2(int n) { 34 | if (n < 1) { 35 | return 0; 36 | } 37 | if (n == 1) { 38 | return 1; 39 | } 40 | int pre = 1; 41 | int cur = 1; 42 | int tmp = 0; 43 | for (int i = 2; i < n + 1; i++) { 44 | tmp = cur; 45 | cur += pre; 46 | pre = tmp; 47 | } 48 | return cur; 49 | } 50 | 51 | public static int getNum3(int n) { 52 | if (n < 1) { 53 | return 0; 54 | } 55 | if (n == 1 || n == 2) { 56 | return n; 57 | } 58 | int[][] base = { { 1, 1 }, { 1, 0 } }; 59 | int[][] res = matrixPower(base, n - 2); 60 | return 2 * res[0][0] + res[1][0]; 61 | } 62 | 63 | public static int[][] matrixPower(int[][] m, int p) { 64 | int[][] res = new int[m.length][m[0].length]; 65 | for (int i = 0; i < res.length; i++) { 66 | res[i][i] = 1; 67 | } 68 | int[][] tmp = m; 69 | for (; p != 0; p >>= 1) { 70 | if ((p & 1) != 0) { 71 | res = muliMatrix(res, tmp); 72 | } 73 | tmp = muliMatrix(tmp, tmp); 74 | } 75 | return res; 76 | } 77 | 78 | // 行列式相乘 79 | public static int[][] muliMatrix(int[][] m1, int[][] m2) { 80 | int[][] res = new int[m1.length][m2[0].length]; 81 | for (int i = 0; i < m1.length; i++) { 82 | for (int j = 0; j < m2[0].length; j++) { 83 | for (int k = 0; k < m2.length; k++) { 84 | res[i][j] += m1[i][k] * m2[k][j]; 85 | } 86 | } 87 | } 88 | return res; 89 | } 90 | 91 | public static void main(String[] args) { 92 | for (int i = 0; i != 20; i++) { 93 | System.out.println(getNum1(i)); 94 | System.out.println(getNum2(i)); 95 | System.out.println(getNum3(i)); 96 | System.out.println("==================="); 97 | } 98 | 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /fibonacci/C02_CowBornNumber.java: -------------------------------------------------------------------------------- 1 | package fibonacci; 2 | 3 | // 一只母牛农场给它进行生育控制,只让他生母牛而且每一年只让她生一只母牛。 4 | // 这个新生的牛在三年之后,成熟了可以继续帮着生母牛。问你n年之后牛的数量,假设牛不会死(若5年后死呢?) 5 | 6 | // f(n, n-1, n-2) = f(3,2,1) * Math.pow(|{x x x} {x x x}{x x x}|, n - 3) 7 | // TODO: 8 | public class C02_CowBornNumber { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /fibonacci/C03_DeleteWood.java: -------------------------------------------------------------------------------- 1 | package fibonacci; 2 | 3 | // 在迷迷糊糊的大草原上,小红捡到了n根木棍,第i根木棍的长度为i, 4 | // 小红现在很开心。想选出其中的三根木棍组成美丽的三角形。 5 | // 但是小明想捉弄小红,想去掉一些木棍,使得小红任意选三根木棍都不能组成三角形。 6 | // 请问小明最少去掉多少根木棍呢? 7 | 8 | public class C03_DeleteWood { 9 | 10 | // public static int minDelete(int m) { 11 | // if (m < 4) { 12 | // return 0; 13 | // } 14 | // int k_2 = 2; 15 | // int k_1 = 3; 16 | // int num = 3; 17 | // while (k_2 + k_1 <= m) { 18 | // num++; 19 | // k_1 += k_2; 20 | // k_2 = k_1 - k_2; 21 | // } 22 | // return m - num; 23 | // } 24 | 25 | public static int minDelete2(int n) { 26 | if (n < 0) { 27 | return -1; 28 | } 29 | if (n < 4) { // 1 2 3 不够 30 | return 0; 31 | } 32 | 33 | int n1 = 1; 34 | int n2 = 2; 35 | int count = 2; 36 | while (n2 + n1 <= n) { 37 | n2 += n1; 38 | n1 = n2 - n1; // 优化, 不用tem缓存 39 | count++; 40 | } 41 | return n - count; 42 | } 43 | 44 | public static void main(String[] args) { 45 | int test = 231; 46 | // System.out.println(minDelete(test)); 47 | System.out.println(minDelete2(test)); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /force_recursion/C01_Hanoi.java: -------------------------------------------------------------------------------- 1 | package force_recursion; 2 | 3 | // 汉诺塔问题 打印n层汉诺塔从最左边移动到最右边的全部过程 4 | public class C01_Hanoi { 5 | 6 | // public static void hanoi(int n) { 7 | // if (n > 0) { 8 | // func(n, n, "left", "mid", "right"); 9 | // } 10 | // } 11 | 12 | // public static void func(int rest, int down, String from, String help, String 13 | // to) { 14 | // if (rest == 1) { 15 | // System.out.println("move " + down + " from " + from + " to " + to); 16 | // } else { 17 | // func(rest - 1, down - 1, from, to, help); 18 | // func(1, down, from, help, to); 19 | // func(rest - 1, down - 1, help, from, to); 20 | // } 21 | // } 22 | 23 | public static void hanoi(int n) { 24 | if (n == 0) { 25 | return; 26 | } 27 | process(n, "left", "right", "mid"); 28 | } 29 | 30 | private static void process(int n, String from, String to, String other) { 31 | if (n <= 1) { 32 | System.out.println("move " + n + " from " + from + " to " + to); 33 | return; 34 | } 35 | process(n - 1, from, other, to); 36 | System.out.println("move " + n + " from " + from + " to " + to); 37 | process(n - 1, other, to, from); 38 | 39 | } 40 | 41 | public static void main(String[] args) { 42 | int n = 3; 43 | hanoi(n); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /force_recursion/C02_CardsInLine.java: -------------------------------------------------------------------------------- 1 | package force_recursion; 2 | 3 | // 给定一个整型数组arr,代表数值不同的纸牌排成一条线。 4 | // 玩家A和玩家B依次拿走每张纸牌,规定玩家A先拿,玩家B后拿,但是每个玩家每次只能拿走最左或最右的纸牌,玩家A和玩家B都绝顶聪明。 5 | // 请返回最后获胜者的分数。 6 | // 【举例】 7 | // arr=[1,2,100,4]。 8 | // 开始时,玩家A只能拿走1或4。如果开始时玩家A拿走1,则排列变为[2,100,4],接下来玩家B可以拿走2或4,然后继续轮到玩家A...如果开始时玩家A拿走4,则排列变为[1,2,100],接下来玩家B可以拿走1或100,然后继续轮到玩家A... 玩家A作为绝顶聪明的人不会先拿4,因为拿4之后,玩家B将拿走100。所以玩家A会先拿1,让排列变为[2,100,4],接下来玩家B不管怎么选,100都会被玩家A拿走。玩家A会获胜,分数为101。所以返回101。 9 | // arr=[1,100,2]。 10 | // 开始时,玩家A不管拿1还是2,玩家B作为绝顶聪明的人,都会把100拿走。玩家B会获胜,分数为100。所以返回100。 11 | public class C02_CardsInLine { 12 | 13 | // public static int win1(int[] arr) { 14 | // if (arr == null || arr.length == 0) { 15 | // return 0; 16 | // } 17 | // return Math.max(f(arr, 0, arr.length - 1), s(arr, 0, arr.length - 1)); 18 | // } 19 | 20 | // public static int f(int[] arr, int i, int j) { 21 | // if (i == j) { 22 | // return arr[i]; 23 | // } 24 | // return Math.max(arr[i] + s(arr, i + 1, j), arr[j] + s(arr, i, j - 1)); 25 | // } 26 | 27 | // public static int s(int[] arr, int i, int j) { 28 | // if (i == j) { 29 | // return 0; 30 | // } 31 | // return Math.min(f(arr, i + 1, j), f(arr, i, j - 1)); 32 | // } 33 | 34 | // public static int win2(int[] arr) { 35 | // if (arr == null || arr.length == 0) { 36 | // return 0; 37 | // } 38 | // int[][] f = new int[arr.length][arr.length]; 39 | // int[][] s = new int[arr.length][arr.length]; 40 | // for (int j = 0; j < arr.length; j++) { 41 | // f[j][j] = arr[j]; 42 | // for (int i = j - 1; i >= 0; i--) { 43 | // f[i][j] = Math.max(arr[i] + s[i + 1][j], arr[j] + s[i][j - 1]); 44 | // s[i][j] = Math.min(f[i + 1][j], f[i][j - 1]); 45 | // } 46 | // } 47 | // return Math.max(f[0][arr.length - 1], s[0][arr.length - 1]); 48 | // } 49 | 50 | // TODO:不明白 51 | public static int win1(int[] arr) { 52 | if (arr == null || arr.length == 0) { 53 | return 0; 54 | } 55 | return Math.max(f(arr, 0, arr.length - 1), s(arr, 0, arr.length - 1)); 56 | } 57 | 58 | private static int f(int[] arr, int left, int right) { 59 | if (left == right) { 60 | return arr[left]; 61 | } 62 | 63 | return Math.max(arr[left] + s(arr, left + 1, right), arr[right] + s(arr, left, right - 1)); 64 | } 65 | 66 | private static int s(int[] arr, int left, int right) { 67 | if (left == right) { 68 | return 0; 69 | } 70 | return Math.min(f(arr, left + 1, right), f(arr, left, right - 1)); 71 | } 72 | 73 | public static int win2(int[] arr) { 74 | return 0; 75 | } 76 | 77 | public static void main(String[] args) { 78 | int[] arr = { 1, 9, 1 }; 79 | System.out.println(win1(arr)); 80 | // System.out.println(win2(arr)); 81 | 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /force_recursion/C03_PrintAllPermutations.java: -------------------------------------------------------------------------------- 1 | package force_recursion; 2 | 3 | import java.util.ArrayList; 4 | 5 | // 打印一个字符串的全部排列,要求不要出现重复的排列 6 | public class C03_PrintAllPermutations { 7 | 8 | // public static ArrayList Permutation(String str) { 9 | // ArrayList res = new ArrayList<>(); 10 | // if (str == null || str.length() == 0) { 11 | // return res; 12 | // } 13 | // char[] chs = str.toCharArray(); 14 | // process(chs, 0, res); 15 | // res.sort(null); 16 | // return res; 17 | // } 18 | 19 | // public static void process(char[] chs, int i, ArrayList res) { 20 | // if (i == chs.length) { 21 | // res.add(String.valueOf(chs)); 22 | // } 23 | // boolean[] visit = new boolean[26]; 24 | // for (int j = i; j < chs.length; j++) { 25 | // if (!visit[chs[j] - 'a']) { 26 | // visit[chs[j] - 'a'] = true; 27 | // swap(chs, i, j); 28 | // process(chs, i + 1, res); 29 | // swap(chs, i, j); 30 | // } 31 | // } 32 | // } 33 | 34 | // public static void swap(char[] chs, int i, int j) { 35 | // char tmp = chs[i]; 36 | // chs[i] = chs[j]; 37 | // chs[j] = tmp; 38 | // } 39 | 40 | public static ArrayList Permutation(String str) { 41 | ArrayList container = new ArrayList<>(); 42 | if (str == null || str.length() == 0) { 43 | return container; 44 | } 45 | 46 | char[] arr = str.toCharArray(); 47 | process(arr, 0, container); 48 | return container; 49 | } 50 | 51 | private static void process(char[] arr, int level, ArrayList container) { 52 | if (level == arr.length - 1) { 53 | container.add(arr.toString()); 54 | } 55 | char tem = arr[level]; 56 | for (int i = level + 1; i < arr.length; i++) { 57 | if (arr[i] != tem) { 58 | swap(arr, i, level); 59 | process(arr, level + 1, container); 60 | swap(arr, i, level); 61 | } 62 | } 63 | } 64 | 65 | private static void swap(char[] arr, int i, int j) { 66 | char tem = arr[i]; 67 | arr[i] = arr[j]; 68 | arr[j] = tem; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /force_recursion/C04_ReverseStackUsingRecursive.java: -------------------------------------------------------------------------------- 1 | package force_recursion; 2 | 3 | import java.util.Stack; 4 | 5 | // 给你一个栈,请你逆序这个栈,不能申请额外的数据结构,只能使用递归函数。 如何实现? 6 | public class C04_ReverseStackUsingRecursive { 7 | 8 | // public static void reverse(Stack stack) { 9 | // if (stack.isEmpty()) { 10 | // return; 11 | // } 12 | // int i = getAndRemoveLastElement(stack); 13 | // reverse(stack); 14 | // stack.push(i); 15 | // } 16 | 17 | // public static int getAndRemoveLastElement(Stack stack) { 18 | // int result = stack.pop(); 19 | // if (stack.isEmpty()) { 20 | // return result; 21 | // } else { 22 | // int last = getAndRemoveLastElement(stack); 23 | // stack.push(result); 24 | // return last; 25 | // } 26 | // } 27 | 28 | public static void reverse(Stack stack) { 29 | if (stack.isEmpty()) { 30 | return; 31 | } 32 | 33 | int tem = getAndRemoveLastElement(stack); 34 | reverse(stack); 35 | stack.push(tem); 36 | } 37 | 38 | private static int getAndRemoveLastElement(Stack stack) { 39 | if (stack.size() <= 1) { 40 | return stack.pop(); 41 | } 42 | int tem1 = stack.pop(); 43 | int tem2 = getAndRemoveLastElement(stack); 44 | stack.push(tem1); 45 | return tem2; 46 | } 47 | 48 | public static void main(String[] args) { 49 | Stack test = new Stack(); 50 | test.push(1); 51 | test.push(2); 52 | test.push(3); 53 | test.push(4); 54 | test.push(5); 55 | reverse(test); 56 | while (!test.isEmpty()) { 57 | System.out.println(test.pop()); 58 | } 59 | 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /force_recursion/C05_ConvertToLetterString.java: -------------------------------------------------------------------------------- 1 | package force_recursion; 2 | 3 | // 规定1和A对应、2和B对应、3和C对应...那么一个数字字符串比如"111",就可以转化为"AAA"、"KA"和"AK"。 4 | // 给定一个只有数字字符组成的字符串str,返回有多少种转化结果。 5 | public class C05_ConvertToLetterString { 6 | 7 | // public static int number(String str) { 8 | // if (str == null || str.length() == 0) { 9 | // return 0; 10 | // } 11 | // return process(str.toCharArray(), 0); 12 | // } 13 | 14 | // public static int process(char[] chs, int i) { 15 | // if (i == chs.length) { 16 | // return 1; 17 | // } 18 | // if (chs[i] == '0') { 19 | // return 0; 20 | // } 21 | // if (chs[i] == '1') { 22 | // int res = process(chs, i + 1); 23 | // if (i + 1 < chs.length) { 24 | // res += process(chs, i + 2); 25 | // } 26 | // return res; 27 | // } 28 | // if (chs[i] == '2') { 29 | // int res = process(chs, i + 1); 30 | // if (i + 1 < chs.length && (chs[i + 1] >= '0' && chs[i + 1] <= '6')) { 31 | // res += process(chs, i + 2); 32 | // } 33 | // return res; 34 | // } 35 | // return process(chs, i + 1); 36 | // } 37 | 38 | public static int number(String string) { 39 | if (string == null || string.length() == 0) { 40 | return 0; 41 | } 42 | 43 | return process(string.toCharArray(), 0); 44 | 45 | } 46 | 47 | private static int process(char[] arr, int i) { 48 | if (i >= arr.length - 1) { 49 | return 1; 50 | } 51 | 52 | if (arr[i] == '0') { 53 | return 0; 54 | } else if (arr[i] == '1') { 55 | return process(arr, i + 1) + (i < arr.length -1 ? process(arr, i + 2) : 0); 56 | } else if (arr[i] == '2') { 57 | if (arr[i + 1] >= '0' && arr[i + 1] <= '6') { 58 | return process(arr, i + 1) + (i < arr.length -1 ? process(arr, i + 2) : 0); 59 | } else { 60 | return process(arr, i + 1); 61 | } 62 | } else { 63 | return process(arr, i + 1); 64 | } 65 | } 66 | 67 | public static void main(String[] args) { 68 | System.out.println(number("11111")); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /force_recursion/C06_Knapsack.java: -------------------------------------------------------------------------------- 1 | package force_recursion; 2 | 3 | // 给定两个长度都为N的数组weights和values,weights[i]和values[i]分别代表i号物品的重量和价值。 4 | // 给定一个正数bag,表示一个载重bag的袋子,你装的物品不能超过这个重量。返回你能装下最多的价值是多少? 5 | public class C06_Knapsack { 6 | 7 | // public static int maxValue1(int[] weights, int[] values, int bag) { 8 | // return process1(weights, values, 0, 0, bag); 9 | // } 10 | 11 | // public static int process1(int[] weights, int[] values, int i, int alreadyWeight, int bag) { 12 | // if (alreadyWeight > bag) { 13 | // return 0; 14 | // } 15 | // // 有bug: 16 | // // if (i == weights.length) { 17 | // // return 0; 18 | // // } 19 | // // return Math.max( 20 | // // process1(weights, values, i + 1, alreadyWeight, bag), 21 | // // values[i] + process1(weights, values, i + 1, alreadyWeight + weights[i], 22 | // // bag)); 23 | 24 | // // 正确写法: 25 | // return Math.max(process1(weights, values, i + 1, alreadyWeight, bag), 26 | // alreadyWeight + weights[i] <= bag 27 | // ? values[i] + process1(weights, values, i + 1, alreadyWeight + weights[i], bag) 28 | // : 0); 29 | // } 30 | 31 | // TODO:动态规划? 32 | // public static int maxValue2(int[] c, int[] p, int bag) { 33 | // int[][] dp = new int[c.length + 1][bag + 1]; 34 | // for (int i = c.length - 1; i >= 0; i--) { 35 | // for (int j = bag; j >= 0; j--) { 36 | // dp[i][j] = dp[i + 1][j]; 37 | // if (j + c[i] <= bag) { 38 | // dp[i][j] = Math.max(dp[i][j], p[i] + dp[i + 1][j + c[i]]); 39 | // } 40 | // } 41 | // } 42 | // return dp[0][0]; 43 | // } 44 | 45 | // 法一 46 | public static int maxValue1(int[] weights, int[] values, int bag) { 47 | return process1(weights, values, bag, 0, 0); 48 | } 49 | 50 | private static int process1(int[] weights, int[] values, int bag, int alreadyWeight, int index) { 51 | if (alreadyWeight > bag) { 52 | return 0; 53 | } 54 | if (index >= weights.length) { 55 | return 0; 56 | } 57 | return Math.max( 58 | alreadyWeight + weights[index] + process1(weights, values, bag, alreadyWeight + weights[index], index + 1), 59 | alreadyWeight + process1(weights, values, bag, alreadyWeight, index + 1)); 60 | } 61 | 62 | // 法二 TODO:未完成 63 | public static int maxValue2(int[] weights, int[] values, int bag) { 64 | return 0; 65 | } 66 | 67 | public static void main(String[] args) { 68 | int[] weights = { 3, 2, 4, 7 }; 69 | int[] values = { 5, 6, 3, 19 }; 70 | int bag = 11; 71 | System.out.println(maxValue1(weights, values, bag)); 72 | System.out.println(maxValue2(weights, values, bag)); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /force_recursion/C07_PrintAllSubsquences.java: -------------------------------------------------------------------------------- 1 | package force_recursion; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | // 打印一个字符串的全部子序列,包括空字符串 7 | public class C07_PrintAllSubsquences { 8 | 9 | // public static void printAllSubsequence(String str) { 10 | // char[] chs = str.toCharArray(); 11 | // process(chs, 0); 12 | // } 13 | 14 | // public static void process(char[] chs, int i) { 15 | // if (i == chs.length) { 16 | // System.out.println(String.valueOf(chs)); 17 | // return; 18 | // } 19 | // process(chs, i + 1); 20 | // char tmp = chs[i]; 21 | // chs[i] = 0; 22 | // process(chs, i + 1); 23 | // chs[i] = tmp; 24 | // } 25 | 26 | // public static void function(String str) { 27 | // char[] chs = str.toCharArray(); 28 | // process(chs, 0, new ArrayList()); 29 | // } 30 | 31 | // public static void process(char[] chs, int i, List res) { 32 | // if(i == chs.length) { 33 | // printList(res); 34 | // } 35 | // List resKeep = copyList(res); 36 | // resKeep.add(chs[i]); 37 | // process(chs, i+1, resKeep); 38 | // List resNoInclude = copyList(res); 39 | // process(chs, i+1, resNoInclude); 40 | // } 41 | 42 | // public static void printList(List res) { 43 | // } 44 | 45 | // public static List copyList(List list){ 46 | // return null; 47 | // } 48 | 49 | // 法一 50 | public static void printAllSubsequence(String str) { 51 | if (str == null) { 52 | return; 53 | } 54 | 55 | process(str.toCharArray(), 0, new ArrayList()); 56 | } 57 | 58 | public static void process(char[] arr, int i, ArrayList container) { 59 | if (i >= arr.length) { 60 | printList(container); 61 | return; 62 | } 63 | container.add(arr[i]); 64 | process(arr, i + 1, container); 65 | container.remove((Object) arr[i]); 66 | process(arr, i + 1, container); 67 | } 68 | 69 | // 法二 70 | public static void printAllSubsequence2(String str) { 71 | if (str == null) { 72 | return; 73 | } 74 | process2(str.toCharArray(), 0); 75 | } 76 | 77 | public static void process2(char[] arr, int i) { 78 | if (i >= arr.length) { 79 | System.out.println(String.valueOf(arr)); 80 | return; 81 | } 82 | char tem = arr[i]; 83 | process2(arr, i + 1); 84 | arr[i] = 0; 85 | process2(arr, i + 1); 86 | arr[i] = tem; 87 | } 88 | 89 | private static void printList(List res) { 90 | for (Character character : res) { 91 | System.out.print(character); 92 | } 93 | System.out.println(); 94 | } 95 | 96 | public static void main(String[] args) { 97 | String test = "abc"; 98 | printAllSubsequence2(test); 99 | 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /force_recursion/C09_MaxHappy.java: -------------------------------------------------------------------------------- 1 | package force_recursion; 2 | 3 | import java.util.List; 4 | 5 | // 派对的最大快乐值 6 | // 员工信息的定义如下: 7 | // class Employee { 8 | // public int happy; // 这名员工可以带来的快乐值 9 | // List subordinates; // 这名员工有哪些直接下级 10 | // } 11 | // 公司的每个员工都符合Employee类的描述。整个公司的人员结构可以看作是一棵标准的、没有环的多叉树。 12 | // 树的头节点是公司唯一的老板。除老板之外的每个员工都有唯一的直接上级。 13 | // 叶节点是没有任何下属的基层员工(subordinates列表为空),除基层员工外,每个员工都有一个或多个直接下级。 14 | // 这个公司现在要办party,你可以决定哪些员工来,哪些员工不来。 15 | // 但是要遵循如下规则。 1.如果某个员工来了,那么这个员工的所有直接下级都不能来 2.派对的整体快乐值是所有到场员工快乐值的累加 16 | // 3.你的目标是让派对的整体快乐值尽量大 17 | // 给定一棵多叉树的头节点boss,请返回派对的最大快乐值。 18 | public class C09_MaxHappy { 19 | // answer: 20 | 21 | // public static int maxHappy(int[][] matrix) { 22 | // int[][] dp = new int[matrix.length][2]; 23 | // boolean[] visited = new boolean[matrix.length]; 24 | // int root = 0; 25 | // for (int i = 0; i < matrix.length; i++) { 26 | // if (i == matrix[i][0]) { 27 | // root = i; 28 | // } 29 | // } 30 | // process(matrix, dp, visited, root); 31 | // return Math.max(dp[root][0], dp[root][1]); 32 | // } 33 | 34 | // public static void process(int[][] matrix, int[][] dp, boolean[] visited, int 35 | // root) { 36 | // visited[root] = true; 37 | // dp[root][1] = matrix[root][1]; 38 | // for (int i = 0; i < matrix.length; i++) { 39 | // if (matrix[i][0] == root && !visited[i]) { 40 | // process(matrix, dp, visited, i); 41 | // dp[root][1] += dp[i][0]; 42 | // dp[root][0] += Math.max(dp[i][1], dp[i][0]); 43 | // } 44 | // } 45 | // } 46 | 47 | public static class Employee { 48 | public int happy; 49 | List subordinates; 50 | } 51 | 52 | private static class Info { 53 | public int comeMaxHappy; 54 | public int notComeMaxHappy; 55 | 56 | public Info(int comeMaxHappy, int notComeMaxHappy) { 57 | this.comeMaxHappy = comeMaxHappy; 58 | this.notComeMaxHappy = notComeMaxHappy; 59 | } 60 | } 61 | 62 | public int maxHappy(Employee boss) { 63 | Info info = process(boss); 64 | return Math.max(info.comeMaxHappy, info.notComeMaxHappy); 65 | } 66 | 67 | public Info process(Employee emp) { 68 | if (emp.subordinates.size() == 0) { 69 | return new Info(emp.happy, 0); 70 | } 71 | 72 | int comeMaxHappy = 0; 73 | int notComeMaxHappy = 0; 74 | 75 | for (Employee e : emp.subordinates) { 76 | Info info = process(e); 77 | comeMaxHappy += info.notComeMaxHappy; 78 | notComeMaxHappy += Math.max(info.comeMaxHappy, info.notComeMaxHappy); 79 | } 80 | 81 | return new Info(comeMaxHappy, notComeMaxHappy); 82 | } 83 | 84 | public static void main(String[] args) { 85 | // int[][] matrix = { { 1, 8 }, { 1, 9 }, { 1, 10 } }; 86 | // System.out.println(maxHappy(matrix)); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /graph/C01_BFS.java: -------------------------------------------------------------------------------- 1 | package graph; 2 | 3 | import java.util.HashSet; 4 | import java.util.LinkedList; 5 | import java.util.Queue; 6 | 7 | // 广度优先 8 | public class C01_BFS { 9 | 10 | // public static void bfs(Node node) { 11 | // if (node == null) { 12 | // return; 13 | // } 14 | // Queue queue = new LinkedList<>(); 15 | // HashSet map = new HashSet<>(); 16 | // queue.add(node); 17 | // map.add(node); 18 | // while (!queue.isEmpty()) { 19 | // Node cur = queue.poll(); 20 | // System.out.println(cur.value); 21 | // for (Node next : cur.nexts) { 22 | // if (!map.contains(next)) { 23 | // map.add(next); 24 | // queue.add(next); 25 | // } 26 | // } 27 | // } 28 | // } 29 | 30 | public static void bfs(Node node) { 31 | if (node == null) { 32 | return; 33 | } 34 | 35 | Queue queue = new LinkedList<>(); 36 | HashSet set = new HashSet<>(); 37 | Node tem = null; 38 | 39 | set.add(node); 40 | queue.add(node); 41 | 42 | while (!queue.isEmpty()) { 43 | tem = queue.poll(); 44 | System.out.println(tem.value); 45 | for (Node tem2 : tem.nexts) { 46 | if (!set.contains(tem2)) { 47 | queue.add(tem2); 48 | set.add(tem2); 49 | } 50 | } 51 | } 52 | 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /graph/C02_DFS.java: -------------------------------------------------------------------------------- 1 | package graph; 2 | 3 | import java.util.HashSet; 4 | import java.util.Stack; 5 | 6 | // 深度优先 7 | public class C02_DFS { 8 | 9 | // public static void dfs(Node node) { 10 | // if (node == null) { 11 | // return; 12 | // } 13 | // Stack stack = new Stack<>(); 14 | // HashSet set = new HashSet<>(); 15 | // stack.add(node); 16 | // set.add(node); 17 | // System.out.println(node.value); 18 | // while (!stack.isEmpty()) { 19 | // Node cur = stack.pop(); 20 | // for (Node next : cur.nexts) { 21 | // if (!set.contains(next)) { 22 | // stack.push(cur); 23 | // stack.push(next); 24 | // set.add(next); 25 | // System.out.println(next.value); 26 | // break; 27 | // } 28 | // } 29 | // } 30 | // } 31 | public static void dfs(Node node) { 32 | if (node == null) { 33 | return; 34 | } 35 | 36 | HashSet set = new HashSet<>(); 37 | Stack stack = new Stack<>(); 38 | Node cur = null; 39 | 40 | stack.add(node); 41 | set.add(node); 42 | System.out.println(node.value); 43 | 44 | while (!stack.isEmpty()) { 45 | cur = stack.pop(); 46 | for (Node tem : cur.nexts) { 47 | if (!set.contains(tem)) { 48 | stack.add(cur); 49 | stack.add(tem); 50 | System.out.println(tem.value); 51 | break; 52 | } 53 | } 54 | } 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /graph/C03_TopologySort.java: -------------------------------------------------------------------------------- 1 | package graph; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.LinkedList; 6 | import java.util.List; 7 | import java.util.Queue; 8 | 9 | // 拓扑排序算法 适用范围:要求有向图,且有入度为0的节点,且没有环 10 | public class C03_TopologySort { 11 | 12 | // directed graph and no loop 13 | // public static List sortedTopology(Graph graph) { 14 | // HashMap inMap = new HashMap<>(); 15 | // Queue zeroInQueue = new LinkedList<>(); 16 | // for (Node node : graph.nodes.values()) { 17 | // inMap.put(node, node.in); 18 | // if (node.in == 0) { 19 | // zeroInQueue.add(node); 20 | // } 21 | // } 22 | // List result = new ArrayList<>(); 23 | // while (!zeroInQueue.isEmpty()) { 24 | // Node cur = zeroInQueue.poll(); 25 | // result.add(cur); 26 | // for (Node next : cur.nexts) { 27 | // inMap.put(next, inMap.get(next) - 1); 28 | // if (inMap.get(next) == 0) { 29 | // zeroInQueue.add(next); 30 | // } 31 | // } 32 | // } 33 | // return result; 34 | // } 35 | 36 | public static List sortedTopology(Graph graph) { // 拓扑排序 37 | List result = new ArrayList<>(); 38 | HashMap inMap = new HashMap<>(); 39 | Queue queue = new LinkedList<>(); 40 | 41 | for (Node node : graph.nodes.values()) { 42 | inMap.put(node, node.in); 43 | if (node.in == 0) { 44 | queue.add(node); 45 | } 46 | } 47 | 48 | Node cur = null; 49 | while (!queue.isEmpty()) { 50 | cur = queue.poll(); 51 | result.add(cur); 52 | for (Node node : cur.nexts) { 53 | inMap.put(node, inMap.get(node) - 1); 54 | if (inMap.get(node) == 0) { 55 | queue.add(node); 56 | } 57 | } 58 | } 59 | return result; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /graph/C04_Kruskal.java: -------------------------------------------------------------------------------- 1 | package graph; 2 | 3 | import java.util.Collection; 4 | import java.util.Comparator; 5 | import java.util.HashMap; 6 | import java.util.HashSet; 7 | import java.util.PriorityQueue; 8 | import java.util.Set; 9 | 10 | // kruskal算法 适用范围:要求无向图 11 | 12 | //undirected graph only 13 | public class C04_Kruskal { 14 | 15 | // P7:85 16 | 17 | // Union-Find Set 18 | public static class UnionFind { 19 | private HashMap fatherMap; 20 | private HashMap rankMap; 21 | 22 | public UnionFind() { 23 | fatherMap = new HashMap(); 24 | rankMap = new HashMap(); 25 | } 26 | 27 | private Node findFather(Node n) { 28 | Node father = fatherMap.get(n); 29 | if (father != n) { 30 | father = findFather(father); 31 | } 32 | fatherMap.put(n, father); 33 | return father; 34 | } 35 | 36 | public void makeSets(Collection nodes) { 37 | fatherMap.clear(); 38 | rankMap.clear(); 39 | for (Node node : nodes) { 40 | fatherMap.put(node, node); 41 | rankMap.put(node, 1); 42 | } 43 | } 44 | 45 | public boolean isSameSet(Node a, Node b) { //判断相等 46 | return findFather(a) == findFather(b); 47 | } 48 | 49 | public void union(Node a, Node b) { // 合并 50 | if (a == null || b == null) { 51 | return; 52 | } 53 | Node aFather = findFather(a); 54 | Node bFather = findFather(b); 55 | if (aFather != bFather) { 56 | int aFrank = rankMap.get(aFather); 57 | int bFrank = rankMap.get(bFather); 58 | if (aFrank <= bFrank) { 59 | fatherMap.put(aFather, bFather); 60 | rankMap.put(bFather, aFrank + bFrank); 61 | } else { 62 | fatherMap.put(bFather, aFather); 63 | rankMap.put(aFather, aFrank + bFrank); 64 | } 65 | } 66 | } 67 | } 68 | 69 | public static class EdgeComparator implements Comparator { 70 | 71 | @Override 72 | public int compare(Edge o1, Edge o2) { 73 | return o1.weight - o2.weight; 74 | } 75 | 76 | } 77 | 78 | public static Set kruskalMST(Graph graph) { 79 | UnionFind unionFind = new UnionFind(); 80 | unionFind.makeSets(graph.nodes.values()); 81 | PriorityQueue priorityQueue = new PriorityQueue<>(new EdgeComparator()); 82 | for (Edge edge : graph.edges) { 83 | priorityQueue.add(edge); 84 | } 85 | Set result = new HashSet<>(); 86 | while (!priorityQueue.isEmpty()) { 87 | Edge edge = priorityQueue.poll(); 88 | if (!unionFind.isSameSet(edge.from, edge.to)) { 89 | result.add(edge); 90 | unionFind.union(edge.from, edge.to); 91 | } 92 | } 93 | return result; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /graph/C05_Prim.java: -------------------------------------------------------------------------------- 1 | package graph; 2 | 3 | import java.util.Comparator; 4 | import java.util.HashSet; 5 | import java.util.PriorityQueue; 6 | import java.util.Set; 7 | 8 | // prim算法 适用范围:要求无向图 9 | 10 | // undirected graph only 11 | public class C05_Prim { 12 | 13 | public static class EdgeComparator implements Comparator { 14 | 15 | @Override 16 | public int compare(Edge o1, Edge o2) { 17 | return o1.weight - o2.weight; 18 | } 19 | 20 | } 21 | 22 | public static Set primMST(Graph graph) { 23 | PriorityQueue priorityQueue = new PriorityQueue<>( 24 | new EdgeComparator()); 25 | HashSet set = new HashSet<>(); 26 | Set result = new HashSet<>(); 27 | for (Node node : graph.nodes.values()) { 28 | if (!set.contains(node)) { 29 | set.add(node); 30 | for (Edge edge : node.edges) { 31 | priorityQueue.add(edge); 32 | } 33 | while (!priorityQueue.isEmpty()) { 34 | Edge edge = priorityQueue.poll(); 35 | Node toNode = edge.to; 36 | if (!set.contains(toNode)) { 37 | set.add(toNode); 38 | result.add(edge); 39 | for (Edge nextEdge : toNode.edges) { 40 | priorityQueue.add(nextEdge); 41 | } 42 | } 43 | } 44 | } 45 | } 46 | return result; 47 | } 48 | 49 | // 请保证graph是连通图 50 | // graph[i][j]表示点i到点j的距离,如果是系统最大值代表无路 51 | // 返回值是最小连通图的路径之和 52 | public static int prim(int[][] graph) { 53 | int size = graph.length; 54 | int[] distances = new int[size]; 55 | boolean[] visit = new boolean[size]; 56 | visit[0] = true; 57 | for (int i = 0; i < size; i++) { 58 | distances[i] = graph[0][i]; 59 | } 60 | int sum = 0; 61 | for (int i = 1; i < size; i++) { 62 | int minPath = Integer.MAX_VALUE; 63 | int minIndex = -1; 64 | for (int j = 0; j < size; j++) { 65 | if (!visit[j] && distances[j] < minPath) { 66 | minPath = distances[j]; 67 | minIndex = j; 68 | } 69 | } 70 | if (minIndex == -1) { 71 | return sum; 72 | } 73 | visit[minIndex] = true; 74 | sum += minPath; 75 | for (int j = 0; j < size; j++) { 76 | if (!visit[j] && distances[j] > graph[minIndex][j]) { 77 | distances[j] = graph[minIndex][j]; 78 | } 79 | } 80 | } 81 | return sum; 82 | } 83 | 84 | public static void main(String[] args) { 85 | System.out.println("hello world!"); 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /graph/Edge.java: -------------------------------------------------------------------------------- 1 | package graph; 2 | 3 | public class Edge { 4 | public int weight; 5 | public Node from; 6 | public Node to; 7 | 8 | public Edge(int weight, Node from, Node to) { 9 | this.weight = weight; 10 | this.from = from; 11 | this.to = to; 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /graph/Graph.java: -------------------------------------------------------------------------------- 1 | package graph; 2 | 3 | import java.util.HashMap; 4 | import java.util.HashSet; 5 | 6 | public class Graph { 7 | public HashMap nodes; 8 | public HashSet edges; 9 | 10 | public Graph() { 11 | nodes = new HashMap<>(); 12 | edges = new HashSet<>(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /graph/GraphGenerator.java: -------------------------------------------------------------------------------- 1 | package graph; 2 | 3 | public class GraphGenerator { 4 | 5 | public static Graph createGraph(Integer[][] matrix) { 6 | Graph graph = new Graph(); 7 | for (int i = 0; i < matrix.length; i++) { 8 | Integer weight = matrix[i][0]; 9 | Integer from = matrix[i][1]; 10 | Integer to = matrix[i][2]; 11 | if (!graph.nodes.containsKey(from)) { 12 | graph.nodes.put(from, new Node(from)); 13 | } 14 | if (!graph.nodes.containsKey(to)) { 15 | graph.nodes.put(to, new Node(to)); 16 | } 17 | Node fromNode = graph.nodes.get(from); 18 | Node toNode = graph.nodes.get(to); 19 | Edge newEdge = new Edge(weight, fromNode, toNode); 20 | fromNode.nexts.add(toNode); 21 | fromNode.out++; 22 | toNode.in++; 23 | fromNode.edges.add(newEdge); 24 | graph.edges.add(newEdge); 25 | } 26 | return graph; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /graph/Node.java: -------------------------------------------------------------------------------- 1 | package graph; 2 | 3 | import java.util.ArrayList; 4 | 5 | public class Node { 6 | public int value; 7 | public int in; 8 | public int out; 9 | public ArrayList nexts; 10 | public ArrayList edges; 11 | 12 | public Node(int value) { 13 | this.value = value; 14 | in = 0; 15 | out = 0; 16 | nexts = new ArrayList<>(); 17 | edges = new ArrayList<>(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /greed/C02_LowestLexicography.java: -------------------------------------------------------------------------------- 1 | package greed; 2 | 3 | import java.util.Arrays; 4 | 5 | // 例子: 6 | // 给定一个字符串类型的数组strs,找到一种拼接方式,使得把所有字符串拼起来之后形成的 字符串具有最小的字典序。 7 | 8 | // 证明贪心策略可能是件非常腌心的事情。平时当然推荐你搞清楚所有的来龙去脉,但是笔试时用对数器的方式! 9 | public class C02_LowestLexicography { 10 | 11 | // public static class MyComparator implements Comparator { 12 | // @Override 13 | // public int compare(String a, String b) { 14 | // return (a + b).compareTo(b + a); 15 | // } 16 | // } 17 | 18 | // public static String lowestString(String[] strs) { 19 | // if (strs == null || strs.length == 0) { 20 | // return ""; 21 | // } 22 | // Arrays.sort(strs, new MyComparator()); 23 | // String res = ""; 24 | // for (int i = 0; i < strs.length; i++) { 25 | // res += strs[i]; 26 | // } 27 | // return res; 28 | // } 29 | 30 | public static String lowestString(String[] strs) { 31 | if (strs == null || strs.length < 1) { 32 | return ""; 33 | } 34 | Arrays.sort(strs, (String o1, String o2) -> { 35 | return (o1 + o2).compareTo(o2 + o1); 36 | }); 37 | 38 | String res = ""; 39 | for (int i = 0; i < strs.length; i++) { 40 | res += strs[i]; 41 | } 42 | return res; 43 | } 44 | 45 | public static void main(String[] args) { 46 | String[] strs1 = { "jibw", "ji", "jp", "bw", "jibw" }; 47 | System.out.println(lowestString(strs1)); 48 | 49 | String[] strs2 = { "ba", "b" }; 50 | System.out.println(lowestString(strs2)); 51 | 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /greed/C03_LessMoneySplitGold.java: -------------------------------------------------------------------------------- 1 | package greed; 2 | 3 | import java.util.Comparator; 4 | import java.util.PriorityQueue; 5 | 6 | // 一块金条切成两半,是需要花费和长度数值一样的铜板的。比如长度为20的金条,不管切成长度多大的两半,都要花费20个铜板。 7 | // 一群人想整分整块金条,怎么分最省铜板? 例如,给定数组{10,20,30},代表一共三个人,整块金条长度为10+20+30=60。金条要分成10,20,30三个部分。 8 | // 如果先把长度60的金条分成10和50,花费60; 再把长度50的金条分成20和30,花费50;一共花费110铜板。 9 | // 但是如果先把长度60的金条分成30和30,花费60;再把长度30金条分成10和20,花费30;一共花费90铜板。 10 | // 输入一个数组,返回分割的最小代价。 11 | 12 | // TODO: 13 | public class C03_LessMoneySplitGold { 14 | 15 | public static int lessMoney(int[] arr) { 16 | PriorityQueue pQ = new PriorityQueue<>(); 17 | for (int i = 0; i < arr.length; i++) { 18 | pQ.add(arr[i]); 19 | } 20 | int sum = 0; 21 | int cur = 0; 22 | while (pQ.size() > 1) { 23 | cur = pQ.poll() + pQ.poll(); 24 | sum += cur; 25 | pQ.add(cur); 26 | } 27 | return sum; 28 | } 29 | 30 | public static class MinheapComparator implements Comparator { 31 | 32 | @Override 33 | public int compare(Integer o1, Integer o2) { 34 | return o1 - o2; // < 0 o1 < o2 负数 35 | } 36 | 37 | } 38 | 39 | public static class MaxheapComparator implements Comparator { 40 | 41 | @Override 42 | public int compare(Integer o1, Integer o2) { 43 | return o2 - o1; // < o2 < o1 44 | } 45 | 46 | } 47 | 48 | public static void main(String[] args) { 49 | // solution 50 | int[] arr = { 6, 7, 8, 9 }; 51 | System.out.println(lessMoney(arr)); 52 | 53 | int[] arrForHeap = { 3, 5, 2, 7, 0, 1, 6, 4 }; 54 | 55 | // min heap 56 | PriorityQueue minQ1 = new PriorityQueue<>(); 57 | for (int i = 0; i < arrForHeap.length; i++) { 58 | minQ1.add(arrForHeap[i]); 59 | } 60 | while (!minQ1.isEmpty()) { 61 | System.out.print(minQ1.poll() + " "); 62 | } 63 | System.out.println(); 64 | 65 | // min heap use Comparator 66 | PriorityQueue minQ2 = new PriorityQueue<>(new MinheapComparator()); 67 | for (int i = 0; i < arrForHeap.length; i++) { 68 | minQ2.add(arrForHeap[i]); 69 | } 70 | while (!minQ2.isEmpty()) { 71 | System.out.print(minQ2.poll() + " "); 72 | } 73 | System.out.println(); 74 | 75 | // max heap use Comparator 76 | PriorityQueue maxQ = new PriorityQueue<>(new MaxheapComparator()); 77 | for (int i = 0; i < arrForHeap.length; i++) { 78 | maxQ.add(arrForHeap[i]); 79 | } 80 | while (!maxQ.isEmpty()) { 81 | System.out.print(maxQ.poll() + " "); 82 | } 83 | 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /greed/C04_BestArrange.java: -------------------------------------------------------------------------------- 1 | package greed; 2 | 3 | import java.util.Arrays; 4 | import java.util.Comparator; 5 | 6 | // 一些项目要占用一个会议室宣讲,会议室不能同时容纳两个项目的宣讲。 7 | // 给你每一个项目开始的时间和结束的时间(给你一个数组,里面是一个个具体的项目),你来安排宣讲的日程,要求会议室进行的宣讲的场次最多。 8 | // 返回这个最多的宣讲场次。 9 | 10 | public class C04_BestArrange { 11 | 12 | public static class Program { 13 | public int start; 14 | public int end; 15 | 16 | public Program(int start, int end) { 17 | this.start = start; 18 | this.end = end; 19 | } 20 | } 21 | 22 | public static class ProgramComparator implements Comparator { 23 | 24 | @Override 25 | public int compare(Program o1, Program o2) { 26 | return o1.end - o2.end; 27 | } 28 | 29 | } 30 | 31 | public static int bestArrange(Program[] programs, int start) { 32 | Arrays.sort(programs, new ProgramComparator()); 33 | int result = 0; 34 | for (int i = 0; i < programs.length; i++) { 35 | if (start <= programs[i].start) { 36 | result++; 37 | start = programs[i].end; 38 | } 39 | } 40 | return result; 41 | } 42 | 43 | public static int bestArrange2(Program[] programs, int start) { 44 | if (programs == null || programs.length == 0) { 45 | return 0; 46 | } 47 | Arrays.sort(programs, new ProgramComparator()); 48 | 49 | int res = 0; 50 | for (int i = 0; i < programs.length; i++) { 51 | if (programs[i].end > start) { 52 | res++; 53 | start = programs[i].end; 54 | } 55 | } 56 | return res; 57 | } 58 | 59 | public static void main(String[] args) { 60 | 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /greed/C05_IPO.java: -------------------------------------------------------------------------------- 1 | package greed; 2 | 3 | import java.util.PriorityQueue; 4 | 5 | // 输入: 6 | // 正数数组costs,正数数组profits,正数k,正数m 7 | // 含义: 8 | // costs[i]表示i号项目的花费,profits[i]表示i号项目在扣除花费之后还能挣到的钱(利润),k表示你只能串行的最多做k个项目,m表示你初始的资金 9 | // 说明: 你每做完一个项目,马上获得的收益,可以支持你去做下一个项目。 10 | // 输出:你最后获得的最大钱数。 11 | public class C05_IPO { 12 | public static class Node { 13 | public int p; 14 | public int c; 15 | 16 | public Node(int p, int c) { 17 | this.p = p; 18 | this.c = c; 19 | } 20 | } 21 | 22 | // public static class MinCostComparator implements Comparator { 23 | 24 | // @Override 25 | // public int compare(Node o1, Node o2) { 26 | // return o1.c - o2.c; 27 | // } 28 | 29 | // } 30 | 31 | // public static class MaxProfitComparator implements Comparator { 32 | 33 | // @Override 34 | // public int compare(Node o1, Node o2) { 35 | // return o2.p - o1.p; 36 | // } 37 | 38 | // } 39 | 40 | // public static int findMaximizedCapital(int k, int W, int[] Profits, int[] 41 | // Capital) { 42 | // Node[] nodes = new Node[Profits.length]; 43 | // for (int i = 0; i < Profits.length; i++) { 44 | // nodes[i] = new Node(Profits[i], Capital[i]); 45 | // } 46 | 47 | // PriorityQueue minCostQ = new PriorityQueue<>(new MinCostComparator()); 48 | // PriorityQueue maxProfitQ = new PriorityQueue<>(new 49 | // MaxProfitComparator()); 50 | // for (int i = 0; i < nodes.length; i++) { 51 | // minCostQ.add(nodes[i]); 52 | // } 53 | // for (int i = 0; i < k; i++) { 54 | // while (!minCostQ.isEmpty() && minCostQ.peek().c <= W) { 55 | // maxProfitQ.add(minCostQ.poll()); 56 | // } 57 | // if (maxProfitQ.isEmpty()) { 58 | // return W; 59 | // } 60 | // W += maxProfitQ.poll().p; 61 | // } 62 | // return W; 63 | // } 64 | 65 | public static int getMaximizedCapital(int[] costs, int[] profits, int k, int m) { 66 | Node[] projects = new Node[profits.length]; 67 | for (int i = 0; i < profits.length; i++) { 68 | projects[i] = new Node(profits[i], costs[i]); 69 | } 70 | 71 | PriorityQueue minCostQueue = new PriorityQueue<>((Node node1, Node node2) -> { 72 | return node1.c - node2.c; 73 | }); 74 | PriorityQueue validProjectQueue = new PriorityQueue<>((Node node1, Node node2) -> { 75 | return node2.p - node1.p; 76 | }); 77 | for (int i = 0; i < projects.length; i++) { 78 | minCostQueue.add(projects[i]); 79 | } 80 | 81 | for (int i = 0; i < k; i++) { 82 | while (m >= minCostQueue.peek().c) { 83 | validProjectQueue.add(minCostQueue.poll()); 84 | } 85 | if (validProjectQueue.isEmpty()) { 86 | return m; 87 | } 88 | m += validProjectQueue.poll().p; 89 | } 90 | return m; 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /hash_function/C01_HashMap.java: -------------------------------------------------------------------------------- 1 | package hash_function; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map.Entry; 7 | 8 | public class C01_HashMap { 9 | 10 | public static void main(String[] args) { 11 | HashMap map = new HashMap<>(); 12 | map.put("zuo", "31"); 13 | 14 | System.out.println(map.containsKey("zuo")); 15 | System.out.println(map.containsKey("chengyun")); 16 | System.out.println("========================="); 17 | 18 | System.out.println(map.get("zuo")); 19 | System.out.println(map.get("chengyun")); 20 | System.out.println("========================="); 21 | 22 | System.out.println(map.isEmpty()); 23 | System.out.println(map.size()); 24 | System.out.println("========================="); 25 | 26 | System.out.println(map.remove("zuo")); 27 | System.out.println(map.containsKey("zuo")); 28 | System.out.println(map.get("zuo")); 29 | System.out.println(map.isEmpty()); 30 | System.out.println(map.size()); 31 | System.out.println("========================="); 32 | 33 | map.put("zuo", "31"); 34 | System.out.println(map.get("zuo")); 35 | map.put("zuo", "32"); 36 | System.out.println(map.get("zuo")); 37 | System.out.println("========================="); 38 | 39 | map.put("zuo", "31"); 40 | map.put("cheng", "32"); 41 | map.put("yun", "33"); 42 | 43 | for (String key : map.keySet()) { 44 | System.out.println(key); 45 | } 46 | System.out.println("========================="); 47 | 48 | for (String values : map.values()) { 49 | System.out.println(values); 50 | } 51 | System.out.println("========================="); 52 | 53 | map.clear(); 54 | map.put("A", "1"); 55 | map.put("B", "2"); 56 | map.put("C", "3"); 57 | map.put("D", "1"); 58 | map.put("E", "2"); 59 | map.put("F", "3"); 60 | map.put("G", "1"); 61 | map.put("H", "2"); 62 | map.put("I", "3"); 63 | for (Entry entry : map.entrySet()) { 64 | String key = entry.getKey(); 65 | String value = entry.getValue(); 66 | System.out.println(key + "," + value); 67 | } 68 | System.out.println("========================="); 69 | 70 | // you can not remove item in map when you use the iterator of map 71 | // for(Entry entry : map.entrySet()){ 72 | // if(!entry.getValue().equals("1")){ 73 | // map.remove(entry.getKey()); 74 | // } 75 | // } 76 | 77 | // if you want to remove items, collect them first, then remove them by 78 | // this way. 79 | List removeKeys = new ArrayList(); 80 | for (Entry entry : map.entrySet()) { 81 | if (!entry.getValue().equals("1")) { 82 | removeKeys.add(entry.getKey()); 83 | } 84 | } 85 | for (String removeKey : removeKeys) { 86 | map.remove(removeKey); 87 | } 88 | for (Entry entry : map.entrySet()) { 89 | String key = entry.getKey(); 90 | String value = entry.getValue(); 91 | System.out.println(key + "," + value); 92 | } 93 | System.out.println("========================="); 94 | 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /hash_function/C02_RandomPool.java: -------------------------------------------------------------------------------- 1 | package hash_function; 2 | 3 | import java.util.HashMap; 4 | 5 | // 设计RandomPool结构 6 | // 【题目】 7 | // 设计一种结构,在该结构中有如下三个功能: 8 | // insert(key):将某个key加入到该结构,做到不重复加入 9 | // delete(key):将原本在结构中的某个key移除 10 | // getRandom(): 等概率随机返回结构中的任何一个key。 11 | // 【要求】 Insert、delete和getRandom方法的时间复杂度都是O(1) 12 | public class C02_RandomPool { 13 | 14 | // public static class Pool { 15 | // private HashMap keyIndexMap; 16 | // private HashMap indexKeyMap; 17 | // private int size; 18 | 19 | // public Pool() { 20 | // this.keyIndexMap = new HashMap(); 21 | // this.indexKeyMap = new HashMap(); 22 | // this.size = 0; 23 | // } 24 | 25 | // public void insert(K key) { 26 | // if (!this.keyIndexMap.containsKey(key)) { 27 | // this.keyIndexMap.put(key, this.size); 28 | // this.indexKeyMap.put(this.size++, key); 29 | // } 30 | // } 31 | 32 | // public void delete(K key) { 33 | // if (this.keyIndexMap.containsKey(key)) { 34 | // int deleteIndex = this.keyIndexMap.get(key); 35 | // int lastIndex = --this.size; 36 | // K lastKey = this.indexKeyMap.get(lastIndex); 37 | // this.keyIndexMap.put(lastKey, deleteIndex); 38 | // this.indexKeyMap.put(deleteIndex, lastKey); 39 | // this.keyIndexMap.remove(key); 40 | // this.indexKeyMap.remove(lastIndex); 41 | // } 42 | // } 43 | 44 | // public K getRandom() { 45 | // if (this.size == 0) { 46 | // return null; 47 | // } 48 | // int randomIndex = (int) (Math.random() * this.size); // 0 ~ size -1 49 | // return this.indexKeyMap.get(randomIndex); 50 | // } 51 | 52 | // } 53 | 54 | public static class Pool { 55 | private HashMap indexMap = new HashMap<>(); 56 | private HashMap valueMap = new HashMap<>(); 57 | 58 | public void insert(T key) { 59 | if (!valueMap.containsKey(key)) { 60 | indexMap.put(indexMap.size(), key); 61 | valueMap.put(key, valueMap.size()); 62 | } 63 | } 64 | 65 | public void delete(T key) { 66 | if (!valueMap.containsKey(key)) { 67 | return; 68 | } 69 | int index = valueMap.get(key); 70 | T element = indexMap.get(indexMap.size() - 1); 71 | indexMap.put(index, element); 72 | indexMap.remove(indexMap.size() - 1); 73 | valueMap.put(element, index); 74 | valueMap.remove(key); 75 | } 76 | 77 | public T getRandom() { 78 | return indexMap.get((int) Math.random() * indexMap.size()); 79 | } 80 | } 81 | 82 | public static void main(String[] args) { 83 | Pool pool = new Pool(); 84 | pool.insert("zuo"); 85 | pool.insert("cheng"); 86 | pool.insert("yun"); 87 | System.out.println(pool.getRandom()); 88 | System.out.println(pool.getRandom()); 89 | System.out.println(pool.getRandom()); 90 | System.out.println(pool.getRandom()); 91 | System.out.println(pool.getRandom()); 92 | System.out.println(pool.getRandom()); 93 | 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /hash_function/C03_Islands.java: -------------------------------------------------------------------------------- 1 | package hash_function; 2 | 3 | // 岛问题 4 | // 【题目】 5 | // 一个矩阵中只有0和1两种值,每个位置都可以和自己的上、下、左、右 四个位置相连,如 果有一片1连在一起,这个部分叫做一个岛,求一个矩阵中有多少个岛? 6 | // 【举例】 7 | // 001010 8 | // 111010 9 | // 100100 10 | // 000000 11 | // 这个矩阵中有三个岛 12 | // 【进阶】 13 | // 如何设计一个并行算法解决这个问题 14 | public class C03_Islands { 15 | 16 | // public static int countIslands(int[][] m) { 17 | // if (m == null || m[0] == null) { 18 | // return 0; 19 | // } 20 | // int N = m.length; 21 | // int M = m[0].length; 22 | // int res = 0; 23 | // for (int i = 0; i < N; i++) { 24 | // for (int j = 0; j < M; j++) { 25 | // if (m[i][j] == 1) { 26 | // res++; 27 | // infect(m, i, j, N, M); 28 | // } 29 | // } 30 | // } 31 | // return res; 32 | // } 33 | 34 | // public static void infect(int[][] m, int i, int j, int N, int M) { 35 | // if (i < 0 || i >= N || j < 0 || j >= M || m[i][j] != 1) { 36 | // return; 37 | // } 38 | // m[i][j] = 2; 39 | // infect(m, i + 1, j, N, M); 40 | // infect(m, i - 1, j, N, M); 41 | // infect(m, i, j + 1, N, M); 42 | // infect(m, i, j - 1, N, M); 43 | // } 44 | 45 | public static int countIslands(int[][] arr) { 46 | int count = 0; 47 | 48 | for (int col = 0; col < arr.length; col++) { 49 | for (int row = 0; row < arr[col].length; row++) { 50 | if (arr[col][row] == 1) { 51 | infect(arr, row, col); 52 | count++; 53 | } 54 | } 55 | } 56 | return count; 57 | } 58 | 59 | private static void infect(int[][] arr, int row, int col) { 60 | if ((col < 0 || col >= arr.length) || (row < 0 || row >= arr[col].length) || arr[col][row] != 1) { 61 | return; 62 | } 63 | arr[col][row] = 2; 64 | infect(arr, row, col - 1); 65 | infect(arr, row, col + 1); 66 | infect(arr, row - 1, col); 67 | infect(arr, row + 1, col); 68 | } 69 | 70 | public static void main(String[] args) { 71 | int[][] m1 = { { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 1, 1, 0, 1, 1, 1, 0 }, { 0, 1, 1, 1, 0, 0, 0, 1, 0 }, 72 | { 0, 1, 1, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 1, 1, 0, 0 }, { 0, 0, 0, 0, 1, 1, 1, 0, 0 }, 73 | { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, }; 74 | System.out.println(countIslands(m1)); 75 | 76 | int[][] m2 = { { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 1, 1, 1, 1, 1, 1, 0 }, { 0, 1, 1, 1, 0, 0, 0, 1, 0 }, 77 | { 0, 1, 1, 0, 0, 0, 1, 1, 0 }, { 0, 0, 0, 0, 0, 1, 1, 0, 0 }, { 0, 0, 0, 0, 1, 1, 1, 0, 0 }, 78 | { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, }; 79 | System.out.println(countIslands(m2)); 80 | 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /hash_function/C05_KMP.java: -------------------------------------------------------------------------------- 1 | package hash_function; 2 | 3 | // KMP算法解决的问题 4 | // 字符串str1和str2,str1是否包含str2,如果包含返回str2在str1中开始的位置。 如何做到时间复杂度O(N)完成? 5 | public class C05_KMP { 6 | 7 | public static int getIndexOf(String s, String m) { 8 | if (s == null || m == null || m.length() < 1 || s.length() < m.length()) { 9 | return -1; 10 | } 11 | char[] str1 = s.toCharArray(); 12 | char[] str2 = m.toCharArray(); 13 | int i1 = 0; 14 | int i2 = 0; 15 | int[] next = getNextArray(str2); 16 | while (i1 < str1.length && i2 < str2.length) { 17 | if (str1[i1] == str2[i2]) { 18 | i1++; 19 | i2++; 20 | } else if (next[i2] == -1) { 21 | i1++; 22 | } else { 23 | i2 = next[i2]; 24 | } 25 | } 26 | return i2 == str2.length ? i1 - i2 : -1; 27 | } 28 | 29 | // public static int[] getNextArray(char[] ms) { 30 | // if (ms.length == 1) { 31 | // return new int[] { -1 }; 32 | // } 33 | // int[] next = new int[ms.length]; 34 | // next[0] = -1; 35 | // next[1] = 0; 36 | // int i = 2; 37 | // int cn = 0; 38 | // while (i < next.length) { 39 | // if (ms[i - 1] == ms[cn]) { 40 | // next[i++] = ++cn; 41 | // } else if (cn > 0) { 42 | // cn = next[cn]; 43 | // } else { 44 | // next[i++] = 0; 45 | // } 46 | // } 47 | // return next; 48 | // } 49 | 50 | public static int KMP(String s1, String s2) { 51 | if (s1 == null || s2 == null || s2.length() < 1 || s1.length() < s2.length()) { 52 | return -1; 53 | } 54 | 55 | char[] c1 = s1.toCharArray(); 56 | char[] c2 = s2.toCharArray(); 57 | int[] next = getNextArray(c2); 58 | 59 | int i1 = 0, i2 = 0; 60 | while (i1 < c1.length && i2 < c2.length) { 61 | if (c1[i1] == c2[i2]) { 62 | i1++; 63 | i2++; 64 | } else { 65 | if (i2 == 0) { 66 | i1++; 67 | } else { 68 | i2 = next[i2]; 69 | } 70 | } 71 | } 72 | return i2 == c2.length ? i1 - i2 : -1; 73 | } 74 | 75 | private static int[] getNextArray(char[] list) { 76 | int[] arr = new int[list.length]; 77 | arr[0] = -1; 78 | arr[1] = 0; 79 | for (int i = 2; i < arr.length; i++) { 80 | if (list[i - 1] == list[arr[i - 1]]) { 81 | arr[i] = arr[i - 1] + 1; 82 | } else { 83 | int j = arr[i - 1]; 84 | while (j != 0 && list[i - 1] != list[j]) { 85 | j = arr[j]; 86 | } 87 | if (list[i - 1] != list[j]) { 88 | arr[i] = 0; 89 | } else { 90 | arr[i] = arr[j] + 1; 91 | } 92 | } 93 | } 94 | return arr; 95 | } 96 | 97 | public static void main(String[] args) { 98 | String str = "abcabcaababaccc"; 99 | String match = "ababa"; 100 | System.out.println(getIndexOf(str, match)); 101 | System.out.println("-----------------"); 102 | System.out.println(KMP(str, match)); 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /hash_function/C07_SlidingWindowMaxArray.java: -------------------------------------------------------------------------------- 1 | package hash_function; 2 | 3 | import java.util.LinkedList; 4 | 5 | // NOTE:滑动窗口 6 | 7 | // 由一个代表题目,引出一种结构 8 | // 【题目】 9 | // 有一个整型数组arr和一个大小为w的窗口从数组的最左边滑到最右边,窗口每次 向右边滑 一个位置。 10 | // 例如,数组为[4,3,5,4,3,3,6,7],窗口大小为3时: 11 | // [4 3 5]4 3 3 6 7 12 | // 4[3 5 4]3 3 6 7 13 | // 4 3[5 4 3]3 6 7 14 | // 4 3 5[4 3 3]6 7 15 | // 4 3 5 4[3 3 6]7 16 | // 4 3 5 4 3[3 6 7] 17 | // 窗口中最大值为5 窗口中最大值为5 窗口中最大值为5 窗口中最大值为4 窗口中最大值为6 窗口中最大值为7 18 | // 如果数组长度为n,窗口大小为w,则一共产生n-w+1个窗口的最大值。 19 | // 请实现一个函数。 输入:整型数组arr,窗口大小为w。 输出:一个长度为n-w+1的数组res,res[i]表示每一种窗口状态下的 以本题为例,结果应该 返回{5,5,5,4,6,7}。 20 | public class C07_SlidingWindowMaxArray { 21 | 22 | // public static int[] getMaxWindow(int[] arr, int w) { 23 | // if (arr == null || w < 1 || arr.length < w) { 24 | // return null; 25 | // } 26 | // LinkedList qmax = new LinkedList(); 27 | // int[] res = new int[arr.length - w + 1]; 28 | // int index = 0; 29 | // for (int i = 0; i < arr.length; i++) { 30 | // while (!qmax.isEmpty() && arr[qmax.peekLast()] <= arr[i]) { 31 | // qmax.pollLast(); 32 | // } 33 | // qmax.addLast(i); 34 | // if (qmax.peekFirst() == i - w) { 35 | // qmax.pollFirst(); 36 | // } 37 | // if (i >= w - 1) { 38 | // res[index++] = arr[qmax.peekFirst()]; 39 | // } 40 | // } 41 | // return res; 42 | // } 43 | 44 | public static int[] getMaxWindow(int[] arr, int w) { 45 | if (arr == null || w <= 0 || arr.length < w) { 46 | return null; 47 | } 48 | 49 | LinkedList queue = new LinkedList<>(); // 存储索引 50 | int[] res = new int[arr.length + 1 - w]; 51 | 52 | queue.addLast(0); 53 | int index = 1; 54 | while (index < w) { // 0 ~ w - 1 55 | if (queue.isEmpty() || arr[queue.peekLast()] > arr[index]) { 56 | queue.addLast(index++); 57 | // index++; 58 | } else if (arr[queue.peekLast()] <= arr[index]) { 59 | queue.pollLast(); 60 | } 61 | } 62 | res[0] = arr[queue.peek()]; 63 | // System.out.println(queue); 64 | 65 | for (int i = 1; i < res.length; i++) { 66 | // System.out.println(queue); 67 | // 从arr[w]开始 68 | while (!queue.isEmpty() && arr[queue.peekLast()] <= arr[i - 1 + w]) { 69 | queue.pollLast(); 70 | } 71 | queue.addLast(i - 1 + w); 72 | 73 | if (queue.peekFirst() == i - 1) { 74 | queue.pollFirst(); 75 | } 76 | 77 | res[i] = arr[queue.peek()]; 78 | } 79 | return res; 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 = { 4, 3, 5, 4, 3, 3, 6, 7 }; 92 | int w = 3; 93 | printArray(getMaxWindow(arr, w)); 94 | 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /hash_function/C09_AllTimesMinToMax.java: -------------------------------------------------------------------------------- 1 | package hash_function; 2 | 3 | import java.util.Stack; 4 | 5 | // 单调栈结构的原理和实现 6 | // 在数组中想找到一个数,左边和右边比这个数小、且离这个数最近的位置。 7 | // 如果对每一个数都想求这样的信息,能不能整体代价达到O(N)?需要使用到单调栈结构 8 | public class C09_AllTimesMinToMax { 9 | 10 | public static int max1(int[] arr) { 11 | int max = Integer.MIN_VALUE; 12 | for (int i = 0; i < arr.length; i++) { 13 | for (int j = i; j < arr.length; j++) { 14 | int minNum = Integer.MAX_VALUE; 15 | int sum = 0; 16 | for (int k = i; k <= j; k++) { 17 | sum += arr[k]; 18 | minNum = Math.min(minNum, arr[k]); 19 | } 20 | max = Math.max(max, minNum * sum); 21 | } 22 | } 23 | return max; 24 | } 25 | 26 | public static int max2(int[] arr) { 27 | int size = arr.length; 28 | int[] sums = new int[size]; 29 | sums[0] = arr[0]; 30 | for (int i = 1; i < size; i++) { 31 | sums[i] = sums[i - 1] + arr[i]; 32 | } 33 | int max = Integer.MIN_VALUE; 34 | Stack stack = new Stack(); 35 | for (int i = 0; i < size; i++) { 36 | while (!stack.isEmpty() && arr[stack.peek()] >= arr[i]) { 37 | int j = stack.pop(); 38 | max = Math.max(max, (stack.isEmpty() ? sums[i - 1] : (sums[i - 1] - sums[stack.peek()])) * arr[j]); 39 | } 40 | stack.push(i); 41 | } 42 | while (!stack.isEmpty()) { 43 | int j = stack.pop(); 44 | max = Math.max(max, (stack.isEmpty() ? sums[size - 1] : (sums[size - 1] - sums[stack.peek()])) * arr[j]); 45 | } 46 | return max; 47 | } 48 | 49 | public static int[] gerenareRondomArray() { 50 | int[] arr = new int[(int) (Math.random() * 20) + 10]; 51 | for (int i = 0; i < arr.length; i++) { 52 | arr[i] = (int) (Math.random() * 101); 53 | } 54 | return arr; 55 | } 56 | 57 | public static void main(String[] args) { 58 | int testTimes = 2000000; 59 | for (int i = 0; i < testTimes; i++) { 60 | int[] arr = gerenareRondomArray(); 61 | if (max1(arr) != max2(arr)) { 62 | System.out.println("FUCK!"); 63 | break; 64 | } 65 | } 66 | 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /hash_function/C10_MaxTarget.java: -------------------------------------------------------------------------------- 1 | package hash_function; 2 | 3 | // 定义:数组中累积和与最小值的乘积,假设叫做指标A。 给定一个数组,请返回子数组中,指标A最大的值。 4 | public class C10_MaxTarget { 5 | 6 | 7 | } 8 | -------------------------------------------------------------------------------- /leetcode/306.java: -------------------------------------------------------------------------------- 1 | package leetcode; 2 | 3 | class Solution306 { 4 | public boolean isAdditiveNumber(String num) { 5 | // 至少三个数 6 | if (num.length() < 3) { 7 | return false; 8 | } 9 | 10 | String left; 11 | String right; 12 | 13 | for (int i = 0; i < num.length() / 2; i++) { 14 | left = num.substring(0, i + 1); 15 | if (left.charAt(0) == '0' && left.length() > 1) { 16 | break; 17 | } 18 | for (int j = i + 1; j < num.length() - 1; j++) { 19 | if (i + 1 > num.length() - j - 1 || j - i > num.length() - j - 1) { 20 | break; 21 | } 22 | right = num.substring(i + 1, j + 1); 23 | if (right.charAt(0) == '0' && right.length() > 1) { 24 | break; 25 | } 26 | if (innerIsAdditive(left, right, num.substring(j + 1))) { 27 | return true; 28 | } 29 | } 30 | } 31 | 32 | return false; 33 | } 34 | 35 | private boolean innerIsAdditive(String pre, String cur, String last) { 36 | while (last.length() != 0) { 37 | String tem = addStrings(pre, cur); 38 | if (!last.startsWith(tem)) { 39 | return false; 40 | } 41 | pre = cur; 42 | cur = tem; 43 | last = last.substring(tem.length()); 44 | } 45 | 46 | return true; 47 | } 48 | 49 | private String addStrings(String a, String b) { 50 | 51 | if (a.length() > b.length()) { 52 | b = "0".repeat(a.length() - b.length()) + b; 53 | } else { 54 | a = "0".repeat(b.length() - a.length()) + a; 55 | } 56 | 57 | char[] arr = new char[a.length()]; 58 | boolean isAdd = false; 59 | 60 | for (int i = arr.length - 1; i >= 0; i--) { 61 | int cha = a.charAt(i) - '0' + b.charAt(i) - '0' + (isAdd ? 1 : 0); 62 | isAdd = cha > 9 ? true : false; 63 | arr[i] = (char) ((cha % 10) + '0'); 64 | } 65 | return isAdd ? "1" + String.valueOf(arr) : String.valueOf(arr); 66 | } 67 | 68 | } -------------------------------------------------------------------------------- /leetcode/43.java: -------------------------------------------------------------------------------- 1 | package leetcode; 2 | 3 | class Solution43 { 4 | public String multiply(String num1, String num2) { 5 | boolean isZero = true; 6 | for (int i = 0; i < num1.length(); i++) { 7 | if (num1.charAt(i) != '0') { 8 | isZero = false; 9 | } 10 | } 11 | if (isZero) { 12 | return "0"; 13 | } 14 | isZero = true; 15 | for (int i = 0; i < num2.length(); i++) { 16 | if (num2.charAt(i) != '0') { 17 | isZero = false; 18 | } 19 | } 20 | if (isZero) { 21 | return "0"; 22 | } 23 | 24 | String res = "0"; 25 | for (int i = num2.length() - 1; i >= 0; i--) { 26 | String cur = mutStrings(num1, num2.charAt(i) - '0') + "0".repeat(num2.length() - i - 1); 27 | res = addStrings(res, cur); 28 | } 29 | 30 | return res; 31 | } 32 | 33 | public String mutStrings(String a, int b) { 34 | if (b == 0) { 35 | return "0"; 36 | } 37 | 38 | char[] arr = new char[a.length()]; 39 | int extra = 0; 40 | 41 | for (int i = arr.length - 1; i >= 0; i--) { 42 | int cha = (a.charAt(i) - '0') * b + extra; 43 | extra = cha / 10; 44 | arr[i] = (char) ((cha % 10) + '0'); 45 | } 46 | 47 | return (extra > 0 ? extra : "") + String.valueOf(arr); 48 | } 49 | 50 | public String addStrings(String a, String b) { 51 | 52 | if (a.length() > b.length()) { 53 | b = "0".repeat(a.length() - b.length()) + b; 54 | } else { 55 | a = "0".repeat(b.length() - a.length()) + a; 56 | } 57 | 58 | char[] arr = new char[a.length()]; 59 | boolean isAdd = false; 60 | 61 | for (int i = arr.length - 1; i >= 0; i--) { 62 | int cha = a.charAt(i) - '0' + b.charAt(i) - '0' + (isAdd ? 1 : 0); 63 | isAdd = cha > 9 ? true : false; 64 | arr[i] = (char) ((cha % 10) + '0'); 65 | } 66 | 67 | return isAdd ? "1" + String.valueOf(arr) : String.valueOf(arr); 68 | } 69 | 70 | public static void main(String[] args) { 71 | System.out.println(new Solution43().multiply("0", "52")); 72 | } 73 | } -------------------------------------------------------------------------------- /leetcode/521.java: -------------------------------------------------------------------------------- 1 | package leetcode; 2 | 3 | // 521 4 | class Solution521 { 5 | public int findLUSlength(String a, String b) { 6 | if (a.length() != b.length()) { 7 | return Math.max(a.length(), b.length()); 8 | } 9 | return a.equals(b) ? -1 : a.length(); 10 | } 11 | 12 | public static void main(String[] args) { 13 | System.out.println(new Solution521().findLUSlength("aba", "cdc")); 14 | } 15 | } -------------------------------------------------------------------------------- /leetcode/Solution150.java: -------------------------------------------------------------------------------- 1 | package leetcode; 2 | 3 | import java.util.Stack; 4 | 5 | class Solution150 { 6 | public int evalRPN(String[] tokens) { 7 | Stack stack = new Stack<>(); 8 | for (int i = 0; i < tokens.length; i++) { 9 | if (tokens[i].equals("+")) { 10 | stack.push(stack.pop() + stack.pop()); 11 | } else if (tokens[i].equals("-")) { 12 | Integer mul = stack.pop(); 13 | Integer muled = stack.pop(); 14 | stack.push(muled - mul); 15 | } else if (tokens[i].equals("*")) { 16 | stack.push(stack.pop() * stack.pop()); 17 | } else if (tokens[i].equals("/")) { 18 | Integer div = stack.pop(); 19 | Integer divided = stack.pop(); 20 | stack.push(divided / div); 21 | } else { 22 | stack.push(Integer.parseInt(tokens[i])); 23 | } 24 | } 25 | 26 | return stack.pop(); 27 | } 28 | 29 | public static void main(String[] args) { 30 | System.out.println(new Solution150().evalRPN(new String[] { "2", "1", "+", "3", "*" })); 31 | System.out.println(new Solution150().evalRPN(new String[] { "4", "13", "5", "/", "+" })); 32 | // System.out.println("22\n\t2123".matches(".*?\n\t[^\t].*?")); 33 | } 34 | } 35 | // dir 36 | // subdir1 37 | // tsubdir2 38 | // file.ext -------------------------------------------------------------------------------- /leetcode/Solution19.java: -------------------------------------------------------------------------------- 1 | package leetcode; 2 | 3 | import java.io.IOException; 4 | 5 | /* ----------------------------------- 6 | * WARNING: 7 | * ----------------------------------- 8 | * Your code may fail to compile 9 | * because it contains public class 10 | * declarations. 11 | * To fix this, please remove the 12 | * "public" keyword from your class 13 | * declarations. 14 | */ 15 | 16 | /** 17 | * Definition for singly-linked list. 18 | * public class ListNode { 19 | * int val; 20 | * ListNode next; 21 | * ListNode() {} 22 | * ListNode(int val) { this.val = val; } 23 | * ListNode(int val, ListNode next) { this.val = val; this.next = next; } 24 | * } 25 | */ 26 | class Solution19 { 27 | public ListNode removeNthFromEnd(ListNode head, int n) { 28 | ListNode[] arr = new ListNode[n + 1]; 29 | int p = 0; 30 | 31 | ListNode guide = new ListNode(); 32 | guide.next = head; 33 | 34 | ListNode node = guide; 35 | while (node != null) { 36 | arr[p] = node; 37 | p = (p == arr.length - 1) ? 0 : (p + 1); 38 | 39 | node = node.next; 40 | } 41 | 42 | if (arr[p].next == null) { 43 | return null; 44 | } 45 | 46 | arr[p].next = arr[p].next.next; 47 | 48 | return guide.next; 49 | } 50 | } 51 | 52 | class MainClass { 53 | public static int[] stringToIntegerArray(String input) { 54 | input = input.trim(); 55 | input = input.substring(1, input.length() - 1); 56 | if (input.length() == 0) { 57 | return new int[0]; 58 | } 59 | 60 | String[] parts = input.split(","); 61 | int[] output = new int[parts.length]; 62 | for (int index = 0; index < parts.length; index++) { 63 | String part = parts[index].trim(); 64 | output[index] = Integer.parseInt(part); 65 | } 66 | return output; 67 | } 68 | 69 | public static ListNode stringToListNode(String input) { 70 | // Generate array from the input 71 | int[] nodeValues = stringToIntegerArray(input); 72 | 73 | // Now convert that list into linked list 74 | ListNode dummyRoot = new ListNode(0); 75 | ListNode ptr = dummyRoot; 76 | for (int item : nodeValues) { 77 | ptr.next = new ListNode(item); 78 | ptr = ptr.next; 79 | } 80 | return dummyRoot.next; 81 | } 82 | 83 | public static String listNodeToString(ListNode node) { 84 | if (node == null) { 85 | return "[]"; 86 | } 87 | 88 | String result = ""; 89 | while (node != null) { 90 | result += Integer.toString(node.val) + ", "; 91 | node = node.next; 92 | } 93 | return "[" + result.substring(0, result.length() - 2) + "]"; 94 | } 95 | 96 | public static void main(String[] args) throws IOException { 97 | ListNode head = stringToListNode("[1,2]"); 98 | int n = Integer.parseInt("1"); 99 | // ListNode head = stringToListNode("[1,2,3,4,5]"); 100 | // int n = Integer.parseInt("2"); 101 | 102 | ListNode ret = new Solution19().removeNthFromEnd(head, n); 103 | 104 | String out = listNodeToString(ret); 105 | 106 | System.out.print(out); 107 | } 108 | } -------------------------------------------------------------------------------- /leetcode/Solution224.java: -------------------------------------------------------------------------------- 1 | package leetcode; 2 | 3 | import java.util.LinkedList; 4 | 5 | // 减法不满足结合律 6 | class Solution224 { 7 | public int calculate(String s) { 8 | char[] arr = s.toCharArray(); 9 | 10 | return process(arr, 0)[0]; 11 | } 12 | 13 | private int[] process(char[] arr, int i) { 14 | LinkedList stack = new LinkedList<>(); 15 | int num = 0; 16 | char preAction = '+'; 17 | 18 | while (true) { 19 | if (i == arr.length || arr[i] == ')') { 20 | 21 | switch (preAction) { 22 | case '+': 23 | stack.addLast(num); 24 | break; 25 | case '-': 26 | stack.addLast(-num); 27 | break; 28 | case '/': 29 | stack.addLast(stack.removeLast() / num); 30 | break; 31 | case '*': 32 | stack.addLast(stack.removeLast() * num); 33 | break; 34 | } 35 | 36 | // stack.addLast(num); 37 | break; 38 | } else if (arr[i] == ' ') { 39 | } else if (Character.isDigit(arr[i])) { 40 | num = num * 10 + arr[i] - '0'; 41 | } else if (arr[i] == '(') { 42 | int[] next = process(arr, i + 1); 43 | num = next[0]; 44 | i = next[1] - 1; 45 | } else { 46 | switch (preAction) { 47 | case '+': 48 | stack.addLast(num); 49 | break; 50 | case '-': 51 | stack.addLast(-num); 52 | break; 53 | case '/': 54 | stack.addLast(stack.removeLast() / num); 55 | break; 56 | case '*': 57 | stack.addLast(stack.removeLast() * num); 58 | break; 59 | } 60 | num = 0; 61 | preAction = arr[i]; 62 | } 63 | 64 | i++; 65 | } 66 | 67 | return new int[] { sumFromStack(stack), i + 1 }; 68 | } 69 | 70 | private int sumFromStack(LinkedList stack) { 71 | int res = 0; 72 | while (!stack.isEmpty()) { 73 | res += stack.removeFirst(); 74 | } 75 | return res; 76 | } 77 | 78 | // private int[] getNextInt(char[] arr, int start) { 79 | // int num = 0; 80 | // while (arr[start] == ' ') { 81 | // start++; 82 | // } 83 | // if (arr[start] == '(') { 84 | // return process(arr, start + 1); 85 | // } 86 | // while (start < arr.length) { 87 | // if (arr[start] < '0' || arr[start] > '9') { 88 | // break; 89 | // } 90 | // num = num * 10 + arr[start++] - '0'; 91 | // } 92 | 93 | // return new int[] { num, start }; 94 | // } 95 | 96 | public static void main(String[] args) { 97 | // System.out.println(new Solution227().calculate(" 3+5 / 2 ")); 98 | // System.out.println(new Solution224().calculate(" 2-1 + 2 ")); 99 | System.out.println(new Solution224().calculate("(1+(4+5+2)-3)+(6+8)")); 100 | // 23 101 | } 102 | } 103 | // dir 104 | // subdir1 105 | // tsubdir2 106 | // file.ext -------------------------------------------------------------------------------- /leetcode/Solution227.java: -------------------------------------------------------------------------------- 1 | package leetcode; 2 | 3 | import java.util.LinkedList; 4 | 5 | // 减法不满足结合律 6 | class Solution227 { 7 | public int calculate(String s) { 8 | int num = 0; 9 | char cur; 10 | LinkedList numStack = new LinkedList<>(); 11 | LinkedList acStack = new LinkedList<>(); 12 | 13 | for (int i = 0; i < s.length(); i++) { 14 | cur = s.charAt(i); 15 | switch (cur) { 16 | case '+': 17 | case '-': 18 | acStack.addLast(cur); 19 | numStack.addLast(num); 20 | num = 0; 21 | break; 22 | case '/': 23 | case '*': 24 | var conf = getNextInt(s, i + 1); 25 | num = (cur == '/' ? num / conf[0] : num * conf[0]); 26 | i = conf[1] - 1; 27 | break; 28 | case ' ': 29 | break; 30 | default: 31 | num = num * 10 + (cur - '0'); 32 | break; 33 | } 34 | } 35 | numStack.addLast(num); 36 | while (!acStack.isEmpty()) { 37 | int first = numStack.removeFirst(); 38 | int last = numStack.removeFirst(); 39 | switch (acStack.removeFirst()) { 40 | case '+': 41 | numStack.addFirst(first + last); 42 | break; 43 | case '-': 44 | numStack.addFirst(first - last); 45 | break; 46 | default: 47 | break; 48 | } 49 | } 50 | return numStack.pop(); 51 | } 52 | 53 | private int[] getNextInt(String str, int i) { 54 | 55 | // ignore left whitespace 56 | while (str.charAt(i) == ' ') { 57 | i++; 58 | } 59 | 60 | int res = 0; 61 | int j = i; 62 | char c; 63 | for (; j < str.length(); j++) { 64 | c = str.charAt(j); 65 | if (c < '0' || c > '9') { 66 | break; 67 | } 68 | res = res * 10 + (c - '0'); 69 | } 70 | 71 | return new int[] { res, j }; 72 | } 73 | 74 | public static void main(String[] args) { 75 | // System.out.println(new Solution227().calculate(" 3+5 / 2 ")); 76 | System.out.println(new Solution227().calculate(" 123 + 13 / 3 * 2 + 24 / 4 + 2 - 12 - 12")); 77 | } 78 | } 79 | // dir 80 | // subdir1 81 | // tsubdir2 82 | // file.ext -------------------------------------------------------------------------------- /leetcode/Solution237.java: -------------------------------------------------------------------------------- 1 | package leetcode; 2 | 3 | public class Solution237 { 4 | public void deleteNode(ListNode node) { 5 | node.val = node.next.val; 6 | node.next = node.next.next; 7 | } 8 | } -------------------------------------------------------------------------------- /leetcode/Solution24.java: -------------------------------------------------------------------------------- 1 | package leetcode; 2 | 3 | /* ----------------------------------- 4 | * WARNING: 5 | * ----------------------------------- 6 | * Your code may fail to compile 7 | * because it contains public class 8 | * declarations. 9 | * To fix this, please remove the 10 | * "public" keyword from your class 11 | * declarations. 12 | */ 13 | 14 | /** 15 | * Definition for singly-linked list. 16 | * public class ListNode { 17 | * int val; 18 | * ListNode next; 19 | * ListNode() {} 20 | * ListNode(int val) { this.val = val; } 21 | * ListNode(int val, ListNode next) { this.val = val; this.next = next; } 22 | * } 23 | */ 24 | 25 | public class Solution24 { 26 | 27 | public ListNode swapPairs(ListNode head) { 28 | ListNode guide = new ListNode(0, head); 29 | ListNode pre = guide; 30 | while (head != null && head.next != null) { 31 | pre.next = head.next; 32 | head.next = head.next.next; 33 | pre.next.next = head; 34 | 35 | pre = head; 36 | head = head.next; 37 | } 38 | 39 | return guide.next; 40 | } 41 | 42 | public static int[] stringToIntegerArray(String input) { 43 | input = input.trim(); 44 | input = input.substring(1, input.length() - 1); 45 | if (input.length() == 0) { 46 | return new int[0]; 47 | } 48 | 49 | String[] parts = input.split(","); 50 | int[] output = new int[parts.length]; 51 | for (int index = 0; index < parts.length; index++) { 52 | String part = parts[index].trim(); 53 | output[index] = Integer.parseInt(part); 54 | } 55 | return output; 56 | } 57 | 58 | public static ListNode stringToListNode(String input) { 59 | // Generate array from the input 60 | int[] nodeValues = stringToIntegerArray(input); 61 | 62 | // Now convert that list into linked list 63 | ListNode dummyRoot = new ListNode(0); 64 | ListNode ptr = dummyRoot; 65 | for (int item : nodeValues) { 66 | ptr.next = new ListNode(item); 67 | ptr = ptr.next; 68 | } 69 | return dummyRoot.next; 70 | } 71 | 72 | public static String listNodeToString(ListNode node) { 73 | if (node == null) { 74 | return "[]"; 75 | } 76 | 77 | String result = ""; 78 | while (node != null) { 79 | result += Integer.toString(node.val) + ", "; 80 | node = node.next; 81 | } 82 | return "[" + result.substring(0, result.length() - 2) + "]"; 83 | } 84 | 85 | public static void main(String[] args) { 86 | ListNode head = stringToListNode("[1,2,3,4]"); 87 | 88 | ListNode ret = new Solution24().swapPairs(head); 89 | 90 | String out = listNodeToString(ret); 91 | 92 | System.out.print(out); 93 | } 94 | 95 | } -------------------------------------------------------------------------------- /leetcode/Solution388.java: -------------------------------------------------------------------------------- 1 | package leetcode; 2 | 3 | class Solution388 { 4 | public int lengthLongestPath(String input) { 5 | if (input == null || input.length() == 0) { 6 | return 0; 7 | } 8 | 9 | String[] arr = input.split("\\n(?!\\t)"); 10 | 11 | int res = 0; 12 | for (int i = 0; i < arr.length; i++) { 13 | int c = process(arr[i], 1); 14 | if (c != 0) { 15 | res = Math.max(res, c); 16 | } 17 | } 18 | 19 | return res; 20 | } 21 | 22 | private int process(String str, int level) { 23 | String[] arr = str.split("\\n" + "\\t".repeat(level) + "(?!\\t)"); 24 | if (arr.length == 1) 25 | return arr[0].contains(".") ? arr[0].length() : 0; 26 | 27 | int res = 0; 28 | // must run 29 | for (int i = 1; i < arr.length; i++) { 30 | int c = process(arr[i], level + 1); 31 | if (c != 0) { 32 | res = Math.max(res, c); 33 | } 34 | } 35 | 36 | return res == 0 ? 0 : res + arr[0].length() + 1; 37 | 38 | } 39 | 40 | public static void main(String[] args) { 41 | System.out.println(new Solution388().lengthLongestPath("dir\n\tsubdir1\n\tsubdir2\n\t\tfile.ext")); 42 | System.out.println(new Solution388().lengthLongestPath( 43 | "dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext")); 44 | System.out.println(new Solution388().lengthLongestPath("a")); 45 | System.out.println(new Solution388().lengthLongestPath("file1.txt\nfile2.txt\nlongfile.txt")); 46 | System.out.println(new Solution388().lengthLongestPath("a\n\tb\n\t\tc")); 47 | System.out.println(new Solution388().lengthLongestPath("dir\n\tsubdir1\n\tsubdir2\n\t\tfile.ext")); 48 | 49 | // System.out.println("22\n\t2123".matches(".*?\n\t[^\t].*?")); 50 | } 51 | } 52 | // dir 53 | // subdir1 54 | // tsubdir2 55 | // file.ext -------------------------------------------------------------------------------- /leetcode/Solution394.java: -------------------------------------------------------------------------------- 1 | package leetcode; 2 | 3 | import java.util.Stack; 4 | 5 | // 1. 递归 6 | // 2. 用栈模拟递归 7 | class Solution394 { 8 | public String decodeString(String what) { 9 | StringBuilder sb = new StringBuilder(what); 10 | Stack stack = new Stack<>(); 11 | 12 | boolean isNum = sb.charAt(0) <= '9' && sb.charAt(0) >= '0'; 13 | String cur = ""; 14 | for (int i = 0; i < sb.length(); i++) { 15 | char c = sb.charAt(i); 16 | if (c == '[') { 17 | stack.push(cur); 18 | cur = ""; 19 | } else if (c == ']') { 20 | String pop; 21 | while (true) { 22 | pop = stack.pop(); 23 | 24 | if (pop.charAt(0) >= '0' && pop.charAt(0) <= '9') { 25 | break; 26 | } else { 27 | cur = pop + cur; 28 | } 29 | } 30 | stack.push(cur.repeat(Integer.parseInt(pop))); 31 | 32 | cur = ""; 33 | } else { 34 | if (isNum != (c <= '9' && c >= '0')) { 35 | isNum = !isNum; 36 | if (cur.length() > 0) { 37 | stack.push(cur); 38 | cur = ""; 39 | } 40 | } 41 | 42 | cur += c; 43 | } 44 | } 45 | stack.push(cur); 46 | 47 | 48 | String res = ""; 49 | while (!stack.isEmpty()) { 50 | res = stack.pop() + res; 51 | } 52 | 53 | return res; 54 | } 55 | 56 | public static void main(String[] args) { 57 | System.out.println(new Solution394().decodeString("3[a]2[bc]")); 58 | System.out.println(new Solution394().decodeString("3[a2[c]]")); 59 | System.out.println(new Solution394().decodeString("2[abc]3[cd]ef")); 60 | System.out.println(new Solution394().decodeString("abc3[cd]xyz")); 61 | } 62 | } -------------------------------------------------------------------------------- /leetcode/Solution482.java: -------------------------------------------------------------------------------- 1 | package leetcode; 2 | 3 | class Solution482 { 4 | public String licenseKeyFormatting(String s, int k) { 5 | String res = ""; 6 | int count = 1; 7 | s = s.replaceAll("-", ""); 8 | for (int i = s.length() - 1; i >= 0; i--) { 9 | if (count % k == 0 && i != 0) { 10 | res = "-" + (char) (s.charAt(i) > 96 ? (int) (s.charAt(i)) - 32 : s.charAt(i)) + res; 11 | } else { 12 | res = (char) (s.charAt(i) > 96 ? (int) (s.charAt(i)) - 32 : s.charAt(i)) + res; 13 | 14 | } 15 | count++; 16 | } 17 | 18 | return res; 19 | } 20 | 21 | public static void main(String[] args) { 22 | System.out.println(new Solution482().licenseKeyFormatting("--a-a-a-a--", 2)); 23 | } 24 | } -------------------------------------------------------------------------------- /leetcode/Solution6.java: -------------------------------------------------------------------------------- 1 | package leetcode; 2 | 3 | class Solution6 { 4 | public String convert(String s, int numRows) { 5 | if (s.length() <= 1 || numRows == 1) { 6 | return s; 7 | } 8 | StringBuilder res = new StringBuilder(); 9 | int loop = 2 * numRows - 2; 10 | for (int i = 0; i < numRows; i++) { 11 | 12 | for (int j = 0; j < s.length(); j++) { 13 | if ((j + i) % loop == 0 || j % loop == i) { 14 | res.append(s.charAt(j)); 15 | } 16 | } 17 | } 18 | 19 | return res.toString(); 20 | 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /leetcode/Solution61.java: -------------------------------------------------------------------------------- 1 | package leetcode; 2 | 3 | /* ----------------------------------- 4 | * WARNING: 5 | * ----------------------------------- 6 | * Your code may fail to compile 7 | * because it contains public class 8 | * declarations. 9 | * To fix this, please remove the 10 | * "public" keyword from your class 11 | * declarations. 12 | */ 13 | 14 | // * Definition for singly-linked list. 15 | class ListNode { 16 | int val; 17 | ListNode next; 18 | 19 | ListNode() { 20 | } 21 | 22 | ListNode(int val) { 23 | this.val = val; 24 | } 25 | 26 | ListNode(int val, ListNode next) { 27 | this.val = val; 28 | this.next = next; 29 | } 30 | } 31 | 32 | class Solution { 33 | public ListNode rotateRight(ListNode head, int k) { 34 | if (head == null) { 35 | return head; 36 | } 37 | 38 | ListNode node = head; 39 | // 将尾节点连到头节点 40 | int count = 0; 41 | while (node != null) { 42 | count++; 43 | node = node.next; 44 | 45 | } 46 | 47 | k = k % count; 48 | 49 | if (k == 0) { 50 | return head; 51 | } 52 | node = head; 53 | ListNode[] cache = new ListNode[k + 1]; 54 | int i = 0; 55 | while (node != null) { 56 | cache[i] = node; 57 | i = i == cache.length - 1 ? 0 : i + 1; 58 | if (node.next == null) { 59 | node.next = head; 60 | node = null; 61 | } else { 62 | node = node.next; 63 | } 64 | } 65 | head = cache[i].next; 66 | cache[i].next = null; 67 | 68 | return head; 69 | } 70 | } 71 | 72 | public class Solution61 { 73 | public static int[] stringToIntegerArray(String input) { 74 | input = input.trim(); 75 | input = input.substring(1, input.length() - 1); 76 | if (input.length() == 0) { 77 | return new int[0]; 78 | } 79 | 80 | String[] parts = input.split(","); 81 | int[] output = new int[parts.length]; 82 | for (int index = 0; index < parts.length; index++) { 83 | String part = parts[index].trim(); 84 | output[index] = Integer.parseInt(part); 85 | } 86 | return output; 87 | } 88 | 89 | public static ListNode stringToListNode(String input) { 90 | // Generate array from the input 91 | int[] nodeValues = stringToIntegerArray(input); 92 | 93 | // Now convert that list into linked list 94 | ListNode dummyRoot = new ListNode(0); 95 | ListNode ptr = dummyRoot; 96 | for (int item : nodeValues) { 97 | ptr.next = new ListNode(item); 98 | ptr = ptr.next; 99 | } 100 | return dummyRoot.next; 101 | } 102 | 103 | public static String listNodeToString(ListNode node) { 104 | if (node == null) { 105 | return "[]"; 106 | } 107 | 108 | String result = ""; 109 | while (node != null) { 110 | result += Integer.toString(node.val) + ", "; 111 | node = node.next; 112 | } 113 | return "[" + result.substring(0, result.length() - 2) + "]"; 114 | } 115 | 116 | public static void main(String[] args) { 117 | ListNode head = stringToListNode("[1,2,3,4,5]"); 118 | int k = 2; 119 | 120 | ListNode ret = new Solution().rotateRight(head, k); 121 | 122 | String out = listNodeToString(ret); 123 | 124 | System.out.print(out); 125 | } 126 | 127 | } -------------------------------------------------------------------------------- /leetcode/Solution636.java: -------------------------------------------------------------------------------- 1 | package leetcode; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | import java.util.Stack; 6 | 7 | class Solution636 { 8 | public int[] exclusiveTime(int n, List logs) { 9 | int[] res = new int[n]; 10 | 11 | Stack stack = new Stack<>(); 12 | 13 | stack.push(new int[] { Integer.parseInt(logs.get(0).split(":")[0]), 0 }); 14 | 15 | for (int i = 0; i < logs.size(); i++) { 16 | String[] cur = logs.get(i).split(":"); 17 | 18 | if ("start".equals(cur[1])) { 19 | int[] top = stack.peek(); 20 | res[top[0]] += Integer.parseInt(cur[2]) - top[1]; 21 | // top[1] = Integer.parseInt(cur[2]); 22 | stack.push(new int[] { Integer.parseInt(cur[0]), Integer.parseInt(cur[2]) }); 23 | } else { 24 | int[] top = stack.pop(); 25 | stack.peek()[1] = Integer.parseInt(cur[2]) + 1; 26 | res[top[0]] += Integer.parseInt(cur[2]) - top[1] + 1; 27 | } 28 | 29 | } 30 | 31 | return res; 32 | } 33 | 34 | public static void main(String[] args) { 35 | System.out 36 | .println(new Solution636().exclusiveTime(2, Arrays.asList("0:start:0", "1:start:2", "1:end:5", "0:end:6"))); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /leetcode/Solution68.java: -------------------------------------------------------------------------------- 1 | package leetcode; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.LinkedList; 6 | import java.util.List; 7 | 8 | class Solution68 { 9 | public List fullJustify(String[] words, int maxWidth) { 10 | if (words == null || words.length == 0) { 11 | return null; 12 | } 13 | 14 | LinkedList counts = new LinkedList<>(); 15 | HashMap map = new HashMap<>(); 16 | 17 | // 获取分界点索引 18 | int len = words[0].length(); 19 | for (int i = 1; i < words.length; i++) { 20 | if (len + words[i].length() + 1 > maxWidth) { 21 | counts.add(i - 1); 22 | map.put(i - 1, len); 23 | len = words[i].length(); 24 | } else { 25 | len += words[i].length() + 1; 26 | } 27 | } 28 | 29 | // 根据分界生成字符串 30 | List res = new ArrayList<>(); 31 | int left = 0; 32 | int right; 33 | 34 | StringBuilder cache = new StringBuilder(); 35 | while (!counts.isEmpty()) { 36 | right = counts.poll(); 37 | cache.delete(0, cache.length()); 38 | if (left == right) { 39 | cache.append(words[left]); 40 | cache.append(" ".repeat(maxWidth - cache.length())); 41 | } else { 42 | int extraLen = (maxWidth - map.get(right)) / (right - left); 43 | int extraIndex = (maxWidth - map.get(right)) % (right - left); 44 | 45 | for (int i = left; i <= right; i++) { 46 | cache.append(words[i]); 47 | if (i == right) { 48 | continue; 49 | } 50 | cache.append(" ".repeat(1 + extraLen + (i - left < extraIndex ? 1 : 0))); 51 | } 52 | 53 | } 54 | res.add(cache.toString()); 55 | left = right + 1; 56 | } 57 | 58 | cache.delete(0, cache.length()); 59 | for (int i = left; i < words.length; i++) { 60 | cache.append(words[i]); 61 | if (i == words.length - 1) { 62 | cache.append(" ".repeat(maxWidth - cache.length())); 63 | continue; 64 | } 65 | cache.append(" "); 66 | } 67 | 68 | res.add(cache.toString()); 69 | 70 | return res; 71 | } 72 | 73 | public static void main(String[] args) { 74 | 75 | System.out.println(new Solution68() 76 | .fullJustify(new String[] { "What", "must", "be", "acknowledgment", "shall", "be" }, 16)); 77 | 78 | // System.out.println("This is an".length()); 79 | // System.out.println(" example of text".length()); 80 | 81 | } 82 | } -------------------------------------------------------------------------------- /leetcode/Solution682.java: -------------------------------------------------------------------------------- 1 | package leetcode; 2 | import java.util.Stack; 3 | 4 | // 栈 或 数组+指针 5 | class Solution682 { 6 | public int calPoints(String[] operations) { 7 | 8 | Stack stack = new Stack<>(); 9 | 10 | for (int i = 0; i < operations.length; i++) { 11 | switch (operations[i]) { 12 | case "+": 13 | int top = stack.pop(); 14 | int val = stack.peek() + top; 15 | stack.push(top); 16 | stack.push(val); 17 | break; 18 | case "D": 19 | stack.push(2 * stack.peek()); 20 | break; 21 | case "C": 22 | stack.pop(); 23 | break; 24 | 25 | default: 26 | stack.push(Integer.parseInt(operations[i])); 27 | break; 28 | } 29 | } 30 | 31 | int sum = 0; 32 | while (!stack.isEmpty()) { 33 | sum += stack.pop(); 34 | } 35 | 36 | return sum; 37 | } 38 | 39 | public static void main(String[] args) { 40 | System.out.println(new Solution682().calPoints(new String[] { "5", "-2", "4", "C", "D", "9", "+", "+" })); 41 | } 42 | } -------------------------------------------------------------------------------- /leetcode/Solution71.java: -------------------------------------------------------------------------------- 1 | package leetcode; 2 | 3 | import java.util.LinkedList; 4 | import java.util.Stack; 5 | 6 | class Solution71 { 7 | public String simplifyPath(String path) { 8 | if (path == null || path.length() == 0) { 9 | return null; 10 | } 11 | LinkedList stack = new LinkedList<>(); 12 | String[] arr = path.split("/"); 13 | 14 | for (int i = 0; i < arr.length; i++) { 15 | if (arr[i].length() == 0) { 16 | continue; 17 | } 18 | 19 | if (arr[i].equals("..")) { 20 | if (!stack.isEmpty()) { 21 | stack.pop(); 22 | } 23 | } else if (!arr[i].equals(".")) { 24 | stack.push(arr[i]); 25 | } 26 | } 27 | 28 | if (stack.isEmpty()) { 29 | return "/"; 30 | } 31 | 32 | String res = ""; 33 | while (!stack.isEmpty()) { 34 | res += "/" + stack.pollLast(); 35 | } 36 | 37 | return res; 38 | } 39 | 40 | public String simplifyPath2(String path) { 41 | 42 | if (path == null || path.length() == 0) { 43 | return null; 44 | } 45 | 46 | Stack stack = new Stack<>(); 47 | 48 | String cur = ""; 49 | for (int i = 0; i < path.length(); i++) { 50 | char c = path.charAt(i); 51 | if (c == '/') { 52 | if (cur.equals("..")) { 53 | if (!stack.isEmpty()) { 54 | stack.pop(); 55 | } 56 | } else if (!cur.equals("") && !cur.equals(".") && !cur.equals("/")) { 57 | stack.push(cur); 58 | } 59 | cur = ""; 60 | } else { 61 | cur += c; 62 | } 63 | } 64 | 65 | if (cur.equals("..")) { 66 | if (!stack.isEmpty()) { 67 | stack.pop(); 68 | } 69 | } else if (!cur.equals("") && !cur.equals(".") && !cur.equals("/")) { 70 | stack.push(cur); 71 | } 72 | 73 | String res = ""; 74 | while (!stack.isEmpty()) { 75 | res = stack.pop() + "/" + res; 76 | } 77 | 78 | return "/" + (res.equals("") ? "" : res.substring(0, res.length() - 1)); 79 | } 80 | 81 | public static void main(String[] args) { 82 | System.out.println(new Solution71().simplifyPath("/a/./b/../../c/")); 83 | System.out.println(new Solution71().simplifyPath("/home//foo/")); 84 | System.out.println(new Solution71().simplifyPath("/../")); 85 | } 86 | } -------------------------------------------------------------------------------- /linked_list/C03_PrintCommonPart.java: -------------------------------------------------------------------------------- 1 | package linked_list; 2 | 3 | // 打印两个有序链表的公共部分 4 | // 【题目】 给定两个有序链表的头指针head1和head2,打印两个链表的公共部分。 5 | // 【要求】如果两个链表的长度之和为N,时间复杂度要求为O(N),额外空间复杂度要求为O(1) 6 | public class C03_PrintCommonPart { 7 | 8 | public static class Node { 9 | public int value; 10 | public Node next; 11 | 12 | public Node(int data) { 13 | this.value = data; 14 | } 15 | } 16 | 17 | // public static void printCommonPart(Node head1, Node head2) { 18 | // System.out.print("Common Part: "); 19 | // while (head1 != null && head2 != null) { 20 | // if (head1.value < head2.value) { 21 | // head1 = head1.next; 22 | // } else if (head1.value > head2.value) { 23 | // head2 = head2.next; 24 | // } else { 25 | // System.out.print(head1.value + " "); 26 | // head1 = head1.next; 27 | // head2 = head2.next; 28 | // } 29 | // } 30 | // System.out.println(); 31 | // } 32 | 33 | private static void printCommonPart(Node node1, Node node2) { 34 | while (node1 != null && node2 != null) { 35 | if (node1.value > node2.value) { 36 | node2 = node2.next; 37 | } else if (node1.value < node2.value) { 38 | node1 = node1.next; 39 | } else { 40 | System.out.print(node1.value + " "); 41 | node1 = node1.next; 42 | node2 = node2.next; 43 | } 44 | 45 | } 46 | 47 | } 48 | 49 | public static void printLinkedList(Node node) { 50 | System.out.print("Linked List: "); 51 | while (node != null) { 52 | System.out.print(node.value + " "); 53 | node = node.next; 54 | } 55 | System.out.println(); 56 | } 57 | 58 | public static void main(String[] args) { 59 | Node node1 = new Node(2); 60 | node1.next = new Node(3); 61 | node1.next.next = new Node(5); 62 | node1.next.next.next = new Node(6); 63 | 64 | Node node2 = new Node(1); 65 | node2.next = new Node(2); 66 | node2.next.next = new Node(5); 67 | node2.next.next.next = new Node(7); 68 | node2.next.next.next.next = new Node(8); 69 | 70 | printLinkedList(node1); 71 | printLinkedList(node2); 72 | printCommonPart(node1, node2); 73 | 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /macro_scheduling/C01_RotateMatrix.java: -------------------------------------------------------------------------------- 1 | package macro_scheduling; 2 | 3 | // 给定一个正方形矩阵,只用有限几个变量,实现矩阵中每个位置的数顺时针转动 90度,比如如下的矩阵 4 | // 0 1 2 3 5 | // 4 5 6 7 6 | // 8 9 10 11 7 | // 12 13 14 15 8 | // 矩阵应该被调整为: 9 | // 12 8 4 0 10 | // 13 9 5 1 11 | // 14 10 6 2 12 | // 15 11 7 3 13 | // NOTE: 宏观调度 14 | public class C01_RotateMatrix { 15 | 16 | // public static void rotate(int[][] matrix) { 17 | // int tR = 0; 18 | // int tC = 0; 19 | // int dR = matrix.length - 1; 20 | // int dC = matrix[0].length - 1; 21 | // while (tR < dR) { 22 | // rotateEdge(matrix, tR++, tC++, dR--, dC--); 23 | // } 24 | // } 25 | 26 | // public static void rotateEdge(int[][] m, int tR, int tC, int dR, int dC) { 27 | // int times = dC - tC; 28 | // int tmp = 0; 29 | // for (int i = 0; i != times; i++) { 30 | // tmp = m[tR][tC + i]; 31 | // m[tR][tC + i] = m[dR - i][tC]; 32 | // m[dR - i][tC] = m[dR][dC - i]; 33 | // m[dR][dC - i] = m[tR + i][dC]; 34 | // m[tR + i][dC] = tmp; 35 | // } 36 | // } 37 | 38 | public static void rotate(int[][] matrix) { 39 | if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { 40 | return; 41 | } 42 | 43 | int a = 0; 44 | int b = 0; 45 | int x = matrix[0].length - 1; 46 | int y = matrix.length - 1; 47 | 48 | while (a <= x && b <= y) { 49 | rotateEdge(matrix, a++, b++, x--, y--); 50 | } 51 | } 52 | 53 | private static void rotateEdge(int[][] matrix, int a, int b, int x, int y) { 54 | int tem; 55 | for (int i = b; i < y; i++) { 56 | tem = matrix[a][b + i]; 57 | matrix[a][b + i] = matrix[x - i][b]; 58 | matrix[x - i][b] = matrix[x][y - i]; 59 | matrix[x][y - i] = matrix[a + i][y]; 60 | matrix[a + i][y] = tem; 61 | } 62 | } 63 | 64 | // for test 65 | public static void printMatrix(int[][] matrix) { 66 | for (int i = 0; i != matrix.length; i++) { 67 | for (int j = 0; j != matrix[0].length; j++) { 68 | System.out.print(matrix[i][j] + " "); 69 | } 70 | System.out.println(); 71 | } 72 | } 73 | 74 | public static void main(String[] args) { 75 | int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 }, { 13, 14, 15, 16 } }; 76 | printMatrix(matrix); 77 | rotate(matrix); 78 | System.out.println("========="); 79 | printMatrix(matrix); 80 | 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /macro_scheduling/C02_ZigZagPrintMatrix.java: -------------------------------------------------------------------------------- 1 | package macro_scheduling; 2 | 3 | // 用zigzag的方式打印矩阵,比如如下的矩阵 0123 4 | // 4567 5 | // 8 91011 6 | // 打印顺序为:0 1 4 8 5 2 3 6 9 10 7 11 7 | public class C02_ZigZagPrintMatrix { 8 | 9 | // public static void printMatrixZigZag(int[][] matrix) { 10 | // int tR = 0; 11 | // int tC = 0; 12 | // int dR = 0; 13 | // int dC = 0; 14 | // int endR = matrix.length - 1; 15 | // int endC = matrix[0].length - 1; 16 | // boolean fromUp = false; 17 | // while (tR != endR + 1) { 18 | // printLevel(matrix, tR, tC, dR, dC, fromUp); 19 | // tR = tC == endC ? tR + 1 : tR; 20 | // tC = tC == endC ? tC : tC + 1; 21 | // dC = dR == endR ? dC + 1 : dC; 22 | // dR = dR == endR ? dR : dR + 1; 23 | // fromUp = !fromUp; 24 | // } 25 | // System.out.println(); 26 | // } 27 | 28 | // public static void printLevel(int[][] m, int tR, int tC, int dR, int dC, 29 | // boolean f) { 30 | // if (f) { 31 | // while (tR != dR + 1) { 32 | // System.out.print(m[tR++][tC--] + " "); 33 | // } 34 | // } else { 35 | // while (dR != tR - 1) { 36 | // System.out.print(m[dR--][dC++] + " "); 37 | // } 38 | // } 39 | // } 40 | 41 | public static void printMatrixZigZag(int[][] matrix) { 42 | if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { 43 | return; 44 | } 45 | 46 | int a = 0; 47 | int b = 0; 48 | int x = 0; 49 | int y = 0; 50 | boolean isPositive = false; // 是否为正斜线 51 | 52 | while (b < matrix[0].length) { 53 | 54 | printSlash(matrix, a, b, x, y, isPositive); 55 | 56 | isPositive = !isPositive; 57 | if (a != matrix.length - 1) { 58 | a++; 59 | } else { 60 | b++; 61 | } 62 | 63 | if (y != matrix[0].length - 1) { 64 | y++; 65 | } else { 66 | x++; 67 | } 68 | } 69 | System.out.println(); 70 | } 71 | 72 | private static void printSlash(int[][] matrix, int a, int b, int x, int y, boolean isPositive) { 73 | if (isPositive) { 74 | while (b <= y) { 75 | System.out.print(matrix[a--][b++] + " "); 76 | } 77 | } else { 78 | while (y >= b) { 79 | System.out.print(matrix[x++][y--] + " "); 80 | } 81 | } 82 | } 83 | 84 | public static void main(String[] args) { 85 | int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } }; 86 | printMatrixZigZag(matrix); 87 | 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /macro_scheduling/C03_PrintMatrixSpiralOrder.java: -------------------------------------------------------------------------------- 1 | package macro_scheduling; 2 | 3 | // 用螺旋的方式打印矩阵,比如如下的矩阵: 4 | // 0 1 2 3 5 | // 4 5 6 7 6 | // 8 9 10 11 7 | // 打印顺序为:0 1 2 3 7 11 10 9 8 4 5 6 8 | 9 | public class C03_PrintMatrixSpiralOrder { 10 | 11 | // public static void spiralOrderPrint(int[][] matrix) { 12 | // int tR = 0; 13 | // int tC = 0; 14 | // int dR = matrix.length - 1; 15 | // int dC = matrix[0].length - 1; 16 | // while (tR <= dR && tC <= dC) { // 正方形,只用满足一个就行 17 | // printEdge(matrix, tR++, tC++, dR--, dC--); 18 | // } 19 | // } 20 | 21 | // public static void printEdge(int[][] m, int tR, int tC, int dR, int dC) { 22 | // if (tR == dR) { 23 | // for (int i = tC; i <= dC; i++) { 24 | // System.out.print(m[tR][i] + " "); 25 | // } 26 | // } else if (tC == dC) { 27 | // for (int i = tR; i <= dR; i++) { 28 | // System.out.print(m[i][tC] + " "); 29 | // } 30 | // } else { 31 | // int curC = tC; 32 | // int curR = tR; 33 | // while (curC != dC) { 34 | // System.out.print(m[tR][curC] + " "); 35 | // curC++; 36 | // } 37 | // while (curR != dR) { 38 | // System.out.print(m[curR][dC] + " "); 39 | // curR++; 40 | // } 41 | // while (curC != tC) { 42 | // System.out.print(m[dR][curC] + " "); 43 | // curC--; 44 | // } 45 | // while (curR != tR) { 46 | // System.out.print(m[curR][tC] + " "); 47 | // curR--; 48 | // } 49 | // } 50 | // } 51 | 52 | public static void spiralOrderPrint(int[][] matrix) { 53 | if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { 54 | return; 55 | } 56 | 57 | int a = 0; 58 | int b = 0; 59 | int x = matrix[0].length - 1; 60 | int y = matrix.length - 1; 61 | 62 | while (a <= x && b <= y) { 63 | printEdge(matrix, a++, b++, x--, y--); 64 | } 65 | } 66 | 67 | public static void printEdge(int[][] matrix, int a, int b, int x, int y) { 68 | for (int i = b; i <= y; i++) { 69 | System.out.print(matrix[a][i] + " "); 70 | } 71 | for (int i = a + 1; i <= x; i++) { 72 | System.out.print(matrix[i][y] + " "); 73 | } 74 | for (int i = y - 1; i >= b; i--) { 75 | System.out.print(matrix[x][i] + " "); 76 | } 77 | for (int i = x - 1; i > a; i--) { 78 | System.out.print(matrix[i][b] + " "); 79 | } 80 | } 81 | 82 | public static void main(String[] args) { 83 | int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 }, { 13, 14, 15, 16 } }; 84 | spiralOrderPrint(matrix); 85 | 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /others/C05_IsRotation.java: -------------------------------------------------------------------------------- 1 | package others; 2 | 3 | // 如果一个字符串为str,把字符串str前面任意的部分挪到后面形成的字符串叫作str的旋转词。 4 | // 比如str="12345",str的旋转词有"12345"、"23451"、 "34512"、"45123"和"51234"。 5 | // 给定两个字符串a和b,请判断a和b是否互为旋转词。 6 | // 比如: 7 | // a="cdab",b="abcd",返回true。 8 | // a="1ab2",b="ab12",返回false。 9 | // a="2ab1",b="ab12",返回true。 10 | 11 | public class C05_IsRotation { 12 | 13 | // public static boolean isRotation(String a, String b) { 14 | // if (a == null || b == null || a.length() != b.length()) { 15 | // return false; 16 | // } 17 | // String b2 = b + b; 18 | // return getIndexOf(b2, a) != -1; 19 | // } 20 | 21 | // // KMP Algorithm 22 | // public static int getIndexOf(String s, String m) { 23 | // if (s.length() < m.length()) { 24 | // return -1; 25 | // } 26 | // char[] ss = s.toCharArray(); 27 | // char[] ms = m.toCharArray(); 28 | // int si = 0; 29 | // int mi = 0; 30 | // int[] next = getNextArray(ms); 31 | // while (si < ss.length && mi < ms.length) { 32 | // if (ss[si] == ms[mi]) { 33 | // si++; 34 | // mi++; 35 | // } else if (next[mi] == -1) { 36 | // si++; 37 | // } else { 38 | // mi = next[mi]; 39 | // } 40 | // } 41 | // return mi == ms.length ? si - mi : -1; 42 | // } 43 | 44 | // public static int[] getNextArray(char[] ms) { 45 | // if (ms.length == 1) { 46 | // return new int[] { -1 }; 47 | // } 48 | // int[] next = new int[ms.length]; 49 | // next[0] = -1; 50 | // next[1] = 0; 51 | // int pos = 2; 52 | // int cn = 0; 53 | // while (pos < next.length) { 54 | // if (ms[pos - 1] == ms[cn]) { 55 | // next[pos++] = ++cn; 56 | // } else if (cn > 0) { 57 | // cn = next[cn]; 58 | // } else { 59 | // next[pos++] = 0; 60 | // } 61 | // } 62 | // return next; 63 | // } 64 | 65 | public static boolean isRotation(String str1, String str2) { 66 | if (str1.length() != str2.length()) { 67 | return false; 68 | } 69 | 70 | str1 += str1; 71 | return getIndexOf(str1, str2) != -1; 72 | } 73 | 74 | // TODO: KMP 75 | private static int getIndexOf(String str1, String str2) { 76 | return 0; 77 | } 78 | 79 | public static void main(String[] args) { 80 | String str1 = "yunzuocheng"; 81 | String str2 = "zuochengyun"; 82 | System.out.println(isRotation(str1, str2)); 83 | 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /others/C06_NearMultiple4Times.java: -------------------------------------------------------------------------------- 1 | package others; 2 | 3 | // 给定一个数组arr,如果通过调整可以做到arr中任意两个相邻的数字相乘是4的倍数,返回true;如果不能返回false 4 | public class C06_NearMultiple4Times { 5 | 6 | // public static boolean nearMultiple4Times(int[] arr) { 7 | // int fourTimes = 0; // 是4的倍数的数有多少个 8 | // int evenExpFourTimes = 0; // 是偶数但不是4的倍数的数有多少个 9 | // int odd = 0; // 奇数有多少个 10 | // for (int i = 0; i < arr.length; i++) { 11 | // if ((arr[i] & 1) != 0) { 12 | // odd++; 13 | // } else { 14 | // if (arr[i] % 4 == 0) { 15 | // fourTimes++; 16 | // } else { 17 | // evenExpFourTimes++; 18 | // } 19 | // } 20 | // } 21 | // return evenExpFourTimes == 0 ? (fourTimes + 1 >= odd) : (evenExpFourTimes >= 22 | // odd); 23 | // } 24 | 25 | public static boolean nearMultiple4Times(int[] arr) { 26 | if (arr == null || arr.length == 0) { 27 | return false; 28 | } 29 | 30 | int fourTimes = 0; 31 | int twoTimes = 0; 32 | int otherTimes = 0; 33 | 34 | for (int i = 0; i < arr.length; i++) { 35 | if (arr[i] % 4 == 0) { 36 | fourTimes++; 37 | } else if (arr[i] % 2 == 0) { // 用arr[i] & 1 == 0更快 38 | twoTimes++; 39 | } else { 40 | otherTimes++; 41 | } 42 | } 43 | 44 | if (twoTimes == 1 || twoTimes == 0) { 45 | return fourTimes >= otherTimes + twoTimes - 1; 46 | } else { 47 | return fourTimes >= otherTimes; 48 | } 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /others/C12_ChooseWork.java: -------------------------------------------------------------------------------- 1 | package others; 2 | 3 | import java.util.Arrays; 4 | import java.util.Comparator; 5 | import java.util.TreeMap; 6 | 7 | // 为了找到自己满意的工作,牛牛收集了每种工作的难度和报酬。牛牛选工作的标准是在难度不超过自身能力值的情况下,牛牛选择报酬最高的工作。 8 | // 在牛牛选定了自己的工作后,牛牛的小伙伴们来找牛牛帮忙选工作,牛牛依然使用自己的标准来帮助小伙伴们。 9 | // 牛牛的小伙伴太多了,于是他只好把这个任务交给了你。 10 | // class Job { 11 | // public int money;// 该工作的报酬 public int hard; // 该工作的难度 12 | // public Job(int money, int hard) { 13 | // this.money = money; 14 | // this.hard = hard; 15 | // } } 16 | // 给定一个Job类型的数组jobarr,表示所有的工作。给定一个int类型的数组arr,表示所有小伙伴的能力。 17 | // 返回int类型的数组,表示每一个小伙伴按照牛牛的标准选工作后所能获得的报酬。 18 | public class C12_ChooseWork { 19 | 20 | public static class Job { 21 | public int money; 22 | public int hard; 23 | 24 | public Job(int money, int hard) { 25 | this.money = money; 26 | this.hard = hard; 27 | } 28 | } 29 | 30 | // public static class JobComparator implements Comparator { 31 | // @Override 32 | // public int compare(Job o1, Job o2) { 33 | // return o1.hard != o2.hard ? (o1.hard - o2.hard) : (o2.money - o1.money); 34 | // } 35 | // } 36 | 37 | // public static int[] getMoneys(Job[] job, int[] ability) { 38 | // Arrays.sort(job, new JobComparator()); 39 | // TreeMap map = new TreeMap<>(); 40 | // map.put(job[0].hard, job[0].money); 41 | // Job pre = job[0]; 42 | // for (int i = 1; i < job.length; i++) { 43 | // if (job[i].hard != pre.hard && job[i].money > pre.money) { 44 | // pre = job[i]; 45 | // map.put(pre.hard, pre.money); 46 | // } 47 | // } 48 | // int[] ans = new int[ability.length]; 49 | // for (int i = 0; i < ability.length; i++) { 50 | // Integer key = map.ceilingKey(ability[i]); 51 | // ans[i] = key != null ? map.get(key) : 0; 52 | // } 53 | // return ans; 54 | // } 55 | 56 | public static int[] getMoneys(Job[] job, int[] ability) { 57 | Arrays.sort(job, new Comparator() { // 保证每次hard相同时,money最多的总在第一个 58 | @Override 59 | public int compare(Job o1, Job o2) { 60 | return o1.hard == o2.hard ? o2.money - o1.money : o1.hard - o2.hard; 61 | } 62 | }); 63 | TreeMap map = new TreeMap<>(); // NOTE: 用普通的数组也行 64 | map.put(job[0].hard, job[0].money); 65 | 66 | Job pre = job[0]; 67 | for (int i = 0; i < job.length; i++) { 68 | if (job[i].hard != pre.hard && job[i].money > pre.money) { 69 | map.put(job[i].hard, job[i].money); 70 | } 71 | } 72 | 73 | int[] res = new int[ability.length]; 74 | for (int i = 0; i < res.length; i++) { 75 | Integer key = map.ceilingKey(ability[i]); 76 | res[i] = key == null ? 0 : key; 77 | } 78 | return res; 79 | } 80 | 81 | public static void main(String[] args) { 82 | 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /skill/C01_CordCoverMaxPoint.java: -------------------------------------------------------------------------------- 1 | package skill; 2 | 3 | // 给定一个有序数组arr,代表数轴上从左到右有n个点arr[0]、arr[1]...arr[n-1], 4 | // 给定一个正数L,代表一根长度为L的绳子,求绳子最多能覆盖其中的几个点 5 | public class C01_CordCoverMaxPoint { 6 | 7 | // 法一: O(Nlog(N))的方式 8 | // 长度为L的绳子最多覆盖几个点,请保证arr有序 9 | // public static int maxPoint(int[] arr, int L) { 10 | // int res = 1; 11 | // for (int i = 0; i < arr.length; i++) { 12 | // int nearest = nearestIndex(arr, i, arr[i] - L); 13 | // res = Math.max(res, i - nearest + 1); 14 | // } 15 | // return res; 16 | // } 17 | 18 | // // 在arr[0..R]范围上,找满足>=value的最左位置 19 | // public static int nearestIndex(int[] arr, int R, int value) { 20 | // int L = 0; 21 | // int index = R; 22 | // while (L < R) { 23 | // int mid = L + ((R - L) >> 1); 24 | // if (arr[mid] >= value) { 25 | // index = mid; 26 | // R = mid - 1; 27 | // } else { 28 | // L = mid + 1; 29 | // } 30 | // } 31 | // return index; 32 | // } 33 | 34 | // 法一:nlog(n) 35 | public static int maxPoint(int[] arr, int L) { 36 | if (arr == null || arr.length < 0 || L < 0) { 37 | return 0; 38 | } 39 | int res = 0; 40 | for (int i = 0; i < arr.length; i++) { 41 | res = Math.max(res, nearestIndex(arr, L, i) - i + 1); 42 | } 43 | return res; 44 | } 45 | 46 | private static int nearestIndex(int[] arr, int L, int left) { 47 | int wishRight = arr[left] + L; 48 | int right = arr.length - 1; 49 | while (left < right) { 50 | int mid = (right + left) / 2; 51 | if (arr[mid] > wishRight) { 52 | right = mid - 1; // 加一减一是避免死循环 53 | } else if (arr[mid] <= wishRight) {// 用等于是考虑到有多个相同的值时,这样最后的值刚好大于wishRight 54 | left = mid + 1; 55 | } 56 | } 57 | 58 | return left - 1; 59 | } 60 | 61 | // 法二:O(N)方式 62 | // 维持一个窗口(L、R)都往右移动 63 | public static int maxPoint2(int[] arr, int L) { 64 | if (arr == null || arr.length < 0 || L < 0) { 65 | return 0; 66 | } 67 | 68 | int l = 0; 69 | int r = 0; 70 | int res = 0; 71 | while (r < arr.length) { 72 | if (arr[r] - arr[l] > L) { 73 | res = Math.max(res, r - l); 74 | l++; 75 | } else { 76 | r++; 77 | } 78 | } 79 | return res; 80 | } 81 | 82 | public static void main(String[] args) { 83 | int[] arr = { 0, 13, 24, 35, 46, 57, 60, 72, 87 }; 84 | int L = 30; 85 | 86 | System.out.println(maxPoint(arr, L)); 87 | System.out.println(maxPoint2(arr, L)); 88 | 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /skill/C02_AppleMinBags.java: -------------------------------------------------------------------------------- 1 | package skill; 2 | 3 | // 小虎去附近的商店买苹果,奸诈的商贩使用了捆绑交易,只提供6个每袋和8个 每袋的包装包装不可拆分。 4 | // 可是小虎现在只想购买恰好n个苹果,小虎想购买尽量少的袋数方便携带。 5 | // 如果不能购买恰好n个苹果,小虎将不会购买。 6 | // 输入一个整数n,表示小虎想购买的个苹果,返回最小使用多少袋子。如果无论如何都不能正好装下,返回-1。 7 | public class C02_AppleMinBags { 8 | 9 | // public static int minBags(int apple) { 10 | // if (apple < 0) { 11 | // return -1; 12 | // } 13 | // int bag6 = -1; 14 | // int bag8 = apple / 8; 15 | // int rest = apple - 8 * bag8; 16 | // while (bag8 >= 0 && rest < 24) { 17 | // int restUse6 = minBagBase6(rest); 18 | // if (restUse6 != -1) { 19 | // bag6 = restUse6; 20 | // break; 21 | // } 22 | // rest = apple - 8 * (--bag8); 23 | // } 24 | // return bag6 == -1 ? -1 : bag6 + bag8; 25 | // } 26 | 27 | // public static int minBagBase6(int rest) { 28 | // return rest % 6 == 0 ? (rest / 6) : -1; 29 | // } 30 | 31 | // public static int minBagAwesome(int apple) { 32 | // if ((apple & 1) != 0) { 33 | // return -1; 34 | // } 35 | // if (apple < 18) { 36 | // return apple == 0 ? 0 : (apple == 6 || apple == 8) ? 1 : (apple == 12 || 37 | // apple == 14 || apple == 16) ? 2 : -1; 38 | // } 39 | // return (apple - 18) / 8 + 3; 40 | // } 41 | 42 | // 暴力方式 43 | public static int minBags1(int n, int bagCount) { 44 | if (n < 0) { 45 | return -1; 46 | } 47 | if (n == 0) { 48 | return bagCount; 49 | } 50 | 51 | int count8 = minBags1(n - 8, bagCount + 1); 52 | if (count8 != -1) { 53 | return count8; 54 | } 55 | int count6 = minBags1(n - 6, bagCount + 1); 56 | if (count6 != -1) { 57 | return count6; 58 | } 59 | return -1; 60 | } 61 | 62 | // 法二 63 | public static int minBags(int n) { 64 | // 不能是奇数 65 | if ((n & 1) == 1) { 66 | return -1; 67 | } 68 | if (n < 0) { 69 | return -1; 70 | } 71 | 72 | int count8 = n / 8; 73 | int count6 = 0; 74 | 75 | while (count8 >= 0) { 76 | if ((n - count8 * 8) % 6 == 0) { 77 | count6 = (n - count8 * 8) / 6; 78 | break; 79 | } 80 | count8--; 81 | } 82 | 83 | if (count8 < 0) { 84 | return -1; 85 | } else { 86 | return count6 + count8; 87 | } 88 | } 89 | 90 | // 打表法:打印结果,发现规律 91 | public static int minBagAwesome(int n) { 92 | if (n == 0) { 93 | return 0; 94 | } 95 | if (n < 0 || (n & 1) == 1 || n == 2 || n == 4 || n == 10) { 96 | return -1; 97 | } 98 | if (n == 6 || n == 8) { 99 | return 1; 100 | } 101 | if (n == 12 || n == 14 || n == 16) { 102 | return 2; 103 | } 104 | // n >= 18 105 | return (n + 6) / 8; 106 | 107 | } 108 | 109 | public static void main(String[] args) { 110 | int max = Integer.MAX_VALUE; 111 | int testTime = 100000000; 112 | for (int test = 0; test < testTime; test++) { 113 | int apple = (int) (Math.random() * max); 114 | if (minBags(apple) != minBagAwesome(apple)) { 115 | System.out.println("error"); 116 | } 117 | } 118 | 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /skill/C03_Eat.java: -------------------------------------------------------------------------------- 1 | package skill; 2 | 3 | // 题目: 4 | // 牛牛和羊羊都很喜欢青草,今天他们决定玩青草游戏。 5 | // 最初有一个装有n份青草的箱子,牛牛和羊羊依次进行,牛牛先开始。 6 | // 在每个回合中,每个玩家必须吃一些箱子中的青草,所吃的青草份数必须是4的x次幂,比如1,4,16,64等等。 7 | // 不能在箱子中吃到有效份数青草的玩家落败。 8 | // 假定牛牛和羊羊都是按照最佳方法进行游戏,请输出胜利者的名字。 9 | 10 | public class C03_Eat { 11 | // 暴力解法 12 | // public static String winner1(int n) { 13 | // // 0 1 2 3 4 14 | // // 后 先 后 先 先 15 | // if (n < 5) { 16 | // return (n == 0 || n == 2) ? "后手" : "先手"; 17 | // } 18 | // // n >= 5时 19 | // int base = 1; // 先手决定吃多少草 20 | // while (base <= n) { 21 | // // 母过程 先手, 在子过程就是后手 22 | // if (winner1(n - base).equals("后手")) { 23 | // return "后手"; 24 | // } 25 | // // 防止base * 4溢出且及时终止,不能写:base * 4 > n 26 | // if (base > n / 4) { 27 | // break; 28 | // } 29 | // base*=4; 30 | // } 31 | // return "后手"; 32 | // } 33 | 34 | // 发现技巧后 35 | // public static String winner2(int n) { 36 | 37 | // if (n % 5 == 0 || n % 5 == 2) { 38 | // return "后手"; 39 | // } else { 40 | // return "先手"; 41 | // } 42 | // } 43 | 44 | // 暴力解法 45 | public static String winner1(int n) { 46 | if (n < 0) { 47 | return "error"; 48 | } 49 | if (n == 0) { 50 | return "后手"; 51 | } 52 | int eat = 1; 53 | while (eat <= n) { 54 | if (winner1(n - eat).equals("后手")) { 55 | return "先手"; 56 | } 57 | if (eat > n / 4) { 58 | break; 59 | } 60 | eat *= 4; 61 | } 62 | return "后手"; 63 | } 64 | 65 | // 打表法 66 | public static String winner2(int n) { 67 | int last = n % 5; 68 | if (last == 0 || last == 2) { 69 | return "后手"; 70 | } else { 71 | return "先手"; 72 | } 73 | } 74 | 75 | public static void main(String[] args) { 76 | int max = 75; 77 | int testTime = 100; 78 | for (int test = 0; test < testTime; test++) { 79 | int grass = (int) (Math.random() * max); 80 | String res = winner1(grass); 81 | System.out.println(grass + " " + res); 82 | if (!res.equals(winner2(grass))) { 83 | System.out.println("error"); 84 | } 85 | } 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /skill/C04_ColorLeftRight.java: -------------------------------------------------------------------------------- 1 | package skill; 2 | 3 | // 题目: 4 | // 牛牛有一些排成一行的正方形。每个正方形已经被染成红色或者绿色。 5 | // 牛牛现在可以选择任意一个正方形然后用这两种颜色的任意一种进行染色,这个正方形的颜色将会被覆盖。 6 | // 牛牛的目标是在完成染色之后,每个红色R都比每个绿色G距离最左侧近。 7 | // 牛牛想知道他最少需要涂染几个正方形。 8 | // 如样例所示: s = RGRGR 我们涂染之后变成RRRGG满足要求了,涂染的个数为2,没有比这个更好的涂染方案。 9 | public class C04_ColorLeftRight { 10 | 11 | // 暴力法:一次讨论左侧R有0,1,2...到arr.length个R时,result为多少,取最小值 12 | 13 | // RGRGR -> RRRGG 14 | // public static int minPaint2(String s) { 15 | // if (s == null || s.length() < 2) { 16 | // return 0; 17 | // } 18 | // char[] chs = s.toCharArray(); 19 | // int[] right = new int[chs.length]; 20 | // right[chs.length - 1] = chs[chs.length - 1] == 'R' ? 1 : 0; 21 | // for (int i = chs.length - 2; i >= 0; i--) { 22 | // right[i] = right[i + 1] + (chs[i] == 'R' ? 1 : 0); 23 | // } 24 | // int res = right[0]; 25 | // int left = 0; 26 | // for (int i = 0; i < chs.length - 1; i++) { 27 | 28 | // left += chs[i] == 'G' ? 1 : 0; 29 | // res = Math.min(res, left + right[i + 1]); 30 | // } 31 | // res = Math.min(res, left + (chs[chs.length - 1] == 'G' ? 1 : 0)); 32 | // return res; 33 | // } 34 | 35 | public static int minPaint1(String s) { 36 | if (s == null || s.length() == 0) { 37 | return 0; 38 | } 39 | int res = Integer.MAX_VALUE; 40 | char[] arr = s.toCharArray(); 41 | // System.out.println(arr[1]); 42 | for (int i = 0; i <= arr.length; i++) { // i表示第一个G块 43 | int cur = 0; 44 | for (int j = 0; j < arr.length; j++) { 45 | if (arr[j] != (j >= i ? 'G' : 'R')) { 46 | cur++; 47 | } 48 | } 49 | res = Math.min(res, cur); 50 | } 51 | return res; 52 | } 53 | 54 | public static int minPaint2(String s) { 55 | if (s == null || s.length() == 0) { 56 | return 0; 57 | } 58 | 59 | char[] arr = s.toCharArray(); 60 | 61 | int[] leftCache = new int[arr.length + 1]; // 记录i索引之前有多少R 62 | int[] rightCache = new int[arr.length]; // 记录i索引以及之后有多少G 63 | leftCache[0] = 0; 64 | leftCache[1] = arr[0] == 'R' ? 1 : 0; 65 | for (int i = 2; i < leftCache.length; i++) { 66 | leftCache[i] = arr[i - 1] == 'R' ? leftCache[i - 1] + 1 : leftCache[i - 1]; 67 | } 68 | rightCache[rightCache.length - 1] = arr[rightCache.length - 1] == 'G' ? 1 : 0; 69 | for (int i = rightCache.length - 2; i >= 0; i--) { 70 | rightCache[i] = arr[i] == 'G' ? rightCache[i + 1] + 1 : rightCache[i + 1]; 71 | } 72 | 73 | int res = Integer.MAX_VALUE; 74 | for (int i = 0; i < arr.length; i++) { // i表示第一个G块 75 | res = Math.min(res, (i - leftCache[i]) + (arr.length - i - rightCache[i])); 76 | } 77 | return res; 78 | } 79 | 80 | public static void main(String[] args) { 81 | String test = "RGGGGGGGRRGRRRGGRRRGGGGR"; 82 | System.out.println(minPaint1(test)); 83 | System.out.println(minPaint2(test)); 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /skill/C08_NeedParentheses.java: -------------------------------------------------------------------------------- 1 | package skill; 2 | 3 | // 一个完整的括号字符串定义规则如下: 4 | // 1空字符串是完整的。 5 | // 2如果s是完整的字符串,那么(s)也是完整的。 6 | // 3如果s和t是完整的字符串,将它们连接起来形成的st也是完整的。 7 | // 例如,"(()())", ""和"(())()"是完整的括号字符串,"())(", "()(" 和 ")" 是不完整的括号字符串。 8 | // 牛牛有一个括号字符串s,现在需要在其中任意位置尽量少地添加括号,将其转化 为一个完整的括号字符串。 9 | // 请问牛牛至少需要添加多少个括号。 10 | public class C08_NeedParentheses { 11 | 12 | // public static int needParentheses(String str) { 13 | // int leftRest = 0; 14 | // int needSolveRight = 0; 15 | // for (int i = 0; i < str.length(); i++) { 16 | // if (str.charAt(i) == '(') { 17 | // leftRest++; 18 | // } else { 19 | // if (leftRest == 0) { 20 | // needSolveRight++; 21 | // } else { 22 | // leftRest--; 23 | // } 24 | // } 25 | // } 26 | // return leftRest + needSolveRight; 27 | // } 28 | 29 | public static int needParentheses(String str) { 30 | int makeUp = 0; 31 | int last = 0; 32 | char[] arr = str.toCharArray(); 33 | for (int i = 0; i < arr.length; i++) { 34 | if (arr[i] == '(') { 35 | last++; 36 | } else if (arr[i] == ')') { 37 | last--; 38 | } 39 | 40 | if (last < 0) { 41 | makeUp++; 42 | last++; 43 | } 44 | } 45 | 46 | return last + makeUp; 47 | } 48 | 49 | public static void main(String args[]) { 50 | 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /skill/C09_SubvalueEqualK.java: -------------------------------------------------------------------------------- 1 | package skill; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.HashSet; 6 | import java.util.List; 7 | 8 | // 给定一个数组arr,求差值为k的去重数字对。 9 | public class C09_SubvalueEqualK { 10 | 11 | // public static List> allPair(int[] arr, int k) { 12 | // HashSet set = new HashSet<>(); 13 | // for (int i = 0; i < arr.length; i++) { 14 | // set.add(arr[i]); 15 | // } 16 | // List> res = new ArrayList<>(); 17 | // for (Integer cur : set) { 18 | // if (set.contains(cur + k)) { 19 | // res.add(Arrays.asList(cur, cur + k)); 20 | // } 21 | // } 22 | // return res; 23 | // } 24 | 25 | public static List> allPair(int[] arr, int k) { 26 | List> res = new ArrayList<>(); 27 | HashSet set = new HashSet<>(); 28 | for (int i = 0; i < arr.length; i++) { 29 | set.add(arr[i]); 30 | } 31 | 32 | for (int i : set) { 33 | if (set.contains(arr[i] + k)) { 34 | res.add(Arrays.asList(arr[i], arr[i] + k)); 35 | } 36 | } 37 | 38 | return res; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /skill/C12_StackSortStack.java: -------------------------------------------------------------------------------- 1 | package skill; 2 | 3 | import java.util.Stack; 4 | 5 | // 请编写一个程序,对一个栈里的整型数据,按升序进行排序(即排序前,栈里 6 | // 的数据是无序的,排序后最大元素位于栈顶),要求最多只能使用一个额外的 7 | // 栈存放临时数据,但不得将元素复制到别的数据结构中。 8 | public class C12_StackSortStack { 9 | 10 | // public static void sortStackByStack(Stack stack) { 11 | // Stack help = new Stack(); 12 | // while (!stack.isEmpty()) { 13 | // int cur = stack.pop(); 14 | // while (!help.isEmpty() && help.peek() < cur) { 15 | // stack.push(help.pop()); 16 | // } 17 | // help.push(cur); 18 | // } 19 | // while (!help.isEmpty()) { 20 | // stack.push(help.pop()); 21 | // } 22 | // } 23 | 24 | public static void sortStackByStack(Stack stack) { 25 | if (stack == null || stack.isEmpty()) { 26 | return; 27 | } 28 | 29 | Stack tem = new Stack<>(); 30 | int n; 31 | tem.push(stack.pop()); 32 | 33 | while (!stack.empty()) { 34 | n = stack.pop(); 35 | while (!tem.isEmpty() && tem.peek() < n) { 36 | stack.push(tem.pop()); 37 | } 38 | tem.push(n); 39 | } 40 | 41 | while (!tem.isEmpty()) { 42 | stack.push(tem.pop()); 43 | } 44 | 45 | } 46 | 47 | public static void main(String[] args) { 48 | Stack stack = new Stack(); 49 | stack.push(3); 50 | stack.push(1); 51 | stack.push(6); 52 | stack.push(2); 53 | stack.push(5); 54 | stack.push(4); 55 | sortStackByStack(stack); 56 | System.out.println(stack.pop()); 57 | System.out.println(stack.pop()); 58 | System.out.println(stack.pop()); 59 | System.out.println(stack.pop()); 60 | System.out.println(stack.pop()); 61 | System.out.println(stack.pop()); 62 | 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /skill/C13_NumToStringWays.java: -------------------------------------------------------------------------------- 1 | package skill; 2 | 3 | // 将给定的数转换为字符串,原则如下:1对应 a,2对应b,.....26对应z, 4 | // 例如12258可以转换为"abbeh", "aveh", "abyh", "lbeh" and "lyh",个数为5, 5 | // 编写一个函数,返回可以转换的不同字符串的个数。 6 | public class C13_NumToStringWays { 7 | 8 | // public static int convertWays(int num) { 9 | // if (num < 1) { 10 | // return 0; 11 | // } 12 | // return process(String.valueOf(num).toCharArray(), 0); 13 | // } 14 | 15 | // public static int process(char[] str, int index) { 16 | // if (index == str.length) { 17 | // return 1; 18 | // } 19 | // if (str[index] == '0') { 20 | // return 0; 21 | // } 22 | // int res = process(str, index + 1); 23 | // if (index == str.length - 1) { 24 | // return res; 25 | // } 26 | // if (((str[index] - '0') * 10 + str[index + 1] - '0') < 27) { 27 | // res += process(str, index + 2); 28 | // } 29 | // return res; 30 | // } 31 | 32 | // // 动态规划 33 | // public static int dpways(int num) { 34 | // if (num < 1) { 35 | // return 0; 36 | // } 37 | // char[] str = String.valueOf(num).toCharArray(); 38 | // int[] dp = new int[str.length + 1]; 39 | // dp[str.length] = 1; 40 | // dp[str.length - 1] = str[str.length - 1] == '0' ? 0 : 1; 41 | // for (int i = str.length - 2; i >= 0; i--) { 42 | // if (str[i] == '0') { 43 | // dp[i] = 0; 44 | // } else { 45 | // dp[i] = dp[i + 1] + (((str[i] - '0') * 10 + str[i + 1] - '0') < 27 ? dp[i + 46 | // 2] : 0); 47 | // } 48 | // } 49 | // return dp[0]; 50 | // } 51 | 52 | public static int convertWays(int num) { 53 | if (num <= 0) { 54 | return 0; 55 | } 56 | 57 | return process(Integer.toString(num).toCharArray(), 0); 58 | } 59 | 60 | private static int process(char[] arr, int i) { 61 | 62 | if (i == arr.length) { 63 | return 1; 64 | } 65 | 66 | if (i > arr.length || arr[i] == '0') { 67 | return 0; 68 | } 69 | 70 | int res = process(arr, i + 1); 71 | if (arr[i] == '1' || (arr[i] == '2' && arr[i + 1] < '7')) { 72 | res += process(arr, i + 2); 73 | } 74 | return res; 75 | } 76 | 77 | public static int dpways(int num) { 78 | String str = String.valueOf(num); 79 | int[] cache = new int[str.length() + 1]; 80 | 81 | cache[cache.length - 1] = 1; 82 | // cache[str.length() - 1] = 1; // 不算这项,下面的i + 1, i + 2会越界 83 | for (int i = cache.length - 2; i >= 0; i--) { 84 | cache[i] = cache[i + 1]; 85 | if (i < cache.length - 2 && (str.charAt(i) == '1' || ( str.charAt(i) == '2' && str.charAt(i + 1) < '7'))) { 86 | cache[i] += cache[i + 2]; 87 | } 88 | } 89 | return cache[0]; 90 | } 91 | 92 | public static void main(String[] args) { 93 | int test = 1121143311; 94 | System.out.println(convertWays(test)); 95 | System.out.println(dpways(test)); 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /skill/C14_MaxSumInTree.java: -------------------------------------------------------------------------------- 1 | package skill; 2 | 3 | import java.util.HashMap; 4 | import java.util.Stack; 5 | 6 | // 二叉树每个结点都有一个int型权值, 7 | // 给定一棵二叉树,要求计算出从根结点到叶结点的所有路径中,最大的权值和为多少。 8 | 9 | public class C14_MaxSumInTree { 10 | 11 | public static class Node { 12 | public int value; 13 | public Node left; 14 | public Node right; 15 | 16 | public Node(int val) { 17 | value = val; 18 | } 19 | } 20 | 21 | // public static int maxSumRecursive(Node head) { 22 | // return process(head, 0); 23 | // } 24 | 25 | // public static int process(Node x, int pre) { 26 | // if (x == null) { 27 | // return Integer.MIN_VALUE; 28 | // } 29 | // if (x.left == null && x.right == null) { 30 | // return pre + x.value; 31 | // } 32 | // int leftMax = process(x.left, pre + x.value); 33 | // int rightMax = process(x.right, pre + x.value); 34 | // return Math.max(leftMax, rightMax); 35 | // } 36 | 37 | // public static int maxSumUnrecursive(Node head) { 38 | // int max = 0; 39 | // HashMap sumMap = new HashMap<>(); 40 | // if (head != null) { 41 | // Stack stack = new Stack(); 42 | // stack.add(head); 43 | // sumMap.put(head, head.value); 44 | // while (!stack.isEmpty()) { 45 | // head = stack.pop(); 46 | // if (head.left == null && head.right == null) { 47 | // max = Math.max(max, sumMap.get(head)); 48 | // } 49 | // if (head.right != null) { 50 | // sumMap.put(head.right, sumMap.get(head) + head.right.value); 51 | // stack.push(head.right); 52 | // } 53 | // if (head.left != null) { 54 | // sumMap.put(head.left, sumMap.get(head) + head.left.value); 55 | // stack.push(head.left); 56 | // } 57 | // } 58 | // } 59 | // return max; 60 | // } 61 | public static int maxSumRecursive(Node head) { 62 | if (head == null) { 63 | return 0; 64 | } 65 | 66 | return Math.max(head.left == null ? 0 : maxSumRecursive(head.left), 67 | head.right == null ? 0 : maxSumRecursive(head.right)) + head.value; 68 | } 69 | 70 | public static int maxSumUnrecursive(Node head) { 71 | if (head == null) { 72 | return 0; 73 | } 74 | 75 | int res = 0; 76 | HashMap preSumMap = new HashMap<>(); 77 | preSumMap.put(head, head.value); 78 | 79 | Stack recurStack = new Stack<>(); 80 | recurStack.push(head); 81 | 82 | while (!recurStack.isEmpty()) { 83 | head = recurStack.pop(); 84 | if (head.left == null && head.right == null) { 85 | res = Math.max(res, preSumMap.get(head)); 86 | } 87 | if (head.left != null) { 88 | preSumMap.put(head.left, head.left.value + preSumMap.get(head)); 89 | recurStack.push(head.left); 90 | } 91 | if (head.right != null) { 92 | preSumMap.put(head.right, head.right.value + preSumMap.get(head)); 93 | recurStack.push(head.right); 94 | } 95 | } 96 | return res; 97 | } 98 | 99 | public static void main(String[] args) { 100 | Node head = new Node(4); 101 | head.left = new Node(1); 102 | head.left.right = new Node(5); 103 | head.right = new Node(-7); 104 | head.right.left = new Node(3); 105 | System.out.println(maxSumRecursive(head)); 106 | System.out.println(maxSumUnrecursive(head)); 107 | 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /skill/C15_FindNumInSortedMatrix.java: -------------------------------------------------------------------------------- 1 | package skill; 2 | 3 | // 给定一个元素为非负整数的二维数组matrix,每行和每列都是从小到大有序的。 4 | // 再给定一个非负整数aim,请判断aim是否在matrix中。 5 | 6 | public class C15_FindNumInSortedMatrix { 7 | 8 | // public static boolean isContains(int[][] matrix, int K) { 9 | // int row = 0; 10 | // int col = matrix[0].length - 1; 11 | // while (row < matrix.length && col > -1) { 12 | // if (matrix[row][col] == K) { 13 | // return true; 14 | // } else if (matrix[row][col] > K) { 15 | // col--; 16 | // } else { 17 | // row++; 18 | // } 19 | // } 20 | // return false; 21 | // } 22 | 23 | // 暴力O(n2) 24 | public static boolean isContains(int[][] matrix, int K) { 25 | if (matrix == null) { 26 | return false; 27 | } 28 | 29 | for (int i = 0; i < matrix.length; i++) { 30 | for (int j = 0; j < matrix[0].length; j++) { 31 | if (matrix[i][j] == K) { 32 | return true; 33 | } 34 | } 35 | } 36 | return false; 37 | } 38 | 39 | // O(n)复杂度 40 | public static boolean isContains2(int[][] matrix, int K) { 41 | if (matrix == null || matrix[0][0] > K) { 42 | return false; 43 | } 44 | 45 | int row = 0; 46 | // 为什么列从最后一列开始,因为这样整个查找过程都是col--; 从0开始的话,一开始的col++,后面可能有要col--,不够固定 47 | int col = matrix[0].length - 1; 48 | while (row < matrix.length && col >= 0) { 49 | if (matrix[row][col] == K) { 50 | return true; 51 | } else if (matrix[row][col] > K) { 52 | col--; 53 | } else if (matrix[row][col] < K) { 54 | row++; 55 | } 56 | } 57 | return false; 58 | } 59 | 60 | public static void main(String[] args) { 61 | int[][] matrix = new int[][] { { 0, 1, 2, 3, 4, 5, 6 }, // 0 62 | { 10, 12, 13, 15, 16, 17, 18 }, // 1 63 | { 23, 24, 25, 26, 27, 28, 29 }, // 2 64 | { 44, 45, 46, 47, 48, 49, 50 }, // 3 65 | { 65, 66, 67, 68, 69, 70, 71 }, // 4 66 | { 96, 97, 98, 99, 100, 111, 122 }, // 5 67 | { 166, 176, 186, 187, 190, 195, 200 }, // 6 68 | { 233, 243, 321, 341, 356, 370, 380 } // 7 69 | }; 70 | int K = 233; 71 | System.out.println(isContains(matrix, K)); 72 | System.out.println(isContains2(matrix, K)); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /skill/C16_PackingMachine.java: -------------------------------------------------------------------------------- 1 | package skill; 2 | 3 | // LeetCode:https://leetcode-cn.com/problems/super-washing-machines/ 4 | // 有n个打包机器从左到右一字排开,上方有一个自动装置会抓取一批放物品到每个打包机上, 5 | // 放到每个机器上的这些物品数量有多有少,由于物品数量不相同, 6 | // 需要工人将每个机器上的物品进行移动从而到达物品数量相等才能打包。(每轮所有位置的包都能移动一次) 7 | // 每个物品重量太大、 每次只能搬一个物品进行移动,为了省力,只在相邻的机器上移动。 8 | // 请计算在搬动最小轮数的前提下,使每个机器上的物品数量相等。如果不能使每个机器上的物品相同,返回-1。 9 | // 例如[1,0,5]表示有3个机器,每个机器上分别有1、0、5个物品,经过这些轮后: 10 | // 第一轮:1 0<-5 => 1 1 4 11 | // 第二轮:1<-1<-4 => 2 1 3 12 | // 第三轮:2 1 <- 3 => 2 2 2 13 | // 移动了3轮,每个机器上的物品相等,所以返回3 14 | // 例如[2,2,3]表示有3个机器,每个机器上分别有2、2、3个物品,这些物品不管怎么移动, 15 | // 都不能使三个机器上物品数量相等,返回-1 16 | 17 | // NOTE:复杂的题目,考虑任意位置i的相关情况,一般是i的值什么情况,左侧什么情况,右侧什么情况,进行分类讨论,发现规律 18 | public class C16_PackingMachine { 19 | 20 | // public static int MinOps(int[] arr) { 21 | // if (arr == null || arr.length == 0) { 22 | // return 0; 23 | // } 24 | // int size = arr.length; 25 | // int sum = 0; 26 | // for (int i = 0; i < size; i++) { 27 | // sum += arr[i]; 28 | // } 29 | // if (sum % size != 0) { 30 | // return -1; 31 | // } 32 | // int avg = sum / size; 33 | // int leftSum = 0; 34 | // int ans = 0; 35 | // for (int i = 0; i < arr.length; i++) { 36 | // int L = i * avg - leftSum; 37 | // int R = (size - i - 1) * avg - (sum - leftSum - arr[i]); 38 | // if (L > 0 && R > 0) { 39 | // ans = Math.max(ans, Math.abs(L) + Math.abs(R)); 40 | // } else { 41 | // ans = Math.max(ans, Math.max(Math.abs(L), Math.abs(R))); 42 | // } 43 | // leftSum += arr[i]; 44 | // } 45 | // return ans; 46 | // } 47 | 48 | public static int MinOps2(int[] arr) { 49 | int sum = 0; 50 | for (int i = 0; i < arr.length; i++) { 51 | sum += arr[i]; 52 | } 53 | if (sum % arr.length != 0) { 54 | return -1; 55 | } 56 | 57 | int average = sum / arr.length; 58 | int preOver = 0; // 当前值之前部分多出的份数 59 | int postOver = (sum - arr[0]) - (average * (arr.length - 1)); // 当前值之后部分多出的份数 60 | int res = arr[0] - average * 1; 61 | for (int i = 1; i < arr.length; i++) { 62 | preOver += (arr[i - 1] - average); 63 | postOver -= (arr[i] - average); 64 | 65 | // if (preOver > 0 && postOver > 0) { 66 | // res = Math.max(res, Math.max(preOver, postOver)); 67 | // } else if (preOver <= 0 && postOver <= 0) { 68 | // res = Math.max(res, -(preOver + postOver)); 69 | // } else { 70 | // res = Math.max(res, Math.max(Math.abs(preOver), Math.abs(postOver))); 71 | // } 72 | 73 | // 简化后 74 | if (preOver <= 0 && postOver <= 0) { 75 | res = Math.max(res, -(preOver + postOver)); 76 | } else { 77 | res = Math.max(res, Math.max(Math.abs(preOver), Math.abs(postOver))); 78 | } 79 | } 80 | 81 | return res; 82 | } 83 | 84 | public static void main(String[] args) { 85 | int[] arr = new int[] { 4, 9, 29 }; 86 | // System.out.println(MinOps(arr)); 87 | System.out.println(MinOps2(arr)); 88 | 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /skill/C17_SplitNbySM.java: -------------------------------------------------------------------------------- 1 | package skill; 2 | 3 | // 假设s和m初始化,s = "a"; m = s; 再定义两种操作, 4 | // 第一种操作: 5 | // m = s; 6 | // s = s + s; 7 | // 第二种操作: 8 | // s = s + m; 9 | // 求最小的操作步骤数,可以将s拼接到长度等于n 10 | 11 | // NOTE:纯数学分析,不要求会 12 | // 结论:1.若n为质数,则只使用操作二的答案就是最小操作数 13 | // 因为:除了2质数都不是偶数,操作二只调一次时,和调一次操作一效果一样;若调了两次以上,s一定是偶数,就不是质数了 14 | public class C17_SplitNbySM { 15 | 16 | // 附加题:怎么判断一个数是不是质数? 17 | public static boolean isPrim(int n) { 18 | if (n < 2) { 19 | return false; 20 | } 21 | int max = (int) Math.sqrt((double) n); 22 | for (int i = 2; i <= max; i++) { 23 | if (n % i == 0) { 24 | return false; 25 | } 26 | } 27 | return true; 28 | } 29 | 30 | // 请保证n不是质数 31 | // 返回: 32 | // 0) 所有因子的和,但是因子不包括1 33 | // 1) 所有因子的个数,但是因子不包括1 34 | public static int[] divsSumAndCount(int n) { 35 | int sum = 0; 36 | int count = 0; 37 | for (int i = 2; i <= n; i++) { 38 | while (n % i == 0) { 39 | sum += i; 40 | count++; 41 | n /= i; 42 | } 43 | } 44 | return new int[] { sum, count }; 45 | } 46 | 47 | public static int minOps(int n) { 48 | if (n < 2) { 49 | return 0; 50 | } 51 | if (isPrim(n)) { 52 | return n - 1; 53 | } 54 | int[] divSumAndCount = divsSumAndCount(n); 55 | return divSumAndCount[0] - divSumAndCount[1]; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /sort/C01_SelectionSort.java: -------------------------------------------------------------------------------- 1 | package sort; 2 | 3 | import java.util.Arrays; 4 | 5 | // 选择排序 6 | public class C01_SelectionSort { 7 | 8 | public static void selectionSort_answer(int[] arr) { 9 | 10 | for (int i = 0; i < arr.length - 1; i++) { 11 | int minIndex = i; 12 | for (int j = i + 1; j < arr.length; j++) { 13 | minIndex = arr[j] < arr[minIndex] ? j : minIndex; 14 | } 15 | swap(arr, i, minIndex); 16 | } 17 | } 18 | 19 | public static void selectionSort(int[] arr) { 20 | if (arr == null || arr.length < 2) { 21 | return; 22 | } 23 | 24 | int minIndex = 0; 25 | for (int i = 0; i < arr.length; i++) { 26 | minIndex = i; 27 | for (int j = i + 1; j < arr.length; j++) { 28 | if (arr[j] < arr[minIndex]) { 29 | minIndex = j; 30 | } 31 | } 32 | swap(arr, i, minIndex); 33 | } 34 | } 35 | 36 | public static void swap(int[] arr, int i, int j) { 37 | int tmp = arr[i]; 38 | arr[i] = arr[j]; 39 | arr[j] = tmp; 40 | } 41 | 42 | // for test 43 | public static void comparator(int[] arr) { 44 | Arrays.sort(arr); 45 | } 46 | 47 | // for test 48 | public static int[] generateRandomArray(int maxSize, int maxValue) { 49 | int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; 50 | for (int i = 0; i < arr.length; i++) { 51 | arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); 52 | } 53 | return arr; 54 | } 55 | 56 | // for test 57 | public static int[] copyArray(int[] arr) { 58 | if (arr == null) { 59 | return null; 60 | } 61 | int[] res = new int[arr.length]; 62 | for (int i = 0; i < arr.length; i++) { 63 | res[i] = arr[i]; 64 | } 65 | return res; 66 | } 67 | 68 | // for test 69 | public static boolean isEqual(int[] arr1, int[] arr2) { 70 | if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) { 71 | return false; 72 | } 73 | if (arr1 == null && arr2 == null) { 74 | return true; 75 | } 76 | if (arr1.length != arr2.length) { 77 | return false; 78 | } 79 | for (int i = 0; i < arr1.length; i++) { 80 | if (arr1[i] != arr2[i]) { 81 | return false; 82 | } 83 | } 84 | return true; 85 | } 86 | 87 | // for test 88 | 89 | public static void printArray(int[] arr) { 90 | if (arr == null) { 91 | return; 92 | } 93 | for (int i = 0; i < arr.length; i++) { 94 | System.out.print(arr[i] + " "); 95 | } 96 | System.out.println();System.out.println(); 97 | } 98 | 99 | // for test 100 | public static void main(String[] args) { 101 | int testTime = 500000; 102 | int maxSize = 100; 103 | int maxValue = 100; 104 | boolean succeed = true; 105 | for (int i = 0; i < testTime; i++) { 106 | int[] arr1 = generateRandomArray(maxSize, maxValue); 107 | int[] arr2 = copyArray(arr1); 108 | selectionSort(arr1); 109 | comparator(arr2); 110 | if (!isEqual(arr1, arr2)) { 111 | succeed = false; 112 | printArray(arr1); 113 | printArray(arr2); 114 | break; 115 | } 116 | } 117 | System.out.println(succeed ? "Nice!" : "Fucking fucked!"); 118 | 119 | int[] arr = generateRandomArray(maxSize, maxValue); 120 | printArray(arr); 121 | selectionSort(arr); 122 | printArray(arr); 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /sort/C02_BubbleSort.java: -------------------------------------------------------------------------------- 1 | package sort; 2 | 3 | import java.util.Arrays; 4 | 5 | // 冒泡排序 6 | public class C02_BubbleSort { 7 | 8 | public static void bubbleSort_answer(int[] arr) { 9 | if (arr == null || arr.length < 2) { 10 | return; 11 | } 12 | for (int e = arr.length - 1; e > 0; e--) { 13 | for (int i = 0; i < e; i++) { 14 | if (arr[i] > arr[i + 1]) { 15 | swap(arr, i, i + 1); 16 | } 17 | } 18 | } 19 | } 20 | 21 | public static void bubbleSort(int[] arr) { 22 | if (arr == null || arr.length < 2) { 23 | return; 24 | } 25 | 26 | for (int i = arr.length - 1; i > 0; i--) { 27 | 28 | for (int j = 0; j < i ; j++) { 29 | if (arr[j] > arr[j + 1]) { 30 | swap(arr, j, j + 1); 31 | } 32 | } 33 | } 34 | } 35 | 36 | public static void swap(int[] arr, int i, int j) { 37 | 38 | arr[i] = arr[i] ^ arr[j]; 39 | arr[j] = arr[i] ^ arr[j]; 40 | arr[i] = arr[i] ^ arr[j]; 41 | } 42 | 43 | // for test 44 | public static void comparator(int[] arr) { 45 | Arrays.sort(arr); 46 | } 47 | 48 | // for test 49 | public static int[] generateRandomArray(int maxSize, int maxValue) { 50 | int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; 51 | for (int i = 0; i < arr.length; i++) { 52 | arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); 53 | } 54 | return arr; 55 | } 56 | 57 | // for test 58 | public static int[] copyArray(int[] arr) { 59 | if (arr == null) { 60 | return null; 61 | } 62 | int[] res = new int[arr.length]; 63 | for (int i = 0; i < arr.length; i++) { 64 | res[i] = arr[i]; 65 | } 66 | return res; 67 | } 68 | 69 | // for test 70 | public static boolean isEqual(int[] arr1, int[] arr2) { 71 | if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) { 72 | return false; 73 | } 74 | if (arr1 == null && arr2 == null) { 75 | return true; 76 | } 77 | if (arr1.length != arr2.length) { 78 | return false; 79 | } 80 | for (int i = 0; i < arr1.length; i++) { 81 | if (arr1[i] != arr2[i]) { 82 | return false; 83 | } 84 | } 85 | return true; 86 | } 87 | 88 | // for test 89 | public static void printArray(int[] arr) { 90 | if (arr == null) { 91 | return; 92 | } 93 | for (int i = 0; i < arr.length; i++) { 94 | System.out.print(arr[i] + " "); 95 | } 96 | System.out.println();System.out.println(); 97 | } 98 | 99 | // for test 100 | public static void main(String[] args) { 101 | int testTime = 500000; 102 | int maxSize = 100; 103 | int maxValue = 100; 104 | boolean succeed = true; 105 | for (int i = 0; i < testTime; i++) { 106 | int[] arr1 = generateRandomArray(maxSize, maxValue); 107 | int[] arr2 = copyArray(arr1); 108 | bubbleSort(arr1); 109 | comparator(arr2); 110 | if (!isEqual(arr1, arr2)) { 111 | succeed = false; 112 | break; 113 | } 114 | } 115 | System.out.println(succeed ? "Nice!" : "Fucking fucked!"); 116 | 117 | int[] arr = generateRandomArray(maxSize, maxValue); 118 | printArray(arr); 119 | bubbleSort(arr); 120 | printArray(arr); 121 | } 122 | 123 | } 124 | -------------------------------------------------------------------------------- /sort/C03_InsertionSort.java: -------------------------------------------------------------------------------- 1 | package sort; 2 | 3 | import java.util.Arrays; 4 | 5 | // 插入排序 6 | public class C03_InsertionSort { 7 | 8 | public static void insertionSort(int[] arr) { 9 | if (arr == null || arr.length < 2) { 10 | return; 11 | } 12 | for (int i = 1; i < arr.length; i++) { 13 | for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) { 14 | swap(arr, j, j + 1); 15 | } 16 | } 17 | } 18 | 19 | public static void swap(int[] arr, int i, int j) { 20 | arr[i] = arr[i] ^ arr[j]; 21 | arr[j] = arr[i] ^ arr[j]; 22 | arr[i] = arr[i] ^ arr[j]; 23 | } 24 | 25 | // for test 26 | public static void comparator(int[] arr) { 27 | Arrays.sort(arr); 28 | } 29 | 30 | // for test 31 | public static int[] generateRandomArray(int maxSize, int maxValue) { 32 | int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; 33 | for (int i = 0; i < arr.length; i++) { 34 | arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); 35 | } 36 | return arr; 37 | } 38 | 39 | // for test 40 | public static int[] copyArray(int[] arr) { 41 | if (arr == null) { 42 | return null; 43 | } 44 | int[] res = new int[arr.length]; 45 | for (int i = 0; i < arr.length; i++) { 46 | res[i] = arr[i]; 47 | } 48 | return res; 49 | } 50 | 51 | // for test 52 | public static boolean isEqual(int[] arr1, int[] arr2) { 53 | if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) { 54 | return false; 55 | } 56 | if (arr1 == null && arr2 == null) { 57 | return true; 58 | } 59 | if (arr1.length != arr2.length) { 60 | return false; 61 | } 62 | for (int i = 0; i < arr1.length; i++) { 63 | if (arr1[i] != arr2[i]) { 64 | return false; 65 | } 66 | } 67 | return true; 68 | } 69 | 70 | // for test 71 | public static void printArray(int[] arr) { 72 | if (arr == null) { 73 | return; 74 | } 75 | for (int i = 0; i < arr.length; i++) { 76 | System.out.print(arr[i] + " "); 77 | } 78 | System.out.println();System.out.println();System.out.println(); 79 | } 80 | 81 | // for test 82 | public static void main(String[] args) { 83 | int testTime = 500000; 84 | int maxSize = 100; 85 | int maxValue = 100; 86 | boolean succeed = true; 87 | for (int i = 0; i < testTime; i++) { 88 | int[] arr1 = generateRandomArray(maxSize, maxValue); 89 | int[] arr2 = copyArray(arr1); 90 | insertionSort(arr1); 91 | comparator(arr2); 92 | if (!isEqual(arr1, arr2)) { 93 | succeed = false; 94 | break; 95 | } 96 | } 97 | System.out.println(succeed ? "Nice!" : "Fucking fucked!"); 98 | 99 | int[] arr = generateRandomArray(maxSize, maxValue); 100 | printArray(arr); 101 | insertionSort(arr); 102 | printArray(arr); 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /sort/C07_EvenTimesOddTimes.java: -------------------------------------------------------------------------------- 1 | package sort; 2 | 3 | // 4)一个数组中有一种数出现了奇数次,其他数都出现了偶数次,怎么找到这一个数 4 | // 5)一个数组中有两种数出现了奇数次,其他数都出现了偶数次,怎么找到这两个数 5 | public class C07_EvenTimesOddTimes { 6 | 7 | public static void printOddTimesNum1(int[] arr) { 8 | int eO = 0; 9 | for (int cur : arr) { 10 | eO ^= cur; 11 | } 12 | System.out.println(eO); 13 | } 14 | 15 | public static void printOddTimesNum2_answer(int[] arr) { 16 | int eO = 0, eOhasOne = 0; 17 | for (int curNum : arr) { 18 | eO ^= curNum; 19 | } 20 | int rightOne = eO & (~eO + 1); 21 | for (int cur : arr) { 22 | if ((cur & rightOne) != 0) { 23 | eOhasOne ^= cur; 24 | } 25 | } 26 | System.out.println(eOhasOne + " " + (eO ^ eOhasOne)); 27 | } 28 | 29 | public static void printOddTimesNum2(int[] arr) { 30 | int r = 0; 31 | for (int val : arr) { 32 | r ^= val; 33 | } 34 | int rightOne = r & (~r + 1); 35 | int a = 0; 36 | for (int val : arr) { 37 | if ((val & rightOne) != 0) { 38 | a ^= val; 39 | } 40 | } 41 | 42 | System.out.println(a + " " +( a ^ r)); 43 | } 44 | 45 | public static void main(String[] args) { 46 | int a = 5; 47 | int b = 7; 48 | 49 | a = a ^ b; 50 | b = a ^ b; 51 | a = a ^ b; 52 | 53 | System.out.println(a); 54 | System.out.println(b); 55 | 56 | int[] arr1 = { 3, 3, 2, 3, 1, 1, 1, 3, 1, 1, 1 }; 57 | printOddTimesNum1(arr1); 58 | 59 | int[] arr2 = { 4, 3, 4, 2, 2, 2, 4, 1, 1, 1, 3, 3, 1, 1, 1, 4, 2, 2 }; 60 | printOddTimesNum2(arr2); 61 | 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /sort/C09_FindOneLessValueIndex.java: -------------------------------------------------------------------------------- 1 | package sort; 2 | 3 | // TODO: unknow question 4 | public class C09_FindOneLessValueIndex { 5 | 6 | public static int getLessIndex(int[] arr) { 7 | if (arr == null || arr.length == 0) { 8 | return -1; // no exist 9 | } 10 | if (arr.length == 1 || arr[0] < arr[1]) { 11 | return 0; 12 | } 13 | if (arr[arr.length - 1] < arr[arr.length - 2]) { 14 | return arr.length - 1; 15 | } 16 | int left = 1; 17 | int right = arr.length - 2; 18 | int mid = 0; 19 | while (left < right) { 20 | mid = (left + right) / 2; 21 | if (arr[mid] > arr[mid - 1]) { 22 | right = mid - 1; 23 | } else if (arr[mid] > arr[mid + 1]) { 24 | left = mid + 1; 25 | } else { 26 | return mid; 27 | } 28 | } 29 | return left; 30 | } 31 | 32 | public static void printArray(int[] arr) { 33 | for (int i = 0; i != arr.length; i++) { 34 | System.out.print(arr[i] + " "); 35 | } 36 | System.out.println(); 37 | } 38 | 39 | public static void main(String[] args) { 40 | int[] arr = { 6, 5, 3, 4, 6, 7, 8 }; 41 | printArray(arr); 42 | int index = getLessIndex(arr); 43 | System.out.println("index: " + index + ", value: " + arr[index]); 44 | 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /sort/C13_SortArrayDistanceLessK.java: -------------------------------------------------------------------------------- 1 | package sort; 2 | 3 | import java.util.PriorityQueue; 4 | 5 | // 已知一个几乎有序的数组,几乎有序是指,如果把数组排好顺序的话,每个元素移动的距离可以不超过k,并且k相对于数组来说比较小。 6 | // 请选择一个合适的排序算法针对这个数据进行排序。 7 | public class C13_SortArrayDistanceLessK { 8 | 9 | public void sortedArrDistanceLessK(int[] arr, int k) { 10 | PriorityQueue heap = new PriorityQueue<>(); 11 | int index = 0; 12 | for (; index < Math.min(arr.length, k); index++) { 13 | heap.add(arr[index]); 14 | } 15 | int i = 0; 16 | for (; index < arr.length; i++, index++) { 17 | heap.add(arr[index]); 18 | arr[i] = heap.poll(); 19 | } 20 | while (!heap.isEmpty()) { 21 | arr[i++] = heap.poll(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /sort/C14_NetherlandsFlag.java: -------------------------------------------------------------------------------- 1 | package sort; 2 | 3 | // 荷兰国旗问题 问题一 4 | // 给定一个数组arr,和一个数num,请把小于等于num的数放在数组的左边,大于num的数放在数组的右边。 5 | // 要求额外空间复杂度O(1),时间复杂度O(N) 6 | 7 | // 问题二(荷兰国旗问题) 8 | // 给定一个数组arr,和一个数num,请把小于num的数放在数组的左边,等于num的数放在数组的中间,大于num的数放在数组的右边。 9 | // 要求额外空间复杂度O(1),时间复杂度O(N) 10 | public class C14_NetherlandsFlag { 11 | 12 | // public static int[] partition(int[] arr, int l, int r, int p) { 13 | // int less = l - 1; 14 | // int more = r + 1; 15 | // while (l < more) { 16 | // if (arr[l] < p) { 17 | // swap(arr, ++less, l++); 18 | // } else if (arr[l] > p) { 19 | // swap(arr, --more, l); 20 | // } else { 21 | // l++; 22 | // } 23 | // } 24 | // return new int[] { less + 1, more - 1 }; 25 | // } 26 | 27 | public static int[] partition(int[] arr, int start, int end, int val) { 28 | int left = start - 1; 29 | int right = end + 1; 30 | int i = start; 31 | while (i < right) { 32 | if (arr[i] > val) { 33 | swap(arr, i, --right); 34 | } else if (arr[i] == val) { 35 | i++; 36 | } else { 37 | swap(arr, i++, ++left); 38 | } 39 | } 40 | 41 | return new int[] { left + 1, right - 1 }; 42 | } 43 | 44 | // for test 45 | public static void swap(int[] arr, int i, int j) { 46 | int tmp = arr[i]; 47 | arr[i] = arr[j]; 48 | arr[j] = tmp; 49 | } 50 | 51 | // for test 52 | public static int[] generateArray() { 53 | int[] arr = new int[10]; 54 | for (int i = 0; i < arr.length; i++) { 55 | arr[i] = (int) (Math.random() * 3); 56 | } 57 | return arr; 58 | } 59 | 60 | // for test 61 | public static void printArray(int[] arr) { 62 | if (arr == null) { 63 | return; 64 | } 65 | for (int i = 0; i < arr.length; i++) { 66 | System.out.print(arr[i] + " "); 67 | } 68 | System.out.println(); 69 | System.out.println(); 70 | System.out.println(); 71 | } 72 | 73 | public static void main(String[] args) { 74 | int[] test = generateArray(); 75 | 76 | printArray(test); 77 | int[] res = partition(test, 0, test.length - 1, 1); 78 | printArray(test); 79 | System.out.println(res[0]); 80 | System.out.println(res[1]); 81 | 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /tree/C02_PrintBinaryTree.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | // 如何直观的打印一颗二叉树 4 | public class C02_PrintBinaryTree { 5 | 6 | public static class Node { 7 | public int value; 8 | public Node left; 9 | public Node right; 10 | 11 | public Node(int data) { 12 | this.value = data; 13 | } 14 | } 15 | 16 | public static void printTree(Node head) { 17 | System.out.println("Binary Tree:"); 18 | printInOrder(head, 0, "H", 17); 19 | System.out.println(); 20 | } 21 | 22 | public static void printInOrder(Node head, int height, String to, int len) { 23 | if (head == null) { 24 | return; 25 | } 26 | printInOrder(head.right, height + 1, "v", len); 27 | String val = to + head.value + to; 28 | int lenM = val.length(); 29 | int lenL = (len - lenM) / 2; 30 | int lenR = len - lenM - lenL; 31 | val = getSpace(lenL) + val + getSpace(lenR); 32 | System.out.println(getSpace(height * len) + val); 33 | printInOrder(head.left, height + 1, "^", len); 34 | } 35 | 36 | public static String getSpace(int num) { 37 | String space = " "; 38 | StringBuffer buf = new StringBuffer(""); 39 | for (int i = 0; i < num; i++) { 40 | buf.append(space); 41 | } 42 | return buf.toString(); 43 | } 44 | 45 | public static void main(String[] args) { 46 | // Node head = new Node(1); 47 | // head.left = new Node(-222222222); 48 | // head.right = new Node(3); 49 | // head.left.left = new Node(Integer.MIN_VALUE); 50 | // head.right.left = new Node(55555555); 51 | // head.right.right = new Node(66); 52 | // head.left.left.right = new Node(777); 53 | // printTree(head); 54 | 55 | // head = new Node(1); 56 | // head.left = new Node(2); 57 | // head.right = new Node(3); 58 | // head.left.left = new Node(4); 59 | // head.right.left = new Node(5); 60 | // head.right.right = new Node(6); 61 | // head.left.left.right = new Node(7); 62 | // printTree(head); 63 | 64 | // head = new Node(1); 65 | // head.left = new Node(1); 66 | // head.right = new Node(1); 67 | // head.left.left = new Node(1); 68 | // head.right.left = new Node(1); 69 | // head.right.right = new Node(1); 70 | // head.left.left.right = new Node(1); 71 | // printTree(head); 72 | 73 | // Node head = new Node(5); 74 | // head.left = new Node(3); 75 | // head.right = new Node(8); 76 | // head.left.left = new Node(2); 77 | // head.left.right = new Node(4); 78 | // head.left.left.left = new Node(1); 79 | // head.right.left = new Node(7); 80 | // head.right.left.left = new Node(6); 81 | // head.right.right = new Node(10); 82 | // head.right.right.left = new Node(9); 83 | // head.right.right.right = new Node(11); 84 | // printTree(head); 85 | 86 | Node head = new Node(5); 87 | head.left = new Node(3); 88 | head.right = new Node(8); 89 | head.left.left = new Node(2); 90 | head.left.right = new Node(4); 91 | head.left.right.left = new Node(12); 92 | head.left.right.right = new Node(13); 93 | head.left.left.left = new Node(1); 94 | head.left.left.right = new Node(10); 95 | head.right.left = new Node(7); 96 | head.right.left.left = new Node(6); 97 | head.right.left.right = new Node(15); 98 | head.right.right = new Node(10); 99 | head.right.right.left = new Node(9); 100 | head.right.right.right = new Node(11); 101 | printTree(head); 102 | 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /tree/C05_IsCBT.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | import java.util.LinkedList; 4 | 5 | // 如何判断一颗二叉树是否是完全二叉树? 6 | public class C05_IsCBT { 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 boolean isCBT(Node head) { // 完全二叉树 19 | // if (head == null) { 20 | // return true; 21 | // } 22 | // LinkedList queue = new LinkedList<>(); 23 | // boolean leaf = false; 24 | // Node l = null; 25 | // Node r = null; 26 | // queue.add(head); 27 | // while (!queue.isEmpty()) { 28 | // head = queue.poll(); 29 | // l = head.left; 30 | // r = head.right; 31 | // if ((leaf && (l != null || r != null)) || (l == null && r != null)) { 32 | // return false; 33 | // } 34 | // if (l != null) { 35 | // queue.add(l); 36 | // } 37 | // if (r != null) { 38 | // queue.add(r); 39 | // } else { 40 | // leaf = true; 41 | // } 42 | // } 43 | // return true; 44 | // } 45 | 46 | public static boolean isCBT(Node head) { // 完全二叉树 47 | if (head == null) { 48 | return true; 49 | } 50 | 51 | LinkedList tem = new LinkedList<>(); 52 | tem.add(head); 53 | boolean shouldBeLeaf = false; 54 | while (!tem.isEmpty()) { 55 | head = tem.poll(); 56 | if (head.right != null && head.left == null) { 57 | return false; 58 | } 59 | 60 | if (shouldBeLeaf && (head.left != null || head.right != null)) { 61 | return false; 62 | } 63 | 64 | if (head.left != null) { 65 | tem.add(head.left); 66 | } else { 67 | shouldBeLeaf = true; 68 | } 69 | if (head.right != null) { 70 | tem.add(head.right); 71 | } else { 72 | shouldBeLeaf = true; 73 | } 74 | } 75 | 76 | return true; 77 | } 78 | 79 | public static void main(String[] args) { 80 | Node head = new Node(5); 81 | head.left = new Node(3); 82 | head.right = new Node(8); 83 | head.left.left = new Node(2); 84 | head.left.right = new Node(4); 85 | head.left.right.left = new Node(12); 86 | head.left.right.right = new Node(13); 87 | head.left.left.left = new Node(1); 88 | head.left.left.right = new Node(10); 89 | head.right.left = new Node(7); 90 | head.right.left.left = new Node(6); 91 | // head.right.left.right = new Node(15); 92 | head.right.right = new Node(10); 93 | // head.right.right.left = new Node(9); 94 | // head.right.right.right = new Node(11); 95 | System.out.println(isCBT(head)); 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /tree/C05_isFullBinaryTree.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | // 如何判断一颗二叉树是否是满二叉树? 4 | public class C05_isFullBinaryTree { 5 | 6 | public static class Node { 7 | public int value; 8 | public Node left; 9 | public Node right; 10 | 11 | public Node(int data) { 12 | this.value = data; 13 | } 14 | } 15 | 16 | private static class ReturnType { 17 | int height; 18 | int nodeCount; 19 | 20 | public ReturnType(int height, int nodeCount) { 21 | this.height = height; 22 | this.nodeCount = nodeCount; 23 | } 24 | 25 | } 26 | 27 | public static boolean isFullBinaryTree(Node head) { // 满二叉树 28 | ReturnType info = process(head); 29 | System.out.println(info.height + " " + info.nodeCount); 30 | return info.nodeCount == Math.pow(2, info.height) - 1; 31 | 32 | } 33 | 34 | private static ReturnType process(Node head) { 35 | if (head == null) { 36 | return new ReturnType(0, 0); 37 | } 38 | 39 | ReturnType left = process(head.left); 40 | ReturnType right = process(head.right); 41 | 42 | return new ReturnType(Math.max(left.height, right.height) + 1, left.nodeCount + right.nodeCount + 1); 43 | } 44 | 45 | public static void main(String[] args) { 46 | Node head = new Node(5); 47 | head.left = new Node(3); 48 | head.right = new Node(8); 49 | head.left.left = new Node(2); 50 | head.left.right = new Node(4); 51 | head.left.right.left = new Node(12); 52 | head.left.right.right = new Node(13); 53 | head.left.left.left = new Node(1); 54 | head.left.left.right = new Node(10); 55 | head.right.left = new Node(7); 56 | head.right.left.left = new Node(6); 57 | head.right.left.right = new Node(15); 58 | head.right.right = new Node(10); 59 | head.right.right.left = new Node(9); 60 | head.right.right.right = new Node(11); 61 | 62 | System.out.println(isFullBinaryTree(head)); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /tree/C06_IsBalancedTree.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | // 如何判断一颗二叉树是否是平衡二叉树? 4 | public class C06_IsBalancedTree { 5 | 6 | public static class Node { 7 | public int value; 8 | public Node left; 9 | public Node right; 10 | 11 | public Node(int data) { 12 | this.value = data; 13 | } 14 | } 15 | 16 | // public static boolean isBalanced(Node head) { 17 | // return process(head).isBalanced; 18 | // } 19 | 20 | // public static class ReturnType { 21 | // public boolean isBalanced; 22 | // public int height; 23 | 24 | // public ReturnType(boolean isB, int hei) { 25 | // isBalanced = isB; 26 | // height = hei; 27 | // } 28 | // } 29 | 30 | // public static ReturnType process(Node x) { 31 | // if (x == null) { 32 | // return new ReturnType(true, 0); 33 | // } 34 | // ReturnType leftData = process(x.left); 35 | // ReturnType rightData = process(x.right); 36 | // int height = Math.max(leftData.height, rightData.height); 37 | // boolean isBalanced = leftData.isBalanced && rightData.isBalanced 38 | // && Math.abs(leftData.height - rightData.height) < 2; 39 | // return new ReturnType(isBalanced, height); 40 | // } 41 | 42 | private static class ReturnType { 43 | int height; 44 | boolean isBalanced; 45 | 46 | public ReturnType(int height, boolean isBalanced) { 47 | this.height = height; 48 | this.isBalanced = isBalanced; 49 | } 50 | } 51 | 52 | public static ReturnType isBalancedTree(Node head) { 53 | if (head == null) { 54 | return new ReturnType(0, true); 55 | } 56 | 57 | ReturnType leftReturn = isBalancedTree(head.left); 58 | ReturnType rightReturn = isBalancedTree(head.right); 59 | 60 | if (leftReturn.isBalanced && rightReturn.isBalanced && (Math.abs(leftReturn.height - rightReturn.height) <= 1)) { 61 | return new ReturnType(Math.max(leftReturn.height, rightReturn.height) + 1, true); 62 | } 63 | 64 | return new ReturnType(0, false); 65 | } 66 | 67 | public static void main(String[] args) { 68 | Node head = new Node(5); 69 | head.left = new Node(3); 70 | head.right = new Node(8); 71 | head.left.left = new Node(2); 72 | head.left.right = new Node(4); 73 | head.left.right.left = new Node(12); 74 | head.left.right.right = new Node(13); 75 | head.left.left.left = new Node(1); 76 | head.left.left.right = new Node(10); 77 | head.right.left = new Node(7); 78 | head.right.left.left = new Node(6); 79 | head.right.left.right = new Node(15); 80 | head.right.right = new Node(10); 81 | head.right.right.left = new Node(9); 82 | // head.right.right.right = new Node(11); 83 | System.out.println(isBalancedTree(head).isBalanced); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /tree/C10_PaperFolding.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | // 折纸问题 4 | // 请把一段纸条竖着放在桌子上,然后从纸条的下边向上方对折1次,压出折痕后展开。 5 | // 此时折痕是凹下去的,即折痕突起的方向指向纸条的背面。如果从纸条的下边向上方连续对折2次,压出折痕后展开,此时有三条折痕,从上到下依次是下折痕、下折痕和上折痕。 6 | // 给定一个输入参数N,代表纸条都从下边向上方连续对折N次。请从上到下打印所有折痕的方向。 7 | // 例如:N=1时,打印: down N=2时,打印: down down up 8 | public class C10_PaperFolding { 9 | 10 | // public static void printAllFolds(int N) { 11 | // printProcess(1, N, true); 12 | // System.out.println(); 13 | // } 14 | 15 | // public static void printProcess(int i, int N, boolean down) { 16 | // if (i > N) { 17 | // return; 18 | // } 19 | // printProcess(i + 1, N, true); 20 | // System.out.print(down ? "down " : "up " + " "); 21 | // printProcess(i + 1, N, false); 22 | // } 23 | 24 | public static void printAllFolds2(int n) { 25 | 26 | print(n, "down"); 27 | System.out.println(); 28 | } 29 | 30 | private static void print(int n, String s) { 31 | if (n == 0) { 32 | return; 33 | } 34 | print(n - 1, "down"); 35 | System.out.print(s + " "); 36 | print(n - 1, "up"); 37 | 38 | } 39 | 40 | public static void main(String[] args) { 41 | int N = 4; 42 | // printAllFolds(N); 43 | printAllFolds2(N); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /tree/prefix_tree/C02_GetFolderTree.java: -------------------------------------------------------------------------------- 1 | package tree.prefix_tree; 2 | 3 | // 给你一个字符串类型的数组arr,譬如: String[] arr = { "b\\cst", "d\\", "a\\d\\e", "a\\b\\c" }; 4 | // 你把这些路径中蕴含的目录结构给画出来,子目录直接列在父目录下面,并比父目录向右进两格,就像这样: 5 | // a 6 | // b 7 | // c 8 | // d 9 | // e 10 | // b 11 | // cst 12 | // d 13 | // 同一级的需要按字母顺序排列,不能乱。 14 | 15 | // NOTE: 前缀树 16 | import java.util.TreeMap; 17 | 18 | public class C02_GetFolderTree { 19 | 20 | // public static class Node { 21 | // public String name; 22 | // public TreeMap nextMap; 23 | 24 | // public Node(String name) { 25 | // this.name = name; 26 | // nextMap = new TreeMap<>(); 27 | // } 28 | // } 29 | 30 | // public static void print(String[] folderPaths) { 31 | // if (folderPaths == null || folderPaths.length == 0) { 32 | // return; 33 | // } 34 | // Node head = generateFolderTree(folderPaths); 35 | // printProcess(head, 0); 36 | // } 37 | 38 | // public static Node generateFolderTree(String[] folderPaths) { 39 | // Node head = new Node(""); 40 | // for (String foldPath : folderPaths) { 41 | // String[] paths = foldPath.split("\\\\"); 42 | // Node cur = head; 43 | // for (int i = 0; i < paths.length; i++) { 44 | // if (!cur.nextMap.containsKey(paths[i])) { 45 | // cur.nextMap.put(paths[i], new Node(paths[i])); 46 | // } 47 | // cur = cur.nextMap.get(paths[i]); 48 | // } 49 | // } 50 | // return head; 51 | // } 52 | 53 | // public static void printProcess(Node head, int level) { 54 | // if (level != 0) { 55 | // System.out.println(get2nSpace(level) + head.name); 56 | // } 57 | // for (Node next : head.nextMap.values()) { 58 | // printProcess(next, level + 1); 59 | // } 60 | // } 61 | 62 | // public static String get2nSpace(int n) { 63 | // String res = ""; 64 | // for (int i = 1; i < n; i++) { 65 | // res += " "; 66 | // } 67 | // return res; 68 | // } 69 | 70 | public static class Node { 71 | public T value; 72 | public TreeMap> map = new TreeMap<>(); 73 | 74 | public Node(T v) { 75 | this.value = v; 76 | } 77 | } 78 | 79 | public static void print(String[] arr) { 80 | Node head = initialTree(arr); 81 | 82 | for (Node node : head.map.values()) { 83 | recurPrint(node, 0); 84 | } 85 | 86 | } 87 | 88 | private static Node initialTree(String[] arr) { 89 | Node head = new Node("HEAD"); 90 | Node curNode = head; 91 | String[] tem; 92 | for (int i = 0; i < arr.length; i++) { 93 | tem = arr[i].split("\\\\"); 94 | for (int j = 0; j < tem.length; j++) { 95 | if (!curNode.map.containsKey(tem[j])) { 96 | curNode.map.put(tem[j], new Node(tem[j])); 97 | } 98 | curNode = curNode.map.get(tem[j]); 99 | } 100 | curNode = head; 101 | } 102 | return head; 103 | } 104 | 105 | private static void recurPrint(Node head, int whitespace) { 106 | System.out.println(" ".repeat(whitespace) + head.value); 107 | for (Node node : head.map.values()) { 108 | recurPrint(node, whitespace + 2); 109 | } 110 | } 111 | 112 | public static void main(String[] args) { 113 | String[] arr = { "b\\cst", "d\\", "a\\d\\e", "a\\b\\c" }; 114 | print(arr); 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /tree/senior_tree/AbstractSelfBalancingBinarySearchTree.java: -------------------------------------------------------------------------------- 1 | package tree.senior_tree; 2 | 3 | /** 4 | * Not implemented by zuochengyun 5 | * 6 | * Abstract class for self balancing binary search trees. Contains some methods 7 | * that is used for self balancing trees. 8 | * 9 | * @author Ignas Lelys 10 | * @created Jul 24, 2011 11 | * 12 | */ 13 | public abstract class AbstractSelfBalancingBinarySearchTree extends AbstractBinarySearchTree { 14 | 15 | /** 16 | * Rotate to the left. 17 | * 18 | * @param node Node on which to rotate. 19 | * @return Node that is in place of provided node after rotation. 20 | */ 21 | protected Node rotateLeft(Node node) { 22 | Node temp = node.right; 23 | temp.parent = node.parent; 24 | 25 | node.right = temp.left; 26 | if (node.right != null) { 27 | node.right.parent = node; 28 | } 29 | 30 | temp.left = node; 31 | node.parent = temp; 32 | 33 | // temp took over node's place so now its parent should point to temp 34 | if (temp.parent != null) { 35 | if (node == temp.parent.left) { 36 | temp.parent.left = temp; 37 | } else { 38 | temp.parent.right = temp; 39 | } 40 | } else { 41 | root = temp; 42 | } 43 | 44 | return temp; 45 | } 46 | 47 | /** 48 | * Rotate to the right. 49 | * 50 | * @param node Node on which to rotate. 51 | * @return Node that is in place of provided node after rotation. 52 | */ 53 | protected Node rotateRight(Node node) { 54 | Node temp = node.left; 55 | temp.parent = node.parent; 56 | 57 | node.left = temp.right; 58 | if (node.left != null) { 59 | node.left.parent = node; 60 | } 61 | 62 | temp.right = node; 63 | node.parent = temp; 64 | 65 | // temp took over node's place so now its parent should point to temp 66 | if (temp.parent != null) { 67 | if (node == temp.parent.left) { 68 | temp.parent.left = temp; 69 | } else { 70 | temp.parent.right = temp; 71 | } 72 | } else { 73 | root = temp; 74 | } 75 | 76 | return temp; 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /tree/senior_tree/BinarySearchTree.java: -------------------------------------------------------------------------------- 1 | package tree.senior_tree; 2 | 3 | /** 4 | * Not implemented by zuochengyun 5 | * 6 | * Binary search tree implementation. 7 | * 8 | * In computer science, a binary search tree (BST), which may sometimes also be 9 | * called an ordered or sorted binary tree, is a node-based binary tree data 10 | * structure which has the following properties: 11 | * 12 | * a) The left subtree of a node contains only nodes with keys less than the node's key.
13 | * b) The right subtree of a node contains only nodes with keys greater than the node's key.
14 | * c) Both the left and right subtrees must also be binary search trees.
15 | * 16 | * @author Ignas Lelys 17 | * @created May 6, 2011 18 | * 19 | */ 20 | public class BinarySearchTree extends AbstractBinarySearchTree { 21 | 22 | @Override 23 | protected Node createNode(int value, Node parent, Node left, Node right) { 24 | return new Node(value, parent, left, right); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /util/Com.java: -------------------------------------------------------------------------------- 1 | package util; 2 | 3 | import java.util.Comparator; 4 | 5 | class Com implements Comparator { 6 | @Override 7 | public int compare(String a, String b) { 8 | return b.length() - a.length(); 9 | } 10 | } -------------------------------------------------------------------------------- /util/Util.java: -------------------------------------------------------------------------------- 1 | package util; 2 | 3 | public class Util { 4 | public static void print(int[] arr) { 5 | for (int i = 0; i < arr.length; i++) { 6 | System.out.print(arr[i] + " "); 7 | } 8 | System.out.println(); 9 | } 10 | 11 | public static void print(int[][] arr) { 12 | for (int i = 0; i < arr.length; i++) { 13 | for (int j = 0; j < arr[0].length; j++) { 14 | System.out.print(arr[i][j] + " "); 15 | } 16 | System.out.println(); 17 | } 18 | } 19 | 20 | public static void print(boolean[] arr) { 21 | for (int i = 0; i < arr.length; i++) { 22 | System.out.print(arr[i] + " "); 23 | } 24 | System.out.println(); 25 | } 26 | 27 | public static void print(boolean[][] arr) { 28 | for (int i = 0; i < arr.length; i++) { 29 | for (int j = 0; j < arr[0].length; j++) { 30 | System.out.print(arr[i][j] + " "); 31 | } 32 | System.out.println(); 33 | } 34 | } 35 | 36 | public static void print(char[] arr) { 37 | for (int i = 0; i < arr.length; i++) { 38 | System.out.print(arr[i] + " "); 39 | } 40 | System.out.println(); 41 | } 42 | 43 | public static void print(char[][] arr) { 44 | for (int i = 0; i < arr.length; i++) { 45 | for (int j = 0; j < arr[0].length; j++) { 46 | System.out.print(arr[i][j] + " "); 47 | } 48 | System.out.println(); 49 | } 50 | } 51 | 52 | private void reverse(char[] s, int left, int right) { 53 | if (left >= right) { 54 | return; 55 | } 56 | char tem; 57 | for (int i = left; i < left + (right - left + 1) / 2; i++) { 58 | tem = s[i]; 59 | s[i] = s[right - (i - left)]; 60 | s[right - (i - left)] = tem; 61 | } 62 | } 63 | 64 | public static void main(String[] args) { 65 | Util.print(new int[][] { { 1, 2, 3 }, { 4, 5, 6 } }); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /左神算法笔记.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheapCoder/zuoshen-algorithm/4e9906f60ff50a99bb88c7dfea32d4054598ae67/左神算法笔记.pdf -------------------------------------------------------------------------------- /范围上尝试模型.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheapCoder/zuoshen-algorithm/4e9906f60ff50a99bb88c7dfea32d4054598ae67/范围上尝试模型.pdf --------------------------------------------------------------------------------