└── src ├── class01 ├── Code01_SelectionSort.java ├── Code02_BubbleSort.java ├── Code03_InsertionSort.java ├── Code04_BSExist.java ├── Code05_BSNearLeft.java ├── Code05_BSNearRight.java └── Code06_BSAwesome.java ├── class02 ├── Code01_Swap.java ├── Code02_EvenTimesOddTimes.java └── Code03_KM.java ├── class03 ├── Code01_ReverseList.java ├── Code02_DeleteGivenValue.java ├── Code03_DoubleEndsQueueToStackAndQueue.java ├── Code04_RingArray.java ├── Code05_GetMinStack.java ├── Code06_TwoStacksImplementQueue.java ├── Code07_TwoQueueImplementStack.java ├── Code08_GetMax.java └── HashMapAndSortedMap.java ├── class04 ├── Code01_MergeSort.java ├── Code02_SmallSum.java ├── Code03_ReversePair.java └── Code04_BiggerThanRightTwice.java ├── class05 ├── Code01_CountOfRangeSum.java ├── Code02_PartitionAndQuickSort.java ├── Code03_QuickSortRecursiveAndUnrecursive.java └── Code04_DoubleLinkedListQuickSort.java ├── class06 ├── Code01_Comparator.java ├── Code02_Heap.java ├── Code03_HeapSort.java └── Code04_SortArrayDistanceLessK.java ├── class07 ├── Code01_CoverMax.java ├── Code02_EveryStepShowBoss.java ├── Code03_ShowHeapGreater.java ├── HeapGreater.java └── Inner.java ├── class08 ├── Code01_Trie.java ├── Code02_Trie.java ├── Code03_CountSort.java ├── Code04_RadixSort.java └── Code05_ShellSort.java ├── class09 ├── Code01_LinkedListMid.java ├── Code02_IsPalindromeList.java ├── Code03_SmallerEqualBigger.java └── Code04_CopyListWithRandom.java ├── class10 ├── Code01_FindFirstIntersectNode.java ├── Code02_RecursiveTraversalBT.java └── Code03_UnRecursiveTraversalBT.java ├── class11 ├── Code01_LevelTraversalBT.java ├── Code02_SerializeAndReconstructTree.java ├── Code03_EncodeNaryTreeToBinaryTree.java ├── Code04_PrintBinaryTree.java ├── Code05_TreeMaxWidth.java ├── Code06_SuccessorNode.java └── Code07_PaperFolding.java ├── class12 ├── Code01_IsCBT.java ├── Code02_IsBST.java ├── Code03_IsBalanced.java ├── Code04_IsFull.java ├── Code05_MaxSubBSTSize.java └── Code06_MaxDistance.java ├── class13 ├── Code01_IsCBT.java ├── Code02_MaxSubBSTHead.java ├── Code03_lowestAncestor.java ├── Code04_MaxHappy.java └── Code05_LowestLexicography.java ├── class14 ├── Code01_Light.java ├── Code02_LessMoneySplitGold.java ├── Code03_BestArrange.java ├── Code04_IPO.java ├── Code05_UnionFind.java └── Code06_UnionFind.java ├── class15 ├── Code01_FriendCircles.java ├── Code02_NumberOfIslands.java └── Code03_NumberOfIslandsII.java ├── class16 ├── Code01_BFS.java ├── Code02_DFS.java ├── Code03_TopologicalOrderBFS1.java ├── Code03_TopologicalOrderBFS2.java ├── Code03_TopologicalOrderDFS1.java ├── Code03_TopologicalOrderDFS2.java ├── Code03_TopologySort.java ├── Code04_Kruskal.java ├── Code04_KruskalNowCoder.java ├── Code05_Prim.java ├── Code05_PrimNowCoder.java ├── Code06_Dijkstra.java ├── Code06_NetworkDelayTime.java ├── Edge.java ├── Graph.java ├── GraphGenerator.java └── Node.java ├── class17 ├── Code01_Dijkstra.java ├── Code02_Hanoi.java ├── Code03_PrintAllSubsquences.java ├── Code04_PrintAllPermutations.java ├── Code05_ReverseStackUsingRecursive.java ├── Edge.java ├── Graph.java └── Node.java ├── class18 ├── Code01_RobotWalk.java └── Code02_CardsInLine.java ├── class19 ├── Code01_Knapsack.java ├── Code02_ConvertToLetterString.java ├── Code03_StickersToSpellWord.java └── Code04_LongestCommonSubsequence.java ├── class20 ├── Code01_PalindromeSubsequence.java ├── Code02_HorseJump.java └── Code03_Coffee.java ├── class21 ├── Code01_MinPathSum.java ├── Code02_CoinsWayEveryPaperDifferent.java ├── Code03_CoinsWayNoLimit.java ├── Code04_CoinsWaySameValueSamePapper.java └── Code05_BobDie.java ├── class22 ├── Code01_KillMonster.java ├── Code02_MinCoinsNoLimit.java └── Code03_SplitNumber.java ├── class23 ├── Code01_SplitSumClosed.java ├── Code02_SplitSumClosedSizeHalf.java └── Code03_NQueens.java ├── class24 ├── Code01_SlidingWindowMaxArray.java ├── Code02_AllLessNumSubArray.java ├── Code03_GasStation.java └── Code04_MinCoinsOnePaper.java ├── class25 ├── Code01_MonotonousStack.java ├── Code01_MonotonousStackForNowcoder.java ├── Code02_AllTimesMinToMax.java ├── Code03_LargestRectangleInHistogram.java ├── Code04_MaximalRectangle.java └── Code05_CountSubmatricesWithAllOnes.java ├── class26 ├── Code01_SumOfSubarrayMinimums.java ├── Code02_FibonacciProblem.java └── Code03_ZeroLeftOneStringNumber.java ├── class27 ├── Code01_KMP.java ├── Code02_TreeEqual.java └── Code03_IsRotation.java ├── class28 ├── Code01_Manacher.java └── Code02_AddShortestEnd.java ├── class29 ├── Code01_FindMinKth.java ├── Code02_MaxTopK.java └── Code03_ReservoirSampling.java ├── class30 ├── Code01_MorrisTraversal.java └── Code02_MinDepth.java ├── class31 ├── Code01_SegmentTree.java └── Code02_FallingSquares.java ├── class32 ├── Code01_IndexTree.java ├── Code02_IndexTree2D.java ├── Code03_AC1.java └── Code04_AC2.java ├── class33 └── Hash.java ├── class34 └── ReadMe.java ├── class35 └── Code01_AVLTreeMap.java ├── class36 ├── Code01_SizeBalancedTreeMap.java └── Code02_SkipListMap.java ├── class37 ├── Code01_CountofRangeSum.java ├── Code02_SlidingWindowMedian.java ├── Code03_AddRemoveGetIndexGreat.java ├── Code04_QueueReconstructionByHeight.java └── Compare.java ├── class38 ├── Code01_AppleMinBags.java ├── Code02_EatGrass.java ├── Code03_MSumToN.java └── Code04_MoneyProblem.java ├── class39 ├── Code01_SubsquenceMaxModM.java ├── Code02_SnacksWays.java ├── Code02_SnacksWaysMain1.java ├── Code02_SnacksWaysMain2.java ├── Code03_10Ways.java ├── Code04_DifferentBTNum.java └── IsSum.java ├── class40 ├── Code01_LongestSumSubArrayLengthInPositiveArray.java ├── Code02_LongestSumSubArrayLength.java ├── Code03_LongestLessSumSubArrayLength.java ├── Code04_AvgLessEqualValueLongestSubarray.java ├── Code05_PrintMatrixSpiralOrder.java ├── Code06_RotateMatrix.java ├── Code07_ZigZagPrintMatrix.java └── Code08_PrintStar.java ├── class41 ├── Code01_BestSplitForAll.java ├── Code02_BestSplitForEveryPosition.java ├── Code03_StoneMerge.java └── Code04_SplitArrayLargestSum.java ├── class42 ├── Code01_PostOfficeProblem.java └── Code02_ThrowChessPiecesProblem.java ├── class43 ├── Code01_CanIWin.java ├── Code02_TSP.java ├── Code03_PavingTile.java ├── Code03_PavingTile1.java └── Code03_PavingTile2.java ├── class44 ├── Code01_LastSubstringInLexicographicalOrder.java ├── DC3.java └── DC3_Algorithm.pdf ├── class45 ├── Code01_InsertS2MakeMostAlphabeticalOrder.java ├── Code02_CreateMaximumNumber.java ├── Code03_LongestCommonSubstringConquerByHeight.java └── Code04_LongestRepeatingSubstring.java ├── class46 ├── Code01_BurstBalloons.java ├── Code02_RemoveBoxes.java ├── Code03_DeleteAdjacentSameCharacter.java ├── Code04_MaxSumLengthNoMore.java └── Code05_HuffmanTree.java └── class47 ├── Code01_StrangePrinter.java ├── Code02_RestoreWays.java └── Code03_DinicAlgorithm.java /src/class01/Code01_SelectionSort.java: -------------------------------------------------------------------------------- 1 | package class01; 2 | 3 | import java.util.Arrays; 4 | 5 | public class Code01_SelectionSort { 6 | 7 | public static void selectionSort(int[] arr) { 8 | if (arr == null || arr.length < 2) { 9 | return; 10 | } 11 | // 0 ~ N-1 找到最小值,在哪,放到0位置上 12 | // 1 ~ n-1 找到最小值,在哪,放到1 位置上 13 | // 2 ~ n-1 找到最小值,在哪,放到2 位置上 14 | for (int i = 0; i < arr.length - 1; i++) { 15 | int minIndex = i; 16 | for (int j = i + 1; j < arr.length; j++) { // i ~ N-1 上找最小值的下标 17 | minIndex = arr[j] < arr[minIndex] ? j : minIndex; 18 | } 19 | swap(arr, i, minIndex); 20 | } 21 | } 22 | 23 | public static void swap(int[] arr, int i, int j) { 24 | int tmp = arr[i]; 25 | arr[i] = arr[j]; 26 | arr[j] = tmp; 27 | } 28 | 29 | // for test 30 | public static void comparator(int[] arr) { 31 | Arrays.sort(arr); 32 | } 33 | 34 | // for test 35 | public static int[] generateRandomArray(int maxSize, int maxValue) { 36 | // Math.random() [0,1) 37 | // Math.random() * N [0,N) 38 | // (int)(Math.random() * N) [0, N-1] 39 | int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; 40 | for (int i = 0; i < arr.length; i++) { 41 | // [-? , +?] 42 | arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); 43 | } 44 | return arr; 45 | } 46 | 47 | // for test 48 | public static int[] copyArray(int[] arr) { 49 | if (arr == null) { 50 | return null; 51 | } 52 | int[] res = new int[arr.length]; 53 | for (int i = 0; i < arr.length; i++) { 54 | res[i] = arr[i]; 55 | } 56 | return res; 57 | } 58 | 59 | // for test 60 | public static boolean isEqual(int[] arr1, int[] arr2) { 61 | if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) { 62 | return false; 63 | } 64 | if (arr1 == null && arr2 == null) { 65 | return true; 66 | } 67 | if (arr1.length != arr2.length) { 68 | return false; 69 | } 70 | for (int i = 0; i < arr1.length; i++) { 71 | if (arr1[i] != arr2[i]) { 72 | return false; 73 | } 74 | } 75 | return true; 76 | } 77 | 78 | // for test 79 | public static void printArray(int[] arr) { 80 | if (arr == null) { 81 | return; 82 | } 83 | for (int i = 0; i < arr.length; i++) { 84 | System.out.print(arr[i] + " "); 85 | } 86 | System.out.println(); 87 | } 88 | 89 | // for test 90 | public static void main(String[] args) { 91 | int testTime = 500000; 92 | int maxSize = 100; 93 | int maxValue = 100; 94 | boolean succeed = true; 95 | for (int i = 0; i < testTime; i++) { 96 | int[] arr1 = generateRandomArray(maxSize, maxValue); 97 | int[] arr2 = copyArray(arr1); 98 | selectionSort(arr1); 99 | comparator(arr2); 100 | if (!isEqual(arr1, arr2)) { 101 | succeed = false; 102 | printArray(arr1); 103 | printArray(arr2); 104 | break; 105 | } 106 | } 107 | System.out.println(succeed ? "Nice!" : "Fucking fucked!"); 108 | 109 | int[] arr = generateRandomArray(maxSize, maxValue); 110 | printArray(arr); 111 | selectionSort(arr); 112 | printArray(arr); 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /src/class01/Code02_BubbleSort.java: -------------------------------------------------------------------------------- 1 | package class01; 2 | 3 | import java.util.Arrays; 4 | 5 | public class Code02_BubbleSort { 6 | 7 | public static void bubbleSort(int[] arr) { 8 | if (arr == null || arr.length < 2) { 9 | return; 10 | } 11 | // 0 ~ N-1 12 | // 0 ~ N-2 13 | // 0 ~ N-3 14 | for (int e = arr.length - 1; e > 0; e--) { // 0 ~ e 15 | for (int i = 0; i < e; i++) { 16 | if (arr[i] > arr[i + 1]) { 17 | swap(arr, i, i + 1); 18 | } 19 | } 20 | } 21 | } 22 | 23 | // 交换arr的i和j位置上的值 24 | public static void swap(int[] arr, int i, int j) { 25 | arr[i] = arr[i] ^ arr[j]; 26 | arr[j] = arr[i] ^ arr[j]; 27 | arr[i] = arr[i] ^ arr[j]; 28 | } 29 | 30 | // for test 31 | public static void comparator(int[] arr) { 32 | Arrays.sort(arr); 33 | } 34 | 35 | // for test 36 | public static int[] generateRandomArray(int maxSize, int maxValue) { 37 | int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; 38 | for (int i = 0; i < arr.length; i++) { 39 | arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); 40 | } 41 | return arr; 42 | } 43 | 44 | // for test 45 | public static int[] copyArray(int[] arr) { 46 | if (arr == null) { 47 | return null; 48 | } 49 | int[] res = new int[arr.length]; 50 | for (int i = 0; i < arr.length; i++) { 51 | res[i] = arr[i]; 52 | } 53 | return res; 54 | } 55 | 56 | // for test 57 | public static boolean isEqual(int[] arr1, int[] arr2) { 58 | if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) { 59 | return false; 60 | } 61 | if (arr1 == null && arr2 == null) { 62 | return true; 63 | } 64 | if (arr1.length != arr2.length) { 65 | return false; 66 | } 67 | for (int i = 0; i < arr1.length; i++) { 68 | if (arr1[i] != arr2[i]) { 69 | return false; 70 | } 71 | } 72 | return true; 73 | } 74 | 75 | // for test 76 | public static void printArray(int[] arr) { 77 | if (arr == null) { 78 | return; 79 | } 80 | for (int i = 0; i < arr.length; i++) { 81 | System.out.print(arr[i] + " "); 82 | } 83 | System.out.println(); 84 | } 85 | 86 | // for test 87 | public static void main(String[] args) { 88 | int testTime = 500000; 89 | int maxSize = 100; 90 | int maxValue = 100; 91 | boolean succeed = true; 92 | for (int i = 0; i < testTime; i++) { 93 | int[] arr1 = generateRandomArray(maxSize, maxValue); 94 | int[] arr2 = copyArray(arr1); 95 | bubbleSort(arr1); 96 | comparator(arr2); 97 | if (!isEqual(arr1, arr2)) { 98 | succeed = false; 99 | break; 100 | } 101 | } 102 | System.out.println(succeed ? "Nice!" : "Fucking fucked!"); 103 | 104 | int[] arr = generateRandomArray(maxSize, maxValue); 105 | printArray(arr); 106 | bubbleSort(arr); 107 | printArray(arr); 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /src/class01/Code04_BSExist.java: -------------------------------------------------------------------------------- 1 | package class01; 2 | 3 | import java.util.Arrays; 4 | 5 | public class Code04_BSExist { 6 | 7 | public static boolean exist(int[] sortedArr, int num) { 8 | if (sortedArr == null || sortedArr.length == 0) { 9 | return false; 10 | } 11 | int L = 0; 12 | int R = sortedArr.length - 1; 13 | int mid = 0; 14 | // L..R 15 | while (L < R) { // L..R 至少两个数的时候 16 | mid = L + ((R - L) >> 1); 17 | if (sortedArr[mid] == num) { 18 | return true; 19 | } else if (sortedArr[mid] > num) { 20 | R = mid - 1; 21 | } else { 22 | L = mid + 1; 23 | } 24 | } 25 | return sortedArr[L] == num; 26 | } 27 | 28 | // for test 29 | public static boolean test(int[] sortedArr, int num) { 30 | for(int cur : sortedArr) { 31 | if(cur == num) { 32 | return true; 33 | } 34 | } 35 | return false; 36 | } 37 | 38 | 39 | // for test 40 | public static int[] generateRandomArray(int maxSize, int maxValue) { 41 | int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; 42 | for (int i = 0; i < arr.length; i++) { 43 | arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); 44 | } 45 | return arr; 46 | } 47 | 48 | public static void main(String[] args) { 49 | int testTime = 500000; 50 | int maxSize = 10; 51 | int maxValue = 100; 52 | boolean succeed = true; 53 | for (int i = 0; i < testTime; i++) { 54 | int[] arr = generateRandomArray(maxSize, maxValue); 55 | Arrays.sort(arr); 56 | int value = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); 57 | if (test(arr, value) != exist(arr, value)) { 58 | succeed = false; 59 | break; 60 | } 61 | } 62 | System.out.println(succeed ? "Nice!" : "Fucking fucked!"); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/class01/Code05_BSNearLeft.java: -------------------------------------------------------------------------------- 1 | package class01; 2 | 3 | import java.util.Arrays; 4 | 5 | public class Code05_BSNearLeft { 6 | 7 | // 在arr上,找满足>=value的最左位置 8 | public static int nearestIndex(int[] arr, int value) { 9 | int L = 0; 10 | int R = arr.length - 1; 11 | int index = -1; // 记录最左的对号 12 | while (L <= R) { // 至少一个数的时候 13 | int mid = L + ((R - L) >> 1); 14 | if (arr[mid] >= value) { 15 | index = mid; 16 | R = mid - 1; 17 | } else { 18 | L = mid + 1; 19 | } 20 | } 21 | return index; 22 | } 23 | 24 | // for test 25 | public static int test(int[] arr, int value) { 26 | for (int i = 0; i < arr.length; i++) { 27 | if (arr[i] >= value) { 28 | return i; 29 | } 30 | } 31 | return -1; 32 | } 33 | 34 | // for test 35 | public static int[] generateRandomArray(int maxSize, int maxValue) { 36 | int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; 37 | for (int i = 0; i < arr.length; i++) { 38 | arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); 39 | } 40 | return arr; 41 | } 42 | 43 | // for test 44 | public static void printArray(int[] arr) { 45 | if (arr == null) { 46 | return; 47 | } 48 | for (int i = 0; i < arr.length; i++) { 49 | System.out.print(arr[i] + " "); 50 | } 51 | System.out.println(); 52 | } 53 | 54 | public static void main(String[] args) { 55 | int testTime = 500000; 56 | int maxSize = 10; 57 | int maxValue = 100; 58 | boolean succeed = true; 59 | for (int i = 0; i < testTime; i++) { 60 | int[] arr = generateRandomArray(maxSize, maxValue); 61 | Arrays.sort(arr); 62 | int value = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); 63 | if (test(arr, value) != nearestIndex(arr, value)) { 64 | printArray(arr); 65 | System.out.println(value); 66 | System.out.println(test(arr, value)); 67 | System.out.println(nearestIndex(arr, value)); 68 | succeed = false; 69 | break; 70 | } 71 | } 72 | System.out.println(succeed ? "Nice!" : "Fucking fucked!"); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/class01/Code05_BSNearRight.java: -------------------------------------------------------------------------------- 1 | package class01; 2 | 3 | import java.util.Arrays; 4 | 5 | public class Code05_BSNearRight { 6 | 7 | // 在arr上,找满足<=value的最右位置 8 | public static int nearestIndex(int[] arr, int value) { 9 | int L = 0; 10 | int R = arr.length - 1; 11 | int index = -1; // 记录最右的对号 12 | while (L <= R) { 13 | int mid = L + ((R - L) >> 1); 14 | if (arr[mid] <= value) { 15 | index = mid; 16 | L = mid + 1; 17 | } else { 18 | R = mid - 1; 19 | } 20 | } 21 | return index; 22 | } 23 | 24 | // for test 25 | public static int test(int[] arr, int value) { 26 | for (int i = arr.length - 1; i >= 0; i--) { 27 | if (arr[i] <= value) { 28 | return i; 29 | } 30 | } 31 | return -1; 32 | } 33 | 34 | // for test 35 | public static int[] generateRandomArray(int maxSize, int maxValue) { 36 | int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; 37 | for (int i = 0; i < arr.length; i++) { 38 | arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); 39 | } 40 | return arr; 41 | } 42 | 43 | // for test 44 | public static void printArray(int[] arr) { 45 | if (arr == null) { 46 | return; 47 | } 48 | for (int i = 0; i < arr.length; i++) { 49 | System.out.print(arr[i] + " "); 50 | } 51 | System.out.println(); 52 | } 53 | 54 | public static void main(String[] args) { 55 | int testTime = 500000; 56 | int maxSize = 10; 57 | int maxValue = 100; 58 | boolean succeed = true; 59 | for (int i = 0; i < testTime; i++) { 60 | int[] arr = generateRandomArray(maxSize, maxValue); 61 | Arrays.sort(arr); 62 | int value = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); 63 | if (test(arr, value) != nearestIndex(arr, value)) { 64 | printArray(arr); 65 | System.out.println(value); 66 | System.out.println(test(arr, value)); 67 | System.out.println(nearestIndex(arr, value)); 68 | succeed = false; 69 | break; 70 | } 71 | } 72 | System.out.println(succeed ? "Nice!" : "Fucking fucked!"); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/class01/Code06_BSAwesome.java: -------------------------------------------------------------------------------- 1 | package class01; 2 | 3 | public class Code06_BSAwesome { 4 | 5 | // 课上的代码 6 | public static int getLessIndex(int[] arr) { 7 | if (arr == null || arr.length == 0) { 8 | return -1; 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 | // 验证得到的结果,是不是局部最小 33 | public static boolean isRight(int[] arr, int index) { 34 | if (arr.length <= 1) { 35 | return true; 36 | } 37 | if (index == 0) { 38 | return arr[index] < arr[index + 1]; 39 | } 40 | if (index == arr.length - 1) { 41 | return arr[index] < arr[index - 1]; 42 | } 43 | return arr[index] < arr[index - 1] && arr[index] < arr[index + 1]; 44 | } 45 | 46 | // 为了测试 47 | // 生成相邻不相等的数组 48 | public static int[] generateRandomArray(int maxSize, int maxValue) { 49 | int[] arr = new int[(int) (Math.random() * maxSize) + 1]; 50 | arr[0] = (int) (Math.random() * maxValue) - (int) (Math.random() * maxValue); 51 | for (int i = 1; i < arr.length; i++) { 52 | do { 53 | arr[i] = (int) (Math.random() * maxValue) - (int) (Math.random() * maxValue); 54 | } while (arr[i] == arr[i - 1]); 55 | } 56 | return arr; 57 | } 58 | 59 | // 为了测试 60 | public static void main(String[] args) { 61 | int testTime = 500000; 62 | int maxSize = 30; 63 | int maxValue = 100; 64 | System.out.println("测试开始"); 65 | for (int i = 0; i < testTime; i++) { 66 | int[] arr = generateRandomArray(maxSize, maxValue); 67 | int ans = getLessIndex(arr); 68 | if (!isRight(arr, ans)) { 69 | System.out.println("出错了!"); 70 | break; 71 | } 72 | } 73 | System.out.println("测试结束"); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/class02/Code01_Swap.java: -------------------------------------------------------------------------------- 1 | package class02; 2 | 3 | public class Code01_Swap { 4 | 5 | public static void main(String[] args) { 6 | 7 | 8 | 9 | 10 | 11 | 12 | int a = 16; 13 | int b = 603; 14 | 15 | System.out.println(a); 16 | System.out.println(b); 17 | 18 | 19 | a = a ^ b; 20 | b = a ^ b; 21 | a = a ^ b; 22 | 23 | 24 | System.out.println(a); 25 | System.out.println(b); 26 | 27 | 28 | 29 | 30 | int[] arr = {3,1,100}; 31 | 32 | int i = 0; 33 | int j = 0; 34 | 35 | arr[i] = arr[i] ^ arr[j]; 36 | arr[j] = arr[i] ^ arr[j]; 37 | arr[i] = arr[i] ^ arr[j]; 38 | 39 | System.out.println(arr[i] + " , " + arr[j]); 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | System.out.println(arr[0]); 50 | System.out.println(arr[2]); 51 | 52 | swap(arr, 0, 0); 53 | 54 | System.out.println(arr[0]); 55 | System.out.println(arr[2]); 56 | 57 | 58 | 59 | } 60 | 61 | 62 | public static void swap (int[] arr, int i, int j) { 63 | // arr[0] = arr[0] ^ arr[0]; 64 | arr[i] = arr[i] ^ arr[j]; 65 | arr[j] = arr[i] ^ arr[j]; 66 | arr[i] = arr[i] ^ arr[j]; 67 | } 68 | 69 | 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/class02/Code02_EvenTimesOddTimes.java: -------------------------------------------------------------------------------- 1 | package class02; 2 | 3 | public class Code02_EvenTimesOddTimes { 4 | 5 | // arr中,只有一种数,出现奇数次 6 | public static void printOddTimesNum1(int[] arr) { 7 | int eor = 0; 8 | for (int i = 0; i < arr.length; i++) { 9 | eor ^= arr[i]; 10 | } 11 | System.out.println(eor); 12 | } 13 | 14 | // arr中,有两种数,出现奇数次 15 | public static void printOddTimesNum2(int[] arr) { 16 | int eor = 0; 17 | for (int i = 0; i < arr.length; i++) { 18 | eor ^= arr[i]; 19 | } 20 | // a 和 b是两种数 21 | // eor != 0 22 | // eor最右侧的1,提取出来 23 | // eor : 00110010110111000 24 | // rightOne :00000000000001000 25 | int rightOne = eor & (-eor); // 提取出最右的1 26 | 27 | 28 | int onlyOne = 0; // eor' 29 | for (int i = 0 ; i < arr.length;i++) { 30 | // arr[1] = 111100011110000 31 | // rightOne= 000000000010000 32 | if ((arr[i] & rightOne) != 0) { 33 | onlyOne ^= arr[i]; 34 | } 35 | } 36 | System.out.println(onlyOne + " " + (eor ^ onlyOne)); 37 | } 38 | 39 | 40 | public static int bit1counts(int N) { 41 | int count = 0; 42 | 43 | // 011011010000 44 | // 000000010000 1 45 | 46 | // 011011000000 47 | // 48 | 49 | 50 | 51 | while(N != 0) { 52 | int rightOne = N & ((~N) + 1); 53 | count++; 54 | N ^= rightOne; 55 | // N -= rightOne 56 | } 57 | 58 | 59 | return count; 60 | 61 | } 62 | 63 | 64 | public static void main(String[] args) { 65 | int a = 5; 66 | int b = 7; 67 | 68 | a = a ^ b; 69 | b = a ^ b; 70 | a = a ^ b; 71 | 72 | System.out.println(a); 73 | System.out.println(b); 74 | 75 | int[] arr1 = { 3, 3, 2, 3, 1, 1, 1, 3, 1, 1, 1 }; 76 | printOddTimesNum1(arr1); 77 | 78 | int[] arr2 = { 4, 3, 4, 2, 2, 2, 4, 1, 1, 1, 3, 3, 1, 1, 1, 4, 2, 2 }; 79 | printOddTimesNum2(arr2); 80 | 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /src/class03/Code02_DeleteGivenValue.java: -------------------------------------------------------------------------------- 1 | package class03; 2 | 3 | public class Code02_DeleteGivenValue { 4 | 5 | public static class Node { 6 | public int value; 7 | public Node next; 8 | 9 | public Node(int data) { 10 | this.value = data; 11 | } 12 | } 13 | 14 | // head = removeValue(head, 2); 15 | public static Node removeValue(Node head, int num) { 16 | // head来到第一个不需要删的位置 17 | while (head != null) { 18 | if (head.value != num) { 19 | break; 20 | } 21 | head = head.next; 22 | } 23 | // 1 ) head == null 24 | // 2 ) head != null 25 | Node pre = head; 26 | Node cur = head; 27 | while (cur != null) { 28 | if (cur.value == num) { 29 | pre.next = cur.next; 30 | } else { 31 | pre = cur; 32 | } 33 | cur = cur.next; 34 | } 35 | return head; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/class03/Code04_RingArray.java: -------------------------------------------------------------------------------- 1 | package class03; 2 | 3 | public class Code04_RingArray { 4 | 5 | public static class MyQueue { 6 | private int[] arr; 7 | private int pushi;// end 8 | private int polli;// begin 9 | private int size; 10 | private final int limit; 11 | 12 | public MyQueue(int limit) { 13 | arr = new int[limit]; 14 | pushi = 0; 15 | polli = 0; 16 | size = 0; 17 | this.limit = limit; 18 | } 19 | 20 | public void push(int value) { 21 | if (size == limit) { 22 | throw new RuntimeException("队列满了,不能再加了"); 23 | } 24 | size++; 25 | arr[pushi] = value; 26 | pushi = nextIndex(pushi); 27 | } 28 | 29 | public int pop() { 30 | if (size == 0) { 31 | throw new RuntimeException("队列空了,不能再拿了"); 32 | } 33 | size--; 34 | int ans = arr[polli]; 35 | polli = nextIndex(polli); 36 | return ans; 37 | } 38 | 39 | public boolean isEmpty() { 40 | return size == 0; 41 | } 42 | 43 | // 如果现在的下标是i,返回下一个位置 44 | private int nextIndex(int i) { 45 | return i < limit - 1 ? i + 1 : 0; 46 | } 47 | 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/class03/Code05_GetMinStack.java: -------------------------------------------------------------------------------- 1 | package class03; 2 | 3 | import java.util.Stack; 4 | 5 | public class Code05_GetMinStack { 6 | 7 | public static class MyStack1 { 8 | private Stack stackData; 9 | private Stack stackMin; 10 | 11 | public MyStack1() { 12 | stackData = new Stack(); 13 | stackMin = new Stack(); 14 | } 15 | 16 | public void push(int newNum) { 17 | if (stackMin.isEmpty() || newNum <= this.getmin()) { 18 | stackMin.push(newNum); 19 | } 20 | stackData.push(newNum); 21 | } 22 | 23 | public int pop() { 24 | if (stackData.isEmpty()) { 25 | throw new RuntimeException("Your stack is empty."); 26 | } 27 | int value = stackData.pop(); 28 | if (value == getmin()) { 29 | stackMin.pop(); 30 | } 31 | return value; 32 | } 33 | 34 | public int getmin() { 35 | if (stackMin.isEmpty()) { 36 | throw new RuntimeException("Your stack is empty."); 37 | } 38 | return stackMin.peek(); 39 | } 40 | } 41 | 42 | public static class MyStack2 { 43 | private Stack stackData; 44 | private Stack stackMin; 45 | 46 | public MyStack2() { 47 | stackData = new Stack(); 48 | stackMin = new Stack(); 49 | } 50 | 51 | public void push(int newNum) { 52 | if (stackMin.isEmpty() || newNum < getmin()) { 53 | stackMin.push(newNum); 54 | } else { 55 | stackMin.push(stackMin.peek()); 56 | } 57 | stackData.push(newNum); 58 | } 59 | 60 | public int pop() { 61 | if (stackData.isEmpty()) { 62 | throw new RuntimeException("Your stack is empty."); 63 | } 64 | stackMin.pop(); 65 | return stackData.pop(); 66 | } 67 | 68 | public int getmin() { 69 | if (stackMin.isEmpty()) { 70 | throw new RuntimeException("Your stack is empty."); 71 | } 72 | return stackMin.peek(); 73 | } 74 | } 75 | 76 | public static void main(String[] args) { 77 | MyStack1 stack1 = new MyStack1(); 78 | stack1.push(3); 79 | System.out.println(stack1.getmin()); 80 | stack1.push(4); 81 | System.out.println(stack1.getmin()); 82 | stack1.push(1); 83 | System.out.println(stack1.getmin()); 84 | System.out.println(stack1.pop()); 85 | System.out.println(stack1.getmin()); 86 | 87 | System.out.println("============="); 88 | 89 | MyStack2 stack2 = new MyStack2(); 90 | stack2.push(3); 91 | System.out.println(stack2.getmin()); 92 | stack2.push(4); 93 | System.out.println(stack2.getmin()); 94 | stack2.push(1); 95 | System.out.println(stack2.getmin()); 96 | System.out.println(stack2.pop()); 97 | System.out.println(stack2.getmin()); 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/class03/Code06_TwoStacksImplementQueue.java: -------------------------------------------------------------------------------- 1 | package class03; 2 | 3 | import java.util.Stack; 4 | 5 | public class Code06_TwoStacksImplementQueue { 6 | 7 | public static class TwoStacksQueue { 8 | public Stack stackPush; 9 | public Stack stackPop; 10 | 11 | public TwoStacksQueue() { 12 | stackPush = new Stack(); 13 | stackPop = new Stack(); 14 | } 15 | 16 | // push栈向pop栈倒入数据 17 | private void pushToPop() { 18 | if (stackPop.empty()) { 19 | while (!stackPush.empty()) { 20 | stackPop.push(stackPush.pop()); 21 | } 22 | } 23 | } 24 | 25 | public void add(int pushInt) { 26 | stackPush.push(pushInt); 27 | pushToPop(); 28 | } 29 | 30 | public int poll() { 31 | if (stackPop.empty() && stackPush.empty()) { 32 | throw new RuntimeException("Queue is empty!"); 33 | } 34 | pushToPop(); 35 | return stackPop.pop(); 36 | } 37 | 38 | public int peek() { 39 | if (stackPop.empty() && stackPush.empty()) { 40 | throw new RuntimeException("Queue is empty!"); 41 | } 42 | pushToPop(); 43 | return stackPop.peek(); 44 | } 45 | } 46 | 47 | public static void main(String[] args) { 48 | TwoStacksQueue test = new TwoStacksQueue(); 49 | test.add(1); 50 | test.add(2); 51 | test.add(3); 52 | System.out.println(test.peek()); 53 | System.out.println(test.poll()); 54 | System.out.println(test.peek()); 55 | System.out.println(test.poll()); 56 | System.out.println(test.peek()); 57 | System.out.println(test.poll()); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/class03/Code07_TwoQueueImplementStack.java: -------------------------------------------------------------------------------- 1 | package class03; 2 | 3 | import java.util.LinkedList; 4 | import java.util.Queue; 5 | import java.util.Stack; 6 | 7 | public class Code07_TwoQueueImplementStack { 8 | 9 | public static class TwoQueueStack { 10 | public Queue queue; 11 | public Queue help; 12 | 13 | public TwoQueueStack() { 14 | queue = new LinkedList<>(); 15 | help = new LinkedList<>(); 16 | } 17 | 18 | public void push(T value) { 19 | queue.offer(value); 20 | } 21 | 22 | public T poll() { 23 | while (queue.size() > 1) { 24 | help.offer(queue.poll()); 25 | } 26 | T ans = queue.poll(); 27 | Queue tmp = queue; 28 | queue = help; 29 | help = tmp; 30 | return ans; 31 | } 32 | 33 | public T peek() { 34 | while (queue.size() > 1) { 35 | help.offer(queue.poll()); 36 | } 37 | T ans = queue.poll(); 38 | help.offer(ans); 39 | Queue tmp = queue; 40 | queue = help; 41 | help = tmp; 42 | return ans; 43 | } 44 | 45 | public boolean isEmpty() { 46 | return queue.isEmpty(); 47 | } 48 | 49 | } 50 | 51 | public static void main(String[] args) { 52 | System.out.println("test begin"); 53 | TwoQueueStack myStack = new TwoQueueStack<>(); 54 | Stack test = new Stack<>(); 55 | int testTime = 1000000; 56 | int max = 1000000; 57 | for (int i = 0; i < testTime; i++) { 58 | if (myStack.isEmpty()) { 59 | if (!test.isEmpty()) { 60 | System.out.println("Oops"); 61 | } 62 | int num = (int) (Math.random() * max); 63 | myStack.push(num); 64 | test.push(num); 65 | } else { 66 | if (Math.random() < 0.25) { 67 | int num = (int) (Math.random() * max); 68 | myStack.push(num); 69 | test.push(num); 70 | } else if (Math.random() < 0.5) { 71 | if (!myStack.peek().equals(test.peek())) { 72 | System.out.println("Oops"); 73 | } 74 | } else if (Math.random() < 0.75) { 75 | if (!myStack.poll().equals(test.pop())) { 76 | System.out.println("Oops"); 77 | } 78 | } else { 79 | if (myStack.isEmpty() != test.isEmpty()) { 80 | System.out.println("Oops"); 81 | } 82 | } 83 | } 84 | } 85 | 86 | System.out.println("test finish!"); 87 | 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /src/class03/Code08_GetMax.java: -------------------------------------------------------------------------------- 1 | package class03; 2 | 3 | public class Code08_GetMax { 4 | 5 | // 求arr中的最大值 6 | public static int getMax(int[] arr) { 7 | return process(arr, 0, arr.length - 1); 8 | } 9 | 10 | // arr[L..R]范围上求最大值 L ... R N 11 | public static int process(int[] arr, int L, int R) { 12 | // arr[L..R]范围上只有一个数,直接返回,base case 13 | if (L == R) { 14 | return arr[L]; 15 | } 16 | // L...R 不只一个数 17 | // mid = (L + R) / 2 18 | int mid = L + ((R - L) >> 1); // 中点 1 19 | int leftMax = process(arr, L, mid); 20 | int rightMax = process(arr, mid + 1, R); 21 | return Math.max(leftMax, rightMax); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/class05/Code01_CountOfRangeSum.java: -------------------------------------------------------------------------------- 1 | package class05; 2 | 3 | // 这道题直接在leetcode测评: 4 | // https://leetcode.com/problems/count-of-range-sum/ 5 | public class Code01_CountOfRangeSum { 6 | 7 | public static int countRangeSum(int[] nums, int lower, int upper) { 8 | if (nums == null || nums.length == 0) { 9 | return 0; 10 | } 11 | long[] sum = new long[nums.length]; 12 | sum[0] = nums[0]; 13 | for (int i = 1; i < nums.length; i++) { 14 | sum[i] = sum[i - 1] + nums[i]; 15 | } 16 | return process(sum, 0, sum.length - 1, lower, upper); 17 | } 18 | 19 | public static int process(long[] sum, int L, int R, int lower, int upper) { 20 | if (L == R) { 21 | return sum[L] >= lower && sum[L] <= upper ? 1 : 0; 22 | } 23 | int M = L + ((R - L) >> 1); 24 | return process(sum, L, M, lower, upper) + process(sum, M + 1, R, lower, upper) 25 | + merge(sum, L, M, R, lower, upper); 26 | } 27 | 28 | public static int merge(long[] arr, int L, int M, int R, int lower, int upper) { 29 | int ans = 0; 30 | int windowL = L; 31 | int windowR = L; 32 | // [windowL, windowR) 33 | for (int i = M + 1; i <= R; i++) { 34 | long min = arr[i] - upper; 35 | long max = arr[i] - lower; 36 | while (windowR <= M && arr[windowR] <= max) { 37 | windowR++; 38 | } 39 | while (windowL <= M && arr[windowL] < min) { 40 | windowL++; 41 | } 42 | ans += windowR - windowL; 43 | } 44 | long[] help = new long[R - L + 1]; 45 | int i = 0; 46 | int p1 = L; 47 | int p2 = M + 1; 48 | while (p1 <= M && p2 <= R) { 49 | help[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++]; 50 | } 51 | while (p1 <= M) { 52 | help[i++] = arr[p1++]; 53 | } 54 | while (p2 <= R) { 55 | help[i++] = arr[p2++]; 56 | } 57 | for (i = 0; i < help.length; i++) { 58 | arr[L + i] = help[i]; 59 | } 60 | return ans; 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/class07/Code03_ShowHeapGreater.java: -------------------------------------------------------------------------------- 1 | package class07; 2 | 3 | // 这个代码课上没有讲,但是非常容易理解 4 | // 一定注意看main函数及其注释,用代码展示加强堆的用法 5 | // 展示了加强堆怎么支持非基础类型和基础类型 6 | public class Code03_ShowHeapGreater { 7 | 8 | // 看这个测试! 9 | // 每一句都看懂 10 | public static void main(String[] args) { 11 | // 展示非基础类型的用法 12 | Student s1 = new Student(17, "A同学"); 13 | Student s2 = new Student(10, "B同学"); 14 | Student s3 = new Student(29, "C同学"); 15 | Student s4 = new Student(33, "D同学"); 16 | Student s5 = new Student(54, "E同学"); 17 | Student s6 = new Student(93, "F同学"); 18 | // 生成一个加强堆 19 | // 排序策略是年龄小的放在堆顶,年龄小根堆 20 | HeapGreater heap1 = new HeapGreater<>((a, b) -> a.age - b.age); 21 | // 把所有学生加入堆 22 | heap1.push(s1); 23 | heap1.push(s2); 24 | heap1.push(s3); 25 | heap1.push(s4); 26 | heap1.push(s5); 27 | heap1.push(s6); 28 | // 加入之后 29 | // 可以把某个同学的年龄改了 30 | // 比如把s5,也就是E同学 31 | // 年龄从54改成了4 32 | s5.age = 4; 33 | // 此时堆被破坏了,因为你擅自改了一个同学的年龄 34 | // 只需要调用resign方法,就能让堆恢复成年龄小根堆 35 | // 而且复杂度是O(log N),很快的 36 | // 系统提供的堆做不到的,加强堆可以 37 | heap1.resign(s5); 38 | // 依次弹出所有学生 39 | // 会发现从年龄小到年龄大依次弹出 40 | // 说明堆是正确的 41 | while (!heap1.isEmpty()) { 42 | Student cur = heap1.pop(); 43 | System.out.println("年龄 : " + cur.age + " , 名字 : " + cur.name); 44 | } 45 | 46 | System.out.println("======================"); 47 | 48 | // 现在展示非基础类型的加强堆用法 49 | int[] arr = { 3, 3, 2, 5, 3 }; 50 | // arr[0] == 3 51 | // arr[1] == 3 52 | // arr[2] == 2 53 | // arr[3] == 5 54 | // arr[4] == 3 55 | // 每个位置的数字一定会自带一个下标,这是一定的! 56 | // 任何基础类型的元素,天生一定会自带一些类似下标的身份信息的!这是一定的! 57 | // 生成一个加强堆 58 | // 加强堆里只放下标即可,因为通过下标可以找到数字 59 | // 排序策略是 : 60 | // 数字小的下标,在堆顶 61 | HeapGreater heap2 = new HeapGreater<>((i, j) -> arr[i] - arr[j]); 62 | 63 | // 把数组所有的下标加入堆 64 | // 就等于加入了所有数字 65 | heap2.push(0); 66 | heap2.push(1); 67 | heap2.push(2); 68 | heap2.push(3); 69 | heap2.push(4); 70 | 71 | // 加入之后 72 | // 可以把某个下标上的数字改了 73 | // arr[1]原来是3,现在变成了-9 74 | arr[1] = -9; 75 | // 此时堆被破坏了,因为你擅自改了一个下标的数字 76 | // 只需要调用resign方法,就能让堆恢复 77 | // 而且复杂度是O(log N),很快的 78 | // 系统提供的堆做不到的,加强堆可以 79 | // 调用resign方法 80 | heap2.resign(1); 81 | 82 | // 依次弹出所有下标 83 | // 会发现下标上的数字越小,下标越早弹出 84 | // 说明堆是正确的 85 | while (!heap2.isEmpty()) { 86 | int curIndex = heap2.pop(); 87 | System.out.println("下标 : " + curIndex + " , 数字 :" + arr[curIndex]); 88 | } 89 | } 90 | 91 | // 一个自己定义的非基础类型 92 | public static class Student { 93 | public int age; 94 | public String name; 95 | 96 | public Student(int a, String n) { 97 | age = a; 98 | name = n; 99 | } 100 | } 101 | 102 | } -------------------------------------------------------------------------------- /src/class07/HeapGreater.java: -------------------------------------------------------------------------------- 1 | package class07; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Comparator; 5 | import java.util.HashMap; 6 | import java.util.List; 7 | 8 | public class HeapGreater { 9 | 10 | private ArrayList heap; 11 | private HashMap indexMap; 12 | private int heapSize; 13 | private Comparator comp; 14 | 15 | public HeapGreater(Comparator c) { 16 | heap = new ArrayList<>(); 17 | indexMap = new HashMap<>(); 18 | heapSize = 0; 19 | comp = c; 20 | } 21 | 22 | public boolean isEmpty() { 23 | return heapSize == 0; 24 | } 25 | 26 | public int size() { 27 | return heapSize; 28 | } 29 | 30 | public boolean contains(T obj) { 31 | return indexMap.containsKey(obj); 32 | } 33 | 34 | public T peek() { 35 | return heap.get(0); 36 | } 37 | 38 | public void push(T obj) { 39 | heap.add(obj); 40 | indexMap.put(obj, heapSize); 41 | heapInsert(heapSize++); 42 | } 43 | 44 | public T pop() { 45 | T ans = heap.get(0); 46 | swap(0, heapSize - 1); 47 | indexMap.remove(ans); 48 | heap.remove(--heapSize); 49 | heapify(0); 50 | return ans; 51 | } 52 | 53 | public void remove(T obj) { 54 | T replace = heap.get(heapSize - 1); 55 | int index = indexMap.get(obj); 56 | indexMap.remove(obj); 57 | heap.remove(--heapSize); 58 | if (obj != replace) { 59 | heap.set(index, replace); 60 | indexMap.put(replace, index); 61 | resign(replace); 62 | } 63 | } 64 | 65 | public void resign(T obj) { 66 | heapInsert(indexMap.get(obj)); 67 | heapify(indexMap.get(obj)); 68 | } 69 | 70 | // 请返回堆上的所有元素 71 | public List getAllElements() { 72 | List ans = new ArrayList<>(); 73 | for (T c : heap) { 74 | ans.add(c); 75 | } 76 | return ans; 77 | } 78 | 79 | private void heapInsert(int index) { 80 | while (comp.compare(heap.get(index), heap.get((index - 1) / 2)) < 0) { 81 | swap(index, (index - 1) / 2); 82 | index = (index - 1) / 2; 83 | } 84 | } 85 | 86 | private void heapify(int index) { 87 | int left = index * 2 + 1; 88 | while (left < heapSize) { 89 | int best = left + 1 < heapSize && comp.compare(heap.get(left + 1), heap.get(left)) < 0 ? (left + 1) : left; 90 | best = comp.compare(heap.get(best), heap.get(index)) < 0 ? best : index; 91 | if (best == index) { 92 | break; 93 | } 94 | swap(best, index); 95 | index = best; 96 | left = index * 2 + 1; 97 | } 98 | } 99 | 100 | private void swap(int i, int j) { 101 | T o1 = heap.get(i); 102 | T o2 = heap.get(j); 103 | heap.set(i, o2); 104 | heap.set(j, o1); 105 | indexMap.put(o2, i); 106 | indexMap.put(o1, j); 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /src/class07/Inner.java: -------------------------------------------------------------------------------- 1 | package class07; 2 | 3 | // 课上讲的包一层,这是不对的! 4 | // 这个文件是废物!留在这里是为了提醒同学们 : 5 | // 看"Code03_ShowHeapGreater",展示了用法 6 | public class Inner { 7 | public T value; 8 | 9 | public Inner(T v) { 10 | value = v; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/class08/Code01_Trie.java: -------------------------------------------------------------------------------- 1 | package class08; 2 | 3 | public class Code01_Trie { 4 | 5 | // 测试链接 : https://leetcode.cn/problems/implement-trie-ii-prefix-tree/ 6 | // 提交Trie类可以直接通过 7 | // 原来代码是对的,但是既然找到了直接测试的链接,那就直接测吧 8 | // 这个链接上要求实现的功能和课上讲的完全一样 9 | // 该前缀树的路用数组实现 10 | class Trie { 11 | 12 | class Node { 13 | public int pass; 14 | public int end; 15 | public Node[] nexts; 16 | 17 | public Node() { 18 | pass = 0; 19 | end = 0; 20 | nexts = new Node[26]; 21 | } 22 | } 23 | 24 | private Node root; 25 | 26 | public Trie() { 27 | root = new Node(); 28 | } 29 | 30 | public void insert(String word) { 31 | if (word == null) { 32 | return; 33 | } 34 | char[] str = word.toCharArray(); 35 | Node node = root; 36 | node.pass++; 37 | int path = 0; 38 | for (int i = 0; i < str.length; i++) { // 从左往右遍历字符 39 | path = str[i] - 'a'; // 由字符,对应成走向哪条路 40 | if (node.nexts[path] == null) { 41 | node.nexts[path] = new Node(); 42 | } 43 | node = node.nexts[path]; 44 | node.pass++; 45 | } 46 | node.end++; 47 | } 48 | 49 | public void erase(String word) { 50 | if (countWordsEqualTo(word) != 0) { 51 | char[] chs = word.toCharArray(); 52 | Node node = root; 53 | node.pass--; 54 | int path = 0; 55 | for (int i = 0; i < chs.length; i++) { 56 | path = chs[i] - 'a'; 57 | if (--node.nexts[path].pass == 0) { 58 | node.nexts[path] = null; 59 | return; 60 | } 61 | node = node.nexts[path]; 62 | } 63 | node.end--; 64 | } 65 | } 66 | 67 | public int countWordsEqualTo(String word) { 68 | if (word == null) { 69 | return 0; 70 | } 71 | char[] chs = word.toCharArray(); 72 | Node node = root; 73 | int index = 0; 74 | for (int i = 0; i < chs.length; i++) { 75 | index = chs[i] - 'a'; 76 | if (node.nexts[index] == null) { 77 | return 0; 78 | } 79 | node = node.nexts[index]; 80 | } 81 | return node.end; 82 | } 83 | 84 | public int countWordsStartingWith(String pre) { 85 | if (pre == null) { 86 | return 0; 87 | } 88 | char[] chs = pre.toCharArray(); 89 | Node node = root; 90 | int index = 0; 91 | for (int i = 0; i < chs.length; i++) { 92 | index = chs[i] - 'a'; 93 | if (node.nexts[index] == null) { 94 | return 0; 95 | } 96 | node = node.nexts[index]; 97 | } 98 | return node.pass; 99 | } 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /src/class08/Code02_Trie.java: -------------------------------------------------------------------------------- 1 | package class08; 2 | 3 | import java.util.HashMap; 4 | 5 | public class Code02_Trie { 6 | 7 | // 测试链接 : https://leetcode.cn/problems/implement-trie-ii-prefix-tree/ 8 | // 提交Trie类可以直接通过 9 | // 原来代码是对的,但是既然找到了直接测试的链接,那就直接测吧 10 | // 这个链接上要求实现的功能和课上讲的完全一样 11 | // 该前缀树的路用哈希表实现 12 | class Trie { 13 | 14 | class Node { 15 | public int pass; 16 | public int end; 17 | public HashMap nexts; 18 | 19 | public Node() { 20 | pass = 0; 21 | end = 0; 22 | nexts = new HashMap<>(); 23 | } 24 | } 25 | 26 | private Node root; 27 | 28 | public Trie() { 29 | root = new Node(); 30 | } 31 | 32 | public void insert(String word) { 33 | if (word == null) { 34 | return; 35 | } 36 | char[] chs = word.toCharArray(); 37 | Node node = root; 38 | node.pass++; 39 | int index = 0; 40 | for (int i = 0; i < chs.length; i++) { 41 | index = (int) chs[i]; 42 | if (!node.nexts.containsKey(index)) { 43 | node.nexts.put(index, new Node()); 44 | } 45 | node = node.nexts.get(index); 46 | node.pass++; 47 | } 48 | node.end++; 49 | } 50 | 51 | public void erase(String word) { 52 | if (countWordsEqualTo(word) != 0) { 53 | char[] chs = word.toCharArray(); 54 | Node node = root; 55 | node.pass--; 56 | int index = 0; 57 | for (int i = 0; i < chs.length; i++) { 58 | index = (int) chs[i]; 59 | if (--node.nexts.get(index).pass == 0) { 60 | node.nexts.remove(index); 61 | return; 62 | } 63 | node = node.nexts.get(index); 64 | } 65 | node.end--; 66 | } 67 | } 68 | 69 | public int countWordsEqualTo(String word) { 70 | if (word == null) { 71 | return 0; 72 | } 73 | char[] chs = word.toCharArray(); 74 | Node node = root; 75 | int index = 0; 76 | for (int i = 0; i < chs.length; i++) { 77 | index = (int) chs[i]; 78 | if (!node.nexts.containsKey(index)) { 79 | return 0; 80 | } 81 | node = node.nexts.get(index); 82 | } 83 | return node.end; 84 | } 85 | 86 | public int countWordsStartingWith(String pre) { 87 | if (pre == null) { 88 | return 0; 89 | } 90 | char[] chs = pre.toCharArray(); 91 | Node node = root; 92 | int index = 0; 93 | for (int i = 0; i < chs.length; i++) { 94 | index = (int) chs[i]; 95 | if (!node.nexts.containsKey(index)) { 96 | return 0; 97 | } 98 | node = node.nexts.get(index); 99 | } 100 | return node.pass; 101 | } 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /src/class08/Code03_CountSort.java: -------------------------------------------------------------------------------- 1 | package class08; 2 | 3 | import java.util.Arrays; 4 | 5 | public class Code03_CountSort { 6 | 7 | // only for 0~200 value 8 | public static void countSort(int[] arr) { 9 | if (arr == null || arr.length < 2) { 10 | return; 11 | } 12 | int max = Integer.MIN_VALUE; 13 | for (int i = 0; i < arr.length; i++) { 14 | max = Math.max(max, arr[i]); 15 | } 16 | int[] bucket = new int[max + 1]; 17 | for (int i = 0; i < arr.length; i++) { 18 | bucket[arr[i]]++; 19 | } 20 | int i = 0; 21 | for (int j = 0; j < bucket.length; j++) { 22 | while (bucket[j]-- > 0) { 23 | arr[i++] = j; 24 | } 25 | } 26 | } 27 | 28 | // for test 29 | public static void comparator(int[] arr) { 30 | Arrays.sort(arr); 31 | } 32 | 33 | // for test 34 | public static int[] generateRandomArray(int maxSize, int maxValue) { 35 | int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; 36 | for (int i = 0; i < arr.length; i++) { 37 | arr[i] = (int) ((maxValue + 1) * Math.random()); 38 | } 39 | return arr; 40 | } 41 | 42 | // for test 43 | public static int[] copyArray(int[] arr) { 44 | if (arr == null) { 45 | return null; 46 | } 47 | int[] res = new int[arr.length]; 48 | for (int i = 0; i < arr.length; i++) { 49 | res[i] = arr[i]; 50 | } 51 | return res; 52 | } 53 | 54 | // for test 55 | public static boolean isEqual(int[] arr1, int[] arr2) { 56 | if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) { 57 | return false; 58 | } 59 | if (arr1 == null && arr2 == null) { 60 | return true; 61 | } 62 | if (arr1.length != arr2.length) { 63 | return false; 64 | } 65 | for (int i = 0; i < arr1.length; i++) { 66 | if (arr1[i] != arr2[i]) { 67 | return false; 68 | } 69 | } 70 | return true; 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 | // for test 85 | public static void main(String[] args) { 86 | int testTime = 500000; 87 | int maxSize = 100; 88 | int maxValue = 150; 89 | boolean succeed = true; 90 | for (int i = 0; i < testTime; i++) { 91 | int[] arr1 = generateRandomArray(maxSize, maxValue); 92 | int[] arr2 = copyArray(arr1); 93 | countSort(arr1); 94 | comparator(arr2); 95 | if (!isEqual(arr1, arr2)) { 96 | succeed = false; 97 | printArray(arr1); 98 | printArray(arr2); 99 | break; 100 | } 101 | } 102 | System.out.println(succeed ? "Nice!" : "Fucking fucked!"); 103 | 104 | int[] arr = generateRandomArray(maxSize, maxValue); 105 | printArray(arr); 106 | countSort(arr); 107 | printArray(arr); 108 | 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /src/class09/Code04_CopyListWithRandom.java: -------------------------------------------------------------------------------- 1 | package class09; 2 | 3 | import java.util.HashMap; 4 | 5 | // 测试链接 : https://leetcode.com/problems/copy-list-with-random-pointer/ 6 | public class Code04_CopyListWithRandom { 7 | 8 | public static class Node { 9 | int val; 10 | Node next; 11 | Node random; 12 | 13 | public Node(int val) { 14 | this.val = val; 15 | this.next = null; 16 | this.random = null; 17 | } 18 | } 19 | 20 | public static Node copyRandomList1(Node head) { 21 | // key 老节点 22 | // value 新节点 23 | HashMap map = new HashMap(); 24 | Node cur = head; 25 | while (cur != null) { 26 | map.put(cur, new Node(cur.val)); 27 | cur = cur.next; 28 | } 29 | cur = head; 30 | while (cur != null) { 31 | // cur 老 32 | // map.get(cur) 新 33 | // 新.next -> cur.next克隆节点找到 34 | map.get(cur).next = map.get(cur.next); 35 | map.get(cur).random = map.get(cur.random); 36 | cur = cur.next; 37 | } 38 | return map.get(head); 39 | } 40 | 41 | public static Node copyRandomList2(Node head) { 42 | if (head == null) { 43 | return null; 44 | } 45 | Node cur = head; 46 | Node next = null; 47 | // 1 -> 2 -> 3 -> null 48 | // 1 -> 1' -> 2 -> 2' -> 3 -> 3' 49 | while (cur != null) { 50 | next = cur.next; 51 | cur.next = new Node(cur.val); 52 | cur.next.next = next; 53 | cur = next; 54 | } 55 | cur = head; 56 | Node copy = null; 57 | // 1 1' 2 2' 3 3' 58 | // 依次设置 1' 2' 3' random指针 59 | while (cur != null) { 60 | next = cur.next.next; 61 | copy = cur.next; 62 | copy.random = cur.random != null ? cur.random.next : null; 63 | cur = next; 64 | } 65 | Node res = head.next; 66 | cur = head; 67 | // 老 新 混在一起,next方向上,random正确 68 | // next方向上,把新老链表分离 69 | while (cur != null) { 70 | next = cur.next.next; 71 | copy = cur.next; 72 | cur.next = next; 73 | copy.next = next != null ? next.next : null; 74 | cur = next; 75 | } 76 | return res; 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/class10/Code02_RecursiveTraversalBT.java: -------------------------------------------------------------------------------- 1 | package class10; 2 | 3 | public class Code02_RecursiveTraversalBT { 4 | 5 | public static class Node { 6 | public int value; 7 | public Node left; 8 | public Node right; 9 | 10 | public Node(int v) { 11 | value = v; 12 | } 13 | } 14 | 15 | public static void f(Node head) { 16 | if (head == null) { 17 | return; 18 | } 19 | // 1 20 | f(head.left); 21 | // 2 22 | f(head.right); 23 | // 3 24 | } 25 | 26 | // 先序打印所有节点 27 | public static void pre(Node head) { 28 | if (head == null) { 29 | return; 30 | } 31 | System.out.println(head.value); 32 | pre(head.left); 33 | pre(head.right); 34 | } 35 | 36 | public static void in(Node head) { 37 | if (head == null) { 38 | return; 39 | } 40 | in(head.left); 41 | System.out.println(head.value); 42 | in(head.right); 43 | } 44 | 45 | public static void pos(Node head) { 46 | if (head == null) { 47 | return; 48 | } 49 | pos(head.left); 50 | pos(head.right); 51 | System.out.println(head.value); 52 | } 53 | 54 | public static void main(String[] args) { 55 | Node 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.left.right = new Node(5); 60 | head.right.left = new Node(6); 61 | head.right.right = new Node(7); 62 | 63 | pre(head); 64 | System.out.println("========"); 65 | in(head); 66 | System.out.println("========"); 67 | pos(head); 68 | System.out.println("========"); 69 | 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/class10/Code03_UnRecursiveTraversalBT.java: -------------------------------------------------------------------------------- 1 | package class10; 2 | 3 | import java.util.Stack; 4 | 5 | public class Code03_UnRecursiveTraversalBT { 6 | 7 | public static class Node { 8 | public int value; 9 | public Node left; 10 | public Node right; 11 | 12 | public Node(int v) { 13 | value = v; 14 | } 15 | } 16 | 17 | public static void pre(Node head) { 18 | System.out.print("pre-order: "); 19 | if (head != null) { 20 | Stack stack = new Stack(); 21 | stack.push(head); 22 | while (!stack.isEmpty()) { 23 | head = stack.pop(); 24 | System.out.print(head.value + " "); 25 | if (head.right != null) { 26 | stack.push(head.right); 27 | } 28 | if (head.left != null) { 29 | stack.push(head.left); 30 | } 31 | } 32 | } 33 | System.out.println(); 34 | } 35 | 36 | public static void in(Node cur) { 37 | System.out.print("in-order: "); 38 | if (cur != null) { 39 | Stack stack = new Stack(); 40 | while (!stack.isEmpty() || cur != null) { 41 | if (cur != null) { 42 | stack.push(cur); 43 | cur = cur.left; 44 | } else { 45 | cur = stack.pop(); 46 | System.out.print(cur.value + " "); 47 | cur = cur.right; 48 | } 49 | } 50 | } 51 | System.out.println(); 52 | } 53 | 54 | public static void pos1(Node head) { 55 | System.out.print("pos-order: "); 56 | if (head != null) { 57 | Stack s1 = new Stack(); 58 | Stack s2 = new Stack(); 59 | s1.push(head); 60 | while (!s1.isEmpty()) { 61 | head = s1.pop(); // 头 右 左 62 | s2.push(head); 63 | if (head.left != null) { 64 | s1.push(head.left); 65 | } 66 | if (head.right != null) { 67 | s1.push(head.right); 68 | } 69 | } 70 | // 左 右 头 71 | while (!s2.isEmpty()) { 72 | System.out.print(s2.pop().value + " "); 73 | } 74 | } 75 | System.out.println(); 76 | } 77 | 78 | public static void pos2(Node h) { 79 | System.out.print("pos-order: "); 80 | if (h != null) { 81 | Stack stack = new Stack(); 82 | stack.push(h); 83 | Node c = null; 84 | while (!stack.isEmpty()) { 85 | c = stack.peek(); 86 | if (c.left != null && h != c.left && h != c.right) { 87 | stack.push(c.left); 88 | } else if (c.right != null && h != c.right) { 89 | stack.push(c.right); 90 | } else { 91 | System.out.print(stack.pop().value + " "); 92 | h = c; 93 | } 94 | } 95 | } 96 | System.out.println(); 97 | } 98 | 99 | public static void main(String[] args) { 100 | Node head = new Node(1); 101 | head.left = new Node(2); 102 | head.right = new Node(3); 103 | head.left.left = new Node(4); 104 | head.left.right = new Node(5); 105 | head.right.left = new Node(6); 106 | head.right.right = new Node(7); 107 | 108 | pre(head); 109 | System.out.println("========"); 110 | in(head); 111 | System.out.println("========"); 112 | pos1(head); 113 | System.out.println("========"); 114 | pos2(head); 115 | System.out.println("========"); 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /src/class11/Code01_LevelTraversalBT.java: -------------------------------------------------------------------------------- 1 | package class11; 2 | 3 | import java.util.LinkedList; 4 | import java.util.Queue; 5 | 6 | public class Code01_LevelTraversalBT { 7 | 8 | public static class Node { 9 | public int value; 10 | public Node left; 11 | public Node right; 12 | 13 | public Node(int v) { 14 | value = v; 15 | } 16 | } 17 | 18 | public static void level(Node head) { 19 | if (head == null) { 20 | return; 21 | } 22 | Queue queue = new LinkedList<>(); 23 | queue.add(head); 24 | while (!queue.isEmpty()) { 25 | Node cur = queue.poll(); 26 | System.out.println(cur.value); 27 | if (cur.left != null) { 28 | queue.add(cur.left); 29 | } 30 | if (cur.right != null) { 31 | queue.add(cur.right); 32 | } 33 | } 34 | } 35 | 36 | public static void main(String[] args) { 37 | Node head = new Node(1); 38 | head.left = new Node(2); 39 | head.right = new Node(3); 40 | head.left.left = new Node(4); 41 | head.left.right = new Node(5); 42 | head.right.left = new Node(6); 43 | head.right.right = new Node(7); 44 | 45 | level(head); 46 | System.out.println("========"); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/class11/Code03_EncodeNaryTreeToBinaryTree.java: -------------------------------------------------------------------------------- 1 | package class11; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | // 本题测试链接:https://leetcode.com/problems/encode-n-ary-tree-to-binary-tree 7 | public class Code03_EncodeNaryTreeToBinaryTree { 8 | 9 | // 提交时不要提交这个类 10 | public static class Node { 11 | public int val; 12 | public List children; 13 | 14 | public Node() { 15 | } 16 | 17 | public Node(int _val) { 18 | val = _val; 19 | } 20 | 21 | public Node(int _val, List _children) { 22 | val = _val; 23 | children = _children; 24 | } 25 | }; 26 | 27 | // 提交时不要提交这个类 28 | public static class TreeNode { 29 | int val; 30 | TreeNode left; 31 | TreeNode right; 32 | 33 | TreeNode(int x) { 34 | val = x; 35 | } 36 | } 37 | 38 | // 只提交这个类即可 39 | class Codec { 40 | // Encodes an n-ary tree to a binary tree. 41 | public TreeNode encode(Node root) { 42 | if (root == null) { 43 | return null; 44 | } 45 | TreeNode head = new TreeNode(root.val); 46 | head.left = en(root.children); 47 | return head; 48 | } 49 | 50 | private TreeNode en(List children) { 51 | TreeNode head = null; 52 | TreeNode cur = null; 53 | for (Node child : children) { 54 | TreeNode tNode = new TreeNode(child.val); 55 | if (head == null) { 56 | head = tNode; 57 | } else { 58 | cur.right = tNode; 59 | } 60 | cur = tNode; 61 | cur.left = en(child.children); 62 | } 63 | return head; 64 | } 65 | 66 | // Decodes your binary tree to an n-ary tree. 67 | public Node decode(TreeNode root) { 68 | if (root == null) { 69 | return null; 70 | } 71 | return new Node(root.val, de(root.left)); 72 | } 73 | 74 | public List de(TreeNode root) { 75 | List children = new ArrayList<>(); 76 | while (root != null) { 77 | Node cur = new Node(root.val, de(root.left)); 78 | children.add(cur); 79 | root = root.right; 80 | } 81 | return children; 82 | } 83 | 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/class11/Code04_PrintBinaryTree.java: -------------------------------------------------------------------------------- 1 | package class11; 2 | 3 | public class Code04_PrintBinaryTree { 4 | 5 | public static class Node { 6 | public int value; 7 | public Node left; 8 | public Node right; 9 | 10 | public Node(int data) { 11 | this.value = data; 12 | } 13 | } 14 | 15 | public static void printTree(Node head) { 16 | System.out.println("Binary Tree:"); 17 | printInOrder(head, 0, "H", 17); 18 | System.out.println(); 19 | } 20 | 21 | public static void printInOrder(Node head, int height, String to, int len) { 22 | if (head == null) { 23 | return; 24 | } 25 | printInOrder(head.right, height + 1, "v", len); 26 | String val = to + head.value + to; 27 | int lenM = val.length(); 28 | int lenL = (len - lenM) / 2; 29 | int lenR = len - lenM - lenL; 30 | val = getSpace(lenL) + val + getSpace(lenR); 31 | System.out.println(getSpace(height * len) + val); 32 | printInOrder(head.left, height + 1, "^", len); 33 | } 34 | 35 | public static String getSpace(int num) { 36 | String space = " "; 37 | StringBuffer buf = new StringBuffer(""); 38 | for (int i = 0; i < num; i++) { 39 | buf.append(space); 40 | } 41 | return buf.toString(); 42 | } 43 | 44 | public static void main(String[] args) { 45 | Node head = new Node(1); 46 | head.left = new Node(-222222222); 47 | head.right = new Node(3); 48 | head.left.left = new Node(Integer.MIN_VALUE); 49 | head.right.left = new Node(55555555); 50 | head.right.right = new Node(66); 51 | head.left.left.right = new Node(777); 52 | printTree(head); 53 | 54 | head = new Node(1); 55 | head.left = new Node(2); 56 | head.right = new Node(3); 57 | head.left.left = new Node(4); 58 | head.right.left = new Node(5); 59 | head.right.right = new Node(6); 60 | head.left.left.right = new Node(7); 61 | printTree(head); 62 | 63 | head = new Node(1); 64 | head.left = new Node(1); 65 | head.right = new Node(1); 66 | head.left.left = new Node(1); 67 | head.right.left = new Node(1); 68 | head.right.right = new Node(1); 69 | head.left.left.right = new Node(1); 70 | printTree(head); 71 | 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/class11/Code05_TreeMaxWidth.java: -------------------------------------------------------------------------------- 1 | package class11; 2 | 3 | import java.util.HashMap; 4 | import java.util.LinkedList; 5 | import java.util.Queue; 6 | 7 | public class Code05_TreeMaxWidth { 8 | 9 | public static class Node { 10 | public int value; 11 | public Node left; 12 | public Node right; 13 | 14 | public Node(int data) { 15 | this.value = data; 16 | } 17 | } 18 | 19 | public static int maxWidthUseMap(Node head) { 20 | if (head == null) { 21 | return 0; 22 | } 23 | Queue queue = new LinkedList<>(); 24 | queue.add(head); 25 | // key 在 哪一层,value 26 | HashMap levelMap = new HashMap<>(); 27 | levelMap.put(head, 1); 28 | int curLevel = 1; // 当前你正在统计哪一层的宽度 29 | int curLevelNodes = 0; // 当前层curLevel层,宽度目前是多少 30 | int max = 0; 31 | while (!queue.isEmpty()) { 32 | Node cur = queue.poll(); 33 | int curNodeLevel = levelMap.get(cur); 34 | if (cur.left != null) { 35 | levelMap.put(cur.left, curNodeLevel + 1); 36 | queue.add(cur.left); 37 | } 38 | if (cur.right != null) { 39 | levelMap.put(cur.right, curNodeLevel + 1); 40 | queue.add(cur.right); 41 | } 42 | if (curNodeLevel == curLevel) { 43 | curLevelNodes++; 44 | } else { 45 | max = Math.max(max, curLevelNodes); 46 | curLevel++; 47 | curLevelNodes = 1; 48 | } 49 | } 50 | max = Math.max(max, curLevelNodes); 51 | return max; 52 | } 53 | 54 | public static int maxWidthNoMap(Node head) { 55 | if (head == null) { 56 | return 0; 57 | } 58 | Queue queue = new LinkedList<>(); 59 | queue.add(head); 60 | Node curEnd = head; // 当前层,最右节点是谁 61 | Node nextEnd = null; // 下一层,最右节点是谁 62 | int max = 0; 63 | int curLevelNodes = 0; // 当前层的节点数 64 | while (!queue.isEmpty()) { 65 | Node cur = queue.poll(); 66 | if (cur.left != null) { 67 | queue.add(cur.left); 68 | nextEnd = cur.left; 69 | } 70 | if (cur.right != null) { 71 | queue.add(cur.right); 72 | nextEnd = cur.right; 73 | } 74 | curLevelNodes++; 75 | if (cur == curEnd) { 76 | max = Math.max(max, curLevelNodes); 77 | curLevelNodes = 0; 78 | curEnd = nextEnd; 79 | } 80 | } 81 | return max; 82 | } 83 | 84 | // for test 85 | public static Node generateRandomBST(int maxLevel, int maxValue) { 86 | return generate(1, maxLevel, maxValue); 87 | } 88 | 89 | // for test 90 | public static Node generate(int level, int maxLevel, int maxValue) { 91 | if (level > maxLevel || Math.random() < 0.5) { 92 | return null; 93 | } 94 | Node head = new Node((int) (Math.random() * maxValue)); 95 | head.left = generate(level + 1, maxLevel, maxValue); 96 | head.right = generate(level + 1, maxLevel, maxValue); 97 | return head; 98 | } 99 | 100 | public static void main(String[] args) { 101 | int maxLevel = 10; 102 | int maxValue = 100; 103 | int testTimes = 1000000; 104 | for (int i = 0; i < testTimes; i++) { 105 | Node head = generateRandomBST(maxLevel, maxValue); 106 | if (maxWidthUseMap(head) != maxWidthNoMap(head)) { 107 | System.out.println("Oops!"); 108 | } 109 | } 110 | System.out.println("finish!"); 111 | 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /src/class11/Code06_SuccessorNode.java: -------------------------------------------------------------------------------- 1 | package class11; 2 | 3 | public class Code06_SuccessorNode { 4 | 5 | public static class Node { 6 | public int value; 7 | public Node left; 8 | public Node right; 9 | public Node parent; 10 | 11 | public Node(int data) { 12 | this.value = data; 13 | } 14 | } 15 | 16 | public static Node getSuccessorNode(Node node) { 17 | if (node == null) { 18 | return node; 19 | } 20 | if (node.right != null) { 21 | return getLeftMost(node.right); 22 | } else { // 无右子树 23 | Node parent = node.parent; 24 | while (parent != null && parent.right == node) { // 当前节点是其父亲节点右孩子 25 | node = parent; 26 | parent = node.parent; 27 | } 28 | return parent; 29 | } 30 | } 31 | 32 | public static Node getLeftMost(Node node) { 33 | if (node == null) { 34 | return node; 35 | } 36 | while (node.left != null) { 37 | node = node.left; 38 | } 39 | return node; 40 | } 41 | 42 | public static void main(String[] args) { 43 | Node head = new Node(6); 44 | head.parent = null; 45 | head.left = new Node(3); 46 | head.left.parent = head; 47 | head.left.left = new Node(1); 48 | head.left.left.parent = head.left; 49 | head.left.left.right = new Node(2); 50 | head.left.left.right.parent = head.left.left; 51 | head.left.right = new Node(4); 52 | head.left.right.parent = head.left; 53 | head.left.right.right = new Node(5); 54 | head.left.right.right.parent = head.left.right; 55 | head.right = new Node(9); 56 | head.right.parent = head; 57 | head.right.left = new Node(8); 58 | head.right.left.parent = head.right; 59 | head.right.left.left = new Node(7); 60 | head.right.left.left.parent = head.right.left; 61 | head.right.right = new Node(10); 62 | head.right.right.parent = head.right; 63 | 64 | Node test = head.left.left; 65 | System.out.println(test.value + " next: " + getSuccessorNode(test).value); 66 | test = head.left.left.right; 67 | System.out.println(test.value + " next: " + getSuccessorNode(test).value); 68 | test = head.left; 69 | System.out.println(test.value + " next: " + getSuccessorNode(test).value); 70 | test = head.left.right; 71 | System.out.println(test.value + " next: " + getSuccessorNode(test).value); 72 | test = head.left.right.right; 73 | System.out.println(test.value + " next: " + getSuccessorNode(test).value); 74 | test = head; 75 | System.out.println(test.value + " next: " + getSuccessorNode(test).value); 76 | test = head.right.left.left; 77 | System.out.println(test.value + " next: " + getSuccessorNode(test).value); 78 | test = head.right.left; 79 | System.out.println(test.value + " next: " + getSuccessorNode(test).value); 80 | test = head.right; 81 | System.out.println(test.value + " next: " + getSuccessorNode(test).value); 82 | test = head.right.right; // 10's next is null 83 | System.out.println(test.value + " next: " + getSuccessorNode(test)); 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/class11/Code07_PaperFolding.java: -------------------------------------------------------------------------------- 1 | package class11; 2 | 3 | public class Code07_PaperFolding { 4 | 5 | public static void printAllFolds(int N) { 6 | process(1, N, true); 7 | System.out.println(); 8 | } 9 | 10 | // 当前你来了一个节点,脑海中想象的! 11 | // 这个节点在第i层,一共有N层,N固定不变的 12 | // 这个节点如果是凹的话,down = T 13 | // 这个节点如果是凸的话,down = F 14 | // 函数的功能:中序打印以你想象的节点为头的整棵树! 15 | public static void process(int i, int N, boolean down) { 16 | if (i > N) { 17 | return; 18 | } 19 | process(i + 1, N, true); 20 | System.out.print(down ? "凹 " : "凸 "); 21 | process(i + 1, N, false); 22 | } 23 | 24 | public static void main(String[] args) { 25 | int N = 4; 26 | printAllFolds(N); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/class12/Code03_IsBalanced.java: -------------------------------------------------------------------------------- 1 | package class12; 2 | 3 | public class Code03_IsBalanced { 4 | 5 | public static class Node { 6 | public int value; 7 | public Node left; 8 | public Node right; 9 | 10 | public Node(int data) { 11 | this.value = data; 12 | } 13 | } 14 | 15 | public static boolean isBalanced1(Node head) { 16 | boolean[] ans = new boolean[1]; 17 | ans[0] = true; 18 | process1(head, ans); 19 | return ans[0]; 20 | } 21 | 22 | public static int process1(Node head, boolean[] ans) { 23 | if (!ans[0] || head == null) { 24 | return -1; 25 | } 26 | int leftHeight = process1(head.left, ans); 27 | int rightHeight = process1(head.right, ans); 28 | if (Math.abs(leftHeight - rightHeight) > 1) { 29 | ans[0] = false; 30 | } 31 | return Math.max(leftHeight, rightHeight) + 1; 32 | } 33 | 34 | public static boolean isBalanced2(Node head) { 35 | return process(head).isBalanced; 36 | } 37 | 38 | public static class Info{ 39 | public boolean isBalanced; 40 | public int height; 41 | 42 | public Info(boolean i, int h) { 43 | isBalanced = i; 44 | height = h; 45 | } 46 | } 47 | 48 | public static Info process(Node x) { 49 | if(x == null) { 50 | return new Info(true, 0); 51 | } 52 | Info leftInfo = process(x.left); 53 | Info rightInfo = process(x.right); 54 | int height = Math.max(leftInfo.height, rightInfo.height) + 1; 55 | boolean isBalanced = true; 56 | if(!leftInfo.isBalanced) { 57 | isBalanced = false; 58 | } 59 | if(!rightInfo.isBalanced) { 60 | isBalanced = false; 61 | } 62 | if(Math.abs(leftInfo.height - rightInfo.height) > 1) { 63 | isBalanced = false; 64 | } 65 | return new Info(isBalanced, height); 66 | } 67 | 68 | 69 | 70 | 71 | 72 | 73 | // for test 74 | public static Node generateRandomBST(int maxLevel, int maxValue) { 75 | return generate(1, maxLevel, maxValue); 76 | } 77 | 78 | // for test 79 | public static Node generate(int level, int maxLevel, int maxValue) { 80 | if (level > maxLevel || Math.random() < 0.5) { 81 | return null; 82 | } 83 | Node head = new Node((int) (Math.random() * maxValue)); 84 | head.left = generate(level + 1, maxLevel, maxValue); 85 | head.right = generate(level + 1, maxLevel, maxValue); 86 | return head; 87 | } 88 | 89 | public static void main(String[] args) { 90 | int maxLevel = 5; 91 | int maxValue = 100; 92 | int testTimes = 1000000; 93 | for (int i = 0; i < testTimes; i++) { 94 | Node head = generateRandomBST(maxLevel, maxValue); 95 | if (isBalanced1(head) != isBalanced2(head)) { 96 | System.out.println("Oops!"); 97 | } 98 | } 99 | System.out.println("finish!"); 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /src/class12/Code04_IsFull.java: -------------------------------------------------------------------------------- 1 | package class12; 2 | 3 | public class Code04_IsFull { 4 | 5 | public static class Node { 6 | public int value; 7 | public Node left; 8 | public Node right; 9 | 10 | public Node(int data) { 11 | this.value = data; 12 | } 13 | } 14 | 15 | // 第一种方法 16 | // 收集整棵树的高度h,和节点数n 17 | // 只有满二叉树满足 : 2 ^ h - 1 == n 18 | public static boolean isFull1(Node head) { 19 | if (head == null) { 20 | return true; 21 | } 22 | Info1 all = process1(head); 23 | return (1 << all.height) - 1 == all.nodes; 24 | } 25 | 26 | public static class Info1 { 27 | public int height; 28 | public int nodes; 29 | 30 | public Info1(int h, int n) { 31 | height = h; 32 | nodes = n; 33 | } 34 | } 35 | 36 | public static Info1 process1(Node head) { 37 | if (head == null) { 38 | return new Info1(0, 0); 39 | } 40 | Info1 leftInfo = process1(head.left); 41 | Info1 rightInfo = process1(head.right); 42 | int height = Math.max(leftInfo.height, rightInfo.height) + 1; 43 | int nodes = leftInfo.nodes + rightInfo.nodes + 1; 44 | return new Info1(height, nodes); 45 | } 46 | 47 | // 第二种方法 48 | // 收集子树是否是满二叉树 49 | // 收集子树的高度 50 | // 左树满 && 右树满 && 左右树高度一样 -> 整棵树是满的 51 | public static boolean isFull2(Node head) { 52 | if (head == null) { 53 | return true; 54 | } 55 | return process2(head).isFull; 56 | } 57 | 58 | public static class Info2 { 59 | public boolean isFull; 60 | public int height; 61 | 62 | public Info2(boolean f, int h) { 63 | isFull = f; 64 | height = h; 65 | } 66 | } 67 | 68 | public static Info2 process2(Node h) { 69 | if (h == null) { 70 | return new Info2(true, 0); 71 | } 72 | Info2 leftInfo = process2(h.left); 73 | Info2 rightInfo = process2(h.right); 74 | boolean isFull = leftInfo.isFull && rightInfo.isFull && leftInfo.height == rightInfo.height; 75 | int height = Math.max(leftInfo.height, rightInfo.height) + 1; 76 | return new Info2(isFull, height); 77 | } 78 | 79 | // for test 80 | public static Node generateRandomBST(int maxLevel, int maxValue) { 81 | return generate(1, maxLevel, maxValue); 82 | } 83 | 84 | // for test 85 | public static Node generate(int level, int maxLevel, int maxValue) { 86 | if (level > maxLevel || Math.random() < 0.5) { 87 | return null; 88 | } 89 | Node head = new Node((int) (Math.random() * maxValue)); 90 | head.left = generate(level + 1, maxLevel, maxValue); 91 | head.right = generate(level + 1, maxLevel, maxValue); 92 | return head; 93 | } 94 | 95 | public static void main(String[] args) { 96 | int maxLevel = 5; 97 | int maxValue = 100; 98 | int testTimes = 1000000; 99 | System.out.println("测试开始"); 100 | for (int i = 0; i < testTimes; i++) { 101 | Node head = generateRandomBST(maxLevel, maxValue); 102 | if (isFull1(head) != isFull2(head)) { 103 | System.out.println("出错了!"); 104 | } 105 | } 106 | System.out.println("测试结束"); 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /src/class13/Code04_MaxHappy.java: -------------------------------------------------------------------------------- 1 | package class13; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class Code04_MaxHappy { 7 | 8 | public static class Employee { 9 | public int happy; 10 | public List nexts; 11 | 12 | public Employee(int h) { 13 | happy = h; 14 | nexts = new ArrayList<>(); 15 | } 16 | 17 | } 18 | 19 | public static int maxHappy1(Employee boss) { 20 | if (boss == null) { 21 | return 0; 22 | } 23 | return process1(boss, false); 24 | } 25 | 26 | // 当前来到的节点叫cur, 27 | // up表示cur的上级是否来, 28 | // 该函数含义: 29 | // 如果up为true,表示在cur上级已经确定来,的情况下,cur整棵树能够提供最大的快乐值是多少? 30 | // 如果up为false,表示在cur上级已经确定不来,的情况下,cur整棵树能够提供最大的快乐值是多少? 31 | public static int process1(Employee cur, boolean up) { 32 | if (up) { // 如果cur的上级来的话,cur没得选,只能不来 33 | int ans = 0; 34 | for (Employee next : cur.nexts) { 35 | ans += process1(next, false); 36 | } 37 | return ans; 38 | } else { // 如果cur的上级不来的话,cur可以选,可以来也可以不来 39 | int p1 = cur.happy; 40 | int p2 = 0; 41 | for (Employee next : cur.nexts) { 42 | p1 += process1(next, true); 43 | p2 += process1(next, false); 44 | } 45 | return Math.max(p1, p2); 46 | } 47 | } 48 | 49 | public static int maxHappy2(Employee head) { 50 | Info allInfo = process(head); 51 | return Math.max(allInfo.no, allInfo.yes); 52 | } 53 | 54 | public static class Info { 55 | public int no; 56 | public int yes; 57 | 58 | public Info(int n, int y) { 59 | no = n; 60 | yes = y; 61 | } 62 | } 63 | 64 | public static Info process(Employee x) { 65 | if (x == null) { 66 | return new Info(0, 0); 67 | } 68 | int no = 0; 69 | int yes = x.happy; 70 | for (Employee next : x.nexts) { 71 | Info nextInfo = process(next); 72 | no += Math.max(nextInfo.no, nextInfo.yes); 73 | yes += nextInfo.no; 74 | 75 | } 76 | return new Info(no, yes); 77 | } 78 | 79 | // for test 80 | public static Employee genarateBoss(int maxLevel, int maxNexts, int maxHappy) { 81 | if (Math.random() < 0.02) { 82 | return null; 83 | } 84 | Employee boss = new Employee((int) (Math.random() * (maxHappy + 1))); 85 | genarateNexts(boss, 1, maxLevel, maxNexts, maxHappy); 86 | return boss; 87 | } 88 | 89 | // for test 90 | public static void genarateNexts(Employee e, int level, int maxLevel, int maxNexts, int maxHappy) { 91 | if (level > maxLevel) { 92 | return; 93 | } 94 | int nextsSize = (int) (Math.random() * (maxNexts + 1)); 95 | for (int i = 0; i < nextsSize; i++) { 96 | Employee next = new Employee((int) (Math.random() * (maxHappy + 1))); 97 | e.nexts.add(next); 98 | genarateNexts(next, level + 1, maxLevel, maxNexts, maxHappy); 99 | } 100 | } 101 | 102 | public static void main(String[] args) { 103 | int maxLevel = 4; 104 | int maxNexts = 7; 105 | int maxHappy = 100; 106 | int testTimes = 100000; 107 | for (int i = 0; i < testTimes; i++) { 108 | Employee boss = genarateBoss(maxLevel, maxNexts, maxHappy); 109 | if (maxHappy1(boss) != maxHappy2(boss)) { 110 | System.out.println("Oops!"); 111 | } 112 | } 113 | System.out.println("finish!"); 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /src/class14/Code01_Light.java: -------------------------------------------------------------------------------- 1 | package class14; 2 | 3 | import java.util.HashSet; 4 | 5 | public class Code01_Light { 6 | 7 | public static int minLight1(String road) { 8 | if (road == null || road.length() == 0) { 9 | return 0; 10 | } 11 | return process(road.toCharArray(), 0, new HashSet<>()); 12 | } 13 | 14 | // str[index....]位置,自由选择放灯还是不放灯 15 | // str[0..index-1]位置呢?已经做完决定了,那些放了灯的位置,存在lights里 16 | // 要求选出能照亮所有.的方案,并且在这些有效的方案中,返回最少需要几个灯 17 | public static int process(char[] str, int index, HashSet lights) { 18 | if (index == str.length) { // 结束的时候 19 | for (int i = 0; i < str.length; i++) { 20 | if (str[i] != 'X') { // 当前位置是点的话 21 | if (!lights.contains(i - 1) && !lights.contains(i) && !lights.contains(i + 1)) { 22 | return Integer.MAX_VALUE; 23 | } 24 | } 25 | } 26 | return lights.size(); 27 | } else { // str还没结束 28 | // i X . 29 | int no = process(str, index + 1, lights); 30 | int yes = Integer.MAX_VALUE; 31 | if (str[index] == '.') { 32 | lights.add(index); 33 | yes = process(str, index + 1, lights); 34 | lights.remove(index); 35 | } 36 | return Math.min(no, yes); 37 | } 38 | } 39 | 40 | public static int minLight2(String road) { 41 | char[] str = road.toCharArray(); 42 | int i = 0; 43 | int light = 0; 44 | while (i < str.length) { 45 | if (str[i] == 'X') { 46 | i++; 47 | } else { 48 | light++; 49 | if (i + 1 == str.length) { 50 | break; 51 | } else { // 有i位置 i+ 1 X . 52 | if (str[i + 1] == 'X') { 53 | i = i + 2; 54 | } else { 55 | i = i + 3; 56 | } 57 | } 58 | } 59 | } 60 | return light; 61 | } 62 | 63 | // 更简洁的解法 64 | // 两个X之间,数一下.的数量,然后除以3,向上取整 65 | // 把灯数累加 66 | public static int minLight3(String road) { 67 | char[] str = road.toCharArray(); 68 | int cur = 0; 69 | int light = 0; 70 | for (char c : str) { 71 | if (c == 'X') { 72 | light += (cur + 2) / 3; 73 | cur = 0; 74 | } else { 75 | cur++; 76 | } 77 | } 78 | light += (cur + 2) / 3; 79 | return light; 80 | } 81 | 82 | // for test 83 | public static String randomString(int len) { 84 | char[] res = new char[(int) (Math.random() * len) + 1]; 85 | for (int i = 0; i < res.length; i++) { 86 | res[i] = Math.random() < 0.5 ? 'X' : '.'; 87 | } 88 | return String.valueOf(res); 89 | } 90 | 91 | public static void main(String[] args) { 92 | int len = 20; 93 | int testTime = 100000; 94 | for (int i = 0; i < testTime; i++) { 95 | String test = randomString(len); 96 | int ans1 = minLight1(test); 97 | int ans2 = minLight2(test); 98 | int ans3 = minLight3(test); 99 | if (ans1 != ans2 || ans1 != ans3) { 100 | System.out.println("oops!"); 101 | } 102 | } 103 | System.out.println("finish!"); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/class14/Code02_LessMoneySplitGold.java: -------------------------------------------------------------------------------- 1 | package class14; 2 | 3 | import java.util.PriorityQueue; 4 | 5 | public class Code02_LessMoneySplitGold { 6 | 7 | // 纯暴力! 8 | public static int lessMoney1(int[] arr) { 9 | if (arr == null || arr.length == 0) { 10 | return 0; 11 | } 12 | return process(arr, 0); 13 | } 14 | 15 | // 等待合并的数都在arr里,pre之前的合并行为产生了多少总代价 16 | // arr中只剩一个数字的时候,停止合并,返回最小的总代价 17 | public static int process(int[] arr, int pre) { 18 | if (arr.length == 1) { 19 | return pre; 20 | } 21 | int ans = Integer.MAX_VALUE; 22 | for (int i = 0; i < arr.length; i++) { 23 | for (int j = i + 1; j < arr.length; j++) { 24 | ans = Math.min(ans, process(copyAndMergeTwo(arr, i, j), pre + arr[i] + arr[j])); 25 | } 26 | } 27 | return ans; 28 | } 29 | 30 | public static int[] copyAndMergeTwo(int[] arr, int i, int j) { 31 | int[] ans = new int[arr.length - 1]; 32 | int ansi = 0; 33 | for (int arri = 0; arri < arr.length; arri++) { 34 | if (arri != i && arri != j) { 35 | ans[ansi++] = arr[arri]; 36 | } 37 | } 38 | ans[ansi] = arr[i] + arr[j]; 39 | return ans; 40 | } 41 | 42 | public static int lessMoney2(int[] arr) { 43 | PriorityQueue pQ = new PriorityQueue<>(); 44 | for (int i = 0; i < arr.length; i++) { 45 | pQ.add(arr[i]); 46 | } 47 | int sum = 0; 48 | int cur = 0; 49 | while (pQ.size() > 1) { 50 | cur = pQ.poll() + pQ.poll(); 51 | sum += cur; 52 | pQ.add(cur); 53 | } 54 | return sum; 55 | } 56 | 57 | // for test 58 | public static int[] generateRandomArray(int maxSize, int maxValue) { 59 | int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; 60 | for (int i = 0; i < arr.length; i++) { 61 | arr[i] = (int) (Math.random() * (maxValue + 1)); 62 | } 63 | return arr; 64 | } 65 | 66 | public static void main(String[] args) { 67 | int testTime = 100000; 68 | int maxSize = 6; 69 | int maxValue = 1000; 70 | for (int i = 0; i < testTime; i++) { 71 | int[] arr = generateRandomArray(maxSize, maxValue); 72 | if (lessMoney1(arr) != lessMoney2(arr)) { 73 | System.out.println("Oops!"); 74 | } 75 | } 76 | System.out.println("finish!"); 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/class14/Code03_BestArrange.java: -------------------------------------------------------------------------------- 1 | package class14; 2 | 3 | import java.util.Arrays; 4 | import java.util.Comparator; 5 | 6 | public class Code03_BestArrange { 7 | 8 | public static class Program { 9 | public int start; 10 | public int end; 11 | 12 | public Program(int start, int end) { 13 | this.start = start; 14 | this.end = end; 15 | } 16 | } 17 | 18 | // 暴力!所有情况都尝试! 19 | public static int bestArrange1(Program[] programs) { 20 | if (programs == null || programs.length == 0) { 21 | return 0; 22 | } 23 | return process(programs, 0, 0); 24 | } 25 | 26 | // 还剩下的会议都放在programs里 27 | // done之前已经安排了多少会议的数量 28 | // timeLine目前来到的时间点是什么 29 | 30 | // 目前来到timeLine的时间点,已经安排了done多的会议,剩下的会议programs可以自由安排 31 | // 返回能安排的最多会议数量 32 | public static int process(Program[] programs, int done, int timeLine) { 33 | if (programs.length == 0) { 34 | return done; 35 | } 36 | // 还剩下会议 37 | int max = done; 38 | // 当前安排的会议是什么会,每一个都枚举 39 | for (int i = 0; i < programs.length; i++) { 40 | if (programs[i].start >= timeLine) { 41 | Program[] next = copyButExcept(programs, i); 42 | max = Math.max(max, process(next, done + 1, programs[i].end)); 43 | } 44 | } 45 | return max; 46 | } 47 | 48 | public static Program[] copyButExcept(Program[] programs, int i) { 49 | Program[] ans = new Program[programs.length - 1]; 50 | int index = 0; 51 | for (int k = 0; k < programs.length; k++) { 52 | if (k != i) { 53 | ans[index++] = programs[k]; 54 | } 55 | } 56 | return ans; 57 | } 58 | 59 | // 会议的开始时间和结束时间,都是数值,不会 < 0 60 | public static int bestArrange2(Program[] programs) { 61 | Arrays.sort(programs, new ProgramComparator()); 62 | int timeLine = 0; 63 | int result = 0; 64 | // 依次遍历每一个会议,结束时间早的会议先遍历 65 | for (int i = 0; i < programs.length; i++) { 66 | if (timeLine <= programs[i].start) { 67 | result++; 68 | timeLine = programs[i].end; 69 | } 70 | } 71 | return result; 72 | } 73 | 74 | public static class ProgramComparator implements Comparator { 75 | 76 | @Override 77 | public int compare(Program o1, Program o2) { 78 | return o1.end - o2.end; 79 | } 80 | 81 | } 82 | 83 | // for test 84 | public static Program[] generatePrograms(int programSize, int timeMax) { 85 | Program[] ans = new Program[(int) (Math.random() * (programSize + 1))]; 86 | for (int i = 0; i < ans.length; i++) { 87 | int r1 = (int) (Math.random() * (timeMax + 1)); 88 | int r2 = (int) (Math.random() * (timeMax + 1)); 89 | if (r1 == r2) { 90 | ans[i] = new Program(r1, r1 + 1); 91 | } else { 92 | ans[i] = new Program(Math.min(r1, r2), Math.max(r1, r2)); 93 | } 94 | } 95 | return ans; 96 | } 97 | 98 | public static void main(String[] args) { 99 | int programSize = 12; 100 | int timeMax = 20; 101 | int timeTimes = 1000000; 102 | for (int i = 0; i < timeTimes; i++) { 103 | Program[] programs = generatePrograms(programSize, timeMax); 104 | if (bestArrange1(programs) != bestArrange2(programs)) { 105 | System.out.println("Oops!"); 106 | } 107 | } 108 | System.out.println("finish!"); 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /src/class14/Code04_IPO.java: -------------------------------------------------------------------------------- 1 | package class14; 2 | 3 | import java.util.Comparator; 4 | import java.util.PriorityQueue; 5 | 6 | public class Code04_IPO { 7 | 8 | // 最多K个项目 9 | // W是初始资金 10 | // Profits[] Capital[] 一定等长 11 | // 返回最终最大的资金 12 | public static int findMaximizedCapital(int K, int W, int[] Profits, int[] Capital) { 13 | PriorityQueue minCostQ = new PriorityQueue<>(new MinCostComparator()); 14 | PriorityQueue maxProfitQ = new PriorityQueue<>(new MaxProfitComparator()); 15 | for (int i = 0; i < Profits.length; i++) { 16 | minCostQ.add(new Program(Profits[i], Capital[i])); 17 | } 18 | for (int i = 0; i < K; i++) { 19 | while (!minCostQ.isEmpty() && minCostQ.peek().c <= W) { 20 | maxProfitQ.add(minCostQ.poll()); 21 | } 22 | if (maxProfitQ.isEmpty()) { 23 | return W; 24 | } 25 | W += maxProfitQ.poll().p; 26 | } 27 | return W; 28 | } 29 | 30 | public static class Program { 31 | public int p; 32 | public int c; 33 | 34 | public Program(int p, int c) { 35 | this.p = p; 36 | this.c = c; 37 | } 38 | } 39 | 40 | public static class MinCostComparator implements Comparator { 41 | 42 | @Override 43 | public int compare(Program o1, Program o2) { 44 | return o1.c - o2.c; 45 | } 46 | 47 | } 48 | 49 | public static class MaxProfitComparator implements Comparator { 50 | 51 | @Override 52 | public int compare(Program o1, Program o2) { 53 | return o2.p - o1.p; 54 | } 55 | 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/class14/Code05_UnionFind.java: -------------------------------------------------------------------------------- 1 | package class14; 2 | 3 | import java.util.HashMap; 4 | import java.util.List; 5 | import java.util.Stack; 6 | 7 | // 课上讲的并查集实现 8 | // 请务必看补充的Code06_UnionFind 9 | // 那是数组实现的并查集,并且有测试链接 10 | // 可以直接通过 11 | // 这个文件的并查集是用map实现的 12 | // 但是笔试或者平时用的并查集一律用数组实现 13 | // 所以Code06_UnionFind更具实战意义 14 | // 一定要看! 15 | public class Code05_UnionFind { 16 | 17 | // 课上讲的时候 18 | // 包了一层 19 | // 其实不用包一层哦 20 | public static class UnionFind { 21 | public HashMap father; 22 | public HashMap size; 23 | 24 | public UnionFind(List values) { 25 | father = new HashMap<>(); 26 | size = new HashMap<>(); 27 | for (V cur : values) { 28 | father.put(cur, cur); 29 | size.put(cur, 1); 30 | } 31 | } 32 | 33 | // 给你一个节点,请你往上到不能再往上,把代表返回 34 | public V findFather(V cur) { 35 | Stack path = new Stack<>(); 36 | while (cur != father.get(cur)) { 37 | path.push(cur); 38 | cur = father.get(cur); 39 | } 40 | while (!path.isEmpty()) { 41 | father.put(path.pop(), cur); 42 | } 43 | return cur; 44 | } 45 | 46 | public boolean isSameSet(V a, V b) { 47 | return findFather(a) == findFather(b); 48 | } 49 | 50 | public void union(V a, V b) { 51 | V aFather = findFather(a); 52 | V bFather = findFather(b); 53 | if (aFather != bFather) { 54 | int aSize = size.get(aFather); 55 | int bSize = size.get(bFather); 56 | if (aSize >= bSize) { 57 | father.put(bFather, aFather); 58 | size.put(aFather, aSize + bSize); 59 | size.remove(bFather); 60 | } else { 61 | father.put(aFather, bFather); 62 | size.put(bFather, aSize + bSize); 63 | size.remove(aFather); 64 | } 65 | } 66 | } 67 | 68 | public int sets() { 69 | return size.size(); 70 | } 71 | 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/class14/Code06_UnionFind.java: -------------------------------------------------------------------------------- 1 | package class14; 2 | 3 | // 这个文件课上没有讲 4 | // 原理和课上讲的完全一样 5 | // 最大的区别就是这个文件实现的并查集是用数组结构,而不是map结构 6 | // 请务必理解这个文件的实现,而且还提供了测试链接 7 | // 提交如下的code,并把"Code06_UnionFind"这个类名改成"Main" 8 | // 在测试链接里可以直接通过 9 | // 请同学们务必参考如下代码中关于输入、输出的处理 10 | // 这是输入输出处理效率很高的写法 11 | // 测试链接 : https://www.nowcoder.com/questionTerminal/e7ed657974934a30b2010046536a5372 12 | import java.io.BufferedReader; 13 | import java.io.IOException; 14 | import java.io.InputStreamReader; 15 | import java.io.OutputStreamWriter; 16 | import java.io.PrintWriter; 17 | import java.io.StreamTokenizer; 18 | 19 | public class Code06_UnionFind { 20 | 21 | public static int MAXN = 1000001; 22 | 23 | public static int[] father = new int[MAXN]; 24 | 25 | public static int[] size = new int[MAXN]; 26 | 27 | public static int[] help = new int[MAXN]; 28 | 29 | // 初始化并查集 30 | public static void init(int n) { 31 | for (int i = 0; i <= n; i++) { 32 | father[i] = i; 33 | size[i] = 1; 34 | } 35 | } 36 | 37 | // 从i开始寻找集合代表点 38 | public static int find(int i) { 39 | int hi = 0; 40 | while (i != father[i]) { 41 | help[hi++] = i; 42 | i = father[i]; 43 | } 44 | for (hi--; hi >= 0; hi--) { 45 | father[help[hi]] = i; 46 | } 47 | return i; 48 | } 49 | 50 | // 查询x和y是不是一个集合 51 | public static boolean isSameSet(int x, int y) { 52 | return find(x) == find(y); 53 | } 54 | 55 | // x所在的集合,和y所在的集合,合并成一个集合 56 | public static void union(int x, int y) { 57 | int fx = find(x); 58 | int fy = find(y); 59 | if (fx != fy) { 60 | if (size[fx] >= size[fy]) { 61 | size[fx] += size[fy]; 62 | father[fy] = fx; 63 | } else { 64 | size[fy] += size[fx]; 65 | father[fx] = fy; 66 | } 67 | } 68 | } 69 | 70 | public static void main(String[] args) throws IOException { 71 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 72 | StreamTokenizer in = new StreamTokenizer(br); 73 | PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out)); 74 | while (in.nextToken() != StreamTokenizer.TT_EOF) { 75 | int n = (int) in.nval; 76 | init(n); 77 | in.nextToken(); 78 | int m = (int) in.nval; 79 | for (int i = 0; i < m; i++) { 80 | in.nextToken(); 81 | int op = (int) in.nval; 82 | in.nextToken(); 83 | int x = (int) in.nval; 84 | in.nextToken(); 85 | int y = (int) in.nval; 86 | if (op == 1) { 87 | out.println(isSameSet(x, y) ? "Yes" : "No"); 88 | out.flush(); 89 | } else { 90 | union(x, y); 91 | } 92 | } 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/class15/Code01_FriendCircles.java: -------------------------------------------------------------------------------- 1 | package class15; 2 | 3 | // 本题为leetcode原题 4 | // 测试链接:https://leetcode.com/problems/friend-circles/ 5 | // 可以直接通过 6 | public class Code01_FriendCircles { 7 | 8 | public static int findCircleNum(int[][] M) { 9 | int N = M.length; 10 | // {0} {1} {2} {N-1} 11 | UnionFind unionFind = new UnionFind(N); 12 | for (int i = 0; i < N; i++) { 13 | for (int j = i + 1; j < N; j++) { 14 | if (M[i][j] == 1) { // i和j互相认识 15 | unionFind.union(i, j); 16 | } 17 | } 18 | } 19 | return unionFind.sets(); 20 | } 21 | 22 | public static class UnionFind { 23 | // parent[i] = k : i的父亲是k 24 | private int[] parent; 25 | // size[i] = k : 如果i是代表节点,size[i]才有意义,否则无意义 26 | // i所在的集合大小是多少 27 | private int[] size; 28 | // 辅助结构 29 | private int[] help; 30 | // 一共有多少个集合 31 | private int sets; 32 | 33 | public UnionFind(int N) { 34 | parent = new int[N]; 35 | size = new int[N]; 36 | help = new int[N]; 37 | sets = N; 38 | for (int i = 0; i < N; i++) { 39 | parent[i] = i; 40 | size[i] = 1; 41 | } 42 | } 43 | 44 | // 从i开始一直往上,往上到不能再往上,代表节点,返回 45 | // 这个过程要做路径压缩 46 | private int find(int i) { 47 | int hi = 0; 48 | while (i != parent[i]) { 49 | help[hi++] = i; 50 | i = parent[i]; 51 | } 52 | for (hi--; hi >= 0; hi--) { 53 | parent[help[hi]] = i; 54 | } 55 | return i; 56 | } 57 | 58 | public void union(int i, int j) { 59 | int f1 = find(i); 60 | int f2 = find(j); 61 | if (f1 != f2) { 62 | if (size[f1] >= size[f2]) { 63 | size[f1] += size[f2]; 64 | parent[f2] = f1; 65 | } else { 66 | size[f2] += size[f1]; 67 | parent[f1] = f2; 68 | } 69 | sets--; 70 | } 71 | } 72 | 73 | public int sets() { 74 | return sets; 75 | } 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/class16/Code01_BFS.java: -------------------------------------------------------------------------------- 1 | package class16; 2 | 3 | import java.util.HashSet; 4 | import java.util.LinkedList; 5 | import java.util.Queue; 6 | 7 | public class Code01_BFS { 8 | 9 | // 从node出发,进行宽度优先遍历 10 | public static void bfs(Node start) { 11 | if (start == null) { 12 | return; 13 | } 14 | Queue queue = new LinkedList<>(); 15 | HashSet set = new HashSet<>(); 16 | queue.add(start); 17 | set.add(start); 18 | while (!queue.isEmpty()) { 19 | Node cur = queue.poll(); 20 | System.out.println(cur.value); 21 | for (Node next : cur.nexts) { 22 | if (!set.contains(next)) { 23 | set.add(next); 24 | queue.add(next); 25 | } 26 | } 27 | } 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/class16/Code02_DFS.java: -------------------------------------------------------------------------------- 1 | package class16; 2 | 3 | import java.util.HashSet; 4 | import java.util.Stack; 5 | 6 | public class Code02_DFS { 7 | 8 | public static void dfs(Node node) { 9 | if (node == null) { 10 | return; 11 | } 12 | Stack stack = new Stack<>(); 13 | HashSet set = new HashSet<>(); 14 | stack.add(node); 15 | set.add(node); 16 | System.out.println(node.value); 17 | while (!stack.isEmpty()) { 18 | Node cur = stack.pop(); 19 | for (Node next : cur.nexts) { 20 | if (!set.contains(next)) { 21 | stack.push(cur); 22 | stack.push(next); 23 | set.add(next); 24 | System.out.println(next.value); 25 | break; 26 | } 27 | } 28 | } 29 | } 30 | 31 | 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/class16/Code03_TopologicalOrderBFS1.java: -------------------------------------------------------------------------------- 1 | package class16; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.LinkedList; 6 | import java.util.Queue; 7 | 8 | // OJ链接:https://www.lintcode.com/problem/topological-sorting 9 | public class Code03_TopologicalOrderBFS1 { 10 | 11 | // 不要提交这个类 12 | public static class DirectedGraphNode { 13 | public int label; 14 | public ArrayList neighbors; 15 | 16 | public DirectedGraphNode(int x) { 17 | label = x; 18 | neighbors = new ArrayList(); 19 | } 20 | } 21 | 22 | // 提交下面的 23 | public static ArrayList topSort(ArrayList graph) { 24 | HashMap indegreeMap = new HashMap<>(); 25 | for (DirectedGraphNode cur : graph) { 26 | indegreeMap.put(cur, 0); 27 | } 28 | for (DirectedGraphNode cur : graph) { 29 | for (DirectedGraphNode next : cur.neighbors) { 30 | indegreeMap.put(next, indegreeMap.get(next) + 1); 31 | } 32 | } 33 | Queue zeroQueue = new LinkedList<>(); 34 | for (DirectedGraphNode cur : indegreeMap.keySet()) { 35 | if (indegreeMap.get(cur) == 0) { 36 | zeroQueue.add(cur); 37 | } 38 | } 39 | ArrayList ans = new ArrayList<>(); 40 | while (!zeroQueue.isEmpty()) { 41 | DirectedGraphNode cur = zeroQueue.poll(); 42 | ans.add(cur); 43 | for (DirectedGraphNode next : cur.neighbors) { 44 | indegreeMap.put(next, indegreeMap.get(next) - 1); 45 | if (indegreeMap.get(next) == 0) { 46 | zeroQueue.offer(next); 47 | } 48 | } 49 | } 50 | return ans; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/class16/Code03_TopologicalOrderBFS2.java: -------------------------------------------------------------------------------- 1 | package class16; 2 | 3 | // 课上没讲这个实现 4 | // 因为是一样的,都是根据入度来求拓扑排序,只不过是牛客网的测试数据 5 | // 测试链接 : https://www.nowcoder.com/questionTerminal/88f7e156ca7d43a1a535f619cd3f495c 6 | // 请同学们务必参考如下代码中关于输入、输出的处理 7 | // 这是输入输出处理效率很高的写法 8 | // 提交以下所有代码,把主类名改成Main,可以直接通过 9 | import java.io.BufferedReader; 10 | import java.io.IOException; 11 | import java.io.InputStreamReader; 12 | import java.io.OutputStreamWriter; 13 | import java.io.PrintWriter; 14 | import java.io.StreamTokenizer; 15 | import java.util.ArrayList; 16 | import java.util.Arrays; 17 | 18 | public class Code03_TopologicalOrderBFS2 { 19 | 20 | public static int MAXN = 200001; 21 | 22 | public static int[] queue = new int[MAXN]; 23 | 24 | public static int[] indegree = new int[MAXN]; 25 | 26 | public static int[] ans = new int[MAXN]; 27 | 28 | public static int n, m, from, to; 29 | 30 | public static void main(String[] args) throws IOException { 31 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 32 | StreamTokenizer in = new StreamTokenizer(br); 33 | PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out)); 34 | while (in.nextToken() != StreamTokenizer.TT_EOF) { 35 | n = (int) in.nval; 36 | in.nextToken(); 37 | m = (int) in.nval; 38 | ArrayList> graph = new ArrayList<>(); 39 | for (int i = 0; i <= n; i++) { 40 | graph.add(new ArrayList<>()); 41 | } 42 | for (int i = 0; i < m; i++) { 43 | in.nextToken(); 44 | from = (int) in.nval; 45 | in.nextToken(); 46 | to = (int) in.nval; 47 | graph.get(from).add(to); 48 | } 49 | if (!topoSort(graph)) { 50 | out.println(-1); 51 | } else { 52 | for (int i = 0; i < n - 1; i++) { 53 | out.print(ans[i] + " "); 54 | } 55 | out.println(ans[n - 1]); 56 | } 57 | out.flush(); 58 | } 59 | } 60 | 61 | // 有拓扑排序返回true 62 | // 没有拓扑排序返回false 63 | public static boolean topoSort(ArrayList> graph) { 64 | Arrays.fill(indegree, 1, n + 1, 0); 65 | for (ArrayList nexts : graph) { 66 | for (int next : nexts) { 67 | indegree[next]++; 68 | } 69 | } 70 | int l = 0; 71 | int r = 0; 72 | for (int i = 1; i <= n; i++) { 73 | if (indegree[i] == 0) { 74 | queue[r++] = i; 75 | } 76 | } 77 | int cnt = 0; 78 | while (l < r) { 79 | int cur = queue[l++]; 80 | ans[cnt++] = cur; 81 | for (int next : graph.get(cur)) { 82 | if (--indegree[next] == 0) { 83 | queue[r++] = next; 84 | } 85 | } 86 | } 87 | return cnt == n; 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /src/class16/Code03_TopologicalOrderDFS1.java: -------------------------------------------------------------------------------- 1 | package class16; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Comparator; 5 | import java.util.HashMap; 6 | 7 | // OJ链接:https://www.lintcode.com/problem/topological-sorting 8 | public class Code03_TopologicalOrderDFS1 { 9 | 10 | // 不要提交这个类 11 | public static class DirectedGraphNode { 12 | public int label; 13 | public ArrayList neighbors; 14 | 15 | public DirectedGraphNode(int x) { 16 | label = x; 17 | neighbors = new ArrayList(); 18 | } 19 | } 20 | 21 | // 提交下面的 22 | public static class Record { 23 | public DirectedGraphNode node; 24 | public int deep; 25 | 26 | public Record(DirectedGraphNode n, int o) { 27 | node = n; 28 | deep = o; 29 | } 30 | } 31 | 32 | public static class MyComparator implements Comparator { 33 | 34 | @Override 35 | public int compare(Record o1, Record o2) { 36 | return o2.deep - o1.deep; 37 | } 38 | } 39 | 40 | public static ArrayList topSort(ArrayList graph) { 41 | HashMap order = new HashMap<>(); 42 | for (DirectedGraphNode cur : graph) { 43 | f(cur, order); 44 | } 45 | ArrayList recordArr = new ArrayList<>(); 46 | for (Record r : order.values()) { 47 | recordArr.add(r); 48 | } 49 | recordArr.sort(new MyComparator()); 50 | ArrayList ans = new ArrayList(); 51 | for (Record r : recordArr) { 52 | ans.add(r.node); 53 | } 54 | return ans; 55 | } 56 | 57 | public static Record f(DirectedGraphNode cur, HashMap order) { 58 | if (order.containsKey(cur)) { 59 | return order.get(cur); 60 | } 61 | int follow = 0; 62 | for (DirectedGraphNode next : cur.neighbors) { 63 | follow = Math.max(follow, f(next, order).deep); 64 | } 65 | Record ans = new Record(cur, follow + 1); 66 | order.put(cur, ans); 67 | return ans; 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/class16/Code03_TopologicalOrderDFS2.java: -------------------------------------------------------------------------------- 1 | package class16; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Comparator; 5 | import java.util.HashMap; 6 | 7 | // OJ链接:https://www.lintcode.com/problem/topological-sorting 8 | public class Code03_TopologicalOrderDFS2 { 9 | 10 | // 不要提交这个类 11 | public static class DirectedGraphNode { 12 | public int label; 13 | public ArrayList neighbors; 14 | 15 | public DirectedGraphNode(int x) { 16 | label = x; 17 | neighbors = new ArrayList(); 18 | } 19 | } 20 | 21 | // 提交下面的 22 | public static class Record { 23 | public DirectedGraphNode node; 24 | public long nodes; 25 | 26 | public Record(DirectedGraphNode n, long o) { 27 | node = n; 28 | nodes = o; 29 | } 30 | } 31 | 32 | public static class MyComparator implements Comparator { 33 | 34 | @Override 35 | public int compare(Record o1, Record o2) { 36 | return o1.nodes == o2.nodes ? 0 : (o1.nodes > o2.nodes ? -1 : 1); 37 | } 38 | } 39 | 40 | public static ArrayList topSort(ArrayList graph) { 41 | HashMap order = new HashMap<>(); 42 | for (DirectedGraphNode cur : graph) { 43 | f(cur, order); 44 | } 45 | ArrayList recordArr = new ArrayList<>(); 46 | for (Record r : order.values()) { 47 | recordArr.add(r); 48 | } 49 | recordArr.sort(new MyComparator()); 50 | ArrayList ans = new ArrayList(); 51 | for (Record r : recordArr) { 52 | ans.add(r.node); 53 | } 54 | return ans; 55 | } 56 | 57 | // 当前来到cur点,请返回cur点所到之处,所有的点次! 58 | // 返回(cur,点次) 59 | // 缓存!!!!!order 60 | // key : 某一个点的点次,之前算过了! 61 | // value : 点次是多少 62 | public static Record f(DirectedGraphNode cur, HashMap order) { 63 | if (order.containsKey(cur)) { 64 | return order.get(cur); 65 | } 66 | // cur的点次之前没算过! 67 | long nodes = 0; 68 | for (DirectedGraphNode next : cur.neighbors) { 69 | nodes += f(next, order).nodes; 70 | } 71 | Record ans = new Record(cur, nodes + 1); 72 | order.put(cur, ans); 73 | return ans; 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/class16/Code03_TopologySort.java: -------------------------------------------------------------------------------- 1 | package class16; 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 | public class Code03_TopologySort { 10 | 11 | // directed graph and no loop 12 | public static List sortedTopology(Graph graph) { 13 | // key 某个节点 value 剩余的入度 14 | HashMap inMap = new HashMap<>(); 15 | // 只有剩余入度为0的点,才进入这个队列 16 | Queue zeroInQueue = new LinkedList<>(); 17 | for (Node node : graph.nodes.values()) { 18 | inMap.put(node, node.in); 19 | if (node.in == 0) { 20 | zeroInQueue.add(node); 21 | } 22 | } 23 | List result = new ArrayList<>(); 24 | while (!zeroInQueue.isEmpty()) { 25 | Node cur = zeroInQueue.poll(); 26 | result.add(cur); 27 | for (Node next : cur.nexts) { 28 | inMap.put(next, inMap.get(next) - 1); 29 | if (inMap.get(next) == 0) { 30 | zeroInQueue.add(next); 31 | } 32 | } 33 | } 34 | return result; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/class16/Code04_Kruskal.java: -------------------------------------------------------------------------------- 1 | package class16; 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 | import java.util.Stack; 10 | 11 | //undirected graph only 12 | public class Code04_Kruskal { 13 | 14 | // Union-Find Set 15 | public static class UnionFind { 16 | // key 某一个节点, value key节点往上的节点 17 | private HashMap fatherMap; 18 | // key 某一个集合的代表节点, value key所在集合的节点个数 19 | private HashMap sizeMap; 20 | 21 | public UnionFind() { 22 | fatherMap = new HashMap(); 23 | sizeMap = new HashMap(); 24 | } 25 | 26 | public void makeSets(Collection nodes) { 27 | fatherMap.clear(); 28 | sizeMap.clear(); 29 | for (Node node : nodes) { 30 | fatherMap.put(node, node); 31 | sizeMap.put(node, 1); 32 | } 33 | } 34 | 35 | private Node findFather(Node n) { 36 | Stack path = new Stack<>(); 37 | while(n != fatherMap.get(n)) { 38 | path.add(n); 39 | n = fatherMap.get(n); 40 | } 41 | while(!path.isEmpty()) { 42 | fatherMap.put(path.pop(), n); 43 | } 44 | return n; 45 | } 46 | 47 | public boolean isSameSet(Node a, Node b) { 48 | return findFather(a) == findFather(b); 49 | } 50 | 51 | public void union(Node a, Node b) { 52 | if (a == null || b == null) { 53 | return; 54 | } 55 | Node aDai = findFather(a); 56 | Node bDai = findFather(b); 57 | if (aDai != bDai) { 58 | int aSetSize = sizeMap.get(aDai); 59 | int bSetSize = sizeMap.get(bDai); 60 | if (aSetSize <= bSetSize) { 61 | fatherMap.put(aDai, bDai); 62 | sizeMap.put(bDai, aSetSize + bSetSize); 63 | sizeMap.remove(aDai); 64 | } else { 65 | fatherMap.put(bDai, aDai); 66 | sizeMap.put(aDai, aSetSize + bSetSize); 67 | sizeMap.remove(bDai); 68 | } 69 | } 70 | } 71 | } 72 | 73 | 74 | public static class EdgeComparator implements Comparator { 75 | 76 | @Override 77 | public int compare(Edge o1, Edge o2) { 78 | return o1.weight - o2.weight; 79 | } 80 | 81 | } 82 | 83 | public static Set kruskalMST(Graph graph) { 84 | UnionFind unionFind = new UnionFind(); 85 | unionFind.makeSets(graph.nodes.values()); 86 | // 从小的边到大的边,依次弹出,小根堆! 87 | PriorityQueue priorityQueue = new PriorityQueue<>(new EdgeComparator()); 88 | for (Edge edge : graph.edges) { // M 条边 89 | priorityQueue.add(edge); // O(logM) 90 | } 91 | Set result = new HashSet<>(); 92 | while (!priorityQueue.isEmpty()) { // M 条边 93 | Edge edge = priorityQueue.poll(); // O(logM) 94 | if (!unionFind.isSameSet(edge.from, edge.to)) { // O(1) 95 | result.add(edge); 96 | unionFind.union(edge.from, edge.to); 97 | } 98 | } 99 | return result; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/class16/Code04_KruskalNowCoder.java: -------------------------------------------------------------------------------- 1 | package class16; 2 | 3 | // 课上没讲这个实现 4 | // 因为是一样的,都是用Kruskal算法实现最小生成树,只不过是牛客网的测试数据 5 | // 测试链接 : https://www.nowcoder.com/questionTerminal/c23eab7bb39748b6b224a8a3afbe396b 6 | // 请同学们务必参考如下代码中关于输入、输出的处理 7 | // 这是输入输出处理效率很高的写法 8 | // 提交以下所有代码,把主类名改成Main,可以直接通过 9 | import java.io.BufferedReader; 10 | import java.io.IOException; 11 | import java.io.InputStreamReader; 12 | import java.io.OutputStreamWriter; 13 | import java.io.PrintWriter; 14 | import java.io.StreamTokenizer; 15 | import java.util.Arrays; 16 | 17 | public class Code04_KruskalNowCoder { 18 | 19 | public static int MAXM = 100001; 20 | 21 | public static int[][] edges = new int[MAXM][3]; 22 | 23 | public static void main(String[] args) throws IOException { 24 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 25 | StreamTokenizer in = new StreamTokenizer(br); 26 | PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out)); 27 | while (in.nextToken() != StreamTokenizer.TT_EOF) { 28 | int n = (int) in.nval; 29 | in.nextToken(); 30 | int m = (int) in.nval; 31 | for (int i = 0; i < m; i++) { 32 | in.nextToken(); 33 | edges[i][0] = (int) in.nval; 34 | in.nextToken(); 35 | edges[i][1] = (int) in.nval; 36 | in.nextToken(); 37 | edges[i][2] = (int) in.nval; 38 | } 39 | Arrays.sort(edges, 0, m, (a, b) -> a[2] - b[2]); 40 | build(n); 41 | int ans = 0; 42 | for (int[] edge : edges) { 43 | if (union(edge[0], edge[1])) { 44 | ans += edge[2]; 45 | } 46 | } 47 | out.println(ans); 48 | out.flush(); 49 | } 50 | } 51 | 52 | // 下面是并查集结构 53 | public static int MAXN = 10001; 54 | 55 | public static int[] father = new int[MAXN]; 56 | 57 | public static int[] size = new int[MAXN]; 58 | 59 | public static int[] help = new int[MAXN]; 60 | 61 | public static void build(int n) { 62 | for (int i = 1; i <= n; i++) { 63 | father[i] = i; 64 | size[i] = 1; 65 | } 66 | } 67 | 68 | private static int find(int i) { 69 | int size = 0; 70 | while (i != father[i]) { 71 | help[size++] = i; 72 | i = father[i]; 73 | } 74 | while (size > 0) { 75 | father[help[--size]] = i; 76 | } 77 | return i; 78 | } 79 | 80 | // 如果i和j,原本是一个集合,返回false 81 | // 如果i和j,不是一个集合,合并,然后返回true 82 | public static boolean union(int i, int j) { 83 | int fi = find(i); 84 | int fj = find(j); 85 | if (fi != fj) { 86 | if (size[fi] >= size[fj]) { 87 | father[fj] = fi; 88 | size[fi] += size[fj]; 89 | } else { 90 | father[fi] = fj; 91 | size[fj] += size[fi]; 92 | } 93 | return true; 94 | } else { 95 | return false; 96 | } 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /src/class16/Code05_Prim.java: -------------------------------------------------------------------------------- 1 | package class16; 2 | 3 | import java.util.Comparator; 4 | import java.util.HashSet; 5 | import java.util.PriorityQueue; 6 | import java.util.Set; 7 | 8 | // undirected graph only 9 | public class Code05_Prim { 10 | 11 | public static class EdgeComparator implements Comparator { 12 | 13 | @Override 14 | public int compare(Edge o1, Edge o2) { 15 | return o1.weight - o2.weight; 16 | } 17 | 18 | } 19 | 20 | public static Set primMST(Graph graph) { 21 | // 解锁的边进入小根堆 22 | PriorityQueue priorityQueue = new PriorityQueue<>(new EdgeComparator()); 23 | 24 | // 哪些点被解锁出来了 25 | HashSet nodeSet = new HashSet<>(); 26 | 27 | 28 | 29 | Set result = new HashSet<>(); // 依次挑选的的边在result里 30 | 31 | for (Node node : graph.nodes.values()) { // 随便挑了一个点 32 | // node 是开始点 33 | if (!nodeSet.contains(node)) { 34 | nodeSet.add(node); 35 | for (Edge edge : node.edges) { // 由一个点,解锁所有相连的边 36 | priorityQueue.add(edge); 37 | } 38 | while (!priorityQueue.isEmpty()) { 39 | Edge edge = priorityQueue.poll(); // 弹出解锁的边中,最小的边 40 | Node toNode = edge.to; // 可能的一个新的点 41 | if (!nodeSet.contains(toNode)) { // 不含有的时候,就是新的点 42 | nodeSet.add(toNode); 43 | result.add(edge); 44 | for (Edge nextEdge : toNode.edges) { 45 | priorityQueue.add(nextEdge); 46 | } 47 | } 48 | } 49 | } 50 | // break; 51 | } 52 | return result; 53 | } 54 | 55 | // 请保证graph是连通图 56 | // graph[i][j]表示点i到点j的距离,如果是系统最大值代表无路 57 | // 返回值是最小连通图的路径之和 58 | public static int prim(int[][] graph) { 59 | int size = graph.length; 60 | int[] distances = new int[size]; 61 | boolean[] visit = new boolean[size]; 62 | visit[0] = true; 63 | for (int i = 0; i < size; i++) { 64 | distances[i] = graph[0][i]; 65 | } 66 | int sum = 0; 67 | for (int i = 1; i < size; i++) { 68 | int minPath = Integer.MAX_VALUE; 69 | int minIndex = -1; 70 | for (int j = 0; j < size; j++) { 71 | if (!visit[j] && distances[j] < minPath) { 72 | minPath = distances[j]; 73 | minIndex = j; 74 | } 75 | } 76 | if (minIndex == -1) { 77 | return sum; 78 | } 79 | visit[minIndex] = true; 80 | sum += minPath; 81 | for (int j = 0; j < size; j++) { 82 | if (!visit[j] && distances[j] > graph[minIndex][j]) { 83 | distances[j] = graph[minIndex][j]; 84 | } 85 | } 86 | } 87 | return sum; 88 | } 89 | 90 | public static void main(String[] args) { 91 | System.out.println("hello world!"); 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /src/class16/Code05_PrimNowCoder.java: -------------------------------------------------------------------------------- 1 | package class16; 2 | 3 | // 课上没讲这个实现 4 | // 因为是一样的,都是用Prim算法实现最小生成树,只不过是牛客网的测试数据 5 | // 测试链接 : https://www.nowcoder.com/questionTerminal/c23eab7bb39748b6b224a8a3afbe396b 6 | // 请同学们务必参考如下代码中关于输入、输出的处理 7 | // 这是输入输出处理效率很高的写法 8 | // 提交以下所有代码,把主类名改成Main,可以直接通过 9 | import java.io.BufferedReader; 10 | import java.io.IOException; 11 | import java.io.InputStreamReader; 12 | import java.io.OutputStreamWriter; 13 | import java.io.PrintWriter; 14 | import java.io.StreamTokenizer; 15 | import java.util.ArrayList; 16 | import java.util.PriorityQueue; 17 | 18 | public class Code05_PrimNowCoder { 19 | 20 | public static void main(String[] args) throws IOException { 21 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 22 | StreamTokenizer in = new StreamTokenizer(br); 23 | PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out)); 24 | while (in.nextToken() != StreamTokenizer.TT_EOF) { 25 | ArrayList> graph = new ArrayList<>(); 26 | int n = (int) in.nval; 27 | for (int i = 0; i <= n; i++) { 28 | graph.add(new ArrayList<>()); 29 | } 30 | in.nextToken(); 31 | int m = (int) in.nval; 32 | for (int i = 0; i < m; i++) { 33 | in.nextToken(); 34 | int A = (int) in.nval; 35 | in.nextToken(); 36 | int B = (int) in.nval; 37 | in.nextToken(); 38 | int cost = (int) in.nval; 39 | graph.get(A).add(new int[] { B, cost }); 40 | graph.get(B).add(new int[] { A, cost }); 41 | } 42 | PriorityQueue heap = new PriorityQueue<>((a, b) -> a[1] - b[1]); 43 | boolean[] visited = new boolean[n + 1]; 44 | for (int[] edge : graph.get(1)) { 45 | heap.add(edge); 46 | } 47 | visited[1] = true; 48 | int ans = 0; 49 | while (!heap.isEmpty()) { 50 | int[] edge = heap.poll(); 51 | int next = edge[0]; 52 | int cost = edge[1]; 53 | if (!visited[next]) { 54 | visited[next] = true; 55 | ans += cost; 56 | for (int[] e : graph.get(next)) { 57 | heap.add(e); 58 | } 59 | } 60 | } 61 | out.println(ans); 62 | out.flush(); 63 | } 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/class16/Edge.java: -------------------------------------------------------------------------------- 1 | package class16; 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 | -------------------------------------------------------------------------------- /src/class16/Graph.java: -------------------------------------------------------------------------------- 1 | package class16; 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 | -------------------------------------------------------------------------------- /src/class16/GraphGenerator.java: -------------------------------------------------------------------------------- 1 | package class16; 2 | 3 | public class GraphGenerator { 4 | 5 | // matrix 所有的边 6 | // N*3 的矩阵 7 | // [weight, from节点上面的值,to节点上面的值] 8 | // 9 | // [ 5 , 0 , 7] 10 | // [ 3 , 0, 1] 11 | // 12 | public static Graph createGraph(int[][] matrix) { 13 | Graph graph = new Graph(); 14 | for (int i = 0; i < matrix.length; i++) { 15 | // 拿到每一条边, matrix[i] 16 | int weight = matrix[i][0]; 17 | int from = matrix[i][1]; 18 | int to = matrix[i][2]; 19 | if (!graph.nodes.containsKey(from)) { 20 | graph.nodes.put(from, new Node(from)); 21 | } 22 | if (!graph.nodes.containsKey(to)) { 23 | graph.nodes.put(to, new Node(to)); 24 | } 25 | Node fromNode = graph.nodes.get(from); 26 | Node toNode = graph.nodes.get(to); 27 | Edge newEdge = new Edge(weight, fromNode, toNode); 28 | fromNode.nexts.add(toNode); 29 | fromNode.out++; 30 | toNode.in++; 31 | fromNode.edges.add(newEdge); 32 | graph.edges.add(newEdge); 33 | } 34 | return graph; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/class16/Node.java: -------------------------------------------------------------------------------- 1 | package class16; 2 | 3 | import java.util.ArrayList; 4 | 5 | // 点结构的描述 6 | public class Node { 7 | public int value; 8 | public int in; 9 | public int out; 10 | public ArrayList nexts; 11 | public ArrayList edges; 12 | 13 | public Node(int value) { 14 | this.value = value; 15 | in = 0; 16 | out = 0; 17 | nexts = new ArrayList<>(); 18 | edges = new ArrayList<>(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/class17/Code03_PrintAllSubsquences.java: -------------------------------------------------------------------------------- 1 | package class17; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashSet; 5 | import java.util.List; 6 | 7 | public class Code03_PrintAllSubsquences { 8 | 9 | // s -> "abc" -> 10 | public static List subs(String s) { 11 | char[] str = s.toCharArray(); 12 | String path = ""; 13 | List ans = new ArrayList<>(); 14 | process1(str, 0, ans, path); 15 | return ans; 16 | } 17 | 18 | // str 固定参数 19 | // 来到了str[index]字符,index是位置 20 | // str[0..index-1]已经走过了!之前的决定,都在path上 21 | // 之前的决定已经不能改变了,就是path 22 | // str[index....]还能决定,之前已经确定,而后面还能自由选择的话, 23 | // 把所有生成的子序列,放入到ans里去 24 | public static void process1(char[] str, int index, List ans, String path) { 25 | if (index == str.length) { 26 | ans.add(path); 27 | return; 28 | } 29 | // 没有要index位置的字符 30 | process1(str, index + 1, ans, path); 31 | // 要了index位置的字符 32 | process1(str, index + 1, ans, path + String.valueOf(str[index])); 33 | } 34 | 35 | public static List subsNoRepeat(String s) { 36 | char[] str = s.toCharArray(); 37 | String path = ""; 38 | HashSet set = new HashSet<>(); 39 | process2(str, 0, set, path); 40 | List ans = new ArrayList<>(); 41 | for (String cur : set) { 42 | ans.add(cur); 43 | } 44 | return ans; 45 | } 46 | 47 | public static void process2(char[] str, int index, HashSet set, String path) { 48 | if (index == str.length) { 49 | set.add(path); 50 | return; 51 | } 52 | String no = path; 53 | process2(str, index + 1, set, no); 54 | String yes = path + String.valueOf(str[index]); 55 | process2(str, index + 1, set, yes); 56 | } 57 | 58 | public static void main(String[] args) { 59 | String test = "acccc"; 60 | List ans1 = subs(test); 61 | List ans2 = subsNoRepeat(test); 62 | 63 | for (String str : ans1) { 64 | System.out.println(str); 65 | } 66 | System.out.println("================="); 67 | for (String str : ans2) { 68 | System.out.println(str); 69 | } 70 | System.out.println("================="); 71 | 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/class17/Code04_PrintAllPermutations.java: -------------------------------------------------------------------------------- 1 | package class17; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class Code04_PrintAllPermutations { 7 | 8 | public static List permutation1(String s) { 9 | List ans = new ArrayList<>(); 10 | if (s == null || s.length() == 0) { 11 | return ans; 12 | } 13 | char[] str = s.toCharArray(); 14 | ArrayList rest = new ArrayList(); 15 | for (char cha : str) { 16 | rest.add(cha); 17 | } 18 | String path = ""; 19 | f(rest, path, ans); 20 | return ans; 21 | } 22 | 23 | public static void f(ArrayList rest, String path, List ans) { 24 | if (rest.isEmpty()) { 25 | ans.add(path); 26 | } else { 27 | int N = rest.size(); 28 | for (int i = 0; i < N; i++) { 29 | char cur = rest.get(i); 30 | rest.remove(i); 31 | f(rest, path + cur, ans); 32 | rest.add(i, cur); 33 | } 34 | } 35 | } 36 | 37 | public static List permutation2(String s) { 38 | List ans = new ArrayList<>(); 39 | if (s == null || s.length() == 0) { 40 | return ans; 41 | } 42 | char[] str = s.toCharArray(); 43 | g1(str, 0, ans); 44 | return ans; 45 | } 46 | 47 | public static void g1(char[] str, int index, List ans) { 48 | if (index == str.length) { 49 | ans.add(String.valueOf(str)); 50 | } else { 51 | for (int i = index; i < str.length; i++) { 52 | swap(str, index, i); 53 | g1(str, index + 1, ans); 54 | swap(str, index, i); 55 | } 56 | } 57 | } 58 | 59 | public static List permutation3(String s) { 60 | List ans = new ArrayList<>(); 61 | if (s == null || s.length() == 0) { 62 | return ans; 63 | } 64 | char[] str = s.toCharArray(); 65 | g2(str, 0, ans); 66 | return ans; 67 | } 68 | 69 | public static void g2(char[] str, int index, List ans) { 70 | if (index == str.length) { 71 | ans.add(String.valueOf(str)); 72 | } else { 73 | boolean[] visited = new boolean[256]; 74 | for (int i = index; i < str.length; i++) { 75 | if (!visited[str[i]]) { 76 | visited[str[i]] = true; 77 | swap(str, index, i); 78 | g2(str, index + 1, ans); 79 | swap(str, index, i); 80 | } 81 | } 82 | } 83 | } 84 | 85 | public static void swap(char[] chs, int i, int j) { 86 | char tmp = chs[i]; 87 | chs[i] = chs[j]; 88 | chs[j] = tmp; 89 | } 90 | 91 | public static void main(String[] args) { 92 | String s = "acc"; 93 | List ans1 = permutation1(s); 94 | for (String str : ans1) { 95 | System.out.println(str); 96 | } 97 | System.out.println("======="); 98 | List ans2 = permutation2(s); 99 | for (String str : ans2) { 100 | System.out.println(str); 101 | } 102 | System.out.println("======="); 103 | List ans3 = permutation3(s); 104 | for (String str : ans3) { 105 | System.out.println(str); 106 | } 107 | 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /src/class17/Code05_ReverseStackUsingRecursive.java: -------------------------------------------------------------------------------- 1 | package class17; 2 | 3 | import java.util.Stack; 4 | 5 | public class Code05_ReverseStackUsingRecursive { 6 | 7 | public static void reverse(Stack stack) { 8 | if (stack.isEmpty()) { 9 | return; 10 | } 11 | int i = f(stack); 12 | reverse(stack); 13 | stack.push(i); 14 | } 15 | 16 | // 栈底元素移除掉 17 | // 上面的元素盖下来 18 | // 返回移除掉的栈底元素 19 | public static int f(Stack stack) { 20 | int result = stack.pop(); 21 | if (stack.isEmpty()) { 22 | return result; 23 | } else { 24 | int last = f(stack); 25 | stack.push(result); 26 | return last; 27 | } 28 | } 29 | 30 | public static void main(String[] args) { 31 | Stack test = new Stack(); 32 | test.push(1); 33 | test.push(2); 34 | test.push(3); 35 | test.push(4); 36 | test.push(5); 37 | reverse(test); 38 | while (!test.isEmpty()) { 39 | System.out.println(test.pop()); 40 | } 41 | 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/class17/Edge.java: -------------------------------------------------------------------------------- 1 | package class17; 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 | -------------------------------------------------------------------------------- /src/class17/Graph.java: -------------------------------------------------------------------------------- 1 | package class17; 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 | -------------------------------------------------------------------------------- /src/class17/Node.java: -------------------------------------------------------------------------------- 1 | package class17; 2 | 3 | import java.util.ArrayList; 4 | 5 | // 点结构的描述 6 | public class Node { 7 | public int value; 8 | public int in; 9 | public int out; 10 | public ArrayList nexts; 11 | public ArrayList edges; 12 | 13 | public Node(int value) { 14 | this.value = value; 15 | in = 0; 16 | out = 0; 17 | nexts = new ArrayList<>(); 18 | edges = new ArrayList<>(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/class18/Code01_RobotWalk.java: -------------------------------------------------------------------------------- 1 | package class18; 2 | 3 | public class Code01_RobotWalk { 4 | 5 | public static int ways1(int N, int start, int aim, int K) { 6 | if (N < 2 || start < 1 || start > N || aim < 1 || aim > N || K < 1) { 7 | return -1; 8 | } 9 | return process1(start, K, aim, N); 10 | } 11 | 12 | // 机器人当前来到的位置是cur, 13 | // 机器人还有rest步需要去走, 14 | // 最终的目标是aim, 15 | // 有哪些位置?1~N 16 | // 返回:机器人从cur出发,走过rest步之后,最终停在aim的方法数,是多少? 17 | public static int process1(int cur, int rest, int aim, int N) { 18 | if (rest == 0) { // 如果已经不需要走了,走完了! 19 | return cur == aim ? 1 : 0; 20 | } 21 | // (cur, rest) 22 | if (cur == 1) { // 1 -> 2 23 | return process1(2, rest - 1, aim, N); 24 | } 25 | // (cur, rest) 26 | if (cur == N) { // N-1 <- N 27 | return process1(N - 1, rest - 1, aim, N); 28 | } 29 | // (cur, rest) 30 | return process1(cur - 1, rest - 1, aim, N) + process1(cur + 1, rest - 1, aim, N); 31 | } 32 | 33 | public static int ways2(int N, int start, int aim, int K) { 34 | if (N < 2 || start < 1 || start > N || aim < 1 || aim > N || K < 1) { 35 | return -1; 36 | } 37 | int[][] dp = new int[N + 1][K + 1]; 38 | for (int i = 0; i <= N; i++) { 39 | for (int j = 0; j <= K; j++) { 40 | dp[i][j] = -1; 41 | } 42 | } 43 | // dp就是缓存表 44 | // dp[cur][rest] == -1 -> process1(cur, rest)之前没算过! 45 | // dp[cur][rest] != -1 -> process1(cur, rest)之前算过!返回值,dp[cur][rest] 46 | // N+1 * K+1 47 | return process2(start, K, aim, N, dp); 48 | } 49 | 50 | // cur 范: 1 ~ N 51 | // rest 范:0 ~ K 52 | public static int process2(int cur, int rest, int aim, int N, int[][] dp) { 53 | if (dp[cur][rest] != -1) { 54 | return dp[cur][rest]; 55 | } 56 | // 之前没算过! 57 | int ans = 0; 58 | if (rest == 0) { 59 | ans = cur == aim ? 1 : 0; 60 | } else if (cur == 1) { 61 | ans = process2(2, rest - 1, aim, N, dp); 62 | } else if (cur == N) { 63 | ans = process2(N - 1, rest - 1, aim, N, dp); 64 | } else { 65 | ans = process2(cur - 1, rest - 1, aim, N, dp) + process2(cur + 1, rest - 1, aim, N, dp); 66 | } 67 | dp[cur][rest] = ans; 68 | return ans; 69 | 70 | } 71 | 72 | public static int ways3(int N, int start, int aim, int K) { 73 | if (N < 2 || start < 1 || start > N || aim < 1 || aim > N || K < 1) { 74 | return -1; 75 | } 76 | int[][] dp = new int[N + 1][K + 1]; 77 | dp[aim][0] = 1; 78 | for (int rest = 1; rest <= K; rest++) { 79 | dp[1][rest] = dp[2][rest - 1]; 80 | for (int cur = 2; cur < N; cur++) { 81 | dp[cur][rest] = dp[cur - 1][rest - 1] + dp[cur + 1][rest - 1]; 82 | } 83 | dp[N][rest] = dp[N - 1][rest - 1]; 84 | } 85 | return dp[start][K]; 86 | } 87 | 88 | public static void main(String[] args) { 89 | System.out.println(ways1(5, 2, 4, 6)); 90 | System.out.println(ways2(5, 2, 4, 6)); 91 | System.out.println(ways3(5, 2, 4, 6)); 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /src/class19/Code01_Knapsack.java: -------------------------------------------------------------------------------- 1 | package class19; 2 | 3 | public class Code01_Knapsack { 4 | 5 | // 所有的货,重量和价值,都在w和v数组里 6 | // 为了方便,其中没有负数 7 | // bag背包容量,不能超过这个载重 8 | // 返回:不超重的情况下,能够得到的最大价值 9 | public static int maxValue(int[] w, int[] v, int bag) { 10 | if (w == null || v == null || w.length != v.length || w.length == 0) { 11 | return 0; 12 | } 13 | // 尝试函数! 14 | return process(w, v, 0, bag); 15 | } 16 | 17 | // index 0~N 18 | // rest 负~bag 19 | public static int process(int[] w, int[] v, int index, int rest) { 20 | if (rest < 0) { 21 | return -1; 22 | } 23 | if (index == w.length) { 24 | return 0; 25 | } 26 | int p1 = process(w, v, index + 1, rest); 27 | int p2 = 0; 28 | int next = process(w, v, index + 1, rest - w[index]); 29 | if (next != -1) { 30 | p2 = v[index] + next; 31 | } 32 | return Math.max(p1, p2); 33 | } 34 | 35 | public static int dp(int[] w, int[] v, int bag) { 36 | if (w == null || v == null || w.length != v.length || w.length == 0) { 37 | return 0; 38 | } 39 | int N = w.length; 40 | int[][] dp = new int[N + 1][bag + 1]; 41 | for (int index = N - 1; index >= 0; index--) { 42 | for (int rest = 0; rest <= bag; rest++) { 43 | int p1 = dp[index + 1][rest]; 44 | int p2 = 0; 45 | int next = rest - w[index] < 0 ? -1 : dp[index + 1][rest - w[index]]; 46 | if (next != -1) { 47 | p2 = v[index] + next; 48 | } 49 | dp[index][rest] = Math.max(p1, p2); 50 | } 51 | } 52 | return dp[0][bag]; 53 | } 54 | 55 | public static void main(String[] args) { 56 | int[] weights = { 3, 2, 4, 7, 3, 1, 7 }; 57 | int[] values = { 5, 6, 3, 19, 12, 4, 2 }; 58 | int bag = 15; 59 | System.out.println(maxValue(weights, values, bag)); 60 | System.out.println(dp(weights, values, bag)); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/class21/Code01_MinPathSum.java: -------------------------------------------------------------------------------- 1 | package class21; 2 | 3 | public class Code01_MinPathSum { 4 | 5 | public static int minPathSum1(int[][] m) { 6 | if (m == null || m.length == 0 || m[0] == null || m[0].length == 0) { 7 | return 0; 8 | } 9 | int row = m.length; 10 | int col = m[0].length; 11 | int[][] dp = new int[row][col]; 12 | dp[0][0] = m[0][0]; 13 | for (int i = 1; i < row; i++) { 14 | dp[i][0] = dp[i - 1][0] + m[i][0]; 15 | } 16 | for (int j = 1; j < col; j++) { 17 | dp[0][j] = dp[0][j - 1] + m[0][j]; 18 | } 19 | for (int i = 1; i < row; i++) { 20 | for (int j = 1; j < col; j++) { 21 | dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + m[i][j]; 22 | } 23 | } 24 | return dp[row - 1][col - 1]; 25 | } 26 | 27 | public static int minPathSum2(int[][] m) { 28 | if (m == null || m.length == 0 || m[0] == null || m[0].length == 0) { 29 | return 0; 30 | } 31 | int row = m.length; 32 | int col = m[0].length; 33 | int[] dp = new int[col]; 34 | dp[0] = m[0][0]; 35 | for (int j = 1; j < col; j++) { 36 | dp[j] = dp[j - 1] + m[0][j]; 37 | } 38 | for (int i = 1; i < row; i++) { 39 | dp[0] += m[i][0]; 40 | for (int j = 1; j < col; j++) { 41 | dp[j] = Math.min(dp[j - 1], dp[j]) + m[i][j]; 42 | } 43 | } 44 | return dp[col - 1]; 45 | } 46 | 47 | // for test 48 | public static int[][] generateRandomMatrix(int rowSize, int colSize) { 49 | if (rowSize < 0 || colSize < 0) { 50 | return null; 51 | } 52 | int[][] result = new int[rowSize][colSize]; 53 | for (int i = 0; i != result.length; i++) { 54 | for (int j = 0; j != result[0].length; j++) { 55 | result[i][j] = (int) (Math.random() * 100); 56 | } 57 | } 58 | return result; 59 | } 60 | 61 | // for test 62 | public static void printMatrix(int[][] matrix) { 63 | for (int i = 0; i != matrix.length; i++) { 64 | for (int j = 0; j != matrix[0].length; j++) { 65 | System.out.print(matrix[i][j] + " "); 66 | } 67 | System.out.println(); 68 | } 69 | } 70 | 71 | public static void main(String[] args) { 72 | int rowSize = 10; 73 | int colSize = 10; 74 | int[][] m = generateRandomMatrix(rowSize, colSize); 75 | System.out.println(minPathSum1(m)); 76 | System.out.println(minPathSum2(m)); 77 | 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/class21/Code02_CoinsWayEveryPaperDifferent.java: -------------------------------------------------------------------------------- 1 | package class21; 2 | 3 | public class Code02_CoinsWayEveryPaperDifferent { 4 | 5 | public static int coinWays(int[] arr, int aim) { 6 | return process(arr, 0, aim); 7 | } 8 | 9 | // arr[index....] 组成正好rest这么多的钱,有几种方法 10 | public static int process(int[] arr, int index, int rest) { 11 | if (rest < 0) { 12 | return 0; 13 | } 14 | if (index == arr.length) { // 没钱了! 15 | return rest == 0 ? 1 : 0; 16 | } else { 17 | return process(arr, index + 1, rest) + process(arr, index + 1, rest - arr[index]); 18 | } 19 | } 20 | 21 | public static int dp(int[] arr, int aim) { 22 | if (aim == 0) { 23 | return 1; 24 | } 25 | int N = arr.length; 26 | int[][] dp = new int[N + 1][aim + 1]; 27 | dp[N][0] = 1; 28 | for (int index = N - 1; index >= 0; index--) { 29 | for (int rest = 0; rest <= aim; rest++) { 30 | dp[index][rest] = dp[index + 1][rest] + (rest - arr[index] >= 0 ? dp[index + 1][rest - arr[index]] : 0); 31 | } 32 | } 33 | return dp[0][aim]; 34 | } 35 | 36 | // 为了测试 37 | public static int[] randomArray(int maxLen, int maxValue) { 38 | int N = (int) (Math.random() * maxLen); 39 | int[] arr = new int[N]; 40 | for (int i = 0; i < N; i++) { 41 | arr[i] = (int) (Math.random() * maxValue) + 1; 42 | } 43 | return arr; 44 | } 45 | 46 | // 为了测试 47 | public static void printArray(int[] arr) { 48 | for (int i = 0; i < arr.length; i++) { 49 | System.out.print(arr[i] + " "); 50 | } 51 | System.out.println(); 52 | } 53 | 54 | // 为了测试 55 | public static void main(String[] args) { 56 | int maxLen = 20; 57 | int maxValue = 30; 58 | int testTime = 1000000; 59 | System.out.println("测试开始"); 60 | for (int i = 0; i < testTime; i++) { 61 | int[] arr = randomArray(maxLen, maxValue); 62 | int aim = (int) (Math.random() * maxValue); 63 | int ans1 = coinWays(arr, aim); 64 | int ans2 = dp(arr, aim); 65 | if (ans1 != ans2) { 66 | System.out.println("Oops!"); 67 | printArray(arr); 68 | System.out.println(aim); 69 | System.out.println(ans1); 70 | System.out.println(ans2); 71 | break; 72 | } 73 | } 74 | System.out.println("测试结束"); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /src/class21/Code05_BobDie.java: -------------------------------------------------------------------------------- 1 | package class21; 2 | 3 | public class Code05_BobDie { 4 | 5 | public static double livePosibility1(int row, int col, int k, int N, int M) { 6 | return (double) process(row, col, k, N, M) / Math.pow(4, k); 7 | } 8 | 9 | // 目前在row,col位置,还有rest步要走,走完了如果还在棋盘中就获得1个生存点,返回总的生存点数 10 | public static long process(int row, int col, int rest, int N, int M) { 11 | if (row < 0 || row == N || col < 0 || col == M) { 12 | return 0; 13 | } 14 | // 还在棋盘中! 15 | if (rest == 0) { 16 | return 1; 17 | } 18 | // 还在棋盘中!还有步数要走 19 | long up = process(row - 1, col, rest - 1, N, M); 20 | long down = process(row + 1, col, rest - 1, N, M); 21 | long left = process(row, col - 1, rest - 1, N, M); 22 | long right = process(row, col + 1, rest - 1, N, M); 23 | return up + down + left + right; 24 | } 25 | 26 | public static double livePosibility2(int row, int col, int k, int N, int M) { 27 | long[][][] dp = new long[N][M][k + 1]; 28 | for (int i = 0; i < N; i++) { 29 | for (int j = 0; j < M; j++) { 30 | dp[i][j][0] = 1; 31 | } 32 | } 33 | for (int rest = 1; rest <= k; rest++) { 34 | for (int r = 0; r < N; r++) { 35 | for (int c = 0; c < M; c++) { 36 | dp[r][c][rest] = pick(dp, N, M, r - 1, c, rest - 1); 37 | dp[r][c][rest] += pick(dp, N, M, r + 1, c, rest - 1); 38 | dp[r][c][rest] += pick(dp, N, M, r, c - 1, rest - 1); 39 | dp[r][c][rest] += pick(dp, N, M, r, c + 1, rest - 1); 40 | } 41 | } 42 | } 43 | return (double) dp[row][col][k] / Math.pow(4, k); 44 | } 45 | 46 | public static long pick(long[][][] dp, int N, int M, int r, int c, int rest) { 47 | if (r < 0 || r == N || c < 0 || c == M) { 48 | return 0; 49 | } 50 | return dp[r][c][rest]; 51 | } 52 | 53 | public static void main(String[] args) { 54 | System.out.println(livePosibility1(6, 6, 10, 50, 50)); 55 | System.out.println(livePosibility2(6, 6, 10, 50, 50)); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/class22/Code01_KillMonster.java: -------------------------------------------------------------------------------- 1 | package class22; 2 | 3 | public class Code01_KillMonster { 4 | 5 | public static double right(int N, int M, int K) { 6 | if (N < 1 || M < 1 || K < 1) { 7 | return 0; 8 | } 9 | long all = (long) Math.pow(M + 1, K); 10 | long kill = process(K, M, N); 11 | return (double) ((double) kill / (double) all); 12 | } 13 | 14 | // 怪兽还剩hp点血 15 | // 每次的伤害在[0~M]范围上 16 | // 还有times次可以砍 17 | // 返回砍死的情况数! 18 | public static long process(int times, int M, int hp) { 19 | if (times == 0) { 20 | return hp <= 0 ? 1 : 0; 21 | } 22 | if (hp <= 0) { 23 | return (long) Math.pow(M + 1, times); 24 | } 25 | long ways = 0; 26 | for (int i = 0; i <= M; i++) { 27 | ways += process(times - 1, M, hp - i); 28 | } 29 | return ways; 30 | } 31 | 32 | public static double dp1(int N, int M, int K) { 33 | if (N < 1 || M < 1 || K < 1) { 34 | return 0; 35 | } 36 | long all = (long) Math.pow(M + 1, K); 37 | long[][] dp = new long[K + 1][N + 1]; 38 | dp[0][0] = 1; 39 | for (int times = 1; times <= K; times++) { 40 | dp[times][0] = (long) Math.pow(M + 1, times); 41 | for (int hp = 1; hp <= N; hp++) { 42 | long ways = 0; 43 | for (int i = 0; i <= M; i++) { 44 | if (hp - i >= 0) { 45 | ways += dp[times - 1][hp - i]; 46 | } else { 47 | ways += (long) Math.pow(M + 1, times - 1); 48 | } 49 | } 50 | dp[times][hp] = ways; 51 | } 52 | } 53 | long kill = dp[K][N]; 54 | return (double) ((double) kill / (double) all); 55 | } 56 | 57 | public static double dp2(int N, int M, int K) { 58 | if (N < 1 || M < 1 || K < 1) { 59 | return 0; 60 | } 61 | long all = (long) Math.pow(M + 1, K); 62 | long[][] dp = new long[K + 1][N + 1]; 63 | dp[0][0] = 1; 64 | for (int times = 1; times <= K; times++) { 65 | dp[times][0] = (long) Math.pow(M + 1, times); 66 | for (int hp = 1; hp <= N; hp++) { 67 | dp[times][hp] = dp[times][hp - 1] + dp[times - 1][hp]; 68 | if (hp - 1 - M >= 0) { 69 | dp[times][hp] -= dp[times - 1][hp - 1 - M]; 70 | } else { 71 | dp[times][hp] -= Math.pow(M + 1, times - 1); 72 | } 73 | } 74 | } 75 | long kill = dp[K][N]; 76 | return (double) ((double) kill / (double) all); 77 | } 78 | 79 | public static void main(String[] args) { 80 | int NMax = 10; 81 | int MMax = 10; 82 | int KMax = 10; 83 | int testTime = 200; 84 | System.out.println("测试开始"); 85 | for (int i = 0; i < testTime; i++) { 86 | int N = (int) (Math.random() * NMax); 87 | int M = (int) (Math.random() * MMax); 88 | int K = (int) (Math.random() * KMax); 89 | double ans1 = right(N, M, K); 90 | double ans2 = dp1(N, M, K); 91 | double ans3 = dp2(N, M, K); 92 | if (ans1 != ans2 || ans1 != ans3) { 93 | System.out.println("Oops!"); 94 | break; 95 | } 96 | } 97 | System.out.println("测试结束"); 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/class22/Code03_SplitNumber.java: -------------------------------------------------------------------------------- 1 | package class22; 2 | 3 | public class Code03_SplitNumber { 4 | 5 | // n为正数 6 | public static int ways(int n) { 7 | if (n < 0) { 8 | return 0; 9 | } 10 | if (n == 1) { 11 | return 1; 12 | } 13 | return process(1, n); 14 | } 15 | 16 | // 上一个拆出来的数是pre 17 | // 还剩rest需要去拆 18 | // 返回拆解的方法数 19 | public static int process(int pre, int rest) { 20 | if (rest == 0) { 21 | return 1; 22 | } 23 | if (pre > rest) { 24 | return 0; 25 | } 26 | int ways = 0; 27 | for (int first = pre; first <= rest; first++) { 28 | ways += process(first, rest - first); 29 | } 30 | return ways; 31 | } 32 | 33 | public static int dp1(int n) { 34 | if (n < 0) { 35 | return 0; 36 | } 37 | if (n == 1) { 38 | return 1; 39 | } 40 | int[][] dp = new int[n + 1][n + 1]; 41 | for (int pre = 1; pre <= n; pre++) { 42 | dp[pre][0] = 1; 43 | dp[pre][pre] = 1; 44 | } 45 | for (int pre = n - 1; pre >= 1; pre--) { 46 | for (int rest = pre + 1; rest <= n; rest++) { 47 | int ways = 0; 48 | for (int first = pre; first <= rest; first++) { 49 | ways += dp[first][rest - first]; 50 | } 51 | dp[pre][rest] = ways; 52 | } 53 | } 54 | return dp[1][n]; 55 | } 56 | 57 | public static int dp2(int n) { 58 | if (n < 0) { 59 | return 0; 60 | } 61 | if (n == 1) { 62 | return 1; 63 | } 64 | int[][] dp = new int[n + 1][n + 1]; 65 | for (int pre = 1; pre <= n; pre++) { 66 | dp[pre][0] = 1; 67 | dp[pre][pre] = 1; 68 | } 69 | for (int pre = n - 1; pre >= 1; pre--) { 70 | for (int rest = pre + 1; rest <= n; rest++) { 71 | dp[pre][rest] = dp[pre + 1][rest]; 72 | dp[pre][rest] += dp[pre][rest - pre]; 73 | } 74 | } 75 | return dp[1][n]; 76 | } 77 | 78 | public static void main(String[] args) { 79 | int test = 39; 80 | System.out.println(ways(test)); 81 | System.out.println(dp1(test)); 82 | System.out.println(dp2(test)); 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/class23/Code01_SplitSumClosed.java: -------------------------------------------------------------------------------- 1 | package class23; 2 | 3 | public class Code01_SplitSumClosed { 4 | 5 | public static int right(int[] arr) { 6 | if (arr == null || arr.length < 2) { 7 | return 0; 8 | } 9 | int sum = 0; 10 | for (int num : arr) { 11 | sum += num; 12 | } 13 | return process(arr, 0, sum / 2); 14 | } 15 | 16 | // arr[i...]可以自由选择,请返回累加和尽量接近rest,但不能超过rest的情况下,最接近的累加和是多少? 17 | public static int process(int[] arr, int i, int rest) { 18 | if (i == arr.length) { 19 | return 0; 20 | } else { // 还有数,arr[i]这个数 21 | // 可能性1,不使用arr[i] 22 | int p1 = process(arr, i + 1, rest); 23 | // 可能性2,要使用arr[i] 24 | int p2 = 0; 25 | if (arr[i] <= rest) { 26 | p2 = arr[i] + process(arr, i + 1, rest - arr[i]); 27 | } 28 | return Math.max(p1, p2); 29 | } 30 | } 31 | 32 | public static int dp(int[] arr) { 33 | if (arr == null || arr.length < 2) { 34 | return 0; 35 | } 36 | int sum = 0; 37 | for (int num : arr) { 38 | sum += num; 39 | } 40 | sum /= 2; 41 | int N = arr.length; 42 | int[][] dp = new int[N + 1][sum + 1]; 43 | for (int i = N - 1; i >= 0; i--) { 44 | for (int rest = 0; rest <= sum; rest++) { 45 | // 可能性1,不使用arr[i] 46 | int p1 = dp[i + 1][rest]; 47 | // 可能性2,要使用arr[i] 48 | int p2 = 0; 49 | if (arr[i] <= rest) { 50 | p2 = arr[i] + dp[i + 1][rest - arr[i]]; 51 | } 52 | dp[i][rest] = Math.max(p1, p2); 53 | } 54 | } 55 | return dp[0][sum]; 56 | } 57 | 58 | public static int[] randomArray(int len, int value) { 59 | int[] arr = new int[len]; 60 | for (int i = 0; i < arr.length; i++) { 61 | arr[i] = (int) (Math.random() * value); 62 | } 63 | return arr; 64 | } 65 | 66 | public static void printArray(int[] arr) { 67 | for (int num : arr) { 68 | System.out.print(num + " "); 69 | } 70 | System.out.println(); 71 | } 72 | 73 | public static void main(String[] args) { 74 | int maxLen = 20; 75 | int maxValue = 50; 76 | int testTime = 10000; 77 | System.out.println("测试开始"); 78 | for (int i = 0; i < testTime; i++) { 79 | int len = (int) (Math.random() * maxLen); 80 | int[] arr = randomArray(len, maxValue); 81 | int ans1 = right(arr); 82 | int ans2 = dp(arr); 83 | if (ans1 != ans2) { 84 | printArray(arr); 85 | System.out.println(ans1); 86 | System.out.println(ans2); 87 | System.out.println("Oops!"); 88 | break; 89 | } 90 | } 91 | System.out.println("测试结束"); 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /src/class23/Code03_NQueens.java: -------------------------------------------------------------------------------- 1 | package class23; 2 | 3 | public class Code03_NQueens { 4 | 5 | public static int num1(int n) { 6 | if (n < 1) { 7 | return 0; 8 | } 9 | int[] record = new int[n]; 10 | return process1(0, record, n); 11 | } 12 | 13 | // 当前来到i行,一共是0~N-1行 14 | // 在i行上放皇后,所有列都尝试 15 | // 必须要保证跟之前所有的皇后不打架 16 | // int[] record record[x] = y 之前的第x行的皇后,放在了y列上 17 | // 返回:不关心i以上发生了什么,i.... 后续有多少合法的方法数 18 | public static int process1(int i, int[] record, int n) { 19 | if (i == n) { 20 | return 1; 21 | } 22 | int res = 0; 23 | // i行的皇后,放哪一列呢?j列, 24 | for (int j = 0; j < n; j++) { 25 | if (isValid(record, i, j)) { 26 | record[i] = j; 27 | res += process1(i + 1, record, n); 28 | } 29 | } 30 | return res; 31 | } 32 | 33 | public static boolean isValid(int[] record, int i, int j) { 34 | // 0..i-1 35 | for (int k = 0; k < i; k++) { 36 | if (j == record[k] || Math.abs(record[k] - j) == Math.abs(i - k)) { 37 | return false; 38 | } 39 | } 40 | return true; 41 | } 42 | 43 | // 请不要超过32皇后问题 44 | public static int num2(int n) { 45 | if (n < 1 || n > 32) { 46 | return 0; 47 | } 48 | // 如果你是13皇后问题,limit 最右13个1,其他都是0 49 | int limit = n == 32 ? -1 : (1 << n) - 1; 50 | return process2(limit, 0, 0, 0); 51 | } 52 | 53 | // 7皇后问题 54 | // limit : 0....0 1 1 1 1 1 1 1 55 | // 之前皇后的列影响:colLim 56 | // 之前皇后的左下对角线影响:leftDiaLim 57 | // 之前皇后的右下对角线影响:rightDiaLim 58 | public static int process2(int limit, int colLim, int leftDiaLim, int rightDiaLim) { 59 | if (colLim == limit) { 60 | return 1; 61 | } 62 | // pos中所有是1的位置,是你可以去尝试皇后的位置 63 | int pos = limit & (~(colLim | leftDiaLim | rightDiaLim)); 64 | int mostRightOne = 0; 65 | int res = 0; 66 | while (pos != 0) { 67 | mostRightOne = pos & (~pos + 1); 68 | pos = pos - mostRightOne; 69 | res += process2(limit, colLim | mostRightOne, (leftDiaLim | mostRightOne) << 1, 70 | (rightDiaLim | mostRightOne) >>> 1); 71 | } 72 | return res; 73 | } 74 | 75 | public static void main(String[] args) { 76 | int n = 15; 77 | 78 | long start = System.currentTimeMillis(); 79 | System.out.println(num2(n)); 80 | long end = System.currentTimeMillis(); 81 | System.out.println("cost time: " + (end - start) + "ms"); 82 | 83 | start = System.currentTimeMillis(); 84 | System.out.println(num1(n)); 85 | end = System.currentTimeMillis(); 86 | System.out.println("cost time: " + (end - start) + "ms"); 87 | 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/class24/Code01_SlidingWindowMaxArray.java: -------------------------------------------------------------------------------- 1 | package class24; 2 | 3 | import java.util.LinkedList; 4 | 5 | public class Code01_SlidingWindowMaxArray { 6 | 7 | // 暴力的对数器方法 8 | public static int[] right(int[] arr, int w) { 9 | if (arr == null || w < 1 || arr.length < w) { 10 | return null; 11 | } 12 | int N = arr.length; 13 | int[] res = new int[N - w + 1]; 14 | int index = 0; 15 | int L = 0; 16 | int R = w - 1; 17 | while (R < N) { 18 | int max = arr[L]; 19 | for (int i = L + 1; i <= R; i++) { 20 | max = Math.max(max, arr[i]); 21 | 22 | } 23 | res[index++] = max; 24 | L++; 25 | R++; 26 | } 27 | return res; 28 | } 29 | 30 | public static int[] getMaxWindow(int[] arr, int w) { 31 | if (arr == null || w < 1 || arr.length < w) { 32 | return null; 33 | } 34 | // qmax 窗口最大值的更新结构 35 | // 放下标 36 | LinkedList qmax = new LinkedList(); 37 | int[] res = new int[arr.length - w + 1]; 38 | int index = 0; 39 | for (int R = 0; R < arr.length; R++) { 40 | while (!qmax.isEmpty() && arr[qmax.peekLast()] <= arr[R]) { 41 | qmax.pollLast(); 42 | } 43 | qmax.addLast(R); 44 | if (qmax.peekFirst() == R - w) { 45 | qmax.pollFirst(); 46 | } 47 | if (R >= w - 1) { 48 | res[index++] = arr[qmax.peekFirst()]; 49 | } 50 | } 51 | return res; 52 | } 53 | 54 | // for test 55 | public static int[] generateRandomArray(int maxSize, int maxValue) { 56 | int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; 57 | for (int i = 0; i < arr.length; i++) { 58 | arr[i] = (int) (Math.random() * (maxValue + 1)); 59 | } 60 | return arr; 61 | } 62 | 63 | // for test 64 | public static boolean isEqual(int[] arr1, int[] arr2) { 65 | if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) { 66 | return false; 67 | } 68 | if (arr1 == null && arr2 == null) { 69 | return true; 70 | } 71 | if (arr1.length != arr2.length) { 72 | return false; 73 | } 74 | for (int i = 0; i < arr1.length; i++) { 75 | if (arr1[i] != arr2[i]) { 76 | return false; 77 | } 78 | } 79 | return true; 80 | } 81 | 82 | public static void main(String[] args) { 83 | int testTime = 100000; 84 | int maxSize = 100; 85 | int maxValue = 100; 86 | System.out.println("test begin"); 87 | for (int i = 0; i < testTime; i++) { 88 | int[] arr = generateRandomArray(maxSize, maxValue); 89 | int w = (int) (Math.random() * (arr.length + 1)); 90 | int[] ans1 = getMaxWindow(arr, w); 91 | int[] ans2 = right(arr, w); 92 | if (!isEqual(ans1, ans2)) { 93 | System.out.println("Oops!"); 94 | } 95 | } 96 | System.out.println("test finish"); 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /src/class24/Code02_AllLessNumSubArray.java: -------------------------------------------------------------------------------- 1 | package class24; 2 | 3 | import java.util.LinkedList; 4 | 5 | public class Code02_AllLessNumSubArray { 6 | 7 | // 暴力的对数器方法 8 | public static int right(int[] arr, int sum) { 9 | if (arr == null || arr.length == 0 || sum < 0) { 10 | return 0; 11 | } 12 | int N = arr.length; 13 | int count = 0; 14 | for (int L = 0; L < N; L++) { 15 | for (int R = L; R < N; R++) { 16 | int max = arr[L]; 17 | int min = arr[L]; 18 | for (int i = L + 1; i <= R; i++) { 19 | max = Math.max(max, arr[i]); 20 | min = Math.min(min, arr[i]); 21 | } 22 | if (max - min <= sum) { 23 | count++; 24 | } 25 | } 26 | } 27 | return count; 28 | } 29 | 30 | public static int num(int[] arr, int sum) { 31 | if (arr == null || arr.length == 0 || sum < 0) { 32 | return 0; 33 | } 34 | int N = arr.length; 35 | int count = 0; 36 | LinkedList maxWindow = new LinkedList<>(); 37 | LinkedList minWindow = new LinkedList<>(); 38 | int R = 0; 39 | for (int L = 0; L < N; L++) { 40 | while (R < N) { 41 | while (!maxWindow.isEmpty() && arr[maxWindow.peekLast()] <= arr[R]) { 42 | maxWindow.pollLast(); 43 | } 44 | maxWindow.addLast(R); 45 | while (!minWindow.isEmpty() && arr[minWindow.peekLast()] >= arr[R]) { 46 | minWindow.pollLast(); 47 | } 48 | minWindow.addLast(R); 49 | if (arr[maxWindow.peekFirst()] - arr[minWindow.peekFirst()] > sum) { 50 | break; 51 | } else { 52 | R++; 53 | } 54 | } 55 | count += R - L; 56 | if (maxWindow.peekFirst() == L) { 57 | maxWindow.pollFirst(); 58 | } 59 | if (minWindow.peekFirst() == L) { 60 | minWindow.pollFirst(); 61 | } 62 | } 63 | return count; 64 | } 65 | 66 | // for test 67 | public static int[] generateRandomArray(int maxLen, int maxValue) { 68 | int len = (int) (Math.random() * (maxLen + 1)); 69 | int[] arr = new int[len]; 70 | for (int i = 0; i < len; i++) { 71 | arr[i] = (int) (Math.random() * (maxValue + 1)) - (int) (Math.random() * (maxValue + 1)); 72 | } 73 | return arr; 74 | } 75 | 76 | // for test 77 | public static void printArray(int[] arr) { 78 | if (arr != null) { 79 | for (int i = 0; i < arr.length; i++) { 80 | System.out.print(arr[i] + " "); 81 | } 82 | System.out.println(); 83 | } 84 | } 85 | 86 | public static void main(String[] args) { 87 | int maxLen = 100; 88 | int maxValue = 200; 89 | int testTime = 100000; 90 | System.out.println("测试开始"); 91 | for (int i = 0; i < testTime; i++) { 92 | int[] arr = generateRandomArray(maxLen, maxValue); 93 | int sum = (int) (Math.random() * (maxValue + 1)); 94 | int ans1 = right(arr, sum); 95 | int ans2 = num(arr, sum); 96 | if (ans1 != ans2) { 97 | System.out.println("Oops!"); 98 | printArray(arr); 99 | System.out.println(sum); 100 | System.out.println(ans1); 101 | System.out.println(ans2); 102 | break; 103 | } 104 | } 105 | System.out.println("测试结束"); 106 | 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /src/class25/Code01_MonotonousStackForNowcoder.java: -------------------------------------------------------------------------------- 1 | package class25; 2 | 3 | // 测试链接 : https://www.nowcoder.com/practice/2a2c00e7a88a498693568cef63a4b7bb 4 | // 如果在牛客上做题,可以用如下的方式来做 5 | // 请同学们务必参考如下代码中关于输入、输出的处理 6 | // 这是输入输出处理效率很高的写法 7 | // 提交如下的代码,并把主类名改成"Main" 8 | // 可以直接通过 9 | import java.io.BufferedReader; 10 | import java.io.IOException; 11 | import java.io.InputStreamReader; 12 | import java.io.OutputStreamWriter; 13 | import java.io.PrintWriter; 14 | import java.io.StreamTokenizer; 15 | 16 | public class Code01_MonotonousStackForNowcoder { 17 | 18 | public static int[] arr = new int[1000000]; 19 | public static int[][] ans = new int[1000000][2]; 20 | // stack1 : 相等值的位置也放 21 | // stack2 : 只放不相等值的最后一个位置 22 | // 比如 : arr = { 3, 3, 3, 4, 4, 6, 6, 6} 23 | // 位置 0 1 2 3 4 5 6 7 24 | // 如果位置依次压栈, 25 | // stack1中的记录是(位置) : 0 1 2 3 4 5 6 7 26 | // stack2中的记录是(位置) : 2 4 7 27 | public static int[] stack1 = new int[1000000]; 28 | public static int[] stack2 = new int[1000000]; 29 | 30 | public static void main(String[] args) throws IOException { 31 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 32 | StreamTokenizer in = new StreamTokenizer(br); 33 | PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out)); 34 | while (in.nextToken() != StreamTokenizer.TT_EOF) { 35 | int n = (int) in.nval; 36 | for (int i = 0; i < n; i++) { 37 | in.nextToken(); 38 | arr[i] = (int) in.nval; 39 | } 40 | getNearLess(n); 41 | for (int i = 0; i < n; i++) { 42 | out.println(ans[i][0] + " " + ans[i][1]); 43 | } 44 | out.flush(); 45 | } 46 | } 47 | 48 | public static void getNearLess(int n) { 49 | int stackSize1 = 0; 50 | int stackSize2 = 0; 51 | for (int i = 0; i < n; i++) { 52 | while (stackSize1 > 0 && arr[stack1[stackSize1 - 1]] > arr[i]) { 53 | int curIndex = stack1[--stackSize1]; 54 | int left = stackSize2 < 2 ? -1 : stack2[stackSize2 - 2]; 55 | ans[curIndex][0] = left; 56 | ans[curIndex][1] = i; 57 | if (stackSize1 == 0 || arr[stack1[stackSize1 - 1]] != arr[curIndex]) { 58 | stackSize2--; 59 | } 60 | } 61 | if (stackSize1 != 0 && arr[stack1[stackSize1 - 1]] == arr[i]) { 62 | stack2[stackSize2 - 1] = i; 63 | } else { 64 | stack2[stackSize2++] = i; 65 | } 66 | stack1[stackSize1++] = i; 67 | } 68 | while (stackSize1 != 0) { 69 | int curIndex = stack1[--stackSize1]; 70 | int left = stackSize2 < 2 ? -1 : stack2[stackSize2 - 2]; 71 | ans[curIndex][0] = left; 72 | ans[curIndex][1] = -1; 73 | if (stackSize1 == 0 || arr[stack1[stackSize1 - 1]] != arr[curIndex]) { 74 | stackSize2--; 75 | } 76 | } 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/class25/Code02_AllTimesMinToMax.java: -------------------------------------------------------------------------------- 1 | package class25; 2 | 3 | import java.util.Stack; 4 | 5 | public class Code02_AllTimesMinToMax { 6 | 7 | public static int max1(int[] arr) { 8 | int max = Integer.MIN_VALUE; 9 | for (int i = 0; i < arr.length; i++) { 10 | for (int j = i; j < arr.length; j++) { 11 | int minNum = Integer.MAX_VALUE; 12 | int sum = 0; 13 | for (int k = i; k <= j; k++) { 14 | sum += arr[k]; 15 | minNum = Math.min(minNum, arr[k]); 16 | } 17 | max = Math.max(max, minNum * sum); 18 | } 19 | } 20 | return max; 21 | } 22 | 23 | public static int max2(int[] arr) { 24 | int size = arr.length; 25 | int[] sums = new int[size]; 26 | sums[0] = arr[0]; 27 | for (int i = 1; i < size; i++) { 28 | sums[i] = sums[i - 1] + arr[i]; 29 | } 30 | int max = Integer.MIN_VALUE; 31 | Stack stack = new Stack(); 32 | for (int i = 0; i < size; i++) { 33 | while (!stack.isEmpty() && arr[stack.peek()] >= arr[i]) { 34 | int j = stack.pop(); 35 | max = Math.max(max, (stack.isEmpty() ? sums[i - 1] : (sums[i - 1] - sums[stack.peek()])) * arr[j]); 36 | } 37 | stack.push(i); 38 | } 39 | while (!stack.isEmpty()) { 40 | int j = stack.pop(); 41 | max = Math.max(max, (stack.isEmpty() ? sums[size - 1] : (sums[size - 1] - sums[stack.peek()])) * arr[j]); 42 | } 43 | return max; 44 | } 45 | 46 | public static int[] gerenareRondomArray() { 47 | int[] arr = new int[(int) (Math.random() * 20) + 10]; 48 | for (int i = 0; i < arr.length; i++) { 49 | arr[i] = (int) (Math.random() * 101); 50 | } 51 | return arr; 52 | } 53 | 54 | public static void main(String[] args) { 55 | int testTimes = 2000000; 56 | System.out.println("test begin"); 57 | for (int i = 0; i < testTimes; i++) { 58 | int[] arr = gerenareRondomArray(); 59 | if (max1(arr) != max2(arr)) { 60 | System.out.println("FUCK!"); 61 | break; 62 | } 63 | } 64 | System.out.println("test finish"); 65 | } 66 | 67 | // 本题可以在leetcode上找到原题 68 | // 测试链接 : https://leetcode.com/problems/maximum-subarray-min-product/ 69 | // 注意测试题目数量大,要取模,但是思路和课上讲的是完全一样的 70 | // 注意溢出的处理即可,也就是用long类型来表示累加和 71 | // 还有优化就是,你可以用自己手写的数组栈,来替代系统实现的栈,也会快很多 72 | public static int maxSumMinProduct(int[] arr) { 73 | int size = arr.length; 74 | long[] sums = new long[size]; 75 | sums[0] = arr[0]; 76 | for (int i = 1; i < size; i++) { 77 | sums[i] = sums[i - 1] + arr[i]; 78 | } 79 | long max = Long.MIN_VALUE; 80 | int[] stack = new int[size]; 81 | int stackSize = 0; 82 | for (int i = 0; i < size; i++) { 83 | while (stackSize != 0 && arr[stack[stackSize - 1]] >= arr[i]) { 84 | int j = stack[--stackSize]; 85 | max = Math.max(max, 86 | (stackSize == 0 ? sums[i - 1] : (sums[i - 1] - sums[stack[stackSize - 1]])) * arr[j]); 87 | } 88 | stack[stackSize++] = i; 89 | } 90 | while (stackSize != 0) { 91 | int j = stack[--stackSize]; 92 | max = Math.max(max, 93 | (stackSize == 0 ? sums[size - 1] : (sums[size - 1] - sums[stack[stackSize - 1]])) * arr[j]); 94 | } 95 | return (int) (max % 1000000007); 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /src/class25/Code03_LargestRectangleInHistogram.java: -------------------------------------------------------------------------------- 1 | package class25; 2 | 3 | import java.util.Stack; 4 | 5 | // 测试链接:https://leetcode.com/problems/largest-rectangle-in-histogram 6 | public class Code03_LargestRectangleInHistogram { 7 | 8 | public static int largestRectangleArea1(int[] height) { 9 | if (height == null || height.length == 0) { 10 | return 0; 11 | } 12 | int maxArea = 0; 13 | Stack stack = new Stack(); 14 | for (int i = 0; i < height.length; i++) { 15 | while (!stack.isEmpty() && height[i] <= height[stack.peek()]) { 16 | int j = stack.pop(); 17 | int k = stack.isEmpty() ? -1 : stack.peek(); 18 | int curArea = (i - k - 1) * height[j]; 19 | maxArea = Math.max(maxArea, curArea); 20 | } 21 | stack.push(i); 22 | } 23 | while (!stack.isEmpty()) { 24 | int j = stack.pop(); 25 | int k = stack.isEmpty() ? -1 : stack.peek(); 26 | int curArea = (height.length - k - 1) * height[j]; 27 | maxArea = Math.max(maxArea, curArea); 28 | } 29 | return maxArea; 30 | } 31 | 32 | public static int largestRectangleArea2(int[] height) { 33 | if (height == null || height.length == 0) { 34 | return 0; 35 | } 36 | int N = height.length; 37 | int[] stack = new int[N]; 38 | int si = -1; 39 | int maxArea = 0; 40 | for (int i = 0; i < height.length; i++) { 41 | while (si != -1 && height[i] <= height[stack[si]]) { 42 | int j = stack[si--]; 43 | int k = si == -1 ? -1 : stack[si]; 44 | int curArea = (i - k - 1) * height[j]; 45 | maxArea = Math.max(maxArea, curArea); 46 | } 47 | stack[++si] = i; 48 | } 49 | while (si != -1) { 50 | int j = stack[si--]; 51 | int k = si == -1 ? -1 : stack[si]; 52 | int curArea = (height.length - k - 1) * height[j]; 53 | maxArea = Math.max(maxArea, curArea); 54 | } 55 | return maxArea; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/class25/Code04_MaximalRectangle.java: -------------------------------------------------------------------------------- 1 | package class25; 2 | 3 | import java.util.Stack; 4 | 5 | // 测试链接:https://leetcode.com/problems/maximal-rectangle/ 6 | public class Code04_MaximalRectangle { 7 | 8 | public static int maximalRectangle(char[][] map) { 9 | if (map == null || map.length == 0 || map[0].length == 0) { 10 | return 0; 11 | } 12 | int maxArea = 0; 13 | int[] height = new int[map[0].length]; 14 | for (int i = 0; i < map.length; i++) { 15 | for (int j = 0; j < map[0].length; j++) { 16 | height[j] = map[i][j] == '0' ? 0 : height[j] + 1; 17 | } 18 | maxArea = Math.max(maxRecFromBottom(height), maxArea); 19 | } 20 | return maxArea; 21 | } 22 | 23 | // height是正方图数组 24 | public static int maxRecFromBottom(int[] height) { 25 | if (height == null || height.length == 0) { 26 | return 0; 27 | } 28 | int maxArea = 0; 29 | Stack stack = new Stack(); 30 | for (int i = 0; i < height.length; i++) { 31 | while (!stack.isEmpty() && height[i] <= height[stack.peek()]) { 32 | int j = stack.pop(); 33 | int k = stack.isEmpty() ? -1 : stack.peek(); 34 | int curArea = (i - k - 1) * height[j]; 35 | maxArea = Math.max(maxArea, curArea); 36 | } 37 | stack.push(i); 38 | } 39 | while (!stack.isEmpty()) { 40 | int j = stack.pop(); 41 | int k = stack.isEmpty() ? -1 : stack.peek(); 42 | int curArea = (height.length - k - 1) * height[j]; 43 | maxArea = Math.max(maxArea, curArea); 44 | } 45 | return maxArea; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/class25/Code05_CountSubmatricesWithAllOnes.java: -------------------------------------------------------------------------------- 1 | package class25; 2 | 3 | // 测试链接:https://leetcode.com/problems/count-submatrices-with-all-ones 4 | public class Code05_CountSubmatricesWithAllOnes { 5 | 6 | public static int numSubmat(int[][] mat) { 7 | if (mat == null || mat.length == 0 || mat[0].length == 0) { 8 | return 0; 9 | } 10 | int nums = 0; 11 | int[] height = new int[mat[0].length]; 12 | for (int i = 0; i < mat.length; i++) { 13 | for (int j = 0; j < mat[0].length; j++) { 14 | height[j] = mat[i][j] == 0 ? 0 : height[j] + 1; 15 | } 16 | nums += countFromBottom(height); 17 | } 18 | return nums; 19 | 20 | } 21 | 22 | // 比如 23 | // 1 24 | // 1 25 | // 1 1 26 | // 1 1 1 27 | // 1 1 1 28 | // 1 1 1 29 | // 30 | // 2 .... 6 .... 9 31 | // 如上图,假设在6位置,1的高度为6 32 | // 在6位置的左边,离6位置最近、且小于高度6的位置是2,2位置的高度是3 33 | // 在6位置的右边,离6位置最近、且小于高度6的位置是9,9位置的高度是4 34 | // 此时我们求什么? 35 | // 1) 求在3~8范围上,必须以高度6作为高的矩形,有几个? 36 | // 2) 求在3~8范围上,必须以高度5作为高的矩形,有几个? 37 | // 也就是说,<=4的高度,一律不求 38 | // 那么,1) 求必须以位置6的高度6作为高的矩形,有几个? 39 | // 3..3 3..4 3..5 3..6 3..7 3..8 40 | // 4..4 4..5 4..6 4..7 4..8 41 | // 5..5 5..6 5..7 5..8 42 | // 6..6 6..7 6..8 43 | // 7..7 7..8 44 | // 8..8 45 | // 这么多!= 21 = (9 - 2 - 1) * (9 - 2) / 2 46 | // 这就是任何一个数字从栈里弹出的时候,计算矩形数量的方式 47 | public static int countFromBottom(int[] height) { 48 | if (height == null || height.length == 0) { 49 | return 0; 50 | } 51 | int nums = 0; 52 | int[] stack = new int[height.length]; 53 | int si = -1; 54 | for (int i = 0; i < height.length; i++) { 55 | while (si != -1 && height[stack[si]] >= height[i]) { 56 | int cur = stack[si--]; 57 | if (height[cur] > height[i]) { 58 | int left = si == -1 ? -1 : stack[si]; 59 | int n = i - left - 1; 60 | int down = Math.max(left == -1 ? 0 : height[left], height[i]); 61 | nums += (height[cur] - down) * num(n); 62 | } 63 | 64 | } 65 | stack[++si] = i; 66 | } 67 | while (si != -1) { 68 | int cur = stack[si--]; 69 | int left = si == -1 ? -1 : stack[si]; 70 | int n = height.length - left - 1; 71 | int down = left == -1 ? 0 : height[left]; 72 | nums += (height[cur] - down) * num(n); 73 | } 74 | return nums; 75 | } 76 | 77 | public static int num(int n) { 78 | return ((n * (1 + n)) >> 1); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/class26/Code03_ZeroLeftOneStringNumber.java: -------------------------------------------------------------------------------- 1 | package class26; 2 | 3 | public class Code03_ZeroLeftOneStringNumber { 4 | 5 | public static int getNum1(int n) { 6 | if (n < 1) { 7 | return 0; 8 | } 9 | return process(1, n); 10 | } 11 | 12 | public static int process(int i, int n) { 13 | if (i == n - 1) { 14 | return 2; 15 | } 16 | if (i == n) { 17 | return 1; 18 | } 19 | return process(i + 1, n) + process(i + 2, n); 20 | } 21 | 22 | public static int getNum2(int n) { 23 | if (n < 1) { 24 | return 0; 25 | } 26 | if (n == 1) { 27 | return 1; 28 | } 29 | int pre = 1; 30 | int cur = 1; 31 | int tmp = 0; 32 | for (int i = 2; i < n + 1; i++) { 33 | tmp = cur; 34 | cur += pre; 35 | pre = tmp; 36 | } 37 | return cur; 38 | } 39 | 40 | public static int getNum3(int n) { 41 | if (n < 1) { 42 | return 0; 43 | } 44 | if (n == 1 || n == 2) { 45 | return n; 46 | } 47 | int[][] base = { { 1, 1 }, { 1, 0 } }; 48 | int[][] res = matrixPower(base, n - 2); 49 | return 2 * res[0][0] + res[1][0]; 50 | } 51 | 52 | 53 | 54 | 55 | 56 | 57 | public static int fi(int n) { 58 | if (n < 1) { 59 | return 0; 60 | } 61 | if (n == 1 || n == 2) { 62 | return 1; 63 | } 64 | int[][] base = { { 1, 1 }, 65 | { 1, 0 } }; 66 | int[][] res = matrixPower(base, n - 2); 67 | return res[0][0] + res[1][0]; 68 | } 69 | 70 | 71 | 72 | 73 | public static int[][] matrixPower(int[][] m, int p) { 74 | int[][] res = new int[m.length][m[0].length]; 75 | for (int i = 0; i < res.length; i++) { 76 | res[i][i] = 1; 77 | } 78 | int[][] tmp = m; 79 | for (; p != 0; p >>= 1) { 80 | if ((p & 1) != 0) { 81 | res = product(res, tmp); 82 | } 83 | tmp = product(tmp, tmp); 84 | } 85 | return res; 86 | } 87 | 88 | // 两个矩阵乘完之后的结果返回 89 | public static int[][] product(int[][] a, int[][] b) { 90 | int n = a.length; 91 | int m = b[0].length; 92 | int k = a[0].length; // a的列数同时也是b的行数 93 | int[][] ans = new int[n][m]; 94 | for(int i = 0 ; i < n; i++) { 95 | for(int j = 0 ; j < m;j++) { 96 | for(int c = 0; c < k; c++) { 97 | ans[i][j] += a[i][c] * b[c][j]; 98 | } 99 | } 100 | } 101 | return ans; 102 | } 103 | 104 | public static void main(String[] args) { 105 | for (int i = 0; i != 20; i++) { 106 | System.out.println(getNum1(i)); 107 | System.out.println(getNum2(i)); 108 | System.out.println(getNum3(i)); 109 | System.out.println("==================="); 110 | } 111 | 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/class27/Code01_KMP.java: -------------------------------------------------------------------------------- 1 | package class27; 2 | 3 | public class Code01_KMP { 4 | 5 | public static int getIndexOf(String s1, String s2) { 6 | if (s1 == null || s2 == null || s2.length() < 1 || s1.length() < s2.length()) { 7 | return -1; 8 | } 9 | char[] str1 = s1.toCharArray(); 10 | char[] str2 = s2.toCharArray(); 11 | int x = 0; 12 | int y = 0; 13 | // O(M) m <= n 14 | int[] next = getNextArray(str2); 15 | // O(N) 16 | while (x < str1.length && y < str2.length) { 17 | if (str1[x] == str2[y]) { 18 | x++; 19 | y++; 20 | } else if (next[y] == -1) { // y == 0 21 | x++; 22 | } else { 23 | y = next[y]; 24 | } 25 | } 26 | return y == str2.length ? x - y : -1; 27 | } 28 | 29 | public static int[] getNextArray(char[] str2) { 30 | if (str2.length == 1) { 31 | return new int[] { -1 }; 32 | } 33 | int[] next = new int[str2.length]; 34 | next[0] = -1; 35 | next[1] = 0; 36 | int i = 2; // 目前在哪个位置上求next数组的值 37 | int cn = 0; // 当前是哪个位置的值再和i-1位置的字符比较 38 | while (i < next.length) { 39 | if (str2[i - 1] == str2[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 | // for test 51 | public static String getRandomString(int possibilities, int size) { 52 | char[] ans = new char[(int) (Math.random() * size) + 1]; 53 | for (int i = 0; i < ans.length; i++) { 54 | ans[i] = (char) ((int) (Math.random() * possibilities) + 'a'); 55 | } 56 | return String.valueOf(ans); 57 | } 58 | 59 | public static void main(String[] args) { 60 | int possibilities = 5; 61 | int strSize = 20; 62 | int matchSize = 5; 63 | int testTimes = 5000000; 64 | System.out.println("test begin"); 65 | for (int i = 0; i < testTimes; i++) { 66 | String str = getRandomString(possibilities, strSize); 67 | String match = getRandomString(possibilities, matchSize); 68 | if (getIndexOf(str, match) != str.indexOf(match)) { 69 | System.out.println("Oops!"); 70 | } 71 | } 72 | System.out.println("test finish"); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/class27/Code02_TreeEqual.java: -------------------------------------------------------------------------------- 1 | package class27; 2 | 3 | import java.util.ArrayList; 4 | 5 | public class Code02_TreeEqual { 6 | 7 | public static class TreeNode { 8 | public int val; 9 | public TreeNode left; 10 | public TreeNode right; 11 | 12 | public TreeNode(int v) { 13 | val = v; 14 | } 15 | } 16 | 17 | // 测试链接 : https://leetcode.cn/problems/subtree-of-another-tree/ 18 | // 提交如下代码可以直接通过 19 | public static boolean isSubtree(TreeNode big, TreeNode small) { 20 | if (small == null) { 21 | return true; 22 | } 23 | if (big == null) { 24 | return false; 25 | } 26 | ArrayList b = preSerial(big); 27 | ArrayList s = preSerial(small); 28 | String[] str = new String[b.size()]; 29 | for (int i = 0; i < str.length; i++) { 30 | str[i] = b.get(i); 31 | } 32 | 33 | String[] match = new String[s.size()]; 34 | for (int i = 0; i < match.length; i++) { 35 | match[i] = s.get(i); 36 | } 37 | return getIndexOf(str, match) != -1; 38 | } 39 | 40 | public static ArrayList preSerial(TreeNode head) { 41 | ArrayList ans = new ArrayList<>(); 42 | pres(head, ans); 43 | return ans; 44 | } 45 | 46 | public static void pres(TreeNode head, ArrayList ans) { 47 | if (head == null) { 48 | ans.add(null); 49 | } else { 50 | ans.add(String.valueOf(head.val)); 51 | pres(head.left, ans); 52 | pres(head.right, ans); 53 | } 54 | } 55 | 56 | public static int getIndexOf(String[] str1, String[] str2) { 57 | if (str1 == null || str2 == null || str1.length < 1 || str1.length < str2.length) { 58 | return -1; 59 | } 60 | int x = 0; 61 | int y = 0; 62 | int[] next = getNextArray(str2); 63 | while (x < str1.length && y < str2.length) { 64 | if (isEqual(str1[x], str2[y])) { 65 | x++; 66 | y++; 67 | } else if (next[y] == -1) { 68 | x++; 69 | } else { 70 | y = next[y]; 71 | } 72 | } 73 | return y == str2.length ? x - y : -1; 74 | } 75 | 76 | public static int[] getNextArray(String[] ms) { 77 | if (ms.length == 1) { 78 | return new int[] { -1 }; 79 | } 80 | int[] next = new int[ms.length]; 81 | next[0] = -1; 82 | next[1] = 0; 83 | int i = 2; 84 | int cn = 0; 85 | while (i < next.length) { 86 | if (isEqual(ms[i - 1], ms[cn])) { 87 | next[i++] = ++cn; 88 | } else if (cn > 0) { 89 | cn = next[cn]; 90 | } else { 91 | next[i++] = 0; 92 | } 93 | } 94 | return next; 95 | } 96 | 97 | public static boolean isEqual(String a, String b) { 98 | if (a == null && b == null) { 99 | return true; 100 | } else { 101 | if (a == null || b == null) { 102 | return false; 103 | } else { 104 | return a.equals(b); 105 | } 106 | } 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /src/class27/Code03_IsRotation.java: -------------------------------------------------------------------------------- 1 | package class27; 2 | 3 | public class Code03_IsRotation { 4 | 5 | public static boolean isRotation(String a, String b) { 6 | if (a == null || b == null || a.length() != b.length()) { 7 | return false; 8 | } 9 | String b2 = b + b; 10 | return getIndexOf(b2, a) != -1; 11 | } 12 | 13 | // KMP Algorithm 14 | public static int getIndexOf(String s, String m) { 15 | if (s.length() < m.length()) { 16 | return -1; 17 | } 18 | char[] ss = s.toCharArray(); 19 | char[] ms = m.toCharArray(); 20 | int si = 0; 21 | int mi = 0; 22 | int[] next = getNextArray(ms); 23 | while (si < ss.length && mi < ms.length) { 24 | if (ss[si] == ms[mi]) { 25 | si++; 26 | mi++; 27 | } else if (next[mi] == -1) { 28 | si++; 29 | } else { 30 | mi = next[mi]; 31 | } 32 | } 33 | return mi == ms.length ? si - mi : -1; 34 | } 35 | 36 | public static int[] getNextArray(char[] ms) { 37 | if (ms.length == 1) { 38 | return new int[] { -1 }; 39 | } 40 | int[] next = new int[ms.length]; 41 | next[0] = -1; 42 | next[1] = 0; 43 | int pos = 2; 44 | int cn = 0; 45 | while (pos < next.length) { 46 | if (ms[pos - 1] == ms[cn]) { 47 | next[pos++] = ++cn; 48 | } else if (cn > 0) { 49 | cn = next[cn]; 50 | } else { 51 | next[pos++] = 0; 52 | } 53 | } 54 | return next; 55 | } 56 | 57 | public static void main(String[] args) { 58 | String str1 = "yunzuocheng"; 59 | String str2 = "zuochengyun"; 60 | System.out.println(isRotation(str1, str2)); 61 | 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/class28/Code01_Manacher.java: -------------------------------------------------------------------------------- 1 | package class28; 2 | 3 | public class Code01_Manacher { 4 | 5 | public static int manacher(String s) { 6 | if (s == null || s.length() == 0) { 7 | return 0; 8 | } 9 | // "12132" -> "#1#2#1#3#2#" 10 | char[] str = manacherString(s); 11 | // 回文半径的大小 12 | int[] pArr = new int[str.length]; 13 | int C = -1; 14 | // 讲述中:R代表最右的扩成功的位置 15 | // coding:最右的扩成功位置的,再下一个位置 16 | int R = -1; 17 | int max = Integer.MIN_VALUE; 18 | for (int i = 0; i < str.length; i++) { // 0 1 2 19 | // R第一个违规的位置,i>= R 20 | // i位置扩出来的答案,i位置扩的区域,至少是多大。 21 | pArr[i] = R > i ? Math.min(pArr[2 * C - i], R - i) : 1; 22 | while (i + pArr[i] < str.length && i - pArr[i] > -1) { 23 | if (str[i + pArr[i]] == str[i - pArr[i]]) 24 | pArr[i]++; 25 | else { 26 | break; 27 | } 28 | } 29 | if (i + pArr[i] > R) { 30 | R = i + pArr[i]; 31 | C = i; 32 | } 33 | max = Math.max(max, pArr[i]); 34 | } 35 | return max - 1; 36 | } 37 | 38 | public static char[] manacherString(String str) { 39 | char[] charArr = str.toCharArray(); 40 | char[] res = new char[str.length() * 2 + 1]; 41 | int index = 0; 42 | for (int i = 0; i != res.length; i++) { 43 | res[i] = (i & 1) == 0 ? '#' : charArr[index++]; 44 | } 45 | return res; 46 | } 47 | 48 | // for test 49 | public static int right(String s) { 50 | if (s == null || s.length() == 0) { 51 | return 0; 52 | } 53 | char[] str = manacherString(s); 54 | int max = 0; 55 | for (int i = 0; i < str.length; i++) { 56 | int L = i - 1; 57 | int R = i + 1; 58 | while (L >= 0 && R < str.length && str[L] == str[R]) { 59 | L--; 60 | R++; 61 | } 62 | max = Math.max(max, R - L - 1); 63 | } 64 | return max / 2; 65 | } 66 | 67 | // for test 68 | public static String getRandomString(int possibilities, int size) { 69 | char[] ans = new char[(int) (Math.random() * size) + 1]; 70 | for (int i = 0; i < ans.length; i++) { 71 | ans[i] = (char) ((int) (Math.random() * possibilities) + 'a'); 72 | } 73 | return String.valueOf(ans); 74 | } 75 | 76 | public static void main(String[] args) { 77 | int possibilities = 5; 78 | int strSize = 20; 79 | int testTimes = 5000000; 80 | System.out.println("test begin"); 81 | for (int i = 0; i < testTimes; i++) { 82 | String str = getRandomString(possibilities, strSize); 83 | if (manacher(str) != right(str)) { 84 | System.out.println("Oops!"); 85 | } 86 | } 87 | System.out.println("test finish"); 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /src/class28/Code02_AddShortestEnd.java: -------------------------------------------------------------------------------- 1 | package class28; 2 | 3 | public class Code02_AddShortestEnd { 4 | 5 | public static String shortestEnd(String s) { 6 | if (s == null || s.length() == 0) { 7 | return null; 8 | } 9 | char[] str = manacherString(s); 10 | int[] pArr = new int[str.length]; 11 | int C = -1; 12 | int R = -1; 13 | int maxContainsEnd = -1; 14 | for (int i = 0; i != str.length; i++) { 15 | pArr[i] = R > i ? Math.min(pArr[2 * C - i], R - i) : 1; 16 | while (i + pArr[i] < str.length && i - pArr[i] > -1) { 17 | if (str[i + pArr[i]] == str[i - pArr[i]]) 18 | pArr[i]++; 19 | else { 20 | break; 21 | } 22 | } 23 | if (i + pArr[i] > R) { 24 | R = i + pArr[i]; 25 | C = i; 26 | } 27 | if (R == str.length) { 28 | maxContainsEnd = pArr[i]; 29 | break; 30 | } 31 | } 32 | char[] res = new char[s.length() - maxContainsEnd + 1]; 33 | for (int i = 0; i < res.length; i++) { 34 | res[res.length - 1 - i] = str[i * 2 + 1]; 35 | } 36 | return String.valueOf(res); 37 | } 38 | 39 | public static char[] manacherString(String str) { 40 | char[] charArr = str.toCharArray(); 41 | char[] res = new char[str.length() * 2 + 1]; 42 | int index = 0; 43 | for (int i = 0; i != res.length; i++) { 44 | res[i] = (i & 1) == 0 ? '#' : charArr[index++]; 45 | } 46 | return res; 47 | } 48 | 49 | public static void main(String[] args) { 50 | String str1 = "abcd123321"; 51 | System.out.println(shortestEnd(str1)); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/class29/Code03_ReservoirSampling.java: -------------------------------------------------------------------------------- 1 | package class29; 2 | 3 | public class Code03_ReservoirSampling { 4 | 5 | public static class RandomBox { 6 | private int[] bag; 7 | private int N; 8 | private int count; 9 | 10 | public RandomBox(int capacity) { 11 | bag = new int[capacity]; 12 | N = capacity; 13 | count = 0; 14 | } 15 | 16 | private int rand(int max) { 17 | return (int) (Math.random() * max) + 1; 18 | } 19 | 20 | public void add(int num) { 21 | count++; 22 | if (count <= N) { 23 | bag[count - 1] = num; 24 | } else { 25 | if (rand(count) <= N) { 26 | bag[rand(N) - 1] = num; 27 | } 28 | } 29 | } 30 | 31 | public int[] choices() { 32 | int[] ans = new int[N]; 33 | for (int i = 0; i < N; i++) { 34 | ans[i] = bag[i]; 35 | } 36 | return ans; 37 | } 38 | 39 | } 40 | 41 | // 请等概率返回1~i中的一个数字 42 | public static int random(int i) { 43 | return (int) (Math.random() * i) + 1; 44 | } 45 | 46 | public static void main(String[] args) { 47 | System.out.println("hello"); 48 | int test = 10000; 49 | int ballNum = 17; 50 | int[] count = new int[ballNum + 1]; 51 | for (int i = 0; i < test; i++) { 52 | int[] bag = new int[10]; 53 | int bagi = 0; 54 | for (int num = 1; num <= ballNum; num++) { 55 | if (num <= 10) { 56 | bag[bagi++] = num; 57 | } else { // num > 10 58 | if (random(num) <= 10) { // 一定要把num球入袋子 59 | bagi = (int) (Math.random() * 10); 60 | bag[bagi] = num; 61 | } 62 | } 63 | 64 | } 65 | for (int num : bag) { 66 | count[num]++; 67 | } 68 | } 69 | for (int i = 0; i <= ballNum; i++) { 70 | System.out.println(count[i]); 71 | } 72 | 73 | System.out.println("hello"); 74 | int all = 100; 75 | int choose = 10; 76 | int testTimes = 50000; 77 | int[] counts = new int[all + 1]; 78 | for (int i = 0; i < testTimes; i++) { 79 | RandomBox box = new RandomBox(choose); 80 | for (int num = 1; num <= all; num++) { 81 | box.add(num); 82 | } 83 | int[] ans = box.choices(); 84 | for (int j = 0; j < ans.length; j++) { 85 | counts[ans[j]]++; 86 | } 87 | } 88 | 89 | for (int i = 0; i < counts.length; i++) { 90 | System.out.println(i + " times : " + counts[i]); 91 | } 92 | 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/class30/Code02_MinDepth.java: -------------------------------------------------------------------------------- 1 | package class30; 2 | 3 | // 本题测试链接 : https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/ 4 | public class Code02_MinDepth { 5 | 6 | // 不提交这个类 7 | public static class TreeNode { 8 | public int val; 9 | public TreeNode left; 10 | public TreeNode right; 11 | 12 | public TreeNode(int x) { 13 | val = x; 14 | } 15 | } 16 | 17 | // 下面的方法是一般解 18 | public static int minDepth1(TreeNode head) { 19 | if (head == null) { 20 | return 0; 21 | } 22 | return p(head); 23 | } 24 | 25 | // 返回x为头的树,最小深度是多少 26 | public static int p(TreeNode x) { 27 | if (x.left == null && x.right == null) { 28 | return 1; 29 | } 30 | // 左右子树起码有一个不为空 31 | int leftH = Integer.MAX_VALUE; 32 | if (x.left != null) { 33 | leftH = p(x.left); 34 | } 35 | int rightH = Integer.MAX_VALUE; 36 | if (x.right != null) { 37 | rightH = p(x.right); 38 | } 39 | return 1 + Math.min(leftH, rightH); 40 | } 41 | 42 | // 下面的方法是morris遍历的解 43 | public static int minDepth2(TreeNode head) { 44 | if (head == null) { 45 | return 0; 46 | } 47 | TreeNode cur = head; 48 | TreeNode mostRight = null; 49 | int curLevel = 0; 50 | int minHeight = Integer.MAX_VALUE; 51 | while (cur != null) { 52 | mostRight = cur.left; 53 | if (mostRight != null) { 54 | int rightBoardSize = 1; 55 | while (mostRight.right != null && mostRight.right != cur) { 56 | rightBoardSize++; 57 | mostRight = mostRight.right; 58 | } 59 | if (mostRight.right == null) { // 第一次到达 60 | curLevel++; 61 | mostRight.right = cur; 62 | cur = cur.left; 63 | continue; 64 | } else { // 第二次到达 65 | if (mostRight.left == null) { 66 | minHeight = Math.min(minHeight, curLevel); 67 | } 68 | curLevel -= rightBoardSize; 69 | mostRight.right = null; 70 | } 71 | } else { // 只有一次到达 72 | curLevel++; 73 | } 74 | cur = cur.right; 75 | } 76 | int finalRight = 1; 77 | cur = head; 78 | while (cur.right != null) { 79 | finalRight++; 80 | cur = cur.right; 81 | } 82 | if (cur.left == null && cur.right == null) { 83 | minHeight = Math.min(minHeight, finalRight); 84 | } 85 | return minHeight; 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /src/class31/Code02_FallingSquares.java: -------------------------------------------------------------------------------- 1 | package class31; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.TreeSet; 7 | 8 | public class Code02_FallingSquares { 9 | 10 | public static class SegmentTree { 11 | private int[] max; 12 | private int[] change; 13 | private boolean[] update; 14 | 15 | public SegmentTree(int size) { 16 | int N = size + 1; 17 | max = new int[N << 2]; 18 | 19 | change = new int[N << 2]; 20 | update = new boolean[N << 2]; 21 | } 22 | 23 | private void pushUp(int rt) { 24 | max[rt] = Math.max(max[rt << 1], max[rt << 1 | 1]); 25 | } 26 | 27 | // ln表示左子树元素结点个数,rn表示右子树结点个数 28 | private void pushDown(int rt, int ln, int rn) { 29 | if (update[rt]) { 30 | update[rt << 1] = true; 31 | update[rt << 1 | 1] = true; 32 | change[rt << 1] = change[rt]; 33 | change[rt << 1 | 1] = change[rt]; 34 | max[rt << 1] = change[rt]; 35 | max[rt << 1 | 1] = change[rt]; 36 | update[rt] = false; 37 | } 38 | } 39 | 40 | public void update(int L, int R, int C, int l, int r, int rt) { 41 | if (L <= l && r <= R) { 42 | update[rt] = true; 43 | change[rt] = C; 44 | max[rt] = C; 45 | return; 46 | } 47 | int mid = (l + r) >> 1; 48 | pushDown(rt, mid - l + 1, r - mid); 49 | if (L <= mid) { 50 | update(L, R, C, l, mid, rt << 1); 51 | } 52 | if (R > mid) { 53 | update(L, R, C, mid + 1, r, rt << 1 | 1); 54 | } 55 | pushUp(rt); 56 | } 57 | 58 | public int query(int L, int R, int l, int r, int rt) { 59 | if (L <= l && r <= R) { 60 | return max[rt]; 61 | } 62 | int mid = (l + r) >> 1; 63 | pushDown(rt, mid - l + 1, r - mid); 64 | int left = 0; 65 | int right = 0; 66 | if (L <= mid) { 67 | left = query(L, R, l, mid, rt << 1); 68 | } 69 | if (R > mid) { 70 | right = query(L, R, mid + 1, r, rt << 1 | 1); 71 | } 72 | return Math.max(left, right); 73 | } 74 | 75 | } 76 | 77 | public HashMap index(int[][] positions) { 78 | TreeSet pos = new TreeSet<>(); 79 | for (int[] arr : positions) { 80 | pos.add(arr[0]); 81 | pos.add(arr[0] + arr[1] - 1); 82 | } 83 | HashMap map = new HashMap<>(); 84 | int count = 0; 85 | for (Integer index : pos) { 86 | map.put(index, ++count); 87 | } 88 | return map; 89 | } 90 | 91 | public List fallingSquares(int[][] positions) { 92 | HashMap map = index(positions); 93 | int N = map.size(); 94 | SegmentTree segmentTree = new SegmentTree(N); 95 | int max = 0; 96 | List res = new ArrayList<>(); 97 | // 每落一个正方形,收集一下,所有东西组成的图像,最高高度是什么 98 | for (int[] arr : positions) { 99 | int L = map.get(arr[0]); 100 | int R = map.get(arr[0] + arr[1] - 1); 101 | int height = segmentTree.query(L, R, 1, N, 1) + arr[1]; 102 | max = Math.max(max, height); 103 | res.add(max); 104 | segmentTree.update(L, R, height, 1, N, 1); 105 | } 106 | return res; 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /src/class32/Code01_IndexTree.java: -------------------------------------------------------------------------------- 1 | package class32; 2 | 3 | public class Code01_IndexTree { 4 | 5 | // 下标从1开始! 6 | public static class IndexTree { 7 | 8 | private int[] tree; 9 | private int N; 10 | 11 | // 0位置弃而不用! 12 | public IndexTree(int size) { 13 | N = size; 14 | tree = new int[N + 1]; 15 | } 16 | 17 | // 1~index 累加和是多少? 18 | public int sum(int index) { 19 | int ret = 0; 20 | while (index > 0) { 21 | ret += tree[index]; 22 | index -= index & -index; 23 | } 24 | return ret; 25 | } 26 | 27 | // index & -index : 提取出index最右侧的1出来 28 | // index : 0011001000 29 | // index & -index : 0000001000 30 | public void add(int index, int d) { 31 | while (index <= N) { 32 | tree[index] += d; 33 | index += index & -index; 34 | } 35 | } 36 | } 37 | 38 | public static class Right { 39 | private int[] nums; 40 | private int N; 41 | 42 | public Right(int size) { 43 | N = size + 1; 44 | nums = new int[N + 1]; 45 | } 46 | 47 | public int sum(int index) { 48 | int ret = 0; 49 | for (int i = 1; i <= index; i++) { 50 | ret += nums[i]; 51 | } 52 | return ret; 53 | } 54 | 55 | public void add(int index, int d) { 56 | nums[index] += d; 57 | } 58 | 59 | } 60 | 61 | public static void main(String[] args) { 62 | int N = 100; 63 | int V = 100; 64 | int testTime = 2000000; 65 | IndexTree tree = new IndexTree(N); 66 | Right test = new Right(N); 67 | System.out.println("test begin"); 68 | for (int i = 0; i < testTime; i++) { 69 | int index = (int) (Math.random() * N) + 1; 70 | if (Math.random() <= 0.5) { 71 | int add = (int) (Math.random() * V); 72 | tree.add(index, add); 73 | test.add(index, add); 74 | } else { 75 | if (tree.sum(index) != test.sum(index)) { 76 | System.out.println("Oops!"); 77 | } 78 | } 79 | } 80 | System.out.println("test finish"); 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /src/class32/Code02_IndexTree2D.java: -------------------------------------------------------------------------------- 1 | package class32; 2 | 3 | // 测试链接:https://leetcode.com/problems/range-sum-query-2d-mutable 4 | // 但这个题是付费题目 5 | // 提交时把类名、构造函数名从Code02_IndexTree2D改成NumMatrix 6 | public class Code02_IndexTree2D { 7 | private int[][] tree; 8 | private int[][] nums; 9 | private int N; 10 | private int M; 11 | 12 | public Code02_IndexTree2D(int[][] matrix) { 13 | if (matrix.length == 0 || matrix[0].length == 0) { 14 | return; 15 | } 16 | N = matrix.length; 17 | M = matrix[0].length; 18 | tree = new int[N + 1][M + 1]; 19 | nums = new int[N][M]; 20 | for (int i = 0; i < N; i++) { 21 | for (int j = 0; j < M; j++) { 22 | update(i, j, matrix[i][j]); 23 | } 24 | } 25 | } 26 | 27 | private int sum(int row, int col) { 28 | int sum = 0; 29 | for (int i = row + 1; i > 0; i -= i & (-i)) { 30 | for (int j = col + 1; j > 0; j -= j & (-j)) { 31 | sum += tree[i][j]; 32 | } 33 | } 34 | return sum; 35 | } 36 | 37 | public void update(int row, int col, int val) { 38 | if (N == 0 || M == 0) { 39 | return; 40 | } 41 | int add = val - nums[row][col]; 42 | nums[row][col] = val; 43 | for (int i = row + 1; i <= N; i += i & (-i)) { 44 | for (int j = col + 1; j <= M; j += j & (-j)) { 45 | tree[i][j] += add; 46 | } 47 | } 48 | } 49 | 50 | public int sumRegion(int row1, int col1, int row2, int col2) { 51 | if (N == 0 || M == 0) { 52 | return 0; 53 | } 54 | return sum(row2, col2) + sum(row1 - 1, col1 - 1) - sum(row1 - 1, col2) - sum(row2, col1 - 1); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/class32/Code03_AC1.java: -------------------------------------------------------------------------------- 1 | package class32; 2 | 3 | import java.util.LinkedList; 4 | import java.util.Queue; 5 | 6 | public class Code03_AC1 { 7 | 8 | public static class Node { 9 | public int end; // 有多少个字符串以该节点结尾 10 | public Node fail; 11 | public Node[] nexts; 12 | 13 | public Node() { 14 | end = 0; 15 | fail = null; 16 | nexts = new Node[26]; 17 | } 18 | } 19 | 20 | public static class ACAutomation { 21 | private Node root; 22 | 23 | public ACAutomation() { 24 | root = new Node(); 25 | } 26 | 27 | // 你有多少个匹配串,就调用多少次insert 28 | public void insert(String s) { 29 | char[] str = s.toCharArray(); 30 | Node cur = root; 31 | int index = 0; 32 | for (int i = 0; i < str.length; i++) { 33 | index = str[i] - 'a'; 34 | if (cur.nexts[index] == null) { 35 | Node next = new Node(); 36 | cur.nexts[index] = next; 37 | } 38 | cur = cur.nexts[index]; 39 | } 40 | cur.end++; 41 | } 42 | 43 | public void build() { 44 | Queue queue = new LinkedList<>(); 45 | queue.add(root); 46 | Node cur = null; 47 | Node cfail = null; 48 | while (!queue.isEmpty()) { 49 | cur = queue.poll(); // 父 50 | for (int i = 0; i < 26; i++) { // 下级所有的路 51 | if (cur.nexts[i] != null) { // 该路下有子节点 52 | cur.nexts[i].fail = root; // 初始时先设置一个值 53 | cfail = cur.fail; 54 | while (cfail != null) { // cur不是头节点 55 | if (cfail.nexts[i] != null) { 56 | cur.nexts[i].fail = cfail.nexts[i]; 57 | break; 58 | } 59 | cfail = cfail.fail; 60 | } 61 | queue.add(cur.nexts[i]); 62 | } 63 | } 64 | } 65 | } 66 | 67 | public int containNum(String content) { 68 | char[] str = content.toCharArray(); 69 | Node cur = root; 70 | Node follow = null; 71 | int index = 0; 72 | int ans = 0; 73 | for (int i = 0; i < str.length; i++) { 74 | index = str[i] - 'a'; 75 | while (cur.nexts[index] == null && cur != root) { 76 | cur = cur.fail; 77 | } 78 | cur = cur.nexts[index] != null ? cur.nexts[index] : root; 79 | follow = cur; 80 | while (follow != root) { 81 | if (follow.end == -1) { 82 | break; 83 | } 84 | { // 不同的需求,在这一段{ }之间修改 85 | ans += follow.end; 86 | follow.end = -1; 87 | } // 不同的需求,在这一段{ }之间修改 88 | follow = follow.fail; 89 | } 90 | } 91 | return ans; 92 | } 93 | 94 | } 95 | 96 | public static void main(String[] args) { 97 | ACAutomation ac = new ACAutomation(); 98 | ac.insert("dhe"); 99 | ac.insert("he"); 100 | ac.insert("c"); 101 | ac.build(); 102 | System.out.println(ac.containNum("cdhe")); 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /src/class33/Hash.java: -------------------------------------------------------------------------------- 1 | package class33; 2 | 3 | import java.security.MessageDigest; 4 | import java.security.NoSuchAlgorithmException; 5 | import java.security.Security; 6 | 7 | // 需要自己找一下javax.xml.bind的jar,然后导入到项目 8 | import javax.xml.bind.DatatypeConverter; 9 | 10 | public class Hash { 11 | 12 | private MessageDigest hash; 13 | 14 | public Hash(String algorithm) { 15 | try { 16 | hash = MessageDigest.getInstance(algorithm); 17 | } catch (NoSuchAlgorithmException e) { 18 | e.printStackTrace(); 19 | } 20 | } 21 | 22 | public String hashCode(String input) { 23 | return DatatypeConverter.printHexBinary(hash.digest(input.getBytes())).toUpperCase(); 24 | } 25 | 26 | public static void main(String[] args) { 27 | System.out.println("支持的算法 : "); 28 | for (String str : Security.getAlgorithms("MessageDigest")) { 29 | System.out.println(str); 30 | } 31 | System.out.println("======="); 32 | 33 | String algorithm = "MD5"; 34 | Hash hash = new Hash(algorithm); 35 | 36 | String input1 = "zuochengyunzuochengyun1"; 37 | String input2 = "zuochengyunzuochengyun2"; 38 | String input3 = "zuochengyunzuochengyun3"; 39 | String input4 = "zuochengyunzuochengyun4"; 40 | String input5 = "zuochengyunzuochengyun5"; 41 | System.out.println(hash.hashCode(input1)); 42 | System.out.println(hash.hashCode(input2)); 43 | System.out.println(hash.hashCode(input3)); 44 | System.out.println(hash.hashCode(input4)); 45 | System.out.println(hash.hashCode(input5)); 46 | 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/class34/ReadMe.java: -------------------------------------------------------------------------------- 1 | // 本章并无code,因为资源限制类题目输入需要的条件较多并且真的实现代码量巨大 2 | // 面试中这类题目出现也就和面试官聊解法,不会有代码实现的要求 -------------------------------------------------------------------------------- /src/class38/Code01_AppleMinBags.java: -------------------------------------------------------------------------------- 1 | package class38; 2 | 3 | public class Code01_AppleMinBags { 4 | 5 | public static int minBags(int apple) { 6 | if (apple < 0) { 7 | return -1; 8 | } 9 | int bag8 = (apple >> 3); 10 | int rest = apple - (bag8 << 3); 11 | while(bag8 >= 0) { 12 | // rest 个 13 | if(rest % 6 ==0) { 14 | return bag8 + (rest / 6); 15 | } else { 16 | bag8--; 17 | rest += 8; 18 | } 19 | } 20 | return -1; 21 | } 22 | 23 | public static int minBagAwesome(int apple) { 24 | if ((apple & 1) != 0) { // 如果是奇数,返回-1 25 | return -1; 26 | } 27 | if (apple < 18) { 28 | return apple == 0 ? 0 : (apple == 6 || apple == 8) ? 1 29 | : (apple == 12 || apple == 14 || apple == 16) ? 2 : -1; 30 | } 31 | return (apple - 18) / 8 + 3; 32 | } 33 | 34 | public static void main(String[] args) { 35 | for(int apple = 1; apple < 200;apple++) { 36 | System.out.println(apple + " : "+ minBags(apple)); 37 | } 38 | 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/class38/Code02_EatGrass.java: -------------------------------------------------------------------------------- 1 | package class38; 2 | 3 | public class Code02_EatGrass { 4 | 5 | // 如果n份草,最终先手赢,返回"先手" 6 | // 如果n份草,最终后手赢,返回"后手" 7 | public static String whoWin(int n) { 8 | if (n < 5) { 9 | return n == 0 || n == 2 ? "后手" : "先手"; 10 | } 11 | // 进到这个过程里来,当前的先手,先选 12 | int want = 1; 13 | while (want <= n) { 14 | if (whoWin(n - want).equals("后手")) { 15 | return "先手"; 16 | } 17 | if (want <= (n / 4)) { 18 | want *= 4; 19 | } else { 20 | break; 21 | } 22 | } 23 | return "后手"; 24 | } 25 | 26 | public static String winner1(int n) { 27 | if (n < 5) { 28 | return (n == 0 || n == 2) ? "后手" : "先手"; 29 | } 30 | int base = 1; 31 | while (base <= n) { 32 | if (winner1(n - base).equals("后手")) { 33 | return "先手"; 34 | } 35 | if (base > n / 4) { // 防止base*4之后溢出 36 | break; 37 | } 38 | base *= 4; 39 | } 40 | return "后手"; 41 | } 42 | 43 | public static String winner2(int n) { 44 | if (n % 5 == 0 || n % 5 == 2) { 45 | return "后手"; 46 | } else { 47 | return "先手"; 48 | } 49 | } 50 | 51 | public static void main(String[] args) { 52 | for (int i = 0; i <= 50; i++) { 53 | System.out.println(i + " : " + whoWin(i)); 54 | } 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/class38/Code03_MSumToN.java: -------------------------------------------------------------------------------- 1 | package class38; 2 | 3 | public class Code03_MSumToN { 4 | 5 | public static boolean isMSum1(int num) { 6 | for (int start = 1; start <= num; start++) { 7 | int sum = start; 8 | for (int j = start + 1; j <= num; j++) { 9 | if (sum + j > num) { 10 | break; 11 | } 12 | if (sum + j == num) { 13 | return true; 14 | } 15 | sum += j; 16 | } 17 | } 18 | return false; 19 | } 20 | 21 | public static boolean isMSum2(int num) { 22 | // 23 | // return num == (num & (~num + 1)); 24 | // 25 | // return num == (num & (-num)); 26 | // 27 | // 28 | return (num & (num - 1)) != 0; 29 | } 30 | 31 | public static void main(String[] args) { 32 | for (int num = 1; num < 200; num++) { 33 | System.out.println(num + " : " + isMSum1(num)); 34 | } 35 | System.out.println("test begin"); 36 | for (int num = 1; num < 5000; num++) { 37 | if (isMSum1(num) != isMSum2(num)) { 38 | System.out.println("Oops!"); 39 | } 40 | } 41 | System.out.println("test end"); 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/class39/Code02_SnacksWays.java: -------------------------------------------------------------------------------- 1 | package class39; 2 | 3 | public class Code02_SnacksWays { 4 | 5 | public static int ways1(int[] arr, int w) { 6 | // arr[0...] 7 | return process(arr, 0, w); 8 | } 9 | 10 | // 从左往右的经典模型 11 | // 还剩的容量是rest,arr[index...]自由选择, 12 | // 返回选择方案 13 | // index : 0~N 14 | // rest : 0~w 15 | public static int process(int[] arr, int index, int rest) { 16 | if (rest < 0) { // 没有容量了 17 | // -1 无方案的意思 18 | return -1; 19 | } 20 | // rest>=0, 21 | if (index == arr.length) { // 无零食可选 22 | return 1; 23 | } 24 | // rest >=0 25 | // 有零食index 26 | // index号零食,要 or 不要 27 | // index, rest 28 | // (index+1, rest) 29 | // (index+1, rest-arr[i]) 30 | int next1 = process(arr, index + 1, rest); // 不要 31 | int next2 = process(arr, index + 1, rest - arr[index]); // 要 32 | return next1 + (next2 == -1 ? 0 : next2); 33 | } 34 | 35 | public static int ways2(int[] arr, int w) { 36 | int N = arr.length; 37 | int[][] dp = new int[N + 1][w + 1]; 38 | for (int j = 0; j <= w; j++) { 39 | dp[N][j] = 1; 40 | } 41 | for (int i = N - 1; i >= 0; i--) { 42 | for (int j = 0; j <= w; j++) { 43 | dp[i][j] = dp[i + 1][j] + ((j - arr[i] >= 0) ? dp[i + 1][j - arr[i]] : 0); 44 | } 45 | } 46 | return dp[0][w]; 47 | } 48 | 49 | public static int ways3(int[] arr, int w) { 50 | int N = arr.length; 51 | int[][] dp = new int[N][w + 1]; 52 | for (int i = 0; i < N; i++) { 53 | dp[i][0] = 1; 54 | } 55 | if (arr[0] <= w) { 56 | dp[0][arr[0]] = 1; 57 | } 58 | for (int i = 1; i < N; i++) { 59 | for (int j = 1; j <= w; j++) { 60 | dp[i][j] = dp[i - 1][j] + ((j - arr[i]) >= 0 ? dp[i - 1][j - arr[i]] : 0); 61 | } 62 | } 63 | int ans = 0; 64 | for (int j = 0; j <= w; j++) { 65 | ans += dp[N - 1][j]; 66 | } 67 | return ans; 68 | } 69 | 70 | public static void main(String[] args) { 71 | int[] arr = { 4, 3, 2, 9 }; 72 | int w = 8; 73 | System.out.println(ways1(arr, w)); 74 | System.out.println(ways2(arr, w)); 75 | System.out.println(ways3(arr, w)); 76 | 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/class39/Code03_10Ways.java: -------------------------------------------------------------------------------- 1 | package class39; 2 | 3 | import java.util.LinkedList; 4 | 5 | public class Code03_10Ways { 6 | 7 | public static long ways1(int N) { 8 | int zero = N; 9 | int one = N; 10 | LinkedList path = new LinkedList<>(); 11 | LinkedList> ans = new LinkedList<>(); 12 | process(zero, one, path, ans); 13 | long count = 0; 14 | for (LinkedList cur : ans) { 15 | int status = 0; 16 | for (Integer num : cur) { 17 | if (num == 0) { 18 | status++; 19 | } else { 20 | status--; 21 | } 22 | if (status < 0) { 23 | break; 24 | } 25 | } 26 | if (status == 0) { 27 | count++; 28 | } 29 | } 30 | return count; 31 | } 32 | 33 | public static void process(int zero, int one, LinkedList path, LinkedList> ans) { 34 | if (zero == 0 && one == 0) { 35 | LinkedList cur = new LinkedList<>(); 36 | for (Integer num : path) { 37 | cur.add(num); 38 | } 39 | ans.add(cur); 40 | } else { 41 | if (zero == 0) { 42 | path.addLast(1); 43 | process(zero, one - 1, path, ans); 44 | path.removeLast(); 45 | } else if (one == 0) { 46 | path.addLast(0); 47 | process(zero - 1, one, path, ans); 48 | path.removeLast(); 49 | } else { 50 | path.addLast(1); 51 | process(zero, one - 1, path, ans); 52 | path.removeLast(); 53 | path.addLast(0); 54 | process(zero - 1, one, path, ans); 55 | path.removeLast(); 56 | } 57 | } 58 | } 59 | 60 | public static long ways2(int N) { 61 | if (N < 0) { 62 | return 0; 63 | } 64 | if (N < 2) { 65 | return 1; 66 | } 67 | long a = 1; 68 | long b = 1; 69 | long limit = N << 1; 70 | for (long i = 1; i <= limit; i++) { 71 | if (i <= N) { 72 | a *= i; 73 | } else { 74 | b *= i; 75 | } 76 | } 77 | return (b / a) / (N + 1); 78 | } 79 | 80 | public static void main(String[] args) { 81 | System.out.println("test begin"); 82 | for (int i = 0; i < 10; i++) { 83 | long ans1 = ways1(i); 84 | long ans2 = ways2(i); 85 | if (ans1 != ans2) { 86 | System.out.println("Oops!"); 87 | } 88 | } 89 | System.out.println("test finish"); 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /src/class39/Code04_DifferentBTNum.java: -------------------------------------------------------------------------------- 1 | package class39; 2 | 3 | public class Code04_DifferentBTNum { 4 | 5 | // k(0) = 1, k(1) = 1 6 | // 7 | // k(n) = k(0) * k(n - 1) + k(1) * k(n - 2) + ... + k(n - 2) * k(1) + k(n - 1) * k(0) 8 | // 或者 9 | // k(n) = c(2n, n) / (n + 1) 10 | // 或者 11 | // k(n) = c(2n, n) - c(2n, n-1) 12 | 13 | public static long num1(int N) { 14 | if (N < 0) { 15 | return 0; 16 | } 17 | if (N < 2) { 18 | return 1; 19 | } 20 | long[] dp = new long[N + 1]; 21 | dp[0] = 1; 22 | dp[1] = 1; 23 | for (int i = 2; i <= N; i++) { 24 | for (int leftSize = 0; leftSize < i; leftSize++) { 25 | dp[i] += dp[leftSize] * dp[i - 1 - leftSize]; 26 | } 27 | } 28 | return dp[N]; 29 | } 30 | 31 | public static long num2(int N) { 32 | if (N < 0) { 33 | return 0; 34 | } 35 | if (N < 2) { 36 | return 1; 37 | } 38 | long a = 1; 39 | long b = 1; 40 | for (int i = 1, j = N + 1; i <= N; i++, j++) { 41 | a *= i; 42 | b *= j; 43 | long gcd = gcd(a, b); 44 | a /= gcd; 45 | b /= gcd; 46 | } 47 | return (b / a) / (N + 1); 48 | } 49 | 50 | public static long gcd(long m, long n) { 51 | return n == 0 ? m : gcd(n, m % n); 52 | } 53 | 54 | public static void main(String[] args) { 55 | System.out.println("test begin"); 56 | for (int i = 0; i < 15; i++) { 57 | long ans1 = num1(i); 58 | long ans2 = num2(i); 59 | if (ans1 != ans2) { 60 | System.out.println("Oops!"); 61 | } 62 | } 63 | System.out.println("test finish"); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/class40/Code01_LongestSumSubArrayLengthInPositiveArray.java: -------------------------------------------------------------------------------- 1 | package class40; 2 | 3 | public class Code01_LongestSumSubArrayLengthInPositiveArray { 4 | 5 | public static int getMaxLength(int[] arr, int K) { 6 | if (arr == null || arr.length == 0 || K <= 0) { 7 | return 0; 8 | } 9 | int left = 0; 10 | int right = 0; 11 | int sum = arr[0]; 12 | int len = 0; 13 | while (right < arr.length) { 14 | if (sum == K) { 15 | len = Math.max(len, right - left + 1); 16 | sum -= arr[left++]; 17 | } else if (sum < K) { 18 | right++; 19 | if (right == arr.length) { 20 | break; 21 | } 22 | sum += arr[right]; 23 | } else { 24 | sum -= arr[left++]; 25 | } 26 | } 27 | return len; 28 | } 29 | 30 | // for test 31 | public static int right(int[] arr, int K) { 32 | int max = 0; 33 | for (int i = 0; i < arr.length; i++) { 34 | for (int j = i; j < arr.length; j++) { 35 | if (valid(arr, i, j, K)) { 36 | max = Math.max(max, j - i + 1); 37 | } 38 | } 39 | } 40 | return max; 41 | } 42 | 43 | // for test 44 | public static boolean valid(int[] arr, int L, int R, int K) { 45 | int sum = 0; 46 | for (int i = L; i <= R; i++) { 47 | sum += arr[i]; 48 | } 49 | return sum == K; 50 | } 51 | 52 | // for test 53 | public static int[] generatePositiveArray(int size, int value) { 54 | int[] ans = new int[size]; 55 | for (int i = 0; i != size; i++) { 56 | ans[i] = (int) (Math.random() * value) + 1; 57 | } 58 | return ans; 59 | } 60 | 61 | // for test 62 | public static void printArray(int[] arr) { 63 | for (int i = 0; i != arr.length; i++) { 64 | System.out.print(arr[i] + " "); 65 | } 66 | System.out.println(); 67 | } 68 | 69 | public static void main(String[] args) { 70 | int len = 50; 71 | int value = 100; 72 | int testTime = 500000; 73 | System.out.println("test begin"); 74 | for (int i = 0; i < testTime; i++) { 75 | int[] arr = generatePositiveArray(len, value); 76 | int K = (int) (Math.random() * value) + 1; 77 | int ans1 = getMaxLength(arr, K); 78 | int ans2 = right(arr, K); 79 | if (ans1 != ans2) { 80 | System.out.println("Oops!"); 81 | printArray(arr); 82 | System.out.println("K : " + K); 83 | System.out.println(ans1); 84 | System.out.println(ans2); 85 | break; 86 | } 87 | } 88 | System.out.println("test end"); 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/class40/Code02_LongestSumSubArrayLength.java: -------------------------------------------------------------------------------- 1 | package class40; 2 | 3 | import java.util.HashMap; 4 | 5 | public class Code02_LongestSumSubArrayLength { 6 | 7 | public static int maxLength(int[] arr, int k) { 8 | if (arr == null || arr.length == 0) { 9 | return 0; 10 | } 11 | // key:前缀和 12 | // value : 0~value这个前缀和是最早出现key这个值的 13 | HashMap map = new HashMap(); 14 | map.put(0, -1); // important 15 | int len = 0; 16 | int sum = 0; 17 | for (int i = 0; i < arr.length; i++) { 18 | sum += arr[i]; 19 | if (map.containsKey(sum - k)) { 20 | len = Math.max(i - map.get(sum - k), len); 21 | } 22 | if (!map.containsKey(sum)) { 23 | map.put(sum, i); 24 | } 25 | } 26 | return len; 27 | } 28 | 29 | // for test 30 | public static int right(int[] arr, int K) { 31 | int max = 0; 32 | for (int i = 0; i < arr.length; i++) { 33 | for (int j = i; j < arr.length; j++) { 34 | if (valid(arr, i, j, K)) { 35 | max = Math.max(max, j - i + 1); 36 | } 37 | } 38 | } 39 | return max; 40 | } 41 | 42 | // for test 43 | public static boolean valid(int[] arr, int L, int R, int K) { 44 | int sum = 0; 45 | for (int i = L; i <= R; i++) { 46 | sum += arr[i]; 47 | } 48 | return sum == K; 49 | } 50 | 51 | // for test 52 | public static int[] generateRandomArray(int size, int value) { 53 | int[] ans = new int[(int) (Math.random() * size) + 1]; 54 | for (int i = 0; i < ans.length; i++) { 55 | ans[i] = (int) (Math.random() * value) - (int) (Math.random() * value); 56 | } 57 | return ans; 58 | } 59 | 60 | // for test 61 | public static void printArray(int[] arr) { 62 | for (int i = 0; i != arr.length; i++) { 63 | System.out.print(arr[i] + " "); 64 | } 65 | System.out.println(); 66 | } 67 | 68 | public static void main(String[] args) { 69 | int len = 50; 70 | int value = 100; 71 | int testTime = 500000; 72 | 73 | System.out.println("test begin"); 74 | for (int i = 0; i < testTime; i++) { 75 | int[] arr = generateRandomArray(len, value); 76 | int K = (int) (Math.random() * value) - (int) (Math.random() * value); 77 | int ans1 = maxLength(arr, K); 78 | int ans2 = right(arr, K); 79 | if (ans1 != ans2) { 80 | System.out.println("Oops!"); 81 | printArray(arr); 82 | System.out.println("K : " + K); 83 | System.out.println(ans1); 84 | System.out.println(ans2); 85 | break; 86 | } 87 | } 88 | System.out.println("test end"); 89 | 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /src/class40/Code03_LongestLessSumSubArrayLength.java: -------------------------------------------------------------------------------- 1 | package class40; 2 | 3 | public class Code03_LongestLessSumSubArrayLength { 4 | 5 | public static int maxLengthAwesome(int[] arr, int k) { 6 | if (arr == null || arr.length == 0) { 7 | return 0; 8 | } 9 | int[] minSums = new int[arr.length]; 10 | int[] minSumEnds = new int[arr.length]; 11 | minSums[arr.length - 1] = arr[arr.length - 1]; 12 | minSumEnds[arr.length - 1] = arr.length - 1; 13 | for (int i = arr.length - 2; i >= 0; i--) { 14 | if (minSums[i + 1] < 0) { 15 | minSums[i] = arr[i] + minSums[i + 1]; 16 | minSumEnds[i] = minSumEnds[i + 1]; 17 | } else { 18 | minSums[i] = arr[i]; 19 | minSumEnds[i] = i; 20 | } 21 | } 22 | // 迟迟扩不进来那一块儿的开头位置 23 | int end = 0; 24 | int sum = 0; 25 | int ans = 0; 26 | for (int i = 0; i < arr.length; i++) { 27 | // while循环结束之后: 28 | // 1) 如果以i开头的情况下,累加和<=k的最长子数组是arr[i..end-1],看看这个子数组长度能不能更新res; 29 | // 2) 如果以i开头的情况下,累加和<=k的最长子数组比arr[i..end-1]短,更新还是不更新res都不会影响最终结果; 30 | while (end < arr.length && sum + minSums[end] <= k) { 31 | sum += minSums[end]; 32 | end = minSumEnds[end] + 1; 33 | } 34 | ans = Math.max(ans, end - i); 35 | if (end > i) { // 还有窗口,哪怕窗口没有数字 [i~end) [4,4) 36 | sum -= arr[i]; 37 | } else { // i == end, 即将 i++, i > end, 此时窗口概念维持不住了,所以end跟着i一起走 38 | end = i + 1; 39 | } 40 | } 41 | return ans; 42 | } 43 | 44 | public static int maxLength(int[] arr, int k) { 45 | int[] h = new int[arr.length + 1]; 46 | int sum = 0; 47 | h[0] = sum; 48 | for (int i = 0; i != arr.length; i++) { 49 | sum += arr[i]; 50 | h[i + 1] = Math.max(sum, h[i]); 51 | } 52 | sum = 0; 53 | int res = 0; 54 | int pre = 0; 55 | int len = 0; 56 | for (int i = 0; i != arr.length; i++) { 57 | sum += arr[i]; 58 | pre = getLessIndex(h, sum - k); 59 | len = pre == -1 ? 0 : i - pre + 1; 60 | res = Math.max(res, len); 61 | } 62 | return res; 63 | } 64 | 65 | public static int getLessIndex(int[] arr, int num) { 66 | int low = 0; 67 | int high = arr.length - 1; 68 | int mid = 0; 69 | int res = -1; 70 | while (low <= high) { 71 | mid = (low + high) / 2; 72 | if (arr[mid] >= num) { 73 | res = mid; 74 | high = mid - 1; 75 | } else { 76 | low = mid + 1; 77 | } 78 | } 79 | return res; 80 | } 81 | 82 | // for test 83 | public static int[] generateRandomArray(int len, int maxValue) { 84 | int[] res = new int[len]; 85 | for (int i = 0; i != res.length; i++) { 86 | res[i] = (int) (Math.random() * maxValue) - (maxValue / 3); 87 | } 88 | return res; 89 | } 90 | 91 | public static void main(String[] args) { 92 | System.out.println("test begin"); 93 | for (int i = 0; i < 10000000; i++) { 94 | int[] arr = generateRandomArray(10, 20); 95 | int k = (int) (Math.random() * 20) - 5; 96 | if (maxLengthAwesome(arr, k) != maxLength(arr, k)) { 97 | System.out.println("Oops!"); 98 | } 99 | } 100 | System.out.println("test finish"); 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /src/class40/Code05_PrintMatrixSpiralOrder.java: -------------------------------------------------------------------------------- 1 | package class40; 2 | 3 | public class Code05_PrintMatrixSpiralOrder { 4 | 5 | public static void spiralOrderPrint(int[][] matrix) { 6 | int tR = 0; 7 | int tC = 0; 8 | int dR = matrix.length - 1; 9 | int dC = matrix[0].length - 1; 10 | while (tR <= dR && tC <= dC) { 11 | printEdge(matrix, tR++, tC++, dR--, dC--); 12 | } 13 | } 14 | 15 | public static void printEdge(int[][] m, int tR, int tC, int dR, int dC) { 16 | if (tR == dR) { 17 | for (int i = tC; i <= dC; i++) { 18 | System.out.print(m[tR][i] + " "); 19 | } 20 | } else if (tC == dC) { 21 | for (int i = tR; i <= dR; i++) { 22 | System.out.print(m[i][tC] + " "); 23 | } 24 | } else { 25 | int curC = tC; 26 | int curR = tR; 27 | while (curC != dC) { 28 | System.out.print(m[tR][curC] + " "); 29 | curC++; 30 | } 31 | while (curR != dR) { 32 | System.out.print(m[curR][dC] + " "); 33 | curR++; 34 | } 35 | while (curC != tC) { 36 | System.out.print(m[dR][curC] + " "); 37 | curC--; 38 | } 39 | while (curR != tR) { 40 | System.out.print(m[curR][tC] + " "); 41 | curR--; 42 | } 43 | } 44 | } 45 | 46 | public static void main(String[] args) { 47 | int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 }, 48 | { 13, 14, 15, 16 } }; 49 | spiralOrderPrint(matrix); 50 | 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/class40/Code06_RotateMatrix.java: -------------------------------------------------------------------------------- 1 | package class40; 2 | 3 | public class Code06_RotateMatrix { 4 | 5 | public static void rotate(int[][] matrix) { 6 | int a = 0; 7 | int b = 0; 8 | int c = matrix.length - 1; 9 | int d = matrix[0].length - 1; 10 | while (a < c) { 11 | rotateEdge(matrix, a++, b++, c--, d--); 12 | } 13 | } 14 | 15 | public static void rotateEdge(int[][] m, int a, int b, int c, int d) { 16 | int tmp = 0; 17 | for (int i = 0; i < d - b; i++) { 18 | tmp = m[a][b + i]; 19 | m[a][b + i] = m[c - i][b]; 20 | m[c - i][b] = m[c][d - i]; 21 | m[c][d - i] = m[a + i][d]; 22 | m[a + i][d] = tmp; 23 | } 24 | } 25 | 26 | public static void printMatrix(int[][] matrix) { 27 | for (int i = 0; i != matrix.length; i++) { 28 | for (int j = 0; j != matrix[0].length; j++) { 29 | System.out.print(matrix[i][j] + " "); 30 | } 31 | System.out.println(); 32 | } 33 | } 34 | 35 | public static void main(String[] args) { 36 | int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 }, { 13, 14, 15, 16 } }; 37 | printMatrix(matrix); 38 | rotate(matrix); 39 | System.out.println("========="); 40 | printMatrix(matrix); 41 | 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/class40/Code07_ZigZagPrintMatrix.java: -------------------------------------------------------------------------------- 1 | package class40; 2 | 3 | public class Code07_ZigZagPrintMatrix { 4 | 5 | public static void printMatrixZigZag(int[][] matrix) { 6 | int tR = 0; 7 | int tC = 0; 8 | int dR = 0; 9 | int dC = 0; 10 | int endR = matrix.length - 1; 11 | int endC = matrix[0].length - 1; 12 | boolean fromUp = false; 13 | while (tR != endR + 1) { 14 | printLevel(matrix, tR, tC, dR, dC, fromUp); 15 | tR = tC == endC ? tR + 1 : tR; 16 | tC = tC == endC ? tC : tC + 1; 17 | dC = dR == endR ? dC + 1 : dC; 18 | dR = dR == endR ? dR : dR + 1; 19 | fromUp = !fromUp; 20 | } 21 | System.out.println(); 22 | } 23 | 24 | public static void printLevel(int[][] m, int tR, int tC, int dR, int dC, boolean f) { 25 | if (f) { 26 | while (tR != dR + 1) { 27 | System.out.print(m[tR++][tC--] + " "); 28 | } 29 | } else { 30 | while (dR != tR - 1) { 31 | System.out.print(m[dR--][dC++] + " "); 32 | } 33 | } 34 | } 35 | 36 | public static void main(String[] args) { 37 | int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } }; 38 | printMatrixZigZag(matrix); 39 | 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/class40/Code08_PrintStar.java: -------------------------------------------------------------------------------- 1 | package class40; 2 | 3 | public class Code08_PrintStar { 4 | 5 | public static void printStar(int N) { 6 | int leftUp = 0; 7 | int rightDown = N - 1; 8 | char[][] m = new char[N][N]; 9 | for (int i = 0; i < N; i++) { 10 | for (int j = 0; j < N; j++) { 11 | m[i][j] = ' '; 12 | } 13 | } 14 | while (leftUp <= rightDown) { 15 | set(m, leftUp, rightDown); 16 | leftUp += 2; 17 | rightDown -= 2; 18 | } 19 | for (int i = 0; i < N; i++) { 20 | for (int j = 0; j < N; j++) { 21 | System.out.print(m[i][j] + " "); 22 | } 23 | System.out.println(); 24 | } 25 | } 26 | 27 | public static void set(char[][] m, int leftUp, int rightDown) { 28 | for (int col = leftUp; col <= rightDown; col++) { 29 | m[leftUp][col] = '*'; 30 | } 31 | for (int row = leftUp + 1; row <= rightDown; row++) { 32 | m[row][rightDown] = '*'; 33 | } 34 | for (int col = rightDown - 1; col > leftUp; col--) { 35 | m[rightDown][col] = '*'; 36 | } 37 | for (int row = rightDown - 1; row > leftUp + 1; row--) { 38 | m[row][leftUp + 1] = '*'; 39 | } 40 | } 41 | 42 | public static void main(String[] args) { 43 | printStar(5); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/class41/Code01_BestSplitForAll.java: -------------------------------------------------------------------------------- 1 | package class41; 2 | 3 | public class Code01_BestSplitForAll { 4 | 5 | public static int bestSplit1(int[] arr) { 6 | if (arr == null || arr.length < 2) { 7 | return 0; 8 | } 9 | int N = arr.length; 10 | int ans = 0; 11 | for (int s = 0; s < N - 1; s++) { 12 | int sumL = 0; 13 | for (int L = 0; L <= s; L++) { 14 | sumL += arr[L]; 15 | } 16 | int sumR = 0; 17 | for (int R = s + 1; R < N; R++) { 18 | sumR += arr[R]; 19 | } 20 | ans = Math.max(ans, Math.min(sumL, sumR)); 21 | } 22 | return ans; 23 | } 24 | 25 | public static int bestSplit2(int[] arr) { 26 | if (arr == null || arr.length < 2) { 27 | return 0; 28 | } 29 | int N = arr.length; 30 | int sumAll = 0; 31 | for (int num : arr) { 32 | sumAll += num; 33 | } 34 | int ans = 0; 35 | int sumL = 0; 36 | // [0...s] [s+1...N-1] 37 | for (int s = 0; s < N - 1; s++) { 38 | sumL += arr[s]; 39 | int sumR = sumAll - sumL; 40 | ans = Math.max(ans, Math.min(sumL, sumR)); 41 | } 42 | return ans; 43 | } 44 | 45 | public static int[] randomArray(int len, int max) { 46 | int[] ans = new int[len]; 47 | for (int i = 0; i < len; i++) { 48 | ans[i] = (int) (Math.random() * max); 49 | } 50 | return ans; 51 | } 52 | 53 | public static void main(String[] args) { 54 | int N = 20; 55 | int max = 30; 56 | int testTime = 1000000; 57 | System.out.println("测试开始"); 58 | for (int i = 0; i < testTime; i++) { 59 | int len = (int) (Math.random() * N); 60 | int[] arr = randomArray(len, max); 61 | int ans1 = bestSplit1(arr); 62 | int ans2 = bestSplit2(arr); 63 | if (ans1 != ans2) { 64 | System.out.println(ans1); 65 | System.out.println(ans2); 66 | System.out.println("Oops!"); 67 | } 68 | } 69 | System.out.println("测试结束"); 70 | } 71 | 72 | } -------------------------------------------------------------------------------- /src/class43/Code01_CanIWin.java: -------------------------------------------------------------------------------- 1 | package class43; 2 | 3 | // leetcode 464题 4 | public class Code01_CanIWin { 5 | 6 | // 1~choose 拥有的数字 7 | // total 一开始的剩余 8 | // 返回先手会不会赢 9 | public static boolean canIWin0(int choose, int total) { 10 | if (total == 0) { 11 | return true; 12 | } 13 | if ((choose * (choose + 1) >> 1) < total) { 14 | return false; 15 | } 16 | int[] arr = new int[choose]; 17 | for (int i = 0; i < choose; i++) { 18 | arr[i] = i + 1; 19 | } 20 | // arr[i] != -1 表示arr[i]这个数字还没被拿走 21 | // arr[i] == -1 表示arr[i]这个数字已经被拿走 22 | // 集合,arr,1~choose 23 | return process(arr, total); 24 | } 25 | 26 | // 当前轮到先手拿, 27 | // 先手只能选择在arr中还存在的数字, 28 | // 还剩rest这么值, 29 | // 返回先手会不会赢 30 | public static boolean process(int[] arr, int rest) { 31 | if (rest <= 0) { 32 | return false; 33 | } 34 | // 先手去尝试所有的情况 35 | for (int i = 0; i < arr.length; i++) { 36 | if (arr[i] != -1) { 37 | int cur = arr[i]; 38 | arr[i] = -1; 39 | boolean next = process(arr, rest - cur); 40 | arr[i] = cur; 41 | if (!next) { 42 | return true; 43 | } 44 | } 45 | } 46 | return false; 47 | } 48 | 49 | // 这个是暴力尝试,思路是正确的,超时而已 50 | public static boolean canIWin1(int choose, int total) { 51 | if (total == 0) { 52 | return true; 53 | } 54 | if ((choose * (choose + 1) >> 1) < total) { 55 | return false; 56 | } 57 | return process1(choose, 0, total); 58 | } 59 | 60 | // 当前轮到先手拿, 61 | // 先手可以拿1~choose中的任何一个数字 62 | // status i位如果为0,代表没拿,当前可以拿 63 | // i位为1,代表已经拿过了,当前不能拿 64 | // 还剩rest这么值, 65 | // 返回先手会不会赢 66 | public static boolean process1(int choose, int status, int rest) { 67 | if (rest <= 0) { 68 | return false; 69 | } 70 | for (int i = 1; i <= choose; i++) { 71 | if (((1 << i) & status) == 0) { // i 这个数字,是此时先手的决定! 72 | if (!process1(choose, (status | (1 << i)), rest - i)) { 73 | return true; 74 | } 75 | } 76 | } 77 | return false; 78 | } 79 | 80 | // 暴力尝试改动态规划而已 81 | public static boolean canIWin2(int choose, int total) { 82 | if (total == 0) { 83 | return true; 84 | } 85 | if ((choose * (choose + 1) >> 1) < total) { 86 | return false; 87 | } 88 | int[] dp = new int[1 << (choose + 1)]; 89 | // dp[status] == 1 true 90 | // dp[status] == -1 false 91 | // dp[status] == 0 process(status) 没算过!去算! 92 | return process2(choose, 0, total, dp); 93 | } 94 | 95 | // 为什么明明status和rest是两个可变参数,却只用status来代表状态(也就是dp) 96 | // 因为选了一批数字之后,得到的和一定是一样的,所以rest是由status决定的,所以rest不需要参与记忆化搜索 97 | public static boolean process2(int choose, int status, int rest, int[] dp) { 98 | if (dp[status] != 0) { 99 | return dp[status] == 1 ? true : false; 100 | } 101 | boolean ans = false; 102 | if (rest > 0) { 103 | for (int i = 1; i <= choose; i++) { 104 | if (((1 << i) & status) == 0) { 105 | if (!process2(choose, (status | (1 << i)), rest - i, dp)) { 106 | ans = true; 107 | break; 108 | } 109 | } 110 | } 111 | } 112 | dp[status] = ans ? 1 : -1; 113 | return ans; 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /src/class43/Code03_PavingTile1.java: -------------------------------------------------------------------------------- 1 | package class43; 2 | 3 | // 找到了贴瓷砖问题在线测试 4 | // 测试链接 : http://poj.org/problem?id=2411 5 | // 注册一个北京大学评测平台的号 6 | // 请同学们务必参考如下代码中关于输入、输出的处理 7 | // 这是输入输出处理效率很高的写法 8 | // 提交以下的code,提交时请把类名改成"Main" 9 | 10 | import java.io.BufferedReader; 11 | import java.io.IOException; 12 | import java.io.InputStreamReader; 13 | import java.io.OutputStreamWriter; 14 | import java.io.PrintWriter; 15 | import java.io.StreamTokenizer; 16 | 17 | // 本文件是状态压缩的动态规划版本,也就是课上讲的版本 18 | public class Code03_PavingTile1 { 19 | 20 | public static void main(String[] args) throws IOException { 21 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 22 | StreamTokenizer in = new StreamTokenizer(br); 23 | PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out)); 24 | while (in.nextToken() != StreamTokenizer.TT_EOF) { 25 | int n = (int) in.nval; 26 | in.nextToken(); 27 | int m = (int) in.nval; 28 | if (n != 0 || m != 0) { 29 | long ans = ways(n, m); 30 | out.println(ans); 31 | out.flush(); 32 | } 33 | } 34 | } 35 | 36 | // 状态压缩动态规划,最后一个版本 37 | // 其实其他版本也能通过 38 | public static long ways(int N, int M) { 39 | if (N < 1 || M < 1 || ((N * M) & 1) != 0) { 40 | return 0; 41 | } 42 | if (N == 1 || M == 1) { 43 | return 1; 44 | } 45 | int big = N > M ? N : M; 46 | int small = big == N ? M : N; 47 | int sn = 1 << small; 48 | int limit = sn - 1; 49 | long[] dp = new long[sn]; 50 | dp[limit] = 1; 51 | long[] cur = new long[sn]; 52 | for (int level = 0; level < big; level++) { 53 | for (int status = 0; status < sn; status++) { 54 | if (dp[status] != 0) { 55 | int op = (~status) & limit; 56 | dfs(dp[status], op, 0, small - 1, cur); 57 | } 58 | } 59 | for (int i = 0; i < sn; i++) { 60 | dp[i] = 0; 61 | } 62 | long[] tmp = dp; 63 | dp = cur; 64 | cur = tmp; 65 | } 66 | return dp[limit]; 67 | } 68 | 69 | public static void dfs(long way, int op, int index, int end, long[] cur) { 70 | if (index == end) { 71 | cur[op] += way; 72 | } else { 73 | dfs(way, op, index + 1, end, cur); 74 | if (((3 << index) & op) == 0) { 75 | dfs(way, op | (3 << index), index + 1, end, cur); 76 | } 77 | } 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/class43/Code03_PavingTile2.java: -------------------------------------------------------------------------------- 1 | package class43; 2 | 3 | // 找到了贴瓷砖问题在线测试 4 | // 测试链接 : http://poj.org/problem?id=2411 5 | // 注册一个北京大学评测平台的号 6 | // 请同学们务必参考如下代码中关于输入、输出的处理 7 | // 这是输入输出处理效率很高的写法 8 | // 提交以下的code,提交时请把类名改成"Main" 9 | import java.io.BufferedReader; 10 | import java.io.IOException; 11 | import java.io.InputStreamReader; 12 | import java.io.OutputStreamWriter; 13 | import java.io.PrintWriter; 14 | import java.io.StreamTokenizer; 15 | 16 | // 本文件是轮廓线dp的版本,轮廓线dp的讲解在每周直播课 : 17 | // 2022年9月第4周的课,看了就能懂 18 | // 这是很难的一类题型,不做要求,大厂几乎不考 19 | public class Code03_PavingTile2 { 20 | 21 | public static void main(String[] args) throws IOException { 22 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 23 | StreamTokenizer in = new StreamTokenizer(br); 24 | PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out)); 25 | while (in.nextToken() != StreamTokenizer.TT_EOF) { 26 | int n = (int) in.nval; 27 | in.nextToken(); 28 | int m = (int) in.nval; 29 | if (n != 0 || m != 0) { 30 | long ans = ways(n, m); 31 | out.println(ans); 32 | out.flush(); 33 | } 34 | } 35 | } 36 | 37 | // 轮廓线dp的版本 38 | // 看课,上面说了看哪的 39 | public static int MAXN = 12; 40 | 41 | public static int MAXM = (1 << MAXN); 42 | 43 | public static long[][][] dp = new long[MAXN][MAXN][MAXM]; 44 | 45 | public static long ways(int n, int m) { 46 | for (int i = 0; i <= n; i++) { 47 | for (int j = 0; j <= m; j++) { 48 | for (int k = 0; k <= (1 << m); k++) { 49 | dp[i][j][k] = -1; 50 | } 51 | } 52 | } 53 | return process(0, 0, 0, n, m); 54 | } 55 | 56 | public static long process(int r, int c, int s, int n, int m) { 57 | if (r == n) { 58 | return s == 0 ? 1 : 0; 59 | } 60 | if (c == m) { 61 | return process(r + 1, 0, s, n, m); 62 | } 63 | if (dp[r][c][s] != -1) { 64 | return dp[r][c][s]; 65 | } 66 | long ans; 67 | int cur = (s & (1 << c)) == 0 ? 0 : 1; 68 | if (cur == 1) { 69 | ans = process(r, c + 1, s ^ (1 << c), n, m); 70 | } else { 71 | long p1 = process(r, c + 1, s | (1 << c), n, m); 72 | long next = c + 1 < m && (s & (1 << (c + 1))) == 0 ? 0 : 1; 73 | long p2 = 0; 74 | if (next == 0) { 75 | p2 = process(r, c + 2, s, n, m); 76 | } 77 | ans = p1 + p2; 78 | } 79 | dp[r][c][s] = ans; 80 | return ans; 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /src/class44/DC3_Algorithm.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/algorithmzuo/algorithmbasic2020/c71953ac3d72158e25ee32435a76d7ece5a09170/src/class44/DC3_Algorithm.pdf -------------------------------------------------------------------------------- /src/class46/Code02_RemoveBoxes.java: -------------------------------------------------------------------------------- 1 | package class46; 2 | 3 | // 本题测试链接 : https://leetcode.com/problems/remove-boxes/ 4 | public class Code02_RemoveBoxes { 5 | 6 | // arr[L...R]消除,而且前面跟着K个arr[L]这个数 7 | // 返回:所有东西都消掉,最大得分 8 | public static int func1(int[] arr, int L, int R, int K) { 9 | if (L > R) { 10 | return 0; 11 | } 12 | int ans = func1(arr, L + 1, R, 0) + (K + 1) * (K + 1); 13 | 14 | // 前面的K个X,和arr[L]数,合在一起了,现在有K+1个arr[L]位置的数 15 | for (int i = L + 1; i <= R; i++) { 16 | if (arr[i] == arr[L]) { 17 | ans = Math.max(ans, func1(arr, L + 1, i - 1, 0) + func1(arr, i, R, K + 1)); 18 | } 19 | } 20 | return ans; 21 | } 22 | 23 | public static int removeBoxes1(int[] boxes) { 24 | int N = boxes.length; 25 | int[][][] dp = new int[N][N][N]; 26 | int ans = process1(boxes, 0, N - 1, 0, dp); 27 | return ans; 28 | } 29 | 30 | public static int process1(int[] boxes, int L, int R, int K, int[][][] dp) { 31 | if (L > R) { 32 | return 0; 33 | } 34 | if (dp[L][R][K] > 0) { 35 | return dp[L][R][K]; 36 | } 37 | int ans = process1(boxes, L + 1, R, 0, dp) + (K + 1) * (K + 1); 38 | for (int i = L + 1; i <= R; i++) { 39 | if (boxes[i] == boxes[L]) { 40 | ans = Math.max(ans, process1(boxes, L + 1, i - 1, 0, dp) + process1(boxes, i, R, K + 1, dp)); 41 | } 42 | } 43 | dp[L][R][K] = ans; 44 | return ans; 45 | } 46 | 47 | public static int removeBoxes2(int[] boxes) { 48 | int N = boxes.length; 49 | int[][][] dp = new int[N][N][N]; 50 | int ans = process2(boxes, 0, N - 1, 0, dp); 51 | return ans; 52 | } 53 | 54 | public static int process2(int[] boxes, int L, int R, int K, int[][][] dp) { 55 | if (L > R) { 56 | return 0; 57 | } 58 | if (dp[L][R][K] > 0) { 59 | return dp[L][R][K]; 60 | } 61 | // 找到开头, 62 | // 1,1,1,1,1,5 63 | // 3 4 5 6 7 8 64 | // ! 65 | int last = L; 66 | while (last + 1 <= R && boxes[last + 1] == boxes[L]) { 67 | last++; 68 | } 69 | // K个1 (K + last - L) last 70 | int pre = K + last - L; 71 | int ans = (pre + 1) * (pre + 1) + process2(boxes, last + 1, R, 0, dp); 72 | for (int i = last + 2; i <= R; i++) { 73 | if (boxes[i] == boxes[L] && boxes[i - 1] != boxes[L]) { 74 | ans = Math.max(ans, process2(boxes, last + 1, i - 1, 0, dp) + process2(boxes, i, R, pre + 1, dp)); 75 | } 76 | } 77 | dp[L][R][K] = ans; 78 | return ans; 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/class46/Code04_MaxSumLengthNoMore.java: -------------------------------------------------------------------------------- 1 | package class46; 2 | 3 | import java.util.LinkedList; 4 | 5 | // 给定一个数组arr,和一个正数M 6 | // 返回在子数组长度不大于M的情况下,最大的子数组累加和 7 | public class Code04_MaxSumLengthNoMore { 8 | 9 | // O(N^2)的解法,暴力解,用作对数器 10 | public static int test(int[] arr, int M) { 11 | if (arr == null || arr.length == 0 || M < 1) { 12 | return 0; 13 | } 14 | int N = arr.length; 15 | int max = Integer.MIN_VALUE; 16 | for (int L = 0; L < N; L++) { 17 | int sum = 0; 18 | for (int R = L; R < N; R++) { 19 | if (R - L + 1 > M) { 20 | break; 21 | } 22 | sum += arr[R]; 23 | max = Math.max(max, sum); 24 | } 25 | } 26 | return max; 27 | } 28 | 29 | // O(N)的解法,最优解 30 | public static int maxSum(int[] arr, int M) { 31 | if (arr == null || arr.length == 0 || M < 1) { 32 | return 0; 33 | } 34 | int N = arr.length; 35 | int[] sum = new int[N]; 36 | sum[0] = arr[0]; 37 | for (int i = 1; i < N; i++) { 38 | sum[i] = sum[i - 1] + arr[i]; 39 | } 40 | LinkedList qmax = new LinkedList<>(); 41 | int i = 0; 42 | int end = Math.min(N, M); 43 | for (; i < end; i++) { 44 | while (!qmax.isEmpty() && sum[qmax.peekLast()] <= sum[i]) { 45 | qmax.pollLast(); 46 | } 47 | qmax.add(i); 48 | } 49 | int max = sum[qmax.peekFirst()]; 50 | int L = 0; 51 | for (; i < N; L++, i++) { 52 | if (qmax.peekFirst() == L) { 53 | qmax.pollFirst(); 54 | } 55 | while (!qmax.isEmpty() && sum[qmax.peekLast()] <= sum[i]) { 56 | qmax.pollLast(); 57 | } 58 | qmax.add(i); 59 | max = Math.max(max, sum[qmax.peekFirst()] - sum[L]); 60 | } 61 | for (; L < N - 1; L++) { 62 | if (qmax.peekFirst() == L) { 63 | qmax.pollFirst(); 64 | } 65 | max = Math.max(max, sum[qmax.peekFirst()] - sum[L]); 66 | } 67 | return max; 68 | } 69 | 70 | // 用作测试 71 | public static int[] randomArray(int len, int max) { 72 | int[] arr = new int[len]; 73 | for (int i = 0; i < len; i++) { 74 | arr[i] = (int) (Math.random() * max) - (int) (Math.random() * max); 75 | } 76 | return arr; 77 | } 78 | 79 | // 用作测试 80 | public static void main(String[] args) { 81 | int maxN = 50; 82 | int maxValue = 100; 83 | int testTime = 1000000; 84 | System.out.println("测试开始"); 85 | for (int i = 0; i < testTime; i++) { 86 | int N = (int) (Math.random() * maxN); 87 | int M = (int) (Math.random() * maxN); 88 | int[] arr = randomArray(N, maxValue); 89 | int ans1 = test(arr, M); 90 | int ans2 = maxSum(arr, M); 91 | if (ans1 != ans2) { 92 | System.out.println(ans1); 93 | System.out.println(ans2); 94 | System.out.println("Oops!"); 95 | } 96 | } 97 | System.out.println("测试结束"); 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/class47/Code01_StrangePrinter.java: -------------------------------------------------------------------------------- 1 | package class47; 2 | 3 | // 本题测试链接 : https://leetcode.com/problems/strange-printer/ 4 | public class Code01_StrangePrinter { 5 | 6 | public static int strangePrinter1(String s) { 7 | if (s == null || s.length() == 0) { 8 | return 0; 9 | } 10 | char[] str = s.toCharArray(); 11 | return process1(str, 0, str.length - 1); 12 | } 13 | 14 | // 要想刷出str[L...R]的样子! 15 | // 返回最少的转数 16 | public static int process1(char[] str, int L, int R) { 17 | if (L == R) { 18 | return 1; 19 | } 20 | // L...R 21 | int ans = R - L + 1; 22 | for (int k = L + 1; k <= R; k++) { 23 | // L...k-1 k....R 24 | ans = Math.min(ans, process1(str, L, k - 1) + process1(str, k, R) - (str[L] == str[k] ? 1 : 0)); 25 | } 26 | return ans; 27 | } 28 | 29 | public static int strangePrinter2(String s) { 30 | if (s == null || s.length() == 0) { 31 | return 0; 32 | } 33 | char[] str = s.toCharArray(); 34 | int N = str.length; 35 | int[][] dp = new int[N][N]; 36 | return process2(str, 0, N - 1, dp); 37 | } 38 | 39 | public static int process2(char[] str, int L, int R, int[][] dp) { 40 | if (dp[L][R] != 0) { 41 | return dp[L][R]; 42 | } 43 | int ans = R - L + 1; 44 | if (L == R) { 45 | ans = 1; 46 | } else { 47 | for (int k = L + 1; k <= R; k++) { 48 | ans = Math.min(ans, process2(str, L, k - 1, dp) + process2(str, k, R, dp) - (str[L] == str[k] ? 1 : 0)); 49 | } 50 | } 51 | dp[L][R] = ans; 52 | return ans; 53 | } 54 | 55 | public static int strangePrinter3(String s) { 56 | if (s == null || s.length() == 0) { 57 | return 0; 58 | } 59 | char[] str = s.toCharArray(); 60 | int N = str.length; 61 | int[][] dp = new int[N][N]; 62 | dp[N - 1][N - 1] = 1; 63 | for (int i = 0; i < N - 1; i++) { 64 | dp[i][i] = 1; 65 | dp[i][i + 1] = str[i] == str[i + 1] ? 1 : 2; 66 | } 67 | for (int L = N - 3; L >= 0; L--) { 68 | for (int R = L + 2; R < N; R++) { 69 | dp[L][R] = R - L + 1; 70 | for (int k = L + 1; k <= R; k++) { 71 | dp[L][R] = Math.min(dp[L][R], dp[L][k - 1] + dp[k][R] - (str[L] == str[k] ? 1 : 0)); 72 | } 73 | } 74 | } 75 | return dp[0][N - 1]; 76 | } 77 | 78 | } 79 | --------------------------------------------------------------------------------