├── README.md └── src ├── class01 ├── Code01_CordCoverMaxPoint.java ├── Code02_CountFiles.java ├── Code03_Near2Power.java ├── Code04_MinSwapStep.java ├── Code05_LongestIncreasingPath.java ├── Code06_AOE.java └── Code07_TargetSum.java ├── class02 ├── Code01_ChooseWork.java ├── Code02_Cola.java ├── Code03_ReceiveAndPrintOrderLine.java ├── Code04_Drive.java ├── Code05_SetAll.java └── Code06_MinLengthForSort.java ├── class03 ├── Code01_LongestSubstringWithoutRepeatingCharacters.java ├── Code02_HowManyTypes.java ├── Code03_Largest1BorderedSquare.java ├── Code04_MaxPairNumber.java ├── Code05_MinBoat.java ├── Code06_ClosestSubsequenceSum.java ├── Code07_FreedomTrail.java └── Code08_DistanceKNodes.java ├── class04 ├── Code01_QueryHobby.java ├── Code02_SubArrayMaxSum.java ├── Code03_SubMatrixMaxSum.java ├── Code04_SubArrayMaxSumFollowUp.java ├── Code05_CandyProblem.java ├── Code06_MakeNo.java ├── Code07_InterleavingString.java └── Code08_TheSkylineProblem.java ├── class05 ├── Code01_ConstructBinarySearchTreeFromPreorderTraversal.java ├── Code02_LeftRightSameTreeNumber.java ├── Code03_EditCost.java ├── Code04_DeleteMinCost.java └── Hash.java ├── class06 ├── Code01_MaxXOR.java ├── Code02_MaximumXorOfTwoNumbersInAnArray.java ├── Code03_MaximumXorWithAnElementFromArray.java ├── Code04_MostXorZero.java └── Code05_Nim.java ├── class07 ├── Code01_MaxAndValue.java ├── Code02_MinCameraCover.java ├── Code03_MaxGap.java ├── Code04_Power2Diffs.java ├── Code05_WorldBreak.java └── Code06_SplitStringMaxValue.java ├── class08 ├── Code01_ExpressionCompute.java ├── Code02_ContainerWithMostWater.java ├── Code03_FindWordInMatrix.java └── Code04_SnakeGame.java ├── class09 ├── Code01_LightProblem.java ├── Code02_RemoveInvalidParentheses.java ├── Code03_LIS.java ├── Code04_EnvelopesProblem.java └── Code05_IsStepSum.java ├── class10 ├── Code01_JumpGame.java ├── Code02_TopK.java ├── Code03_KInversePairs.java ├── Code04_BSTtoDoubleLinkedList.java └── Code05_BooleanEvaluation.java ├── class11 ├── Code01_MinimumInsertionStepsToMakeAStringPalindrome.java └── Code02_PalindromePartitioningII.java ├── class12 ├── Code01_ContainAllCharExactly.java ├── Code03_FindKthMinNumber.java ├── Code03_LongestConsecutive.java └── Code04_RegularExpressionMatch.java ├── class13 ├── Code01_NCardsABWin.java ├── Code02_SuperWashingMachines.java ├── Code03_ScrambleString.java └── Code04_BricksFallingWhenHit.java ├── class14 ├── Code01_Parentheses.java ├── Code02_MaxSubArraySumLessOrEqualK.java ├── Code03_BiggestBSTTopologyInTree.java ├── Code04_CompleteTreeNodeNumber.java ├── Code05_RecoverBinarySearchTree.java └── Code06_MissingNumber.java ├── class15 ├── Code01_BestTimeToBuyAndSellStock.java ├── Code02_BestTimeToBuyAndSellStockII.java ├── Code03_BestTimeToBuyAndSellStockIII.java ├── Code04_BestTimeToBuyAndSellStockIV.java ├── Code05_BestTimeToBuyAndSellStockWithCooldown.java └── Code06_BestTimeToBuyAndSellStockWithTransactionFee.java ├── class16 ├── Code01_IsSum.java ├── Code02_SmallestUnFormedSum.java ├── Code03_MinPatches.java ├── Code04_MergeRecord.java └── Code05_JosephusProblem.java ├── class17 ├── Code01_FindNumInSortedMatrix.java ├── Code02_KthSmallestElementInSortedMatrix.java ├── Code03_PalindromePairs.java ├── Code04_DistinctSubseq.java └── Code05_DistinctSubseqValue.java ├── class18 ├── Code01_HanoiProblem.java ├── Code02_ShortestBridge.java ├── Code03_CherryPickup.java └── Code04_TopKSumCrossTwoArrays.java ├── class19 ├── Code01_LRUCache.java ├── Code02_LFUCache.java ├── Code03_OneNumber.java ├── Code04_SmallestRangeCoveringElementsfromKLists.java └── Code05_CardsProblem.java ├── class20 ├── Code01_PreAndInArrayToPosArray.java ├── Code02_LargestComponentSizebyCommonFactor.java ├── Code03_ShuffleProblem.java └── Code04_PalindromeWays.java ├── class21 └── TreeChainPartition.java ├── class22 ├── Code01_MaximumSumof3NonOverlappingSubarrays.java ├── Code02_TrappingRainWater.java ├── Code03_TrappingRainWaterII.java ├── Code04_VisibleMountains.java └── Code05_TallestBillboard.java ├── class23 ├── Code01_LCATarjanAndTreeChainPartition.java ├── Code02_MaxABSBetweenLeftAndRight.java ├── Code03_LongestIntegratedLength.java ├── Code04_FindKMajority.java └── Code05_MinimumCostToMergeStones.java ├── class24 ├── Code01_Split4Parts.java ├── Code02_KthMinPair.java ├── Code03_NotContains4.java ├── Code04_Painting.java ├── Code05_MinWindowLength.java └── Code06_RemoveDuplicateLettersLessLexi.java ├── class25 ├── Code01_IPToCIDR.java ├── Code02_3Sum.java ├── Code03_MaxPointsOnALine.java └── Code04_GasStation.java ├── class26 ├── Code01_MinRange.java ├── Code02_WordSearchII.java ├── Code03_ExpressionAddOperators.java └── Code04_WordLadderII.java ├── class27 ├── Code01_PickBands.java ├── Code02_MinPeople.java ├── Problem_0001_TwoSum.java ├── Problem_0007_ReverseInteger.java └── 说明 ├── class28 ├── Problem_0008_StringToInteger.java ├── Problem_0012_IntegerToRoman.java ├── Problem_0013_RomanToInteger.java ├── Problem_0014_LongestCommonPrefix.java ├── Problem_0017_LetterCombinationsOfAPhoneNumber.java ├── Problem_0019_RemoveNthNodeFromEndofList.java ├── Problem_0020_ValidParentheses.java ├── Problem_0022_GenerateParentheses.java ├── Problem_0026_RemoveDuplicatesFromSortedArray.java ├── Problem_0034_FindFirstAndLastPositionOfElementInSortedArray.java ├── Problem_0036_ValidSudoku.java ├── Problem_0037_SudokuSolver.java ├── Problem_0038_CountAndSay.java ├── Problem_0049_GroupAnagrams.java └── 说明 ├── class29 ├── Problem_0033_SearchInRotatedSortedArray.java ├── Problem_0050_PowXN.java ├── Problem_0056_MergeIntervals.java ├── Problem_0062_UniquePaths.java ├── Problem_0066_PlusOne.java ├── Problem_0069_SqrtX.java ├── Problem_0073_SetMatrixZeroes.java └── 说明 ├── class30 ├── Problem_0079_WordSearch.java ├── Problem_0088_MergeSortedArray.java ├── Problem_0091_DecodeWays.java ├── Problem_0098_ValidateBinarySearchTree.java ├── Problem_0101_SymmetricTree.java ├── Problem_0103_BinaryTreeZigzagLevelOrderTraversal.java ├── Problem_0108_ConvertSortedArrayToBinarySearchTree.java ├── Problem_0116_PopulatingNextRightPointersInEachNode.java ├── Problem_0118_PascalTriangle.java ├── Problem_0119_PascalTriangleII.java ├── Problem_0124_BinaryTreeMaximumPathSum.java ├── Problem_0639_DecodeWaysII.java └── 说明 ├── class31 ├── Problem_0125_ValidPalindrome.java ├── Problem_0127_WordLadder.java ├── Problem_0130_SurroundedRegions.java ├── Problem_0139_WordBreak.java ├── Problem_0140_WordBreakII.java ├── Problem_0148_SortList.java ├── Problem_0150_EvaluateReversePolishNotation.java └── 说明 ├── class32 ├── Problem_0152_MaximumProductSubarray.java ├── Problem_0163_MissingRanges.java ├── Problem_0166_FractionToRecurringDecimal.java ├── Problem_0171_ExcelSheetColumnNumber.java ├── Problem_0172_FactorialTrailingZeroes.java ├── Problem_0189_RotateArray.java ├── Problem_0190_ReverseBits.java ├── Problem_0191_NumberOf1Bits.java ├── Problem_0202_HappyNumber.java ├── Problem_0204_CountPrimes.java ├── SequenceM.java └── 说明 ├── class33 ├── Problem_0207_CourseSchedule.java ├── Problem_0210_CourseScheduleII.java ├── Problem_0213_HouseRobberII.java ├── Problem_0237_DeleteNodeInLinkedList.java ├── Problem_0238_ProductOfArrayExceptSelf.java ├── Problem_0242_ValidAnagram.java ├── Problem_0251_Flatten2DVector.java ├── Problem_0269_AlienDictionary.java ├── Problem_0277_FindTheCelebrity.java ├── Problem_0279_PerfectSquares.java ├── Problem_0283_MoveZeroes.java └── 说明 ├── class34 ├── Problem_0287_FindTheDuplicateNumber.java ├── Problem_0289_GameOfLife.java ├── Problem_0295_FindMedianFromDataStream.java ├── Problem_0315_CountOfSmallerNumbersAfterSelf.java ├── Problem_0324_WiggleSortII.java ├── Problem_0326_PowerOfThree.java ├── Problem_0328_OddEvenLinkedList.java ├── Problem_0340_LongestSubstringWithAtMostKDistinctCharacters.java ├── Problem_0341_FlattenNestedListIterator.java ├── Problem_0348_DesignTicTacToe.java ├── Problem_0380_InsertDeleteGetRandom.java ├── Problem_0384_ShuffleAnArray.java └── 说明 ├── class35 ├── Code01_StringKth.java ├── Code02_MagicStone.java ├── Code03_WatchMovieMaxTime.java ├── Code04_WalkToEnd.java ├── Code05_CircleCandy.java ├── Problem_0347_TopKFrequentElements.java ├── Problem_0395_LongestSubstringWithAtLeastKRepeatingCharacters.java ├── Problem_0412_FizzBuzz.java ├── Problem_0454_4SumII.java ├── Problem_0673_NumberOfLongestIncreasingSubsequence.java ├── Problem_0687_LongestUnivaluePath.java └── 说明 ├── class36 ├── Code01_ReverseInvertString.java ├── Code02_Ratio01Split.java ├── Code03_MatchCount.java ├── Code04_ComputeExpressionValue.java ├── Code05_Query3Problems.java ├── Code06_NodeWeight.java ├── Code07_ModMHeads.java ├── Code08_PickAddMax.java ├── Code09_MinBoatEvenNumbers.java ├── Code10_MaxKLenSequence.java ├── Code11_StoneGameIV.java ├── Code12_BusRoutes.java └── 说明 ├── class37 ├── Code01_ArrangeProject.java ├── Code02_GameForEveryStepWin.java ├── Problem_0114_FlattenBinaryTreeToLinkedList.java ├── Problem_0221_MaximalSquare.java ├── Problem_0226_InvertBinaryTree.java ├── Problem_0394_DecodeString.java ├── Problem_0406_QueueReconstructionByHeight.java ├── Problem_0437_PathSumIII.java └── 说明 ├── class38 ├── Code01_FillGapMinStep.java ├── Code02_GreatWall.java ├── Problem_0438_FindAllAnagramsInAString.java ├── Problem_0448_FindAllNumbersDisappearedInAnArray.java ├── Problem_0617_MergeTwoBinaryTrees.java ├── Problem_0621_TaskScheduler.java ├── Problem_0647_PalindromicSubstrings.java ├── Problem_0739_DailyTemperatures.java ├── Problem_0763_PartitionLabels.java └── 说明 ├── class39 ├── Code01_01AddValue.java ├── Code02_ValidSequence.java ├── Code03_SequenceKDifferentKinds.java ├── Code04_JumpGameOnMatrix.java └── Code05_0123Disappear.java ├── class40 ├── Code01_SplitTo01.java ├── Code02_Mod3Max.java ├── Code03_MaxMeetingScore.java ├── Code04_LetASorted.java └── Code05_AllSame.java ├── class41 ├── Code01_MinSwapTimes.java ├── Code02_PoemProblem.java ├── Code03_MagicGoToAim.java └── Problem_0031_NextPermutation.java ├── class42 ├── Problem_0265_PaintHouseII.java ├── Problem_0272_ClosestBinarySearchTreeValueII.java ├── Problem_0273_IntegerToEnglishWords.java ├── Problem_0296_BestMeetingPoint.java └── Problem_0335_SelfCrossing.java ├── class43 ├── Code01_SumNoPositiveMinCost.java └── Code02_MinCostToYeahArray.java ├── class44 ├── Problem_0248_StrobogrammaticNumberIII.java ├── Problem_0317_ShortestDistanceFromAllBuildings.java └── Problem_0992_SubarraysWithKDifferentIntegers.java ├── class45 ├── Code01_SplitBuildingBlock.java ├── Problem_0291_WordPatternII.java ├── Problem_0403_FrogJump.java └── Problem_2035_PartitionArrayIntoTwoArraysToMinimizeSumDifference.java ├── class46 ├── Problem_0363_MaxSumOfRectangleNoLargerThanK.java ├── Problem_0391_PerfectRectangle.java ├── Problem_0411_MinimumUniqueWordAbbreviation.java └── Problem_0425_WordSquares.java ├── class47 ├── Code01_DynamicSegmentTree.java ├── Code02_DynamicSegmentTree.java ├── Problem_0315_CountOfSmallerNumbersAfterSelf.java ├── Problem_0358_RearrangeStringKDistanceApart.java ├── Problem_0428_SerializeAndDeserializeNaryTree.java ├── Problem_0465_OptimalAccountBalancing.java └── Problem_0475_Heaters.java ├── class48 ├── Code01_MinKthPairMinusABS.java ├── Problem_0472_ConcatenatedWords.java ├── Problem_0483_SmallestGoodBase.java └── Problem_0499_TheMazeIII.java ├── class49 ├── Problem_0377_CombinationSumIV.java ├── Problem_0440_KthSmallestInLexicographicalOrder.java ├── Problem_0446_ArithmeticSlicesIISubsequence.java ├── Problem_0489_RobotRoomCleaner.java ├── Problem_0527_WordAbbreviation.java ├── Problem_0548_SplitArrayEithEqualSum.java └── Problem_0564_FindTheClosestPalindrome.java ├── class50 ├── Problem_0568_MaximumVacationDays.java ├── Problem_0587_ErectTheFence.java ├── Problem_0588_DesignInMemoryFileSystem.java └── Problem_0600_NonnegativeIntegersWithoutConsecutiveOnes.java ├── class51 ├── LCP_0003_Robot.java ├── Problem_0630_CourseScheduleIII.java ├── Problem_0642_DesignSearchAutocompleteSystem.java ├── Problem_0875_KokoEatingBananas.java └── Problem_1035_UncrossedLines.java └── class52 ├── Problem_0656_CoinPath.java ├── Problem_0683_KEmptySlots.java └── Problem_1488_AvoidFloodInTheCity.java /README.md: -------------------------------------------------------------------------------- 1 | # algorithmzuo-coding-for-great-offer 2 | 大厂刷题班 3 | -------------------------------------------------------------------------------- /src/class01/Code02_CountFiles.java: -------------------------------------------------------------------------------- 1 | package class01; 2 | 3 | import java.io.File; 4 | import java.util.Stack; 5 | 6 | public class Code02_CountFiles { 7 | 8 | // 注意这个函数也会统计隐藏文件 9 | public static int getFileNumber(String folderPath) { 10 | File root = new File(folderPath); 11 | if (!root.isDirectory() && !root.isFile()) { 12 | return 0; 13 | } 14 | if (root.isFile()) { 15 | return 1; 16 | } 17 | Stack stack = new Stack<>(); 18 | stack.add(root); 19 | int files = 0; 20 | while (!stack.isEmpty()) { 21 | File folder = stack.pop(); 22 | for (File next : folder.listFiles()) { 23 | if (next.isFile()) { 24 | files++; 25 | } 26 | if (next.isDirectory()) { 27 | stack.push(next); 28 | } 29 | } 30 | } 31 | return files; 32 | } 33 | 34 | public static void main(String[] args) { 35 | // 你可以自己更改目录 36 | String path = "/Users/zuochengyun/Desktop/"; 37 | System.out.println(getFileNumber(path)); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/class01/Code03_Near2Power.java: -------------------------------------------------------------------------------- 1 | package class01; 2 | 3 | public class Code03_Near2Power { 4 | 5 | // 已知n是正数 6 | // 返回大于等于,且最接近n的,2的某次方的值 7 | public static final int tableSizeFor(int n) { 8 | n--; 9 | n |= n >>> 1; 10 | n |= n >>> 2; 11 | n |= n >>> 4; 12 | n |= n >>> 8; 13 | n |= n >>> 16; 14 | return (n < 0) ? 1 : n + 1; 15 | } 16 | 17 | public static void main(String[] args) { 18 | int cap = 120; 19 | System.out.println(tableSizeFor(cap)); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/class01/Code05_LongestIncreasingPath.java: -------------------------------------------------------------------------------- 1 | package class01; 2 | 3 | public class Code05_LongestIncreasingPath { 4 | 5 | public static int longestIncreasingPath1(int[][] matrix) { 6 | int ans = 0; 7 | int N = matrix.length; 8 | int M = matrix[0].length; 9 | for (int i = 0; i < N; i++) { 10 | for (int j = 0; j < M; j++) { 11 | ans = Math.max(ans, process1(matrix, i, j)); 12 | } 13 | } 14 | return ans; 15 | } 16 | 17 | // 从m[i][j]开始走,走出来的最长递增链,返回! 18 | public static int process1(int[][] m, int i, int j) { 19 | int up = i > 0 && m[i][j] < m[i - 1][j] ? process1(m, i - 1, j) : 0; 20 | int down = i < (m.length - 1) && m[i][j] < m[i + 1][j] ? process1(m, i + 1, j) : 0; 21 | int left = j > 0 && m[i][j] < m[i][j - 1] ? process1(m, i, j - 1) : 0; 22 | int right = j < (m[0].length - 1) && m[i][j] < m[i][j + 1] ? process1(m, i, j + 1) : 0; 23 | return Math.max(Math.max(up, down), Math.max(left, right)) + 1; 24 | } 25 | 26 | public static int longestIncreasingPath2(int[][] matrix) { 27 | int ans = 0; 28 | int N = matrix.length; 29 | int M = matrix[0].length; 30 | int[][] dp = new int[N][M]; 31 | for (int i = 0; i < N; i++) { 32 | for (int j = 0; j < M; j++) { 33 | ans = Math.max(ans, process2(matrix, i, j, dp)); 34 | } 35 | } 36 | return ans; 37 | } 38 | 39 | // 从m[i][j]开始走,走出来的最长递增链,返回! 40 | public static int process2(int[][] m, int i, int j, int[][] dp) { 41 | if (dp[i][j] != 0) { 42 | return dp[i][j]; 43 | } 44 | // (i,j)不越界 45 | int up = i > 0 && m[i][j] < m[i - 1][j] ? process2(m, i - 1, j, dp) : 0; 46 | int down = i < (m.length - 1) && m[i][j] < m[i + 1][j] ? process2(m, i + 1, j, dp) : 0; 47 | int left = j > 0 && m[i][j] < m[i][j - 1] ? process2(m, i, j - 1, dp) : 0; 48 | int right = j < (m[0].length - 1) && m[i][j] < m[i][j + 1] ? process2(m, i, j + 1, dp) : 0; 49 | int ans = Math.max(Math.max(up, down), Math.max(left, right)) + 1; 50 | dp[i][j] = ans; 51 | return ans; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/class02/Code01_ChooseWork.java: -------------------------------------------------------------------------------- 1 | package class02; 2 | 3 | import java.util.Arrays; 4 | import java.util.Comparator; 5 | import java.util.TreeMap; 6 | 7 | public class Code01_ChooseWork { 8 | 9 | public static class Job { 10 | public int money; 11 | public int hard; 12 | 13 | public Job(int m, int h) { 14 | money = m; 15 | hard = h; 16 | } 17 | } 18 | 19 | public static class JobComparator implements Comparator { 20 | @Override 21 | public int compare(Job o1, Job o2) { 22 | return o1.hard != o2.hard ? (o1.hard - o2.hard) : (o2.money - o1.money); 23 | } 24 | } 25 | 26 | public static int[] getMoneys(Job[] job, int[] ability) { 27 | Arrays.sort(job, new JobComparator()); 28 | // key : 难度 value:报酬 29 | TreeMap map = new TreeMap<>(); 30 | map.put(job[0].hard, job[0].money); 31 | // pre : 上一份进入map的工作 32 | Job pre = job[0]; 33 | for (int i = 1; i < job.length; i++) { 34 | if (job[i].hard != pre.hard && job[i].money > pre.money) { 35 | pre = job[i]; 36 | map.put(pre.hard, pre.money); 37 | } 38 | } 39 | int[] ans = new int[ability.length]; 40 | for (int i = 0; i < ability.length; i++) { 41 | // ability[i] 当前人的能力 <= ability[i] 且离它最近的 42 | Integer key = map.floorKey(ability[i]); 43 | ans[i] = key != null ? map.get(key) : 0; 44 | } 45 | return ans; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/class02/Code05_SetAll.java: -------------------------------------------------------------------------------- 1 | package class02; 2 | 3 | import java.util.HashMap; 4 | 5 | public class Code05_SetAll { 6 | 7 | public static class MyValue { 8 | public V value; 9 | public long time; 10 | 11 | public MyValue(V v, long t) { 12 | value = v; 13 | time = t; 14 | } 15 | } 16 | 17 | public static class MyHashMap { 18 | private HashMap> map; 19 | private long time; 20 | private MyValue setAll; 21 | 22 | public MyHashMap() { 23 | map = new HashMap<>(); 24 | time = 0; 25 | setAll = new MyValue(null, -1); 26 | } 27 | 28 | public void put(K key, V value) { 29 | map.put(key, new MyValue(value, time++)); 30 | } 31 | 32 | public void setAll(V value) { 33 | setAll = new MyValue(value, time++); 34 | } 35 | 36 | public V get(K key) { 37 | if (!map.containsKey(key)) { 38 | return null; 39 | } 40 | if (map.get(key).time > setAll.time) { 41 | return map.get(key).value; 42 | } else { 43 | return setAll.value; 44 | } 45 | } 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/class02/Code06_MinLengthForSort.java: -------------------------------------------------------------------------------- 1 | package class02; 2 | 3 | // 本题测试链接 : https://leetcode.com/problems/shortest-unsorted-continuous-subarray/ 4 | public class Code06_MinLengthForSort { 5 | 6 | public static int findUnsortedSubarray(int[] nums) { 7 | if (nums == null || nums.length < 2) { 8 | return 0; 9 | } 10 | int N = nums.length; 11 | int right = -1; 12 | int max = Integer.MIN_VALUE; 13 | for (int i = 0; i < N; i++) { 14 | if (max > nums[i]) { 15 | right = i; 16 | } 17 | max = Math.max(max, nums[i]); 18 | } 19 | int min = Integer.MAX_VALUE; 20 | int left = N; 21 | for (int i = N - 1; i >= 0; i--) { 22 | if (min < nums[i]) { 23 | left = i; 24 | } 25 | min = Math.min(min, nums[i]); 26 | } 27 | return Math.max(0, right - left + 1); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/class03/Code01_LongestSubstringWithoutRepeatingCharacters.java: -------------------------------------------------------------------------------- 1 | package class03; 2 | 3 | // 本题测试链接 : https://leetcode.com/problems/longest-substring-without-repeating-characters/ 4 | public class Code01_LongestSubstringWithoutRepeatingCharacters { 5 | 6 | public static int lengthOfLongestSubstring(String s) { 7 | if (s == null || s.equals("")) { 8 | return 0; 9 | } 10 | char[] str = s.toCharArray(); 11 | int[] map = new int[256]; 12 | for (int i = 0; i < 256; i++) { 13 | map[i] = -1; 14 | } 15 | map[str[0]] = 0; 16 | int N = str.length; 17 | int ans = 1; 18 | int pre = 1; 19 | for (int i = 1; i < N; i++) { 20 | pre = Math.min(i - map[str[i]], pre + 1); 21 | ans = Math.max(ans, pre); 22 | map[str[i]] = i; 23 | } 24 | return ans; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/class03/Code03_Largest1BorderedSquare.java: -------------------------------------------------------------------------------- 1 | package class03; 2 | 3 | // 本题测试链接 : https://leetcode.com/problems/largest-1-bordered-square/ 4 | public class Code03_Largest1BorderedSquare { 5 | 6 | public static int largest1BorderedSquare(int[][] m) { 7 | int[][] right = new int[m.length][m[0].length]; 8 | int[][] down = new int[m.length][m[0].length]; 9 | setBorderMap(m, right, down); 10 | for (int size = Math.min(m.length, m[0].length); size != 0; size--) { 11 | if (hasSizeOfBorder(size, right, down)) { 12 | return size * size; 13 | } 14 | } 15 | return 0; 16 | } 17 | 18 | public static void setBorderMap(int[][] m, int[][] right, int[][] down) { 19 | int r = m.length; 20 | int c = m[0].length; 21 | if (m[r - 1][c - 1] == 1) { 22 | right[r - 1][c - 1] = 1; 23 | down[r - 1][c - 1] = 1; 24 | } 25 | for (int i = r - 2; i != -1; i--) { 26 | if (m[i][c - 1] == 1) { 27 | right[i][c - 1] = 1; 28 | down[i][c - 1] = down[i + 1][c - 1] + 1; 29 | } 30 | } 31 | for (int i = c - 2; i != -1; i--) { 32 | if (m[r - 1][i] == 1) { 33 | right[r - 1][i] = right[r - 1][i + 1] + 1; 34 | down[r - 1][i] = 1; 35 | } 36 | } 37 | for (int i = r - 2; i != -1; i--) { 38 | for (int j = c - 2; j != -1; j--) { 39 | if (m[i][j] == 1) { 40 | right[i][j] = right[i][j + 1] + 1; 41 | down[i][j] = down[i + 1][j] + 1; 42 | } 43 | } 44 | } 45 | } 46 | 47 | public static boolean hasSizeOfBorder(int size, int[][] right, int[][] down) { 48 | for (int i = 0; i != right.length - size + 1; i++) { 49 | for (int j = 0; j != right[0].length - size + 1; j++) { 50 | if (right[i][j] >= size && down[i][j] >= size && right[i + size - 1][j] >= size 51 | && down[i][j + size - 1] >= size) { 52 | return true; 53 | } 54 | } 55 | } 56 | return false; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/class03/Code05_MinBoat.java: -------------------------------------------------------------------------------- 1 | package class03; 2 | 3 | import java.util.Arrays; 4 | 5 | // 给定一个正数数组arr,代表若干人的体重 6 | // 再给定一个正数limit,表示所有船共同拥有的载重量 7 | // 每艘船最多坐两人,且不能超过载重 8 | // 想让所有的人同时过河,并且用最好的分配方法让船尽量少 9 | // 返回最少的船数 10 | public class Code05_MinBoat { 11 | 12 | public static int minBoat(int[] arr, int limit) { 13 | if (arr == null || arr.length == 0) { 14 | return 0; 15 | } 16 | int N = arr.length; 17 | Arrays.sort(arr); 18 | if (arr[N - 1] > limit) { 19 | return -1; 20 | } 21 | int lessR = -1; 22 | for (int i = N - 1; i >= 0; i--) { 23 | if (arr[i] <= (limit / 2)) { 24 | lessR = i; 25 | break; 26 | } 27 | } 28 | if (lessR == -1) { 29 | return N; 30 | } 31 | int L = lessR; 32 | int R = lessR + 1; 33 | int noUsed = 0; 34 | while (L >= 0) { 35 | int solved = 0; 36 | while (R < N && arr[L] + arr[R] <= limit) { 37 | R++; 38 | solved++; 39 | } 40 | if (solved == 0) { 41 | noUsed++; 42 | L--; 43 | } else { 44 | L = Math.max(-1, L - solved); 45 | } 46 | } 47 | int all = lessR + 1; 48 | int used = all - noUsed; 49 | int moreUnsolved = (N - all) - used; 50 | return used + ((noUsed + 1) >> 1) + moreUnsolved; 51 | } 52 | 53 | // 练习 : 自己补出对数器,这包括一个暴力方法,和生成随机数据发生器的,以及main函数做验证 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/class03/Code06_ClosestSubsequenceSum.java: -------------------------------------------------------------------------------- 1 | package class03; 2 | 3 | import java.util.Arrays; 4 | 5 | // 本题测试链接 : https://leetcode.com/problems/closest-subsequence-sum/ 6 | // 本题数据量描述: 7 | // 1 <= nums.length <= 40 8 | // -10^7 <= nums[i] <= 10^7 9 | // -10^9 <= goal <= 10^9 10 | // 通过这个数据量描述可知,需要用到分治,因为数组长度不大 11 | // 而值很大,用动态规划的话,表会爆 12 | public class Code06_ClosestSubsequenceSum { 13 | 14 | public static int[] l = new int[1 << 20]; 15 | public static int[] r = new int[1 << 20]; 16 | 17 | public static int minAbsDifference(int[] nums, int goal) { 18 | if (nums == null || nums.length == 0) { 19 | return goal; 20 | } 21 | int le = process(nums, 0, nums.length >> 1, 0, 0, l); 22 | int re = process(nums, nums.length >> 1, nums.length, 0, 0, r); 23 | Arrays.sort(l, 0, le); 24 | Arrays.sort(r, 0, re--); 25 | int ans = Math.abs(goal); 26 | for (int i = 0; i < le; i++) { 27 | int rest = goal - l[i]; 28 | while (re > 0 && Math.abs(rest - r[re - 1]) <= Math.abs(rest - r[re])) { 29 | re--; 30 | } 31 | ans = Math.min(ans, Math.abs(rest - r[re])); 32 | } 33 | return ans; 34 | } 35 | 36 | public static int process(int[] nums, int index, int end, int sum, int fill, int[] arr) { 37 | if (index == end) { 38 | arr[fill++] = sum; 39 | } else { 40 | fill = process(nums, index + 1, end, sum, fill, arr); 41 | fill = process(nums, index + 1, end, sum + nums[index], fill, arr); 42 | } 43 | return fill; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/class03/Code07_FreedomTrail.java: -------------------------------------------------------------------------------- 1 | package class03; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | 6 | // 本题测试链接 : https://leetcode.com/problems/freedom-trail/ 7 | public class Code07_FreedomTrail { 8 | 9 | public static int findRotateSteps(String r, String k) { 10 | char[] ring = r.toCharArray(); 11 | int N = ring.length; 12 | HashMap> map = new HashMap<>(); 13 | for (int i = 0; i < N; i++) { 14 | if (!map.containsKey(ring[i])) { 15 | map.put(ring[i], new ArrayList<>()); 16 | } 17 | map.get(ring[i]).add(i); 18 | } 19 | char[] str = k.toCharArray(); 20 | int M = str.length; 21 | int[][] dp = new int[N][M + 1]; 22 | // hashmap 23 | // dp[][] == -1 : 表示没算过! 24 | for (int i = 0; i < N; i++) { 25 | for (int j = 0; j <= M; j++) { 26 | dp[i][j] = -1; 27 | } 28 | } 29 | return process(0, 0, str, map, N, dp); 30 | } 31 | 32 | // 电话里:指针指着的上一个按键preButton 33 | // 目标里:此时要搞定哪个字符?keyIndex 34 | // map : key 一种字符 value: 哪些位置拥有这个字符 35 | // N: 电话大小 36 | // f(0, 0, aim, map, N) 37 | public static int process(int preButton, int index, char[] str, HashMap> map, int N, 38 | int[][] dp) { 39 | if (dp[preButton][index] != -1) { 40 | return dp[preButton][index]; 41 | } 42 | int ans = Integer.MAX_VALUE; 43 | if (index == str.length) { 44 | ans = 0; 45 | } else { 46 | // 还有字符需要搞定呢! 47 | char cur = str[index]; 48 | ArrayList nextPositions = map.get(cur); 49 | for (int next : nextPositions) { 50 | int cost = dial(preButton, next, N) + 1 + process(next, index + 1, str, map, N, dp); 51 | ans = Math.min(ans, cost); 52 | } 53 | } 54 | dp[preButton][index] = ans; 55 | return ans; 56 | } 57 | 58 | public static int dial(int i1, int i2, int size) { 59 | return Math.min(Math.abs(i1 - i2), Math.min(i1, i2) + size - Math.max(i1, i2)); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/class04/Code02_SubArrayMaxSum.java: -------------------------------------------------------------------------------- 1 | package class04; 2 | 3 | // 本题测试链接 : https://leetcode.com/problems/maximum-subarray/ 4 | public class Code02_SubArrayMaxSum { 5 | 6 | public static int maxSubArray(int[] arr) { 7 | if (arr == null || arr.length == 0) { 8 | return 0; 9 | } 10 | int max = Integer.MIN_VALUE; 11 | int cur = 0; 12 | for (int i = 0; i < arr.length; i++) { 13 | cur += arr[i]; 14 | max = Math.max(max, cur); 15 | cur = cur < 0 ? 0 : cur; 16 | } 17 | return max; 18 | } 19 | 20 | public static int maxSubArray2(int[] arr) { 21 | if (arr == null || arr.length == 0) { 22 | return 0; 23 | } 24 | // 上一步,dp的值 25 | // dp[0] 26 | int pre = arr[0]; 27 | int max = arr[0]; 28 | for (int i = 1; i < arr.length; i++) { 29 | pre = Math.max(arr[i], arr[i] + pre); 30 | max = Math.max(max, pre); 31 | } 32 | return max; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/class04/Code03_SubMatrixMaxSum.java: -------------------------------------------------------------------------------- 1 | package class04; 2 | 3 | public class Code03_SubMatrixMaxSum { 4 | 5 | public static int maxSum(int[][] m) { 6 | if (m == null || m.length == 0 || m[0].length == 0) { 7 | return 0; 8 | } 9 | // O(N^2 * M) 10 | int N = m.length; 11 | int M = m[0].length; 12 | int max = Integer.MIN_VALUE; 13 | for (int i = 0; i < N; i++) { 14 | // i~j 15 | int[] s = new int[M]; 16 | for (int j = i; j < N; j++) { 17 | for (int k = 0; k < M; k++) { 18 | s[k] += m[j][k]; 19 | } 20 | max = Math.max(max, maxSubArray(s)); 21 | } 22 | } 23 | return max; 24 | } 25 | 26 | public static int maxSubArray(int[] arr) { 27 | if (arr == null || arr.length == 0) { 28 | return 0; 29 | } 30 | int max = Integer.MIN_VALUE; 31 | int cur = 0; 32 | for (int i = 0; i < arr.length; i++) { 33 | cur += arr[i]; 34 | max = Math.max(max, cur); 35 | cur = cur < 0 ? 0 : cur; 36 | } 37 | return max; 38 | } 39 | 40 | // 本题测试链接 : https://leetcode-cn.com/problems/max-submatrix-lcci/ 41 | public static int[] getMaxMatrix(int[][] m) { 42 | int N = m.length; 43 | int M = m[0].length; 44 | int max = Integer.MIN_VALUE; 45 | int cur = 0; 46 | int a = 0; 47 | int b = 0; 48 | int c = 0; 49 | int d = 0; 50 | for (int i = 0; i < N; i++) { 51 | int[] s = new int[M]; 52 | for (int j = i; j < N; j++) { 53 | cur = 0; 54 | int begin = 0; 55 | for (int k = 0; k < M; k++) { 56 | s[k] += m[j][k]; 57 | cur += s[k]; 58 | if (max < cur) { 59 | max = cur; 60 | a = i; 61 | b = begin; 62 | c = j; 63 | d = k; 64 | } 65 | if (cur < 0) { 66 | cur = 0; 67 | begin = k + 1; 68 | } 69 | } 70 | } 71 | } 72 | return new int[] { a, b, c, d }; 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/class04/Code04_SubArrayMaxSumFollowUp.java: -------------------------------------------------------------------------------- 1 | package class04; 2 | 3 | public class Code04_SubArrayMaxSumFollowUp { 4 | 5 | public static int subSqeMaxSumNoNext(int[] arr) { 6 | if (arr == null || arr.length == 0) { 7 | return 0; 8 | } 9 | if (arr.length == 1) { 10 | return arr[0]; 11 | } 12 | int[] dp = new int[arr.length]; 13 | // dp[i] : arr[0..i]挑选,满足不相邻设定的情况下,随意挑选,最大的累加和 14 | dp[0] = arr[0]; 15 | dp[1] = Math.max(arr[0], arr[1]); 16 | for (int i = 2; i < arr.length; i++) { 17 | int p1 = dp[i - 1]; 18 | int p2 = arr[i] + Math.max(dp[i - 2], 0); 19 | dp[i] = Math.max(p1, p2); 20 | } 21 | return dp[arr.length - 1]; 22 | } 23 | 24 | // 给定一个数组arr,在不能取相邻数的情况下,返回所有组合中的最大累加和 25 | // 思路: 26 | // 定义dp[i] : 表示arr[0...i]范围上,在不能取相邻数的情况下,返回所有组合中的最大累加和 27 | // 在arr[0...i]范围上,在不能取相邻数的情况下,得到的最大累加和,可能性分类: 28 | // 可能性 1) 选出的组合,不包含arr[i]。那么dp[i] = dp[i-1] 29 | // 比如,arr[0...i] = {3,4,-4},最大累加和是不包含i位置数的时候 30 | // 31 | // 可能性 2) 选出的组合,只包含arr[i]。那么dp[i] = arr[i] 32 | // 比如,arr[0...i] = {-3,-4,4},最大累加和是只包含i位置数的时候 33 | // 34 | // 可能性 3) 选出的组合,包含arr[i], 且包含arr[0...i-2]范围上的累加和。那么dp[i] = arr[i] + dp[i-2] 35 | // 比如,arr[0...i] = {3,1,4},最大累加和是3和4组成的7,因为相邻不能选,所以i-1位置的数要跳过 36 | // 37 | // 综上所述:dp[i] = Max { dp[i-1], arr[i] , arr[i] + dp[i-2] } 38 | public static int maxSum(int[] arr) { 39 | if (arr == null || arr.length == 0) { 40 | return 0; 41 | } 42 | int N = arr.length; 43 | if (N == 1) { 44 | return arr[0]; 45 | } 46 | if (N == 2) { 47 | return Math.max(arr[0], arr[1]); 48 | } 49 | int[] dp = new int[N]; 50 | dp[0] = arr[0]; 51 | dp[1] = Math.max(arr[0], arr[1]); 52 | for (int i = 2; i < N; i++) { 53 | dp[i] = Math.max(Math.max(dp[i - 1], arr[i]), arr[i] + dp[i - 2]); 54 | } 55 | return dp[N - 1]; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/class04/Code06_MakeNo.java: -------------------------------------------------------------------------------- 1 | package class04; 2 | 3 | public class Code06_MakeNo { 4 | 5 | // 生成长度为size的达标数组 6 | // 达标:对于任意的 i 等长奇数达标来 19 | // base -> 等长偶数达标来 20 | int[] ans = new int[size]; 21 | int index = 0; 22 | for (; index < halfSize; index++) { 23 | ans[index] = base[index] * 2 - 1; 24 | } 25 | for (int i = 0; index < size; index++, i++) { 26 | ans[index] = base[i] * 2; 27 | } 28 | return ans; 29 | } 30 | 31 | // 检验函数 32 | public static boolean isValid(int[] arr) { 33 | int N = arr.length; 34 | for (int i = 0; i < N; i++) { 35 | for (int k = i + 1; k < N; k++) { 36 | for (int j = k + 1; j < N; j++) { 37 | if (arr[i] + arr[j] == 2 * arr[k]) { 38 | return false; 39 | } 40 | } 41 | } 42 | } 43 | return true; 44 | } 45 | 46 | public static void main(String[] args) { 47 | System.out.println("test begin"); 48 | for (int N = 1; N < 1000; N++) { 49 | int[] arr = makeNo(N); 50 | if (!isValid(arr)) { 51 | System.out.println("Oops!"); 52 | } 53 | } 54 | System.out.println("test end"); 55 | System.out.println(isValid(makeNo(1042))); 56 | System.out.println(isValid(makeNo(2981))); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/class04/Code07_InterleavingString.java: -------------------------------------------------------------------------------- 1 | package class04; 2 | 3 | // 本题测试链接 : https://leetcode.com/problems/interleaving-string/ 4 | public class Code07_InterleavingString { 5 | 6 | public static boolean isInterleave(String s1, String s2, String s3) { 7 | if (s1 == null || s2 == null || s3 == null) { 8 | return false; 9 | } 10 | char[] str1 = s1.toCharArray(); 11 | char[] str2 = s2.toCharArray(); 12 | char[] str3 = s3.toCharArray(); 13 | if (str3.length != str1.length + str2.length) { 14 | return false; 15 | } 16 | boolean[][] dp = new boolean[str1.length + 1][str2.length + 1]; 17 | dp[0][0] = true; 18 | for (int i = 1; i <= str1.length; i++) { 19 | if (str1[i - 1] != str3[i - 1]) { 20 | break; 21 | } 22 | dp[i][0] = true; 23 | } 24 | for (int j = 1; j <= str2.length; j++) { 25 | if (str2[j - 1] != str3[j - 1]) { 26 | break; 27 | } 28 | dp[0][j] = true; 29 | } 30 | for (int i = 1; i <= str1.length; i++) { 31 | for (int j = 1; j <= str2.length; j++) { 32 | if ( 33 | (str1[i - 1] == str3[i + j - 1] && dp[i - 1][j]) 34 | 35 | 36 | 37 | 38 | || 39 | 40 | 41 | 42 | (str2[j - 1] == str3[i + j - 1] && dp[i][j - 1]) 43 | 44 | 45 | ) { 46 | dp[i][j] = true; 47 | } 48 | } 49 | } 50 | return dp[str1.length][str2.length]; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/class05/Hash.java: -------------------------------------------------------------------------------- 1 | package class05; 2 | 3 | import java.security.MessageDigest; 4 | import java.security.NoSuchAlgorithmException; 5 | import java.security.Security; 6 | 7 | import javax.xml.bind.DatatypeConverter; 8 | 9 | public class Hash { 10 | 11 | private MessageDigest hash; 12 | 13 | public Hash(String algorithm) { 14 | try { 15 | hash = MessageDigest.getInstance(algorithm); 16 | } catch (NoSuchAlgorithmException e) { 17 | e.printStackTrace(); 18 | } 19 | } 20 | 21 | public String hashCode(String input) { 22 | return DatatypeConverter.printHexBinary(hash.digest(input.getBytes())).toUpperCase(); 23 | } 24 | 25 | public static void main(String[] args) { 26 | System.out.println("支持的算法 : "); 27 | for (String str : Security.getAlgorithms("MessageDigest")) { 28 | System.out.println(str); 29 | } 30 | System.out.println("======="); 31 | 32 | String algorithm = "SHA-256"; 33 | Hash hash = new Hash(algorithm); 34 | 35 | String input1 = "zuochengyunzuochengyun1"; 36 | String input2 = "zuochengyunzuochengyun2"; 37 | String input3 = "zuochengyunzuochengyun3"; 38 | String input4 = "zuochengyunzuochengyun4"; 39 | String input5 = "zuochengyunzuochengyun5"; 40 | System.out.println(hash.hashCode(input1)); 41 | System.out.println(hash.hashCode(input2)); 42 | System.out.println(hash.hashCode(input3)); 43 | System.out.println(hash.hashCode(input4)); 44 | System.out.println(hash.hashCode(input5)); 45 | 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/class06/Code02_MaximumXorOfTwoNumbersInAnArray.java: -------------------------------------------------------------------------------- 1 | package class06; 2 | 3 | // 本题测试链接 : https://leetcode.com/problems/maximum-xor-of-two-numbers-in-an-array/ 4 | public class Code02_MaximumXorOfTwoNumbersInAnArray { 5 | 6 | public static class Node { 7 | public Node[] nexts = new Node[2]; 8 | } 9 | 10 | public static class NumTrie { 11 | public Node head = new Node(); 12 | 13 | public void add(int newNum) { 14 | Node cur = head; 15 | for (int move = 31; move >= 0; move--) { 16 | int path = ((newNum >> move) & 1); 17 | cur.nexts[path] = cur.nexts[path] == null ? new Node() : cur.nexts[path]; 18 | cur = cur.nexts[path]; 19 | } 20 | } 21 | 22 | public int maxXor(int sum) { 23 | Node cur = head; 24 | int res = 0; 25 | for (int move = 31; move >= 0; move--) { 26 | int path = (sum >> move) & 1; 27 | int best = move == 31 ? path : (path ^ 1); 28 | best = cur.nexts[best] != null ? best : (best ^ 1); 29 | res |= (path ^ best) << move; 30 | cur = cur.nexts[best]; 31 | } 32 | return res; 33 | } 34 | } 35 | 36 | public static int findMaximumXOR(int[] arr) { 37 | if (arr == null || arr.length < 2) { 38 | return 0; 39 | } 40 | int max = Integer.MIN_VALUE; 41 | NumTrie numTrie = new NumTrie(); 42 | numTrie.add(arr[0]); 43 | for (int i = 1; i < arr.length; i++) { 44 | max = Math.max(max, numTrie.maxXor(arr[i])); 45 | numTrie.add(arr[i]); 46 | } 47 | return max; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/class06/Code03_MaximumXorWithAnElementFromArray.java: -------------------------------------------------------------------------------- 1 | package class06; 2 | 3 | // 测试链接 : https://leetcode.com/problems/maximum-xor-with-an-element-from-array/ 4 | public class Code03_MaximumXorWithAnElementFromArray { 5 | 6 | public static int[] maximizeXor(int[] nums, int[][] queries) { 7 | int N = nums.length; 8 | NumTrie trie = new NumTrie(); 9 | for (int i = 0; i < N; i++) { 10 | trie.add(nums[i]); 11 | } 12 | int M = queries.length; 13 | int[] ans = new int[M]; 14 | for (int i = 0; i < M; i++) { 15 | ans[i] = trie.maxXorWithXBehindM(queries[i][0], queries[i][1]); 16 | } 17 | return ans; 18 | } 19 | 20 | public static class Node { 21 | public int min; 22 | public Node[] nexts; 23 | 24 | public Node() { 25 | min = Integer.MAX_VALUE; 26 | nexts = new Node[2]; 27 | } 28 | } 29 | 30 | public static class NumTrie { 31 | public Node head = new Node(); 32 | 33 | public void add(int num) { 34 | Node cur = head; 35 | head.min = Math.min(head.min, num); 36 | for (int move = 30; move >= 0; move--) { 37 | int path = ((num >> move) & 1); 38 | cur.nexts[path] = cur.nexts[path] == null ? new Node() : cur.nexts[path]; 39 | cur = cur.nexts[path]; 40 | cur.min = Math.min(cur.min, num); 41 | } 42 | } 43 | 44 | // 这个结构中,已经收集了一票数字 45 | // 请返回哪个数字与X异或的结果最大,返回最大结果 46 | // 但是,只有<=m的数字,可以被考虑 47 | public int maxXorWithXBehindM(int x, int m) { 48 | if (head.min > m) { 49 | return -1; 50 | } 51 | // 一定存在某个数可以和x结合 52 | Node cur = head; 53 | int ans = 0; 54 | for (int move = 30; move >= 0; move--) { 55 | int path = (x >> move) & 1; 56 | // 期待遇到的东西 57 | int best = (path ^ 1); 58 | best ^= (cur.nexts[best] == null || cur.nexts[best].min > m) ? 1 : 0; 59 | // best变成了实际遇到的 60 | ans |= (path ^ best) << move; 61 | cur = cur.nexts[best]; 62 | } 63 | return ans; 64 | } 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/class06/Code05_Nim.java: -------------------------------------------------------------------------------- 1 | package class06; 2 | 3 | public class Code05_Nim { 4 | 5 | // 保证arr是正数数组 6 | public static void printWinner(int[] arr) { 7 | int eor = 0; 8 | for (int num : arr) { 9 | eor ^= num; 10 | } 11 | if (eor == 0) { 12 | System.out.println("后手赢"); 13 | } else { 14 | System.out.println("先手赢"); 15 | } 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/class08/Code01_ExpressionCompute.java: -------------------------------------------------------------------------------- 1 | package class08; 2 | 3 | import java.util.LinkedList; 4 | 5 | // 本题测试链接 : https://leetcode.com/problems/basic-calculator-iii/ 6 | public class Code01_ExpressionCompute { 7 | 8 | public static int calculate(String str) { 9 | return f(str.toCharArray(), 0)[0]; 10 | } 11 | 12 | // 请从str[i...]往下算,遇到字符串终止位置或者右括号,就停止 13 | // 返回两个值,长度为2的数组 14 | // 0) 负责的这一段的结果是多少 15 | // 1) 负责的这一段计算到了哪个位置 16 | public static int[] f(char[] str, int i) { 17 | LinkedList que = new LinkedList(); 18 | int cur = 0; 19 | int[] bra = null; 20 | // 从i出发,开始撸串 21 | while (i < str.length && str[i] != ')') { 22 | if (str[i] >= '0' && str[i] <= '9') { 23 | cur = cur * 10 + str[i++] - '0'; 24 | } else if (str[i] != '(') { // 遇到的是运算符号 25 | addNum(que, cur); 26 | que.addLast(String.valueOf(str[i++])); 27 | cur = 0; 28 | } else { // 遇到左括号了 29 | bra = f(str, i + 1); 30 | cur = bra[0]; 31 | i = bra[1] + 1; 32 | } 33 | } 34 | addNum(que, cur); 35 | return new int[] { getNum(que), i }; 36 | } 37 | 38 | public static void addNum(LinkedList que, int num) { 39 | if (!que.isEmpty()) { 40 | int cur = 0; 41 | String top = que.pollLast(); 42 | if (top.equals("+") || top.equals("-")) { 43 | que.addLast(top); 44 | } else { 45 | cur = Integer.valueOf(que.pollLast()); 46 | num = top.equals("*") ? (cur * num) : (cur / num); 47 | } 48 | } 49 | que.addLast(String.valueOf(num)); 50 | } 51 | 52 | public static int getNum(LinkedList que) { 53 | int res = 0; 54 | boolean add = true; 55 | String cur = null; 56 | int num = 0; 57 | while (!que.isEmpty()) { 58 | cur = que.pollFirst(); 59 | if (cur.equals("+")) { 60 | add = true; 61 | } else if (cur.equals("-")) { 62 | add = false; 63 | } else { 64 | num = Integer.valueOf(cur); 65 | res += add ? num : (-num); 66 | } 67 | } 68 | return res; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/class08/Code02_ContainerWithMostWater.java: -------------------------------------------------------------------------------- 1 | package class08; 2 | 3 | // 本题测试链接 : https://leetcode.com/problems/container-with-most-water/ 4 | public class Code02_ContainerWithMostWater { 5 | 6 | public static int maxArea1(int[] h) { 7 | int max = 0; 8 | int N = h.length; 9 | for (int i = 0; i < N; i++) { // h[i] 10 | for (int j = i + 1; j < N; j++) { // h[j] 11 | max = Math.max(max, Math.min(h[i], h[j]) * (j - i)); 12 | } 13 | } 14 | return max; 15 | } 16 | 17 | public static int maxArea2(int[] h) { 18 | int max = 0; 19 | int l = 0; 20 | int r = h.length - 1; 21 | while (l < r) { 22 | max = Math.max(max, Math.min(h[l], h[r]) * (r - l)); 23 | if (h[l] > h[r]) { 24 | r--; 25 | } else { 26 | l++; 27 | } 28 | } 29 | return max; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/class09/Code02_RemoveInvalidParentheses.java: -------------------------------------------------------------------------------- 1 | package class09; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | // 测试链接 : https://leetcode.com/problems/remove-invalid-parentheses/ 7 | public class Code02_RemoveInvalidParentheses { 8 | 9 | // 来自leetcode投票第一的答案,实现非常好,我们来赏析一下 10 | public static List removeInvalidParentheses(String s) { 11 | List ans = new ArrayList<>(); 12 | remove(s, ans, 0, 0, new char[] { '(', ')' }); 13 | return ans; 14 | } 15 | 16 | // modifyIndex <= checkIndex 17 | // 只查s[checkIndex....]的部分,因为之前的一定已经调整对了 18 | // 但是之前的部分是怎么调整对的,调整到了哪?就是modifyIndex 19 | // 比如: 20 | // ( ( ) ( ) ) ) ... 21 | // 0 1 2 3 4 5 6 22 | // 一开始当然checkIndex = 0,modifyIndex = 0 23 | // 当查到6的时候,发现不对了, 24 | // 然后可以去掉2位置、4位置的 ),都可以 25 | // 如果去掉2位置的 ), 那么下一步就是 26 | // ( ( ( ) ) ) ... 27 | // 0 1 2 3 4 5 6 28 | // checkIndex = 6 ,modifyIndex = 2 29 | // 如果去掉4位置的 ), 那么下一步就是 30 | // ( ( ) ( ) ) ... 31 | // 0 1 2 3 4 5 6 32 | // checkIndex = 6 ,modifyIndex = 4 33 | // 也就是说, 34 | // checkIndex和modifyIndex,分别表示查的开始 和 调的开始,之前的都不用管了 par ( ) 35 | public static void remove(String s, List ans, int checkIndex, int deleteIndex, char[] par) { 36 | for (int count = 0, i = checkIndex; i < s.length(); i++) { 37 | if (s.charAt(i) == par[0]) { 38 | count++; 39 | } 40 | if (s.charAt(i) == par[1]) { 41 | count--; 42 | } 43 | // i check计数<0的第一个位置 44 | if (count < 0) { 45 | for (int j = deleteIndex; j <= i; ++j) { 46 | // 比如 47 | if (s.charAt(j) == par[1] && (j == deleteIndex || s.charAt(j - 1) != par[1])) { 48 | remove( 49 | s.substring(0, j) + s.substring(j + 1, s.length()), 50 | ans, i, j, par); 51 | } 52 | } 53 | return; 54 | } 55 | } 56 | String reversed = new StringBuilder(s).reverse().toString(); 57 | if (par[0] == '(') { 58 | remove(reversed, ans, 0, 0, new char[] { ')', '(' }); 59 | } else { 60 | ans.add(reversed); 61 | } 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/class09/Code03_LIS.java: -------------------------------------------------------------------------------- 1 | package class09; 2 | 3 | // 本题测试链接 : https://leetcode.com/problems/longest-increasing-subsequence 4 | public class Code03_LIS { 5 | 6 | public static int lengthOfLIS(int[] arr) { 7 | if (arr == null || arr.length == 0) { 8 | return 0; 9 | } 10 | int[] ends = new int[arr.length]; 11 | ends[0] = arr[0]; 12 | int right = 0; 13 | int l = 0; 14 | int r = 0; 15 | int m = 0; 16 | int max = 1; 17 | for (int i = 1; i < arr.length; i++) { 18 | l = 0; 19 | r = right; 20 | while (l <= r) { 21 | m = (l + r) / 2; 22 | if (arr[i] > ends[m]) { 23 | l = m + 1; 24 | } else { 25 | r = m - 1; 26 | } 27 | } 28 | right = Math.max(right, l); 29 | ends[l] = arr[i]; 30 | max = Math.max(max, l + 1); 31 | } 32 | return max; 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /src/class09/Code04_EnvelopesProblem.java: -------------------------------------------------------------------------------- 1 | package class09; 2 | 3 | import java.util.Arrays; 4 | import java.util.Comparator; 5 | 6 | // 本题测试链接 : https://leetcode.com/problems/russian-doll-envelopes/ 7 | public class Code04_EnvelopesProblem { 8 | 9 | public static int maxEnvelopes(int[][] matrix) { 10 | Envelope[] arr = sort(matrix); 11 | int[] ends = new int[matrix.length]; 12 | ends[0] = arr[0].h; 13 | int right = 0; 14 | int l = 0; 15 | int r = 0; 16 | int m = 0; 17 | for (int i = 1; i < arr.length; i++) { 18 | l = 0; 19 | r = right; 20 | while (l <= r) { 21 | m = (l + r) / 2; 22 | if (arr[i].h > ends[m]) { 23 | l = m + 1; 24 | } else { 25 | r = m - 1; 26 | } 27 | } 28 | right = Math.max(right, l); 29 | ends[l] = arr[i].h; 30 | } 31 | return right + 1; 32 | } 33 | 34 | public static class Envelope { 35 | public int l; 36 | public int h; 37 | 38 | public Envelope(int weight, int hight) { 39 | l = weight; 40 | h = hight; 41 | } 42 | } 43 | 44 | public static class EnvelopeComparator implements Comparator { 45 | @Override 46 | public int compare(Envelope o1, Envelope o2) { 47 | return o1.l != o2.l ? o1.l - o2.l : o2.h - o1.h; 48 | } 49 | } 50 | 51 | public static Envelope[] sort(int[][] matrix) { 52 | Envelope[] res = new Envelope[matrix.length]; 53 | for (int i = 0; i < matrix.length; i++) { 54 | res[i] = new Envelope(matrix[i][0], matrix[i][1]); 55 | } 56 | Arrays.sort(res, new EnvelopeComparator()); 57 | return res; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/class09/Code05_IsStepSum.java: -------------------------------------------------------------------------------- 1 | package class09; 2 | 3 | import java.util.HashMap; 4 | 5 | public class Code05_IsStepSum { 6 | 7 | public static boolean isStepSum(int stepSum) { 8 | int L = 0; 9 | int R = stepSum; 10 | int M = 0; 11 | int cur = 0; 12 | while (L <= R) { 13 | M = L + ((R - L) >> 1); 14 | cur = stepSum(M); 15 | if (cur == stepSum) { 16 | return true; 17 | } else if (cur < stepSum) { 18 | L = M + 1; 19 | } else { 20 | R = M - 1; 21 | } 22 | } 23 | return false; 24 | } 25 | 26 | public static int stepSum(int num) { 27 | int sum = 0; 28 | while (num != 0) { 29 | sum += num; 30 | num /= 10; 31 | } 32 | return sum; 33 | } 34 | 35 | // for test 36 | public static HashMap generateStepSumNumberMap(int numMax) { 37 | HashMap map = new HashMap<>(); 38 | for (int i = 0; i <= numMax; i++) { 39 | map.put(stepSum(i), i); 40 | } 41 | return map; 42 | } 43 | 44 | // for test 45 | public static void main(String[] args) { 46 | int max = 1000000; 47 | int maxStepSum = stepSum(max); 48 | HashMap ans = generateStepSumNumberMap(max); 49 | System.out.println("测试开始"); 50 | for (int i = 0; i <= maxStepSum; i++) { 51 | if (isStepSum(i) ^ ans.containsKey(i)) { 52 | System.out.println("出错了!"); 53 | } 54 | } 55 | System.out.println("测试结束"); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/class10/Code01_JumpGame.java: -------------------------------------------------------------------------------- 1 | package class10; 2 | 3 | // 本题测试链接 : https://leetcode.com/problems/jump-game-ii/ 4 | public class Code01_JumpGame { 5 | 6 | public static int jump(int[] arr) { 7 | if (arr == null || arr.length == 0) { 8 | return 0; 9 | } 10 | int step = 0; 11 | int cur = 0; 12 | int next = 0; 13 | for (int i = 0; i < arr.length; i++) { 14 | if (cur < i) { 15 | step++; 16 | cur = next; 17 | } 18 | next = Math.max(next, i + arr[i]); 19 | } 20 | return step; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/class10/Code03_KInversePairs.java: -------------------------------------------------------------------------------- 1 | package class10; 2 | 3 | // 测试链接 : https://leetcode.com/problems/k-inverse-pairs-array/ 4 | public class Code03_KInversePairs { 5 | 6 | public static int kInversePairs(int n, int k) { 7 | if (n < 1 || k < 0) { 8 | return 0; 9 | } 10 | int[][] dp = new int[n + 1][k + 1]; 11 | dp[0][0] = 1; 12 | int mod = 1000000007; 13 | for (int i = 1; i <= n; i++) { 14 | dp[i][0] = 1; 15 | for (int j = 1; j <= k; j++) { 16 | dp[i][j] = (dp[i][j - 1] + dp[i - 1][j]) % mod; 17 | if (j >= i) { 18 | dp[i][j] = (dp[i][j] - dp[i - 1][j - i] + mod) % mod; 19 | } 20 | } 21 | } 22 | return dp[n][k]; 23 | } 24 | 25 | public static int kInversePairs2(int n, int k) { 26 | if (n < 1 || k < 0) { 27 | return 0; 28 | } 29 | int[][] dp = new int[n + 1][k + 1]; 30 | dp[0][0] = 1; 31 | for (int i = 1; i <= n; i++) { 32 | dp[i][0] = 1; 33 | for (int j = 1; j <= k; j++) { 34 | dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; 35 | if (j >= i) { 36 | dp[i][j] -= dp[i - 1][j - i]; 37 | } 38 | } 39 | } 40 | return dp[n][k]; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/class10/Code04_BSTtoDoubleLinkedList.java: -------------------------------------------------------------------------------- 1 | package class10; 2 | 3 | // 本题测试链接 : https://leetcode.com/problems/convert-binary-search-tree-to-sorted-doubly-linked-list/ 4 | public class Code04_BSTtoDoubleLinkedList { 5 | 6 | // 提交时不要提交这个类 7 | public static class Node { 8 | public int value; 9 | public Node left; 10 | public Node right; 11 | 12 | public Node(int data) { 13 | this.value = data; 14 | } 15 | } 16 | 17 | // 提交下面的代码 18 | public static Node treeToDoublyList(Node head) { 19 | if (head == null) { 20 | return null; 21 | } 22 | Info allInfo = process(head); 23 | allInfo.end.right = allInfo.start; 24 | allInfo.start.left = allInfo.end; 25 | return allInfo.start; 26 | } 27 | 28 | public static class Info { 29 | public Node start; 30 | public Node end; 31 | 32 | public Info(Node start, Node end) { 33 | this.start = start; 34 | this.end = end; 35 | } 36 | } 37 | 38 | public static Info process(Node X) { 39 | if (X == null) { 40 | return new Info(null, null); 41 | } 42 | Info lInfo = process(X.left); 43 | Info rInfo = process(X.right); 44 | if (lInfo.end != null) { 45 | lInfo.end.right = X; 46 | } 47 | X.left = lInfo.end; 48 | X.right = rInfo.start; 49 | if (rInfo.start != null) { 50 | rInfo.start.left = X; 51 | } 52 | // 整体链表的头 lInfo.start != null ? lInfo.start : X 53 | // 整体链表的尾 rInfo.end != null ? rInfo.end : X 54 | return new Info(lInfo.start != null ? lInfo.start : X, rInfo.end != null ? rInfo.end : X); 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /src/class12/Code03_LongestConsecutive.java: -------------------------------------------------------------------------------- 1 | package class12; 2 | 3 | import java.util.HashMap; 4 | 5 | // 本题测试链接 : https://leetcode.com/problems/longest-consecutive-sequence/ 6 | public class Code03_LongestConsecutive { 7 | 8 | public static int longestConsecutive(int[] nums) { 9 | HashMap map = new HashMap<>(); 10 | int len = 0; 11 | for (int num : nums) { 12 | if (!map.containsKey(num)) { 13 | map.put(num, 1); 14 | int preLen = map.containsKey(num - 1) ? map.get(num - 1) : 0; 15 | int posLen = map.containsKey(num + 1) ? map.get(num + 1) : 0; 16 | int all = preLen + posLen + 1; 17 | map.put(num - preLen, all); 18 | map.put(num + posLen, all); 19 | len = Math.max(len, all); 20 | } 21 | } 22 | return len; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/class13/Code02_SuperWashingMachines.java: -------------------------------------------------------------------------------- 1 | package class13; 2 | 3 | // 本题测试链接 : https://leetcode.com/problems/super-washing-machines/ 4 | public class Code02_SuperWashingMachines { 5 | 6 | public static int findMinMoves(int[] arr) { 7 | if (arr == null || arr.length == 0) { 8 | return 0; 9 | } 10 | int size = arr.length; 11 | int sum = 0; 12 | for (int i = 0; i < size; i++) { 13 | sum += arr[i]; 14 | } 15 | if (sum % size != 0) { 16 | return -1; 17 | } 18 | int avg = sum / size; 19 | int leftSum = 0; 20 | int ans = 0; 21 | for (int i = 0; i < arr.length; i++) { 22 | int leftRest = leftSum - i * avg; 23 | int rightRest = (sum - leftSum - arr[i]) - (size - i - 1) * avg; 24 | if (leftRest < 0 && rightRest < 0) { 25 | ans = Math.max(ans, Math.abs(leftRest) + Math.abs(rightRest)); 26 | } else { 27 | ans = Math.max(ans, Math.max(Math.abs(leftRest), Math.abs(rightRest))); 28 | } 29 | leftSum += arr[i]; 30 | } 31 | return ans; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/class14/Code02_MaxSubArraySumLessOrEqualK.java: -------------------------------------------------------------------------------- 1 | package class14; 2 | 3 | import java.util.TreeSet; 4 | 5 | public class Code02_MaxSubArraySumLessOrEqualK { 6 | 7 | // 请返回arr中,求个子数组的累加和,是<=K的,并且是最大的。 8 | // 返回这个最大的累加和 9 | public static int getMaxLessOrEqualK(int[] arr, int K) { 10 | // 记录i之前的,前缀和,按照有序表组织 11 | TreeSet set = new TreeSet(); 12 | // 一个数也没有的时候,就已经有一个前缀和是0了 13 | set.add(0); 14 | int max = Integer.MIN_VALUE; 15 | int sum = 0; 16 | // 每一步的i,都求子数组必须以i结尾的情况下,求个子数组的累加和,是<=K的,并且是最大的 17 | for (int i = 0; i < arr.length; i++) { 18 | sum += arr[i]; // sum -> arr[0..i]; 19 | if (set.ceiling(sum - K) != null) { 20 | max = Math.max(max, sum - set.ceiling(sum - K)); 21 | } 22 | set.add(sum); // 当前的前缀和加入到set中去 23 | } 24 | return max; 25 | 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/class14/Code03_BiggestBSTTopologyInTree.java: -------------------------------------------------------------------------------- 1 | package class14; 2 | 3 | // 本题测试链接 : https://www.nowcoder.com/practice/e13bceaca5b14860b83cbcc4912c5d4a 4 | // 提交以下的代码,并把主类名改成Main 5 | // 可以直接通过 6 | import java.util.Scanner; 7 | 8 | public class Code03_BiggestBSTTopologyInTree { 9 | 10 | public static void main(String[] args) { 11 | Scanner sc = new Scanner(System.in); 12 | int n = sc.nextInt(); 13 | int h = sc.nextInt(); 14 | int[][] tree = new int[n + 1][3]; 15 | for (int i = 1; i <= n; i++) { 16 | int c = sc.nextInt(); 17 | int l = sc.nextInt(); 18 | int r = sc.nextInt(); 19 | tree[l][0] = c; 20 | tree[r][0] = c; 21 | tree[c][1] = l; 22 | tree[c][2] = r; 23 | } 24 | System.out.println(maxBSTTopology(h, tree, new int[n + 1])); 25 | sc.close(); 26 | } 27 | 28 | // h: 代表当前的头节点 29 | // t: 代表树 t[i][0]是i节点的父节点、t[i][1]是i节点的左孩子、t[i][2]是i节点的右孩子 30 | // m: i节点为头的最大bst拓扑结构大小 -> m[i] 31 | // 返回: 以h为头的整棵树上,最大bst拓扑结构的大小 32 | public static int maxBSTTopology(int h, int[][] t, int[] m) { 33 | if (h == 0) { 34 | return 0; 35 | } 36 | int l = t[h][1]; 37 | int r = t[h][2]; 38 | int c = 0; 39 | int p1 = maxBSTTopology(l, t, m); 40 | int p2 = maxBSTTopology(r, t, m); 41 | while (l < h && m[l] != 0) { 42 | l = t[l][2]; 43 | } 44 | if (m[l] != 0) { 45 | c = m[l]; 46 | while (l != h) { 47 | m[l] -= c; 48 | l = t[l][0]; 49 | } 50 | } 51 | while (r > h && m[r] != 0) { 52 | r = t[r][1]; 53 | } 54 | if (m[r] != 0) { 55 | c = m[r]; 56 | while (r != h) { 57 | m[r] -= c; 58 | r = t[r][0]; 59 | } 60 | } 61 | m[h] = m[t[h][1]] + m[t[h][2]] + 1; 62 | return Math.max(Math.max(p1, p2), m[h]); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/class14/Code04_CompleteTreeNodeNumber.java: -------------------------------------------------------------------------------- 1 | package class14; 2 | 3 | public class Code04_CompleteTreeNodeNumber { 4 | 5 | public static class Node { 6 | public int value; 7 | public Node left; 8 | public Node right; 9 | 10 | public Node(int data) { 11 | this.value = data; 12 | } 13 | } 14 | 15 | // 请保证head为头的树,是完全二叉树 16 | public static int nodeNum(Node head) { 17 | if (head == null) { 18 | return 0; 19 | } 20 | return bs(head, 1, mostLeftLevel(head, 1)); 21 | } 22 | 23 | // 当前来到node节点,node节点在level层,总层数是h 24 | // 返回node为头的子树(必是完全二叉树),有多少个节点 25 | public static int bs(Node node, int Level, int h) { 26 | if (Level == h) { 27 | return 1; 28 | } 29 | if (mostLeftLevel(node.right, Level + 1) == h) { 30 | return (1 << (h - Level)) + bs(node.right, Level + 1, h); 31 | } else { 32 | return (1 << (h - Level - 1)) + bs(node.left, Level + 1, h); 33 | } 34 | } 35 | 36 | // 如果node在第level层, 37 | // 求以node为头的子树,最大深度是多少 38 | // node为头的子树,一定是完全二叉树 39 | public static int mostLeftLevel(Node node, int level) { 40 | while (node != null) { 41 | level++; 42 | node = node.left; 43 | } 44 | return level - 1; 45 | } 46 | 47 | public static void main(String[] args) { 48 | Node head = new Node(1); 49 | head.left = new Node(2); 50 | head.right = new Node(3); 51 | head.left.left = new Node(4); 52 | head.left.right = new Node(5); 53 | head.right.left = new Node(6); 54 | System.out.println(nodeNum(head)); 55 | 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/class14/Code06_MissingNumber.java: -------------------------------------------------------------------------------- 1 | package class14; 2 | 3 | // 测试链接:https://leetcode.com/problems/first-missing-positive/ 4 | public class Code06_MissingNumber { 5 | 6 | public static int firstMissingPositive(int[] arr) { 7 | // l是盯着的位置 8 | // 0 ~ L-1有效区 9 | int L = 0; 10 | int R = arr.length; 11 | while (L != R) { 12 | if (arr[L] == L + 1) { 13 | L++; 14 | } else if (arr[L] <= L || arr[L] > R || arr[arr[L] - 1] == arr[L]) { // 垃圾的情况 15 | swap(arr, L, --R); 16 | } else { 17 | swap(arr, L, arr[L] - 1); 18 | } 19 | } 20 | return L + 1; 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 | } 30 | -------------------------------------------------------------------------------- /src/class15/Code01_BestTimeToBuyAndSellStock.java: -------------------------------------------------------------------------------- 1 | package class15; 2 | 3 | // leetcode 121 4 | public class Code01_BestTimeToBuyAndSellStock { 5 | 6 | public static int maxProfit(int[] prices) { 7 | if (prices == null || prices.length == 0) { 8 | return 0; 9 | } 10 | // 必须在0时刻卖掉,[0] - [0] 11 | int ans = 0; 12 | // arr[0...0] 13 | int min = prices[0]; 14 | for (int i = 1; i < prices.length; i++) { 15 | min = Math.min(min, prices[i]); 16 | ans = Math.max(ans, prices[i] - min); 17 | } 18 | return ans; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/class15/Code02_BestTimeToBuyAndSellStockII.java: -------------------------------------------------------------------------------- 1 | package class15; 2 | 3 | //leetcode 122 4 | public class Code02_BestTimeToBuyAndSellStockII { 5 | 6 | public static int maxProfit(int[] prices) { 7 | if (prices == null || prices.length == 0) { 8 | return 0; 9 | } 10 | int ans = 0; 11 | for (int i = 1; i < prices.length; i++) { 12 | ans += Math.max(prices[i] - prices[i-1], 0); 13 | } 14 | return ans; 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/class15/Code03_BestTimeToBuyAndSellStockIII.java: -------------------------------------------------------------------------------- 1 | package class15; 2 | 3 | //leetcode 123 4 | public class Code03_BestTimeToBuyAndSellStockIII { 5 | 6 | public static int maxProfit(int[] prices) { 7 | if (prices == null || prices.length < 2) { 8 | return 0; 9 | } 10 | int ans = 0; 11 | int doneOnceMinusBuyMax = -prices[0]; 12 | int doneOnceMax = 0; 13 | int min = prices[0]; 14 | for (int i = 1; i < prices.length; i++) { 15 | min = Math.min(min, prices[i]); 16 | ans = Math.max(ans, doneOnceMinusBuyMax + prices[i]); 17 | doneOnceMax = Math.max(doneOnceMax, prices[i] - min); 18 | doneOnceMinusBuyMax = Math.max(doneOnceMinusBuyMax, doneOnceMax - prices[i]); 19 | } 20 | return ans; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/class15/Code04_BestTimeToBuyAndSellStockIV.java: -------------------------------------------------------------------------------- 1 | package class15; 2 | 3 | //leetcode 188 4 | public class Code04_BestTimeToBuyAndSellStockIV { 5 | 6 | public static int maxProfit(int K, int[] prices) { 7 | if (prices == null || prices.length == 0) { 8 | return 0; 9 | } 10 | int N = prices.length; 11 | if (K >= N / 2) { 12 | return allTrans(prices); 13 | } 14 | int[][] dp = new int[K + 1][N]; 15 | int ans = 0; 16 | for (int tran = 1; tran <= K; tran++) { 17 | int pre = dp[tran][0]; 18 | int best = pre - prices[0]; 19 | for (int index = 1; index < N; index++) { 20 | pre = dp[tran - 1][index]; 21 | dp[tran][index] = Math.max(dp[tran][index - 1], prices[index] + best); 22 | best = Math.max(best, pre - prices[index]); 23 | ans = Math.max(dp[tran][index], ans); 24 | } 25 | } 26 | return ans; 27 | } 28 | 29 | public static int allTrans(int[] prices) { 30 | int ans = 0; 31 | for (int i = 1; i < prices.length; i++) { 32 | ans += Math.max(prices[i] - prices[i - 1], 0); 33 | } 34 | return ans; 35 | } 36 | 37 | // 课上写的版本,对了 38 | public static int maxProfit2(int K, int[] arr) { 39 | if (arr == null || arr.length == 0 || K < 1) { 40 | return 0; 41 | } 42 | int N = arr.length; 43 | if (K >= N / 2) { 44 | return allTrans(arr); 45 | } 46 | int[][] dp = new int[N][K + 1]; 47 | // dp[...][0] = 0 48 | // dp[0][...] = arr[0.0] 0 49 | for (int j = 1; j <= K; j++) { 50 | // dp[1][j] 51 | int p1 = dp[0][j]; 52 | int best = Math.max(dp[1][j - 1] - arr[1], dp[0][j - 1] - arr[0]); 53 | dp[1][j] = Math.max(p1, best + arr[1]); 54 | // dp[1][j] 准备好一些枚举,接下来准备好的枚举 55 | for (int i = 2; i < N; i++) { 56 | p1 = dp[i - 1][j]; 57 | int newP = dp[i][j - 1] - arr[i]; 58 | best = Math.max(newP, best); 59 | dp[i][j] = Math.max(p1, best + arr[i]); 60 | } 61 | } 62 | return dp[N - 1][K]; 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/class15/Code06_BestTimeToBuyAndSellStockWithTransactionFee.java: -------------------------------------------------------------------------------- 1 | package class15; 2 | 3 | //leetcode 714 4 | public class Code06_BestTimeToBuyAndSellStockWithTransactionFee { 5 | 6 | public static int maxProfit(int[] arr, int fee) { 7 | if (arr == null || arr.length < 2) { 8 | return 0; 9 | } 10 | int N = arr.length; 11 | // 0..0 0 -[0] - fee 12 | int bestbuy = -arr[0] - fee; 13 | // 0..0 卖 0 14 | int bestsell = 0; 15 | for (int i = 1; i < N; i++) { 16 | // 来到i位置了! 17 | // 如果在i必须买 收入 - 批发价 - fee 18 | int curbuy = bestsell - arr[i] - fee; 19 | // 如果在i必须卖 整体最优(收入 - 良好批发价 - fee) 20 | int cursell = bestbuy + arr[i]; 21 | bestbuy = Math.max(bestbuy, curbuy); 22 | bestsell = Math.max(bestsell, cursell); 23 | } 24 | return bestsell; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/class17/Code01_FindNumInSortedMatrix.java: -------------------------------------------------------------------------------- 1 | package class17; 2 | 3 | public class Code01_FindNumInSortedMatrix { 4 | 5 | public static boolean isContains(int[][] matrix, int K) { 6 | int row = 0; 7 | int col = matrix[0].length - 1; 8 | while (row < matrix.length && col > -1) { 9 | if (matrix[row][col] == K) { 10 | return true; 11 | } else if (matrix[row][col] > K) { 12 | col--; 13 | } else { 14 | row++; 15 | } 16 | } 17 | return false; 18 | } 19 | 20 | public static void main(String[] args) { 21 | int[][] matrix = new int[][] { { 0, 1, 2, 3, 4, 5, 6 }, // 0 22 | { 10, 12, 13, 15, 16, 17, 18 }, // 1 23 | { 23, 24, 25, 26, 27, 28, 29 }, // 2 24 | { 44, 45, 46, 47, 48, 49, 50 }, // 3 25 | { 65, 66, 67, 68, 69, 70, 71 }, // 4 26 | { 96, 97, 98, 99, 100, 111, 122 }, // 5 27 | { 166, 176, 186, 187, 190, 195, 200 }, // 6 28 | { 233, 243, 321, 341, 356, 370, 380 } // 7 29 | }; 30 | int K = 233; 31 | System.out.println(isContains(matrix, K)); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/class17/Code05_DistinctSubseqValue.java: -------------------------------------------------------------------------------- 1 | package class17; 2 | 3 | import java.util.HashMap; 4 | 5 | // 本题测试链接 : https://leetcode.com/problems/distinct-subsequences-ii/ 6 | public class Code05_DistinctSubseqValue { 7 | 8 | public static int distinctSubseqII(String s) { 9 | if (s == null || s.length() == 0) { 10 | return 0; 11 | } 12 | int m = 1000000007; 13 | char[] str = s.toCharArray(); 14 | int[] count = new int[26]; 15 | int all = 1; // 算空集 16 | for (char x : str) { 17 | int add = (all - count[x - 'a'] + m) % m; 18 | all = (all + add) % m; 19 | count[x - 'a'] = (count[x - 'a'] + add) % m; 20 | } 21 | return all - 1; 22 | } 23 | 24 | public static int zuo(String s) { 25 | if (s == null || s.length() == 0) { 26 | return 0; 27 | } 28 | int m = 1000000007; 29 | char[] str = s.toCharArray(); 30 | HashMap map = new HashMap<>(); 31 | int all = 1; // 一个字符也没遍历的时候,有空集 32 | for (char x : str) { 33 | int newAdd = all; 34 | // int curAll = all + newAdd - (map.containsKey(x) ? map.get(x) : 0); 35 | int curAll = all; 36 | curAll = (curAll + newAdd) % m; 37 | curAll = (curAll - (map.containsKey(x) ? map.get(x) : 0) + m) % m; 38 | all = curAll; 39 | map.put(x, newAdd); 40 | } 41 | return all; 42 | } 43 | 44 | public static void main(String[] args) { 45 | String s = "bccaccbaabbc"; 46 | System.out.println(distinctSubseqII(s) + 1); 47 | System.out.println(zuo(s)); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/class19/Code04_SmallestRangeCoveringElementsfromKLists.java: -------------------------------------------------------------------------------- 1 | package class19; 2 | 3 | import java.util.Comparator; 4 | import java.util.List; 5 | import java.util.TreeSet; 6 | 7 | // 本题测试链接 : https://leetcode.com/problems/smallest-range-covering-elements-from-k-lists/ 8 | public class Code04_SmallestRangeCoveringElementsfromKLists { 9 | 10 | public static class Node { 11 | public int value; 12 | public int arrid; 13 | public int index; 14 | 15 | public Node(int v, int ai, int i) { 16 | value = v; 17 | arrid = ai; 18 | index = i; 19 | } 20 | } 21 | 22 | public static class NodeComparator implements Comparator { 23 | 24 | @Override 25 | public int compare(Node o1, Node o2) { 26 | return o1.value != o2.value ? o1.value - o2.value : o1.arrid - o2.arrid; 27 | } 28 | 29 | } 30 | 31 | public static int[] smallestRange(List> nums) { 32 | int N = nums.size(); 33 | TreeSet orderSet = new TreeSet<>(new NodeComparator()); 34 | for (int i = 0; i < N; i++) { 35 | orderSet.add(new Node(nums.get(i).get(0), i, 0)); 36 | } 37 | boolean set = false; 38 | int a = 0; 39 | int b = 0; 40 | while (orderSet.size() == N) { 41 | Node min = orderSet.first(); 42 | Node max = orderSet.last(); 43 | if (!set || (max.value - min.value < b - a)) { 44 | set = true; 45 | a = min.value; 46 | b = max.value; 47 | } 48 | min = orderSet.pollFirst(); 49 | int arrid = min.arrid; 50 | int index = min.index + 1; 51 | if (index != nums.get(arrid).size()) { 52 | orderSet.add(new Node(nums.get(arrid).get(index), arrid, index)); 53 | } 54 | } 55 | return new int[] { a, b }; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/class22/Code02_TrappingRainWater.java: -------------------------------------------------------------------------------- 1 | package class22; 2 | 3 | // 本题测试链接 : https://leetcode.com/problems/trapping-rain-water/ 4 | public class Code02_TrappingRainWater { 5 | 6 | public static int trap(int[] arr) { 7 | if (arr == null || arr.length < 2) { 8 | return 0; 9 | } 10 | int N = arr.length; 11 | int L = 1; 12 | int leftMax = arr[0]; 13 | int R = N - 2; 14 | int rightMax = arr[N - 1]; 15 | int water = 0; 16 | while (L <= R) { 17 | if (leftMax <= rightMax) { 18 | water += Math.max(0, leftMax - arr[L]); 19 | leftMax = Math.max(leftMax, arr[L++]); 20 | } else { 21 | water += Math.max(0, rightMax - arr[R]); 22 | rightMax = Math.max(rightMax, arr[R--]); 23 | } 24 | } 25 | return water; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/class22/Code05_TallestBillboard.java: -------------------------------------------------------------------------------- 1 | package class22; 2 | 3 | import java.util.HashMap; 4 | 5 | // 本题测试链接 : https://leetcode.com/problems/tallest-billboard/ 6 | public class Code05_TallestBillboard { 7 | 8 | public int tallestBillboard(int[] rods) { 9 | // key 集合对的某个差 10 | // value 满足差值为key的集合对中,最好的一对,较小集合的累加和 11 | // 较大 -> value + key 12 | HashMap dp = new HashMap<>(), cur; 13 | dp.put(0, 0);// 空集 和 空集 14 | for (int num : rods) { 15 | if (num != 0) { 16 | // cur 内部数据完全和dp一样 17 | cur = new HashMap<>(dp); // 考虑x之前的集合差值状况拷贝下来 18 | for (int d : cur.keySet()) { 19 | int diffMore = cur.get(d); // 最好的一对,较小集合的累加和 20 | // x决定放入,比较大的那个 21 | dp.put(d + num, Math.max(diffMore, dp.getOrDefault(num + d, 0))); 22 | // x决定放入,比较小的那个 23 | // 新的差值 Math.abs(x - d) 24 | // 之前差值为Math.abs(x - d),的那一对,就要和这一对,决策一下 25 | // 之前那一对,较小集合的累加和diffXD 26 | int diffXD = dp.getOrDefault(Math.abs(num - d), 0); 27 | if (d >= num) { // x决定放入比较小的那个, 但是放入之后,没有超过这一对较大的那个 28 | dp.put(d - num, Math.max(diffMore + num, diffXD)); 29 | } else { // x决定放入比较小的那个, 但是放入之后,没有超过这一对较大的那个 30 | dp.put(num - d, Math.max(diffMore + d, diffXD)); 31 | } 32 | } 33 | } 34 | } 35 | return dp.get(0); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/class23/Code02_MaxABSBetweenLeftAndRight.java: -------------------------------------------------------------------------------- 1 | package class23; 2 | 3 | public class Code02_MaxABSBetweenLeftAndRight { 4 | 5 | public static int maxABS1(int[] arr) { 6 | int res = Integer.MIN_VALUE; 7 | int maxLeft = 0; 8 | int maxRight = 0; 9 | for (int i = 0; i != arr.length - 1; i++) { 10 | maxLeft = Integer.MIN_VALUE; 11 | for (int j = 0; j != i + 1; j++) { 12 | maxLeft = Math.max(arr[j], maxLeft); 13 | } 14 | maxRight = Integer.MIN_VALUE; 15 | for (int j = i + 1; j != arr.length; j++) { 16 | maxRight = Math.max(arr[j], maxRight); 17 | } 18 | res = Math.max(Math.abs(maxLeft - maxRight), res); 19 | } 20 | return res; 21 | } 22 | 23 | public static int maxABS2(int[] arr) { 24 | int[] lArr = new int[arr.length]; 25 | int[] rArr = new int[arr.length]; 26 | lArr[0] = arr[0]; 27 | rArr[arr.length - 1] = arr[arr.length - 1]; 28 | for (int i = 1; i < arr.length; i++) { 29 | lArr[i] = Math.max(lArr[i - 1], arr[i]); 30 | } 31 | for (int i = arr.length - 2; i > -1; i--) { 32 | rArr[i] = Math.max(rArr[i + 1], arr[i]); 33 | } 34 | int max = 0; 35 | for (int i = 0; i < arr.length - 1; i++) { 36 | max = Math.max(max, Math.abs(lArr[i] - rArr[i + 1])); 37 | } 38 | return max; 39 | } 40 | 41 | public static int maxABS3(int[] arr) { 42 | int max = Integer.MIN_VALUE; 43 | for (int i = 0; i < arr.length; i++) { 44 | max = Math.max(arr[i], max); 45 | } 46 | return max - Math.min(arr[0], arr[arr.length - 1]); 47 | } 48 | 49 | public static int[] generateRandomArray(int length) { 50 | int[] arr = new int[length]; 51 | for (int i = 0; i != arr.length; i++) { 52 | arr[i] = (int) (Math.random() * 1000) - 499; 53 | } 54 | return arr; 55 | } 56 | 57 | public static void main(String[] args) { 58 | int[] arr = generateRandomArray(200); 59 | System.out.println(maxABS1(arr)); 60 | System.out.println(maxABS2(arr)); 61 | System.out.println(maxABS3(arr)); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/class24/Code05_MinWindowLength.java: -------------------------------------------------------------------------------- 1 | package class24; 2 | 3 | public class Code05_MinWindowLength { 4 | 5 | public static int minLength(String s1, String s2) { 6 | if (s1 == null || s2 == null || s1.length() < s2.length()) { 7 | return Integer.MAX_VALUE; 8 | } 9 | char[] str1 = s1.toCharArray(); 10 | char[] str2 = s2.toCharArray(); 11 | int[] map = new int[256]; // map[37] = 4 37 4次 12 | for (int i = 0; i != str2.length; i++) { 13 | map[str2[i]]++; 14 | } 15 | int all = str2.length; 16 | 17 | // [L,R-1] R 18 | // [L,R) -> [0,0) 19 | int L = 0; 20 | int R = 0; 21 | int minLen = Integer.MAX_VALUE; 22 | while (R != str1.length) { 23 | map[str1[R]]--; 24 | if (map[str1[R]] >= 0) { 25 | all--; 26 | } 27 | if (all == 0) { // 还完了 28 | while (map[str1[L]] < 0) { 29 | map[str1[L++]]++; 30 | } 31 | // [L..R] 32 | minLen = Math.min(minLen, R - L + 1); 33 | all++; 34 | map[str1[L++]]++; 35 | } 36 | R++; 37 | } 38 | return minLen == Integer.MAX_VALUE ? 0 : minLen; 39 | } 40 | 41 | public static void main(String[] args) { 42 | String str1 = "adabbca"; 43 | String str2 = "acb"; 44 | System.out.println(minLength(str1, str2)); 45 | 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/class25/Code02_3Sum.java: -------------------------------------------------------------------------------- 1 | package class25; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | // 本题测试链接 : https://leetcode.com/problems/3sum/ 8 | public class Code02_3Sum { 9 | 10 | public static List> threeSum(int[] nums) { 11 | Arrays.sort(nums); 12 | int N = nums.length; 13 | List> ans = new ArrayList<>(); 14 | for (int i = N - 1; i > 1; i--) { // 三元组最后一个数,是arr[i] 之前....二元组 + arr[i] 15 | if (i == N - 1 || nums[i] != nums[i + 1]) { 16 | List> nexts = twoSum(nums, i - 1, -nums[i]); 17 | for (List cur : nexts) { 18 | cur.add(nums[i]); 19 | ans.add(cur); 20 | } 21 | } 22 | } 23 | return ans; 24 | } 25 | 26 | // nums[0...end]这个范围上,有多少个不同二元组,相加==target,全返回 27 | // {-1,5} K = 4 28 | // {1, 3} 29 | public static List> twoSum(int[] nums, int end, int target) { 30 | int L = 0; 31 | int R = end; 32 | List> ans = new ArrayList<>(); 33 | while (L < R) { 34 | if (nums[L] + nums[R] > target) { 35 | R--; 36 | } else if (nums[L] + nums[R] < target) { 37 | L++; 38 | } else { // nums[L] + nums[R] == target 39 | if (L == 0 || nums[L - 1] != nums[L]) { 40 | List cur = new ArrayList<>(); 41 | cur.add(nums[L]); 42 | cur.add(nums[R]); 43 | ans.add(cur); 44 | } 45 | L++; 46 | } 47 | } 48 | return ans; 49 | } 50 | 51 | public static int findPairs(int[] nums, int k) { 52 | Arrays.sort(nums); 53 | int left = 0, right = 1; 54 | int result = 0; 55 | while (left < nums.length && right < nums.length) { 56 | if (left == right || nums[right] - nums[left] < k) { 57 | right++; 58 | } else if (nums[right] - nums[left] > k) { 59 | left++; 60 | } else { 61 | left++; 62 | result++; 63 | while (left < nums.length && nums[left] == nums[left - 1]) 64 | left++; 65 | } 66 | } 67 | return result; 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/class25/Code03_MaxPointsOnALine.java: -------------------------------------------------------------------------------- 1 | package class25; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | // 本题测试链接: https://leetcode.com/problems/max-points-on-a-line/ 7 | public class Code03_MaxPointsOnALine { 8 | 9 | // [ 10 | // [1,3] 11 | // [4,9] 12 | // [5,7] 13 | // ] 14 | 15 | public static int maxPoints(int[][] points) { 16 | if (points == null) { 17 | return 0; 18 | } 19 | if (points.length <= 2) { 20 | return points.length; 21 | } 22 | // key = 3 23 | // value = {7 , 10} -> 斜率为3/7的点 有10个 24 | // {5, 15} -> 斜率为3/5的点 有15个 25 | Map> map = new HashMap>(); 26 | int result = 0; 27 | for (int i = 0; i < points.length; i++) { 28 | map.clear(); 29 | int samePosition = 1; 30 | int sameX = 0; 31 | int sameY = 0; 32 | int line = 0; 33 | for (int j = i + 1; j < points.length; j++) { // i号点,和j号点,的斜率关系 34 | int x = points[j][0] - points[i][0]; 35 | int y = points[j][1] - points[i][1]; 36 | if (x == 0 && y == 0) { 37 | samePosition++; 38 | } else if (x == 0) { 39 | sameX++; 40 | } else if (y == 0) { 41 | sameY++; 42 | } else { // 普通斜率 43 | int gcd = gcd(x, y); 44 | x /= gcd; 45 | y /= gcd; 46 | // x / y 47 | if (!map.containsKey(x)) { 48 | map.put(x, new HashMap()); 49 | } 50 | if (!map.get(x).containsKey(y)) { 51 | map.get(x).put(y, 0); 52 | } 53 | map.get(x).put(y, map.get(x).get(y) + 1); 54 | line = Math.max(line, map.get(x).get(y)); 55 | } 56 | } 57 | result = Math.max(result, Math.max(Math.max(sameX, sameY), line) + samePosition); 58 | } 59 | return result; 60 | } 61 | 62 | // 保证初始调用的时候,a和b不等于0 63 | // O(1) 64 | public static int gcd(int a, int b) { 65 | return b == 0 ? a : gcd(b, a % b); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/class26/Code03_ExpressionAddOperators.java: -------------------------------------------------------------------------------- 1 | package class26; 2 | 3 | import java.util.LinkedList; 4 | import java.util.List; 5 | 6 | // 本题测试链接 : https://leetcode.com/problems/expression-add-operators/ 7 | public class Code03_ExpressionAddOperators { 8 | 9 | public static List addOperators(String num, int target) { 10 | List ret = new LinkedList<>(); 11 | if (num.length() == 0) { 12 | return ret; 13 | } 14 | // 沿途的数字拷贝和+ - * 的决定,放在path里 15 | char[] path = new char[num.length() * 2 - 1]; 16 | // num -> char[] 17 | char[] digits = num.toCharArray(); 18 | long n = 0; 19 | for (int i = 0; i < digits.length; i++) { // 尝试0~i前缀作为第一部分 20 | n = n * 10 + digits[i] - '0'; 21 | path[i] = digits[i]; 22 | dfs(ret, path, i + 1, 0, n, digits, i + 1, target); // 后续过程 23 | if (n == 0) { 24 | break; 25 | } 26 | } 27 | return ret; 28 | } 29 | 30 | // char[] digits 固定参数,字符类型数组,等同于num 31 | // int target 目标 32 | // char[] path 之前做的决定,已经从左往右依次填写的字符在其中,可能含有'0'~'9' 与 * - + 33 | // int len path[0..len-1]已经填写好,len是终止 34 | // int pos 字符类型数组num, 使用到了哪 35 | // left -> 前面固定的部分 cur -> 前一块 36 | // 默认 left + cur ... 37 | public static void dfs(List res, char[] path, int len, 38 | long left, long cur, 39 | char[] num, int index, int aim) { 40 | if (index == num.length) { 41 | if (left + cur == aim) { 42 | res.add(new String(path, 0, len)); 43 | } 44 | return; 45 | } 46 | long n = 0; 47 | int j = len + 1; 48 | for (int i = index; i < num.length; i++) { // pos ~ i 49 | // 试每一个可能的前缀,作为第一个数字! 50 | // num[index...i] 作为第一个数字! 51 | n = n * 10 + num[i] - '0'; 52 | path[j++] = num[i]; 53 | path[len] = '+'; 54 | dfs(res, path, j, left + cur, n, num, i + 1, aim); 55 | path[len] = '-'; 56 | dfs(res, path, j, left + cur, -n, num, i + 1, aim); 57 | path[len] = '*'; 58 | dfs(res, path, j, left, cur * n, num, i + 1, aim); 59 | if (num[index] == '0') { 60 | break; 61 | } 62 | } 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/class27/Code02_MinPeople.java: -------------------------------------------------------------------------------- 1 | package class27; 2 | 3 | import java.util.Arrays; 4 | 5 | public class Code02_MinPeople { 6 | 7 | // 三道题如下: 8 | // 微信面试题 9 | // 题目一: 10 | // 股民小 A 有一天穿越回到了 n 天前,他能记住某只股票连续 n 天的价格;他手上有足够多的启动资金,他可以在这 n 天内多次交易,但是有个限制 11 | // 如果已经购买了一个股票,在卖出它之前就不能再继续购买股票了。 12 | // 到 n 天之后,小 A 不能再持有股票。 13 | // 求问 这 n 天内,小 A 能够获得的利润的最大值 14 | // 如果不需要手续费的话,求最大的利润 15 | // function(number) { 16 | // return number 17 | // } 18 | // 输入: prices = [3, 1, 2, 8, 5, 9] 19 | // 输出: 11 20 | // 21 | // 题目二: 22 | // 企鹅厂每年都会发文化衫,文化衫有很多种,厂庆的时候,企鹅们都需要穿文化衫来拍照 23 | // 一次采访中,记者随机遇到的企鹅,企鹅会告诉记者还有多少企鹅跟他穿一种文化衫 24 | // 我们将这些回答放在 answers 数组里,返回鹅厂中企鹅的最少数量。 25 | // 输入: answers = [1] 输出:2 26 | // 输入: answers = [1, 1, 2] 输出:5 27 | // Leetcode题目:https://leetcode.com/problems/rabbits-in-forest/ 28 | // 29 | // 题目三: 30 | // WXG 的秘书有一堆的文件袋,现在秘书需要把文件袋嵌套收纳起来。请你帮他计算下,最大嵌套数量。 31 | // 给你一个二维整数数组 folders ,其中 folders[i] = [wi, hi] ,表示第 i 个文件袋的宽度和长度 32 | // 当某一个文件袋的宽度和长度都比这个另外一个文件袋大的时候,前者就能把后者装起来,称之为一组文件袋。 33 | // 请计算,最大的一组文件袋的数量是多少。 34 | // 实例 35 | // 输入:[[6,10],[11,14],[6,1],[16,14],[13,2]] 36 | // 输出: 3 37 | 38 | // 题目一,股票系列专题,大厂刷题班15节 39 | // 题目三,最长递增子序列专题,大厂刷题班第9节 40 | // 我们来讲一下题目二 41 | public static int numRabbits(int[] arr) { 42 | if (arr == null || arr.length == 0) { 43 | return 0; 44 | } 45 | Arrays.sort(arr); 46 | int x = arr[0]; 47 | int c = 1; 48 | int ans = 0; 49 | for (int i = 1; i < arr.length; i++) { 50 | if (x != arr[i]) { 51 | ans += ((c + x) / (x + 1)) * (x + 1); 52 | x = arr[i]; 53 | c = 1; 54 | } else { 55 | c++; 56 | } 57 | } 58 | return ans + ((c + x) / (x + 1)) * (x + 1); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/class27/Problem_0001_TwoSum.java: -------------------------------------------------------------------------------- 1 | package class27; 2 | 3 | import java.util.HashMap; 4 | 5 | public class Problem_0001_TwoSum { 6 | 7 | public static int[] twoSum(int[] nums, int target) { 8 | // key 某个之前的数 value 这个数出现的位置 9 | HashMap map = new HashMap<>(); 10 | for (int i = 0; i < nums.length; i++) { 11 | if (map.containsKey(target - nums[i])) { 12 | return new int[] { map.get(target - nums[i]), i }; 13 | } 14 | map.put(nums[i], i); 15 | } 16 | return new int[] { -1, -1 }; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/class27/Problem_0007_ReverseInteger.java: -------------------------------------------------------------------------------- 1 | package class27; 2 | 3 | public class Problem_0007_ReverseInteger { 4 | 5 | public static int reverse(int x) { 6 | boolean neg = ((x >>> 31) & 1) == 1; 7 | x = neg ? x : -x; 8 | int m = Integer.MIN_VALUE / 10; 9 | int o = Integer.MIN_VALUE % 10; 10 | int res = 0; 11 | while (x != 0) { 12 | if (res < m || (res == m && x % 10 < o)) { 13 | return 0; 14 | } 15 | res = res * 10 + x % 10; 16 | x /= 10; 17 | } 18 | return neg ? res : Math.abs(res); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/class27/说明: -------------------------------------------------------------------------------- 1 | leetcode高频题 2 | leetcode全题目列表 : https://leetcode.com/problemset/all/ 3 | 在全题目列表的右侧栏,点击Top Interview Questions 4 | 或者直接进入右侧链接 : https://leetcode.com/problemset/all/?listId=wpwgkgt 5 | 即可看到leetcode高频题全列表 6 | 本节课解决leetcode高频题列表中的如下题目 : 7 | 0001 : 大厂刷题班, 第27节, 本节 8 | 0002 : 算法新手班, 第4节第5题 9 | 0003 : 大厂刷题班, 第3节第1题 10 | 0004 : 大厂刷题班, 第12节第3题 11 | 0005 : 体系学习班, Manacher算法 12 | 0007 : 大厂刷题班, 第27节, 本节 -------------------------------------------------------------------------------- /src/class28/Problem_0012_IntegerToRoman.java: -------------------------------------------------------------------------------- 1 | package class28; 2 | 3 | public class Problem_0012_IntegerToRoman { 4 | 5 | public static String intToRoman(int num) { 6 | String[][] c = { 7 | { "", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX" }, 8 | { "", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC" }, 9 | { "", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM" }, 10 | { "", "M", "MM", "MMM" } }; 11 | StringBuilder roman = new StringBuilder(); 12 | roman 13 | .append(c[3][num / 1000 % 10]) 14 | .append(c[2][num / 100 % 10]) 15 | .append(c[1][num / 10 % 10]) 16 | .append(c[0][num % 10]); 17 | return roman.toString(); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/class28/Problem_0013_RomanToInteger.java: -------------------------------------------------------------------------------- 1 | package class28; 2 | 3 | public class Problem_0013_RomanToInteger { 4 | 5 | public static int romanToInt(String s) { 6 | // C M X C I X 7 | // 100 1000 10 100 1 10 8 | int nums[] = new int[s.length()]; 9 | for (int i = 0; i < s.length(); i++) { 10 | switch (s.charAt(i)) { 11 | case 'M': 12 | nums[i] = 1000; 13 | break; 14 | case 'D': 15 | nums[i] = 500; 16 | break; 17 | case 'C': 18 | nums[i] = 100; 19 | break; 20 | case 'L': 21 | nums[i] = 50; 22 | break; 23 | case 'X': 24 | nums[i] = 10; 25 | break; 26 | case 'V': 27 | nums[i] = 5; 28 | break; 29 | case 'I': 30 | nums[i] = 1; 31 | break; 32 | } 33 | } 34 | int sum = 0; 35 | for (int i = 0; i < nums.length - 1; i++) { 36 | if (nums[i] < nums[i + 1]) { 37 | sum -= nums[i]; 38 | } else { 39 | sum += nums[i]; 40 | } 41 | } 42 | return sum + nums[nums.length - 1]; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/class28/Problem_0014_LongestCommonPrefix.java: -------------------------------------------------------------------------------- 1 | package class28; 2 | 3 | public class Problem_0014_LongestCommonPrefix { 4 | 5 | public static String longestCommonPrefix(String[] strs) { 6 | if (strs == null || strs.length == 0) { 7 | return ""; 8 | } 9 | char[] chs = strs[0].toCharArray(); 10 | int min = Integer.MAX_VALUE; 11 | for (String str : strs) { 12 | char[] tmp = str.toCharArray(); 13 | int index = 0; 14 | while (index < tmp.length && index < chs.length) { 15 | if (chs[index] != tmp[index]) { 16 | break; 17 | } 18 | index++; 19 | } 20 | min = Math.min(index, min); 21 | if (min == 0) { 22 | return ""; 23 | } 24 | } 25 | return strs[0].substring(0, min); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/class28/Problem_0017_LetterCombinationsOfAPhoneNumber.java: -------------------------------------------------------------------------------- 1 | package class28; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class Problem_0017_LetterCombinationsOfAPhoneNumber { 7 | 8 | public static char[][] phone = { 9 | { 'a', 'b', 'c' }, // 2 0 10 | { 'd', 'e', 'f' }, // 3 1 11 | { 'g', 'h', 'i' }, // 4 2 12 | { 'j', 'k', 'l' }, // 5 3 13 | { 'm', 'n', 'o' }, // 6 14 | { 'p', 'q', 'r', 's' }, // 7 15 | { 't', 'u', 'v' }, // 8 16 | { 'w', 'x', 'y', 'z' }, // 9 17 | }; 18 | 19 | // "23" 20 | public static List letterCombinations(String digits) { 21 | List ans = new ArrayList<>(); 22 | if (digits == null || digits.length() == 0) { 23 | return ans; 24 | } 25 | char[] str = digits.toCharArray(); 26 | char[] path = new char[str.length]; 27 | process(str, 0, path, ans); 28 | return ans; 29 | } 30 | 31 | public static void process(char[] str, int index, char[] path, List ans) { 32 | if (index == str.length) { 33 | ans.add(String.valueOf(path)); 34 | } else { 35 | char[] cands = phone[str[index] - '2']; 36 | for (char cur : cands) { 37 | path[index] = cur; 38 | process(str, index + 1, path, ans); 39 | } 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/class28/Problem_0019_RemoveNthNodeFromEndofList.java: -------------------------------------------------------------------------------- 1 | package class28; 2 | 3 | public class Problem_0019_RemoveNthNodeFromEndofList { 4 | 5 | public static class ListNode { 6 | public int val; 7 | public ListNode next; 8 | } 9 | 10 | public static ListNode removeNthFromEnd(ListNode head, int n) { 11 | ListNode cur = head; 12 | ListNode pre = null; 13 | while (cur != null) { 14 | n--; 15 | if (n == -1) { 16 | pre = head; 17 | } 18 | if (n < -1) { 19 | pre = pre.next; 20 | } 21 | cur = cur.next; 22 | } 23 | if (n > 0) { 24 | return head; 25 | } 26 | if (pre == null) { 27 | return head.next; 28 | } 29 | pre.next = pre.next.next; 30 | return head; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/class28/Problem_0020_ValidParentheses.java: -------------------------------------------------------------------------------- 1 | package class28; 2 | 3 | public class Problem_0020_ValidParentheses { 4 | 5 | public static boolean isValid(String s) { 6 | if (s == null || s.length() == 0) { 7 | return true; 8 | } 9 | char[] str = s.toCharArray(); 10 | int N = str.length; 11 | char[] stack = new char[N]; 12 | int size = 0; 13 | for (int i = 0; i < N; i++) { 14 | char cha = str[i]; 15 | if (cha == '(' || cha == '[' || cha == '{') { 16 | stack[size++] = cha == '(' ? ')' : (cha == '[' ? ']' : '}'); 17 | } else { 18 | if (size == 0) { 19 | return false; 20 | } 21 | char last = stack[--size]; 22 | if (cha != last) { 23 | return false; 24 | } 25 | } 26 | } 27 | return size == 0; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/class28/Problem_0022_GenerateParentheses.java: -------------------------------------------------------------------------------- 1 | package class28; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class Problem_0022_GenerateParentheses { 7 | 8 | public static List generateParenthesis(int n) { 9 | char[] path = new char[n << 1]; 10 | List ans = new ArrayList<>(); 11 | process(path, 0, 0, n, ans); 12 | return ans; 13 | } 14 | 15 | 16 | // path 做的决定 path[0....index-1]做完决定的! 17 | // path[index.....] 还没做决定,当前轮到index位置做决定! 18 | 19 | public static void process(char[] path, int index, int leftMinusRight, int leftRest, List ans) { 20 | if (index == path.length) { 21 | ans.add(String.valueOf(path)); 22 | } else { 23 | // index ( ) 24 | if (leftRest > 0) { 25 | path[index] = '('; 26 | process(path, index + 1, leftMinusRight + 1, leftRest - 1, ans); 27 | } 28 | if (leftMinusRight > 0) { 29 | path[index] = ')'; 30 | process(path, index + 1, leftMinusRight - 1, leftRest, ans); 31 | } 32 | } 33 | } 34 | 35 | // 不剪枝的做法 36 | public static List generateParenthesis2(int n) { 37 | char[] path = new char[n << 1]; 38 | List ans = new ArrayList<>(); 39 | process2(path, 0, ans); 40 | return ans; 41 | } 42 | 43 | public static void process2(char[] path, int index, List ans) { 44 | if (index == path.length) { 45 | if (isValid(path)) { 46 | ans.add(String.valueOf(path)); 47 | } 48 | } else { 49 | path[index] = '('; 50 | process2(path, index + 1, ans); 51 | path[index] = ')'; 52 | process2(path, index + 1, ans); 53 | } 54 | } 55 | 56 | public static boolean isValid(char[] path) { 57 | int count = 0; 58 | for (char cha : path) { 59 | if (cha == '(') { 60 | count++; 61 | } else { 62 | count--; 63 | } 64 | if (count < 0) { 65 | return false; 66 | } 67 | } 68 | return count == 0; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/class28/Problem_0026_RemoveDuplicatesFromSortedArray.java: -------------------------------------------------------------------------------- 1 | package class28; 2 | 3 | public class Problem_0026_RemoveDuplicatesFromSortedArray { 4 | 5 | public static int removeDuplicates(int[] nums) { 6 | if (nums == null) { 7 | return 0; 8 | } 9 | if (nums.length < 2) { 10 | return nums.length; 11 | } 12 | int done = 0; 13 | for (int i = 1; i < nums.length; i++) { 14 | if (nums[i] != nums[done]) { 15 | nums[++done] = nums[i]; 16 | } 17 | } 18 | return done + 1; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/class28/Problem_0034_FindFirstAndLastPositionOfElementInSortedArray.java: -------------------------------------------------------------------------------- 1 | package class28; 2 | 3 | public class Problem_0034_FindFirstAndLastPositionOfElementInSortedArray { 4 | 5 | public static int[] searchRange(int[] nums, int target) { 6 | if (nums == null || nums.length == 0) { 7 | return new int[] { -1, -1 }; 8 | } 9 | int L = lessMostRight(nums, target) + 1; 10 | if (L == nums.length || nums[L] != target) { 11 | return new int[] { -1, -1 }; 12 | } 13 | return new int[] { L, lessMostRight(nums, target + 1) }; 14 | } 15 | 16 | public static int lessMostRight(int[] arr, int num) { 17 | int L = 0; 18 | int R = arr.length - 1; 19 | int M = 0; 20 | int ans = -1; 21 | while (L <= R) { 22 | M = L + ((R - L) >> 1); 23 | if (arr[M] < num) { 24 | ans = M; 25 | L = M + 1; 26 | } else { 27 | R = M - 1; 28 | } 29 | } 30 | return ans; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/class28/Problem_0036_ValidSudoku.java: -------------------------------------------------------------------------------- 1 | package class28; 2 | 3 | public class Problem_0036_ValidSudoku { 4 | 5 | public static boolean isValidSudoku(char[][] board) { 6 | boolean[][] row = new boolean[9][10]; 7 | boolean[][] col = new boolean[9][10]; 8 | boolean[][] bucket = new boolean[9][10]; 9 | for (int i = 0; i < 9; i++) { 10 | for (int j = 0; j < 9; j++) { 11 | int bid = 3 * (i / 3) + (j / 3); 12 | if (board[i][j] != '.') { 13 | int num = board[i][j] - '0'; 14 | if (row[i][num] || col[j][num] || bucket[bid][num]) { 15 | return false; 16 | } 17 | row[i][num] = true; 18 | col[j][num] = true; 19 | bucket[bid][num] = true; 20 | } 21 | } 22 | } 23 | return true; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/class28/Problem_0037_SudokuSolver.java: -------------------------------------------------------------------------------- 1 | package class28; 2 | 3 | public class Problem_0037_SudokuSolver { 4 | 5 | public static void solveSudoku(char[][] board) { 6 | boolean[][] row = new boolean[9][10]; 7 | boolean[][] col = new boolean[9][10]; 8 | boolean[][] bucket = new boolean[9][10]; 9 | initMaps(board, row, col, bucket); 10 | process(board, 0, 0, row, col, bucket); 11 | } 12 | 13 | public static void initMaps(char[][] board, boolean[][] row, boolean[][] col, boolean[][] bucket) { 14 | for (int i = 0; i < 9; i++) { 15 | for (int j = 0; j < 9; j++) { 16 | int bid = 3 * (i / 3) + (j / 3); 17 | if (board[i][j] != '.') { 18 | int num = board[i][j] - '0'; 19 | row[i][num] = true; 20 | col[j][num] = true; 21 | bucket[bid][num] = true; 22 | } 23 | } 24 | } 25 | } 26 | 27 | // 当前来到(i,j)这个位置,如果已经有数字,跳到下一个位置上 28 | // 如果没有数字,尝试1~9,不能和row、col、bucket冲突 29 | public static boolean process(char[][] board, int i, int j, boolean[][] row, boolean[][] col, boolean[][] bucket) { 30 | if (i == 9) { 31 | return true; 32 | } 33 | // 当离开(i,j),应该去哪?(nexti, nextj) 34 | int nexti = j != 8 ? i : i + 1; 35 | int nextj = j != 8 ? j + 1 : 0; 36 | if (board[i][j] != '.') { 37 | return process(board, nexti, nextj, row, col, bucket); 38 | } else { 39 | // 可以尝试1~9 40 | int bid = 3 * (i / 3) + (j / 3); 41 | for (int num = 1; num <= 9; num++) { // 尝试每一个数字1~9 42 | if ((!row[i][num]) && (!col[j][num]) && (!bucket[bid][num])) { 43 | // 可以尝试num 44 | row[i][num] = true; 45 | col[j][num] = true; 46 | bucket[bid][num] = true; 47 | board[i][j] = (char) (num + '0'); 48 | if (process(board, nexti, nextj, row, col, bucket)) { 49 | return true; 50 | } 51 | row[i][num] = false; 52 | col[j][num] = false; 53 | bucket[bid][num] = false; 54 | board[i][j] = '.'; 55 | } 56 | } 57 | return false; 58 | } 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/class28/Problem_0038_CountAndSay.java: -------------------------------------------------------------------------------- 1 | package class28; 2 | 3 | public class Problem_0038_CountAndSay { 4 | 5 | public static String countAndSay(int n) { 6 | if (n < 1) { 7 | return ""; 8 | } 9 | if (n == 1) { 10 | return "1"; 11 | } 12 | char[] last = countAndSay(n - 1).toCharArray(); 13 | StringBuilder ans = new StringBuilder(); 14 | int times = 1; 15 | for (int i = 1; i < last.length; i++) { 16 | if (last[i - 1] == last[i]) { 17 | times++; 18 | } else { 19 | ans.append(String.valueOf(times)); 20 | ans.append(String.valueOf(last[i - 1])); 21 | times = 1; 22 | } 23 | } 24 | ans.append(String.valueOf(times)); 25 | ans.append(String.valueOf(last[last.length - 1])); 26 | return ans.toString(); 27 | } 28 | 29 | public static void main(String[] args) { 30 | System.out.println(countAndSay(20)); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/class28/Problem_0049_GroupAnagrams.java: -------------------------------------------------------------------------------- 1 | package class28; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.HashMap; 6 | import java.util.List; 7 | 8 | public class Problem_0049_GroupAnagrams { 9 | 10 | public static List> groupAnagrams1(String[] strs) { 11 | HashMap> map = new HashMap>(); 12 | for (String str : strs) { 13 | int[] record = new int[26]; 14 | for (char cha : str.toCharArray()) { 15 | record[cha - 'a']++; 16 | } 17 | StringBuilder builder = new StringBuilder(); 18 | for (int value : record) { 19 | builder.append(String.valueOf(value)).append("_"); 20 | } 21 | String key = builder.toString(); 22 | if (!map.containsKey(key)) { 23 | map.put(key, new ArrayList()); 24 | } 25 | map.get(key).add(str); 26 | } 27 | List> res = new ArrayList>(); 28 | for (List list : map.values()) { 29 | res.add(list); 30 | } 31 | return res; 32 | } 33 | 34 | public static List> groupAnagrams2(String[] strs) { 35 | HashMap> map = new HashMap>(); 36 | for (String str : strs) { 37 | char[] chs = str.toCharArray(); 38 | Arrays.sort(chs); 39 | String key = String.valueOf(chs); 40 | if (!map.containsKey(key)) { 41 | map.put(key, new ArrayList()); 42 | } 43 | map.get(key).add(str); 44 | } 45 | List> res = new ArrayList>(); 46 | for (List list : map.values()) { 47 | res.add(list); 48 | } 49 | return res; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/class28/说明: -------------------------------------------------------------------------------- 1 | leetcode高频题 2 | leetcode全题目列表 : https://leetcode.com/problemset/all/ 3 | 在全题目列表的右侧栏,点击Top Interview Questions 4 | 或者直接进入右侧链接 : https://leetcode.com/problemset/all/?listId=wpwgkgt 5 | 即可看到leetcode高频题全列表 6 | 本节课解决leetcode高频题列表中的如下题目 : 7 | 0008 : 大厂刷题班, 第28节, 本节 8 | 0010 : 大厂刷题班, 第12节第4题 9 | 0011 : 大厂刷题班, 第8节第2题 10 | 0012 : 大厂刷题班, 第28节, 本节 11 | 0013 : 大厂刷题班, 第28节, 本节 12 | 0014 : 大厂刷题班, 第28节, 本节 13 | 0015 : 大厂刷题班, 第25节第2题 14 | 0017 : 大厂刷题班, 第28节, 本节 15 | 0019 : 大厂刷题班, 第28节, 本节 16 | 0020 : 大厂刷题班, 第28节, 本节 17 | 0021 : 算法新手班, 第4节第6题 18 | 0022 : 大厂刷题班, 第28节, 本节 19 | 0023 : 算法新手班, 第6节第1题 20 | 0026 : 大厂刷题班, 第28节, 本节 21 | 0028 : 体系学习班, KMP算法 22 | 0029 : 算法新手班, 第5节第3题 23 | 0034 : 大厂刷题班, 第28节, 本节 24 | 0036 : 大厂刷题班, 第28节, 本节 25 | 0037 : 大厂刷题班, 第28节, 本节 26 | 0038 : 大厂刷题班, 第28节, 本节 27 | 0041 : 大厂刷题班, 第14节第6题 28 | 0042 : 大厂刷题班, 第22节第2题 29 | 0044 : 大厂刷题班, 第12节第4题 30 | 0045 : 大厂刷题班, 第10节第1题 31 | 0046 : 体系学习班, KMP算法 32 | 0048 : 体系学习班, 第40节第6题 33 | 0049 : 大厂刷题班, 第28节, 本节 -------------------------------------------------------------------------------- /src/class29/Problem_0033_SearchInRotatedSortedArray.java: -------------------------------------------------------------------------------- 1 | package class29; 2 | 3 | public class Problem_0033_SearchInRotatedSortedArray { 4 | 5 | // arr,原本是有序数组,旋转过,而且左部分长度不知道 6 | // 找num 7 | // num所在的位置返回 8 | public static int search(int[] arr, int num) { 9 | int L = 0; 10 | int R = arr.length - 1; 11 | int M = 0; 12 | while (L <= R) { 13 | // M = L + ((R - L) >> 1) 14 | M = (L + R) / 2; 15 | if (arr[M] == num) { 16 | return M; 17 | } 18 | // arr[M] != num 19 | // [L] == [M] == [R] != num 无法二分 20 | if (arr[L] == arr[M] && arr[M] == arr[R]) { 21 | while (L != M && arr[L] == arr[M]) { 22 | L++; 23 | } 24 | // 1) L == M L...M 一路都相等 25 | // 2) 从L到M终于找到了一个不等的位置 26 | if (L == M) { // L...M 一路都相等 27 | L = M + 1; 28 | continue; 29 | } 30 | } 31 | // ... 32 | // arr[M] != num 33 | // [L] [M] [R] 不都一样的情况, 如何二分的逻辑 34 | if (arr[L] != arr[M]) { 35 | if (arr[M] > arr[L]) { // L...M 一定有序 36 | if (num >= arr[L] && num < arr[M]) { // 3 [L] == 1 [M] = 5 L...M - 1 37 | R = M - 1; 38 | } else { // 9 [L] == 2 [M] = 7 M... R 39 | L = M + 1; 40 | } 41 | } else { // [L] > [M] L....M 存在断点 42 | if (num > arr[M] && num <= arr[R]) { 43 | L = M + 1; 44 | } else { 45 | R = M - 1; 46 | } 47 | } 48 | } else { /// [L] [M] [R] 不都一样, [L] === [M] -> [M]!=[R] 49 | if (arr[M] < arr[R]) { 50 | if (num > arr[M] && num <= arr[R]) { 51 | L = M + 1; 52 | } else { 53 | R = M - 1; 54 | } 55 | } else { 56 | if (num >= arr[L] && num < arr[M]) { 57 | R = M - 1; 58 | } else { 59 | L = M + 1; 60 | } 61 | } 62 | } 63 | } 64 | return -1; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/class29/Problem_0050_PowXN.java: -------------------------------------------------------------------------------- 1 | package class29; 2 | 3 | public class Problem_0050_PowXN { 4 | 5 | public static int pow(int a, int n) { 6 | int ans = 1; 7 | int t = a; 8 | while (n != 0) { 9 | if ((n & 1) != 0) { 10 | ans *= t; 11 | } 12 | t *= t; 13 | n >>= 1; 14 | } 15 | return ans; 16 | } 17 | 18 | // x的n次方,n可能是负数 19 | public static double myPow(double x, int n) { 20 | if (n == 0) { 21 | return 1D; 22 | } 23 | int pow = Math.abs(n == Integer.MIN_VALUE ? n + 1 : n); 24 | double t = x; 25 | double ans = 1D; 26 | while (pow != 0) { 27 | if ((pow & 1) != 0) { 28 | ans *= t; 29 | } 30 | pow >>= 1; 31 | t = t * t; 32 | } 33 | if (n == Integer.MIN_VALUE) { 34 | ans *= x; 35 | } 36 | return n < 0 ? (1D / ans) : ans; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/class29/Problem_0056_MergeIntervals.java: -------------------------------------------------------------------------------- 1 | package class29; 2 | 3 | import java.util.Arrays; 4 | 5 | public class Problem_0056_MergeIntervals { 6 | 7 | public static int[][] merge(int[][] intervals) { 8 | if (intervals.length == 0) { 9 | return new int[0][0]; 10 | } 11 | Arrays.sort(intervals, (a, b) -> a[0] - b[0]); 12 | int s = intervals[0][0]; 13 | int e = intervals[0][1]; 14 | int size = 0; 15 | for (int i = 1; i < intervals.length; i++) { 16 | if (intervals[i][0] > e) { 17 | intervals[size][0] = s; 18 | intervals[size++][1] = e; 19 | s = intervals[i][0]; 20 | e = intervals[i][1]; 21 | } else { 22 | e = Math.max(e, intervals[i][1]); 23 | } 24 | } 25 | intervals[size][0] = s; 26 | intervals[size++][1] = e; 27 | return Arrays.copyOf(intervals, size); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/class29/Problem_0062_UniquePaths.java: -------------------------------------------------------------------------------- 1 | package class29; 2 | 3 | public class Problem_0062_UniquePaths { 4 | 5 | // m 行 6 | // n 列 7 | // 下:m-1 8 | // 右:n-1 9 | public static int uniquePaths(int m, int n) { 10 | int right = n - 1; 11 | int all = m + n - 2; 12 | long o1 = 1; 13 | long o2 = 1; 14 | // o1乘进去的个数 一定等于 o2乘进去的个数 15 | for (int i = right + 1, j = 1; i <= all; i++, j++) { 16 | o1 *= i; 17 | o2 *= j; 18 | long gcd = gcd(o1, o2); 19 | o1 /= gcd; 20 | o2 /= gcd; 21 | } 22 | return (int) o1; 23 | } 24 | 25 | // 调用的时候,请保证初次调用时,m和n都不为0 26 | public static long gcd(long m, long n) { 27 | return n == 0 ? m : gcd(n, m % n); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/class29/Problem_0066_PlusOne.java: -------------------------------------------------------------------------------- 1 | package class29; 2 | 3 | public class Problem_0066_PlusOne { 4 | 5 | public static int[] plusOne(int[] digits) { 6 | int n = digits.length; 7 | for (int i = n - 1; i >= 0; i--) { 8 | if (digits[i] < 9) { 9 | digits[i]++; 10 | return digits; 11 | } 12 | digits[i] = 0; 13 | } 14 | int[] ans = new int[n + 1]; 15 | ans[0] = 1; 16 | return ans; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/class29/Problem_0069_SqrtX.java: -------------------------------------------------------------------------------- 1 | package class29; 2 | 3 | public class Problem_0069_SqrtX { 4 | 5 | // x一定非负,输入可以保证 6 | public static int mySqrt(int x) { 7 | if (x == 0) { 8 | return 0; 9 | } 10 | if (x < 3) { 11 | return 1; 12 | } 13 | // x >= 3 14 | long ans = 1; 15 | long L = 1; 16 | long R = x; 17 | long M = 0; 18 | while (L <= R) { 19 | M = (L + R) / 2; 20 | if (M * M <= x) { 21 | ans = M; 22 | L = M + 1; 23 | } else { 24 | R = M - 1; 25 | } 26 | } 27 | return (int) ans; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/class29/Problem_0073_SetMatrixZeroes.java: -------------------------------------------------------------------------------- 1 | package class29; 2 | 3 | public class Problem_0073_SetMatrixZeroes { 4 | 5 | public static void setZeroes1(int[][] matrix) { 6 | boolean row0Zero = false; 7 | boolean col0Zero = false; 8 | int i = 0; 9 | int j = 0; 10 | for (i = 0; i < matrix[0].length; i++) { 11 | if (matrix[0][i] == 0) { 12 | row0Zero = true; 13 | break; 14 | } 15 | } 16 | for (i = 0; i < matrix.length; i++) { 17 | if (matrix[i][0] == 0) { 18 | col0Zero = true; 19 | break; 20 | } 21 | } 22 | for (i = 1; i < matrix.length; i++) { 23 | for (j = 1; j < matrix[0].length; j++) { 24 | if (matrix[i][j] == 0) { 25 | matrix[i][0] = 0; 26 | matrix[0][j] = 0; 27 | } 28 | } 29 | } 30 | for (i = 1; i < matrix.length; i++) { 31 | for (j = 1; j < matrix[0].length; j++) { 32 | if (matrix[i][0] == 0 || matrix[0][j] == 0) { 33 | matrix[i][j] = 0; 34 | } 35 | } 36 | } 37 | if (row0Zero) { 38 | for (i = 0; i < matrix[0].length; i++) { 39 | matrix[0][i] = 0; 40 | } 41 | } 42 | if (col0Zero) { 43 | for (i = 0; i < matrix.length; i++) { 44 | matrix[i][0] = 0; 45 | } 46 | } 47 | } 48 | 49 | public static void setZeroes2(int[][] matrix) { 50 | boolean col0 = false; 51 | int i = 0; 52 | int j = 0; 53 | for (i = 0; i < matrix.length; i++) { 54 | for (j = 0; j < matrix[0].length; j++) { 55 | if (matrix[i][j] == 0) { 56 | matrix[i][0] = 0; 57 | if (j == 0) { 58 | col0 = true; 59 | } else { 60 | matrix[0][j] = 0; 61 | } 62 | } 63 | } 64 | } 65 | for (i = matrix.length - 1; i >= 0; i--) { 66 | for (j = 1; j < matrix[0].length; j++) { 67 | if (matrix[i][0] == 0 || matrix[0][j] == 0) { 68 | matrix[i][j] = 0; 69 | } 70 | } 71 | } 72 | if (col0) { 73 | for (i = 0; i < matrix.length; i++) { 74 | matrix[i][0] = 0; 75 | } 76 | } 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/class29/说明: -------------------------------------------------------------------------------- 1 | leetcode高频题 2 | leetcode全题目列表 : https://leetcode.com/problemset/all/ 3 | 在全题目列表的右侧栏,点击Top Interview Questions 4 | 或者直接进入右侧链接 : https://leetcode.com/problemset/all/?listId=wpwgkgt 5 | 即可看到leetcode高频题全列表 6 | 本节课解决leetcode高频题列表中的如下题目 : 7 | 0033 : 大厂刷题班, 第29节, 本节 8 | 0050 : 大厂刷题班, 第29节, 本节 9 | 0053 : 体系学习班, 第40节第2题 10 | 0054 : 体系学习班, 第40节第5题 11 | 0055 : 大厂刷题班, 第10节第1题 12 | 0056 : 大厂刷题班, 第29节, 本节 13 | 0062 : 大厂刷题班, 第29节, 本节 14 | 0066 : 大厂刷题班, 第29节, 本节 15 | 0069 : 大厂刷题班, 第29节, 本节 16 | 0070 : 体系学习班, 第26节第2题 17 | 0073 : 大厂刷题班, 第29节, 本节 18 | 0075 : 体系学习班, 第5节第2题, 快排中的荷兰国旗问题 19 | 0076 : 大厂刷题班, 第24节第5题 20 | 0078 : 体系学习班, 第17节题目3, 生成子序列问题和本题一样的 -------------------------------------------------------------------------------- /src/class30/Problem_0079_WordSearch.java: -------------------------------------------------------------------------------- 1 | package class30; 2 | 3 | public class Problem_0079_WordSearch { 4 | 5 | public static boolean exist(char[][] board, String word) { 6 | char[] w = word.toCharArray(); 7 | for (int i = 0; i < board.length; i++) { 8 | for (int j = 0; j < board[0].length; j++) { 9 | if (f(board, i, j, w, 0)) { 10 | return true; 11 | } 12 | } 13 | } 14 | return false; 15 | } 16 | 17 | // 目前到达了b[i][j],word[k....] 18 | // 从b[i][j]出发,能不能搞定word[k....] true false 19 | public static boolean f(char[][] b, int i, int j, char[] w, int k) { 20 | if (k == w.length) { 21 | return true; 22 | } 23 | // word[k.....] 有字符 24 | // 如果(i,j)越界,返回false 25 | if (i < 0 || i == b.length || j < 0 || j == b[0].length) { 26 | return false; 27 | } 28 | if (b[i][j] != w[k]) { 29 | return false; 30 | } 31 | char tmp = b[i][j]; 32 | b[i][j] = 0; 33 | boolean ans = f(b, i - 1, j, w, k + 1) 34 | || f(b, i + 1, j, w, k + 1) 35 | || f(b, i, j - 1, w, k + 1) 36 | || f(b, i, j + 1, w, k + 1); 37 | b[i][j] = tmp; 38 | return ans; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/class30/Problem_0088_MergeSortedArray.java: -------------------------------------------------------------------------------- 1 | package class30; 2 | 3 | public class Problem_0088_MergeSortedArray { 4 | 5 | public static void merge(int[] nums1, int m, int[] nums2, int n) { 6 | int index = nums1.length; 7 | while (m > 0 && n > 0) { 8 | if (nums1[m - 1] >= nums2[n - 1]) { 9 | nums1[--index] = nums1[--m]; 10 | } else { 11 | nums1[--index] = nums2[--n]; 12 | } 13 | } 14 | while (m > 0) { 15 | nums1[--index] = nums1[--m]; 16 | } 17 | while (n > 0) { 18 | nums1[--index] = nums2[--n]; 19 | } 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/class30/Problem_0098_ValidateBinarySearchTree.java: -------------------------------------------------------------------------------- 1 | package class30; 2 | 3 | public class Problem_0098_ValidateBinarySearchTree { 4 | 5 | public static class TreeNode { 6 | int val; 7 | TreeNode left; 8 | TreeNode right; 9 | } 10 | 11 | public boolean isValidBST(TreeNode root) { 12 | if (root == null) { 13 | return true; 14 | } 15 | TreeNode cur = root; 16 | TreeNode mostRight = null; 17 | Integer pre = null; 18 | boolean ans = true; 19 | while (cur != null) { 20 | mostRight = cur.left; 21 | if (mostRight != null) { 22 | while (mostRight.right != null && mostRight.right != cur) { 23 | mostRight = mostRight.right; 24 | } 25 | if (mostRight.right == null) { 26 | mostRight.right = cur; 27 | cur = cur.left; 28 | continue; 29 | } else { 30 | mostRight.right = null; 31 | } 32 | } 33 | if (pre != null && pre >= cur.val) { 34 | ans = false; 35 | } 36 | pre = cur.val; 37 | cur = cur.right; 38 | } 39 | return ans; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/class30/Problem_0101_SymmetricTree.java: -------------------------------------------------------------------------------- 1 | package class30; 2 | 3 | public class Problem_0101_SymmetricTree { 4 | 5 | public static class TreeNode { 6 | int val; 7 | TreeNode left; 8 | TreeNode right; 9 | } 10 | 11 | public boolean isSymmetric(TreeNode root) { 12 | return isMirror(root, root); 13 | } 14 | 15 | // 一棵树是原始树 head1 16 | // 另一棵是翻面树 head2 17 | public static boolean isMirror(TreeNode head1, TreeNode head2) { 18 | if (head1 == null && head2 == null) { 19 | return true; 20 | } 21 | if (head1 != null && head2 != null) { 22 | return head1.val == head2.val 23 | && isMirror(head1.left, head2.right) 24 | && isMirror(head1.right, head2.left); 25 | } 26 | // 一个为空,一个不为空 false 27 | return false; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/class30/Problem_0103_BinaryTreeZigzagLevelOrderTraversal.java: -------------------------------------------------------------------------------- 1 | package class30; 2 | 3 | import java.util.ArrayList; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | 7 | public class Problem_0103_BinaryTreeZigzagLevelOrderTraversal { 8 | 9 | public static class TreeNode { 10 | int val; 11 | TreeNode left; 12 | TreeNode right; 13 | } 14 | 15 | public static List> zigzagLevelOrder(TreeNode root) { 16 | List> ans = new ArrayList<>(); 17 | if (root == null) { 18 | return ans; 19 | } 20 | LinkedList deque = new LinkedList<>(); 21 | deque.add(root); 22 | int size = 0; 23 | boolean isHead = true; 24 | while (!deque.isEmpty()) { 25 | size = deque.size(); 26 | List curLevel = new ArrayList<>(); 27 | for (int i = 0; i < size; i++) { 28 | TreeNode cur = isHead ? deque.pollFirst() : deque.pollLast(); 29 | curLevel.add(cur.val); 30 | if(isHead) { 31 | if (cur.left != null) { 32 | deque.addLast(cur.left); 33 | } 34 | if (cur.right != null) { 35 | deque.addLast(cur.right); 36 | } 37 | }else { 38 | if (cur.right != null) { 39 | deque.addFirst(cur.right); 40 | } 41 | if (cur.left != null) { 42 | deque.addFirst(cur.left); 43 | } 44 | } 45 | } 46 | ans.add(curLevel); 47 | isHead = !isHead; 48 | } 49 | return ans; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/class30/Problem_0108_ConvertSortedArrayToBinarySearchTree.java: -------------------------------------------------------------------------------- 1 | package class30; 2 | 3 | public class Problem_0108_ConvertSortedArrayToBinarySearchTree { 4 | 5 | public static class TreeNode { 6 | int val; 7 | TreeNode left; 8 | TreeNode right; 9 | 10 | TreeNode(int val) { 11 | this.val = val; 12 | } 13 | } 14 | 15 | public TreeNode sortedArrayToBST(int[] nums) { 16 | return process(nums, 0, nums.length - 1); 17 | } 18 | 19 | public static TreeNode process(int[] nums, int L, int R) { 20 | if (L > R) { 21 | return null; 22 | } 23 | if (L == R) { 24 | return new TreeNode(nums[L]); 25 | } 26 | int M = (L + R) / 2; 27 | TreeNode head = new TreeNode(nums[M]); 28 | head.left = process(nums, L, M - 1); 29 | head.right = process(nums, M + 1, R); 30 | return head; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/class30/Problem_0116_PopulatingNextRightPointersInEachNode.java: -------------------------------------------------------------------------------- 1 | package class30; 2 | 3 | public class Problem_0116_PopulatingNextRightPointersInEachNode { 4 | 5 | // 不要提交这个类 6 | public static class Node { 7 | public int val; 8 | public Node left; 9 | public Node right; 10 | public Node next; 11 | } 12 | 13 | // 提交下面的代码 14 | public static Node connect(Node root) { 15 | if (root == null) { 16 | return root; 17 | } 18 | MyQueue queue = new MyQueue(); 19 | queue.offer(root); 20 | while (!queue.isEmpty()) { 21 | // 第一个弹出的节点 22 | Node pre = null; 23 | int size = queue.size; 24 | for (int i = 0; i < size; i++) { 25 | Node cur = queue.poll(); 26 | if (cur.left != null) { 27 | queue.offer(cur.left); 28 | } 29 | if (cur.right != null) { 30 | queue.offer(cur.right); 31 | } 32 | if (pre != null) { 33 | pre.next = cur; 34 | } 35 | pre = cur; 36 | } 37 | } 38 | return root; 39 | } 40 | 41 | public static class MyQueue { 42 | public Node head; 43 | public Node tail; 44 | public int size; 45 | 46 | public MyQueue() { 47 | head = null; 48 | tail = null; 49 | size = 0; 50 | } 51 | 52 | public boolean isEmpty() { 53 | return size == 0; 54 | } 55 | 56 | public void offer(Node cur) { 57 | size++; 58 | if (head == null) { 59 | head = cur; 60 | tail = cur; 61 | } else { 62 | tail.next = cur; 63 | tail = cur; 64 | } 65 | } 66 | 67 | public Node poll() { 68 | size--; 69 | Node ans = head; 70 | head = head.next; 71 | ans.next = null; 72 | return ans; 73 | } 74 | 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /src/class30/Problem_0118_PascalTriangle.java: -------------------------------------------------------------------------------- 1 | package class30; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class Problem_0118_PascalTriangle { 7 | 8 | public static List> generate(int numRows) { 9 | List> ans = new ArrayList<>(); 10 | for (int i = 0; i < numRows; i++) { 11 | ans.add(new ArrayList<>()); 12 | ans.get(i).add(1); 13 | } 14 | for (int i = 1; i < numRows; i++) { 15 | for (int j = 1; j < i; j++) { 16 | ans.get(i).add(ans.get(i - 1).get(j - 1) + ans.get(i - 1).get(j)); 17 | } 18 | ans.get(i).add(1); 19 | } 20 | return ans; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/class30/Problem_0119_PascalTriangleII.java: -------------------------------------------------------------------------------- 1 | package class30; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class Problem_0119_PascalTriangleII { 7 | 8 | public List getRow(int rowIndex) { 9 | List ans = new ArrayList<>(); 10 | for (int i = 0; i <= rowIndex; i++) { 11 | for (int j = i - 1; j > 0; j--) { 12 | ans.set(j, ans.get(j - 1) + ans.get(j)); 13 | } 14 | ans.add(1); 15 | } 16 | return ans; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/class30/说明: -------------------------------------------------------------------------------- 1 | leetcode高频题 2 | leetcode全题目列表 : https://leetcode.com/problemset/all/ 3 | 在全题目列表的右侧栏,点击Top Interview Questions 4 | 或者直接进入右侧链接 : https://leetcode.com/problemset/all/?listId=wpwgkgt 5 | 即可看到leetcode高频题全列表 6 | 本节课解决leetcode高频题列表中的如下题目 : 7 | 0079 : 大厂刷题班, 第30节, 本节 8 | 0084 : 体系学习班, 第25节第3题 9 | 0088 : 大厂刷题班, 第30节, 本节 10 | 0091 : 体系学习班, 第19节第2题 11 | 0639 : 本题不再高频题列表中, 但本题是0091的难度加强题, 相似度很强, 大厂刷题班, 第30节, 本节 12 | 0094 : 体系学习班, 第30节第1题, Morris遍历 13 | 0098 : 大厂刷题班, 第30节, 本节 14 | 0101 : 大厂刷题班, 第30节, 本节 15 | 0102 : 新手班, 第7节第1题 16 | 0103 : 大厂刷题班, 第30节, 本节 17 | 0104 : 太简单了, 体系学习班, 二叉树的递归套路、Morris遍历都可以做, 跳过 18 | 0105 : 新手班, 第6节第5题 19 | 0108 : 大厂刷题班, 第30节, 本节 20 | 0116 : 大厂刷题班, 第30节, 本节 21 | 0118 : 大厂刷题班, 第30节, 本节 22 | 0119 : 本题不在高频题列表中,但和0118类似, 大厂刷题班, 第30节, 本节 23 | 0121 : 大厂刷题班, 第15节第1题 24 | 0122 : 大厂刷题班, 第15节第2题 25 | 0123 : 大厂刷题班, 第15节第3题 26 | 0124 : 大厂刷题班, 第30节, 本节 -------------------------------------------------------------------------------- /src/class31/Problem_0125_ValidPalindrome.java: -------------------------------------------------------------------------------- 1 | package class31; 2 | 3 | public class Problem_0125_ValidPalindrome { 4 | 5 | // 忽略空格、忽略大小写 -> 是不是回文 6 | // 数字不在忽略大小写的范围内 7 | public static boolean isPalindrome(String s) { 8 | if (s == null || s.length() == 0) { 9 | return true; 10 | } 11 | char[] str = s.toCharArray(); 12 | int L = 0; 13 | int R = str.length - 1; 14 | while (L < R) { 15 | // 英文(大小写) + 数字 16 | if (validChar(str[L]) && validChar(str[R])) { 17 | if (!equal(str[L], str[R])) { 18 | return false; 19 | } 20 | L++; 21 | R--; 22 | } else { 23 | L += validChar(str[L]) ? 0 : 1; 24 | R -= validChar(str[R]) ? 0 : 1; 25 | } 26 | } 27 | return true; 28 | } 29 | 30 | public static boolean validChar(char c) { 31 | return isLetter(c) || isNumber(c); 32 | } 33 | 34 | public static boolean equal(char c1, char c2) { 35 | if (isNumber(c1) || isNumber(c2)) { 36 | return c1 == c2; 37 | } 38 | // a A 32 39 | // b B 32 40 | // c C 32 41 | return (c1 == c2) || (Math.max(c1, c2) - Math.min(c1, c2) == 32); 42 | } 43 | 44 | public static boolean isLetter(char c) { 45 | return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); 46 | } 47 | 48 | public static boolean isNumber(char c) { 49 | return (c >= '0' && c <= '9'); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/class31/Problem_0150_EvaluateReversePolishNotation.java: -------------------------------------------------------------------------------- 1 | package class31; 2 | 3 | import java.util.Stack; 4 | 5 | public class Problem_0150_EvaluateReversePolishNotation { 6 | 7 | public static int evalRPN(String[] tokens) { 8 | Stack stack = new Stack<>(); 9 | for (String str : tokens) { 10 | if (str.equals("+") || str.equals("-") || str.equals("*") || str.equals("/")) { 11 | compute(stack, str); 12 | } else { 13 | stack.push(Integer.valueOf(str)); 14 | } 15 | } 16 | return stack.peek(); 17 | } 18 | 19 | public static void compute(Stack stack, String op) { 20 | int num2 = stack.pop(); 21 | int num1 = stack.pop(); 22 | int ans = 0; 23 | switch (op) { 24 | case "+": 25 | ans = num1 + num2; 26 | break; 27 | case "-": 28 | ans = num1 - num2; 29 | break; 30 | case "*": 31 | ans = num1 * num2; 32 | break; 33 | case "/": 34 | ans = num1 / num2; 35 | break; 36 | } 37 | stack.push(ans); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/class31/说明: -------------------------------------------------------------------------------- 1 | leetcode高频题 2 | leetcode全题目列表 : https://leetcode.com/problemset/all/ 3 | 在全题目列表的右侧栏,点击Top Interview Questions 4 | 或者直接进入右侧链接 : https://leetcode.com/problemset/all/?listId=wpwgkgt 5 | 即可看到leetcode高频题全列表 6 | 本节课解决leetcode高频题列表中的如下题目 : 7 | 0125 : 大厂刷题班, 第31节, 本节 8 | 0127 : 大厂刷题班, 第31节, 本节 9 | 0128 : 大厂刷题班, 第12节第3题 10 | 0130 : 大厂刷题班, 第31节, 本节 11 | 0131 : 大厂刷题班, 第11节第2题 12 | 0134 : 体系学习班, 第24节第3题 & 大厂刷题班, 第25节第4题 13 | 0136 : 体系学习班, 第2节第2题 14 | 0138 : 体系学习班, 第9节第4题 15 | 0139 : 大厂刷题班, 第31节, 本节 16 | 0140 : 大厂刷题班, 第31节, 本节 17 | 0141 : 体系学习班, 第10节第1题 18 | 0146 : 大厂刷题班, 第19节第1题 19 | 0148 : 大厂刷题班, 第31节, 本节 20 | 0149 : 大厂刷题班, 第25节第3题 21 | 0150 : 大厂刷题班, 第31节, 本节 -------------------------------------------------------------------------------- /src/class32/Problem_0152_MaximumProductSubarray.java: -------------------------------------------------------------------------------- 1 | package class32; 2 | 3 | public class Problem_0152_MaximumProductSubarray { 4 | 5 | 6 | public static double max(double[] arr) { 7 | if(arr == null || arr.length == 0) { 8 | return 0; // 报错! 9 | } 10 | int n = arr.length; 11 | // 上一步的最大 12 | double premax = arr[0]; 13 | // 上一步的最小 14 | double premin = arr[0]; 15 | double ans = arr[0]; 16 | for(int i = 1; i < n; i++) { 17 | double p1 = arr[i]; 18 | double p2 = arr[i] * premax; 19 | double p3 = arr[i] * premin; 20 | double curmax = Math.max(Math.max(p1, p2), p3); 21 | double curmin = Math.min(Math.min(p1, p2), p3); 22 | ans = Math.max(ans, curmax); 23 | premax = curmax; 24 | premin = curmin; 25 | } 26 | return ans; 27 | } 28 | 29 | 30 | 31 | public static int maxProduct(int[] nums) { 32 | int ans = nums[0]; 33 | int min = nums[0]; 34 | int max = nums[0]; 35 | for (int i = 1; i < nums.length; i++) { 36 | int curmin = Math.min(nums[i], Math.min(min * nums[i], max * nums[i])); 37 | int curmax = Math.max(nums[i], Math.max(min * nums[i], max * nums[i])); 38 | min = curmin; 39 | max = curmax; 40 | ans = Math.max(ans, max); 41 | } 42 | return ans; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/class32/Problem_0163_MissingRanges.java: -------------------------------------------------------------------------------- 1 | package class32; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class Problem_0163_MissingRanges { 7 | 8 | public static List findMissingRanges(int[] nums, int lower, int upper) { 9 | List ans = new ArrayList<>(); 10 | for (int num : nums) { 11 | if (num > lower) { 12 | ans.add(miss(lower, num - 1)); 13 | } 14 | if (num == upper) { 15 | return ans; 16 | } 17 | lower = num + 1; 18 | } 19 | if (lower <= upper) { 20 | ans.add(miss(lower, upper)); 21 | } 22 | return ans; 23 | } 24 | 25 | // 生成"lower->upper"的字符串,如果lower==upper,只用生成"lower" 26 | public static String miss(int lower, int upper) { 27 | String left = String.valueOf(lower); 28 | String right = ""; 29 | if (upper > lower) { 30 | right = "->" + String.valueOf(upper); 31 | } 32 | return left + right; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/class32/Problem_0166_FractionToRecurringDecimal.java: -------------------------------------------------------------------------------- 1 | package class32; 2 | 3 | import java.util.HashMap; 4 | 5 | public class Problem_0166_FractionToRecurringDecimal { 6 | 7 | public static String fractionToDecimal(int numerator, int denominator) { 8 | if (numerator == 0) { 9 | return "0"; 10 | } 11 | StringBuilder res = new StringBuilder(); 12 | // "+" or "-" 13 | res.append(((numerator > 0) ^ (denominator > 0)) ? "-" : ""); 14 | long num = Math.abs((long) numerator); 15 | long den = Math.abs((long) denominator); 16 | // integral part 17 | res.append(num / den); 18 | num %= den; 19 | if (num == 0) { 20 | return res.toString(); 21 | } 22 | // fractional part 23 | res.append("."); 24 | HashMap map = new HashMap(); 25 | map.put(num, res.length()); 26 | while (num != 0) { 27 | num *= 10; 28 | res.append(num / den); 29 | num %= den; 30 | if (map.containsKey(num)) { 31 | int index = map.get(num); 32 | res.insert(index, "("); 33 | res.append(")"); 34 | break; 35 | } else { 36 | map.put(num, res.length()); 37 | } 38 | } 39 | return res.toString(); 40 | } 41 | 42 | public static void main(String[] args) { 43 | System.out.println(fractionToDecimal(127, 999)); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/class32/Problem_0171_ExcelSheetColumnNumber.java: -------------------------------------------------------------------------------- 1 | package class32; 2 | 3 | public class Problem_0171_ExcelSheetColumnNumber { 4 | 5 | // 这道题反过来也要会写 6 | public static int titleToNumber(String s) { 7 | char[] str = s.toCharArray(); 8 | int ans = 0; 9 | for (int i = 0; i < str.length; i++) { 10 | ans = ans * 26 + (str[i] - 'A') + 1; 11 | } 12 | return ans; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/class32/Problem_0172_FactorialTrailingZeroes.java: -------------------------------------------------------------------------------- 1 | package class32; 2 | 3 | public class Problem_0172_FactorialTrailingZeroes { 4 | 5 | public static int trailingZeroes(int n) { 6 | int ans = 0; 7 | while (n != 0) { 8 | n /= 5; 9 | ans += n; 10 | } 11 | return ans; 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/class32/Problem_0189_RotateArray.java: -------------------------------------------------------------------------------- 1 | package class32; 2 | 3 | public class Problem_0189_RotateArray { 4 | 5 | public void rotate1(int[] nums, int k) { 6 | int N = nums.length; 7 | k = k % N; 8 | reverse(nums, 0, N - k - 1); 9 | reverse(nums, N - k, N - 1); 10 | reverse(nums, 0, N - 1); 11 | } 12 | 13 | public static void reverse(int[] nums, int L, int R) { 14 | while (L < R) { 15 | int tmp = nums[L]; 16 | nums[L++] = nums[R]; 17 | nums[R--] = tmp; 18 | } 19 | } 20 | 21 | public static void rotate2(int[] nums, int k) { 22 | int N = nums.length; 23 | k = k % N; 24 | if (k == 0) { 25 | return; 26 | } 27 | int L = 0; 28 | int R = N - 1; 29 | int lpart = N - k; 30 | int rpart = k; 31 | int same = Math.min(lpart, rpart); 32 | int diff = lpart - rpart; 33 | exchange(nums, L, R, same); 34 | while (diff != 0) { 35 | if (diff > 0) { 36 | L += same; 37 | lpart = diff; 38 | } else { 39 | R -= same; 40 | rpart = -diff; 41 | } 42 | same = Math.min(lpart, rpart); 43 | diff = lpart - rpart; 44 | exchange(nums, L, R, same); 45 | } 46 | } 47 | 48 | public static void exchange(int[] nums, int start, int end, int size) { 49 | int i = end - size + 1; 50 | int tmp = 0; 51 | while (size-- != 0) { 52 | tmp = nums[start]; 53 | nums[start] = nums[i]; 54 | nums[i] = tmp; 55 | start++; 56 | i++; 57 | } 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/class32/Problem_0190_ReverseBits.java: -------------------------------------------------------------------------------- 1 | package class32; 2 | 3 | public class Problem_0190_ReverseBits { 4 | 5 | // 代码看着很魔幻吧? 6 | // 给个例子,假设n二进制为: 7 | // 1011 0111 0011 1001 0011 1111 0110 1010 8 | // 解释一下,第一行,是把n左边16位,和n右边16位交换 9 | // n = (n >>> 16) | (n << 16); 10 | // 因为 n >>> 16 就是左边16位被移动到了右侧 11 | // 同时 n << 16 就是右边16位被移动到了左侧 12 | // 又 | 在了一起,所以,n变成了 13 | // 0011 1111 0110 1010 1011 0111 0011 1001 14 | 15 | // 第二行, 16 | // n = ((n & 0xff00ff00) >>> 8) | ((n & 0x00ff00ff) << 8); 17 | // (n & 0xff00ff00) 18 | // 这一句意思是,左侧开始算0~7位,保留;8~15位,全变0;16~23位,保留;24~31位,全变0 19 | // 0011 1111 0000 0000 1011 0111 0000 0000 20 | // (n & 0xff00ff00) >>> 8 这句就是上面的值,统一向右移动8位,变成: 21 | // 0000 0000 0011 1111 0000 0000 1011 0111 22 | // 23 | // 24 | // (n & 0x00ff00ff) 25 | // 这一句意思是,左侧开始算0~7位,全变0;8~15位,保留;16~23位,全变0;24~31位,保留 26 | // 0000 0000 0110 1010 0000 0000 0011 1001 27 | // (n & 0x00ff00ff) << 8 这句就是上面的值,统一向左移动8位,变成: 28 | // 0110 1010 0000 0000 0011 1001 0000 0000 29 | // 那么 ((n & 0xff00ff00) >>> 8) | ((n & 0x00ff00ff) << 8) 30 | // 什么效果?就是n的0~7位和8~15位交换了,16~23位和24~31位交换了 31 | // 0110 1010 0011 1111 0011 1001 1011 0111 32 | 33 | // 也就是说,整个过程是n的左16位,和右16位交换 34 | // n的左16位的内部,左8位和右8位交换;n的右16位的内部,左8位和右8位交换 35 | // 接下来的一行,其实是,从左边开始算,0~7位内部,左4和右4交换;8~15位,左4和右4交换;... 36 | // 接下来的一行,其实是,从左边开始算,0~3位内部,左2和右2交换;4~7位,左2和右2交换;... 37 | // 最后的一行,其实是,从左边开始算,0~1位内部,左1和右1交换;2~3位,左1和右1交换;... 38 | public static int reverseBits(int n) { 39 | // n的高16位,和n的低16位,交换 40 | n = (n >>> 16) | (n << 16); 41 | n = ((n & 0xff00ff00) >>> 8) | ((n & 0x00ff00ff) << 8); 42 | n = ((n & 0xf0f0f0f0) >>> 4) | ((n & 0x0f0f0f0f) << 4); 43 | n = ((n & 0xcccccccc) >>> 2) | ((n & 0x33333333) << 2); 44 | n = ((n & 0xaaaaaaaa) >>> 1) | ((n & 0x55555555) << 1); 45 | return n; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/class32/Problem_0191_NumberOf1Bits.java: -------------------------------------------------------------------------------- 1 | package class32; 2 | 3 | public class Problem_0191_NumberOf1Bits { 4 | 5 | // n的二进制形式,有几个1? 6 | public static int hammingWeight1(int n) { 7 | int bits = 0; 8 | int rightOne = 0; 9 | while(n != 0) { 10 | bits++; 11 | rightOne = n & (-n); 12 | n ^= rightOne; 13 | } 14 | return bits; 15 | } 16 | 17 | public static int hammingWeight2(int n) { 18 | n = (n & 0x55555555) + ((n >>> 1) & 0x55555555); 19 | n = (n & 0x33333333) + ((n >>> 2) & 0x33333333); 20 | n = (n & 0x0f0f0f0f) + ((n >>> 4) & 0x0f0f0f0f); 21 | n = (n & 0x00ff00ff) + ((n >>> 8) & 0x00ff00ff); 22 | n = (n & 0x0000ffff) + ((n >>> 16) & 0x0000ffff); 23 | return n; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/class32/Problem_0202_HappyNumber.java: -------------------------------------------------------------------------------- 1 | package class32; 2 | 3 | import java.util.HashSet; 4 | import java.util.TreeSet; 5 | 6 | public class Problem_0202_HappyNumber { 7 | 8 | public static boolean isHappy1(int n) { 9 | HashSet set = new HashSet<>(); 10 | while (n != 1) { 11 | int sum = 0; 12 | while (n != 0) { 13 | int r = n % 10; 14 | sum += r * r; 15 | n /= 10; 16 | } 17 | n = sum; 18 | if (set.contains(n)) { 19 | break; 20 | } 21 | set.add(n); 22 | } 23 | return n == 1; 24 | } 25 | 26 | // 实验代码 27 | public static TreeSet sum(int n) { 28 | TreeSet set = new TreeSet<>(); 29 | while (!set.contains(n)) { 30 | set.add(n); 31 | int sum = 0; 32 | while (n != 0) { 33 | sum += (n % 10) * (n % 10); 34 | n /= 10; 35 | } 36 | n = sum; 37 | } 38 | return set; 39 | } 40 | 41 | public static boolean isHappy2(int n) { 42 | while (n != 1 && n != 4) { 43 | int sum = 0; 44 | while (n != 0) { 45 | sum += (n % 10) * (n % 10); 46 | n /= 10; 47 | } 48 | n = sum; 49 | } 50 | return n == 1; 51 | } 52 | 53 | public static void main(String[] args) { 54 | for (int i = 1; i < 1000; i++) { 55 | System.out.println(sum(i)); 56 | } 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/class32/Problem_0204_CountPrimes.java: -------------------------------------------------------------------------------- 1 | package class32; 2 | 3 | public class Problem_0204_CountPrimes { 4 | 5 | public static int countPrimes(int n) { 6 | if (n < 3) { 7 | return 0; 8 | } 9 | // j已经不是素数了,f[j] = true; 10 | boolean[] f = new boolean[n]; 11 | int count = n / 2; // 所有偶数都不要,还剩几个数 12 | // 跳过了1、2 3、5、7、 13 | for (int i = 3; i * i < n; i += 2) { 14 | if (f[i]) { 15 | continue; 16 | } 17 | // 3 -> 3 * 3 = 9 3 * 5 = 15 3 * 7 = 21 18 | // 7 -> 7 * 7 = 49 7 * 9 = 63 19 | // 13 -> 13 * 13 13 * 15 20 | for (int j = i * i; j < n; j += 2 * i) { 21 | if (!f[j]) { 22 | --count; 23 | f[j] = true; 24 | } 25 | } 26 | } 27 | return count; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/class32/说明: -------------------------------------------------------------------------------- 1 | leetcode高频题 2 | leetcode全题目列表 : https://leetcode.com/problemset/all/ 3 | 在全题目列表的右侧栏,点击Top Interview Questions 4 | 或者直接进入右侧链接 : https://leetcode.com/problemset/all/?listId=wpwgkgt 5 | 即可看到leetcode高频题全列表 6 | 本节课解决leetcode高频题列表中的如下题目 : 7 | 0152 : 大厂刷题班, 第32节, 本节 8 | 0155 : 体系学习班, 第3节第5题 9 | 0160 : 体系学习班, 第10节第1题 10 | 0162 : 体系学习班, 第1节第6题 11 | 0163 : 大厂刷题班, 第32节, 本节 12 | 0166 : 大厂刷题班, 第32节, 本节 13 | 0169 : 大厂刷题班, 第23节第4题 14 | 0171 : 大厂刷题班, 第32节, 本节 15 | 0172 : 大厂刷题班, 第32节, 本节 16 | 0179 : 体系学习班, 第13节第5题 17 | 0188 : 大厂刷题班, 第15节第4题 18 | 0189 : 大厂刷题班, 第32节, 本节 19 | 0190 : 大厂刷题班, 第32节, 本节 20 | 0191 : 大厂刷题班, 第32节, 本节 21 | 0198 : 大厂刷题班, 第4节第4题 22 | 0200 : 体系学习班, 第15节第2题、第3题 23 | 0202 : 大厂刷题班, 第32节, 本节 24 | 0204 : 大厂刷题班, 第32节, 本节 25 | 补充题 SequenceM : 拼多多, 卷子合法数量问题 -------------------------------------------------------------------------------- /src/class33/Problem_0210_CourseScheduleII.java: -------------------------------------------------------------------------------- 1 | package class33; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.LinkedList; 6 | import java.util.Queue; 7 | 8 | public class Problem_0210_CourseScheduleII { 9 | 10 | public static class Node { 11 | public int name; 12 | public int in; 13 | public ArrayList nexts; 14 | 15 | public Node(int n) { 16 | name = n; 17 | in = 0; 18 | nexts = new ArrayList<>(); 19 | } 20 | } 21 | 22 | public int[] findOrder(int numCourses, int[][] prerequisites) { 23 | int[] ans = new int[numCourses]; 24 | for (int i = 0; i < numCourses; i++) { 25 | ans[i] = i; 26 | } 27 | if (prerequisites == null || prerequisites.length == 0) { 28 | return ans; 29 | } 30 | HashMap nodes = new HashMap<>(); 31 | for (int[] arr : prerequisites) { 32 | int to = arr[0]; 33 | int from = arr[1]; 34 | if (!nodes.containsKey(to)) { 35 | nodes.put(to, new Node(to)); 36 | } 37 | if (!nodes.containsKey(from)) { 38 | nodes.put(from, new Node(from)); 39 | } 40 | Node t = nodes.get(to); 41 | Node f = nodes.get(from); 42 | f.nexts.add(t); 43 | t.in++; 44 | } 45 | int index = 0; 46 | Queue zeroInQueue = new LinkedList<>(); 47 | for (int i = 0; i < numCourses; i++) { 48 | if (!nodes.containsKey(i)) { 49 | ans[index++] = i; 50 | } else { 51 | if (nodes.get(i).in == 0) { 52 | zeroInQueue.add(nodes.get(i)); 53 | } 54 | } 55 | } 56 | int needPrerequisiteNums = nodes.size(); 57 | int count = 0; 58 | while (!zeroInQueue.isEmpty()) { 59 | Node cur = zeroInQueue.poll(); 60 | ans[index++] = cur.name; 61 | count++; 62 | for (Node next : cur.nexts) { 63 | if (--next.in == 0) { 64 | zeroInQueue.add(next); 65 | } 66 | } 67 | } 68 | return count == needPrerequisiteNums ? ans : new int[0]; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/class33/Problem_0213_HouseRobberII.java: -------------------------------------------------------------------------------- 1 | package class33; 2 | 3 | public class Problem_0213_HouseRobberII { 4 | 5 | // arr 长度大于等于1 6 | public static int pickMaxSum(int[] arr) { 7 | int n = arr.length; 8 | // dp[i] : arr[0..i]范围上,随意选择,但是,任何两数不能相邻。得到的最大累加和是多少? 9 | int[] dp = new int[n]; 10 | dp[0] = arr[0]; 11 | dp[1] = Math.max(arr[0], arr[1]); 12 | for (int i = 2; i < n; i++) { 13 | int p1 = arr[i]; 14 | int p2 = dp[i - 1]; 15 | int p3 = arr[i] + dp[i - 2]; 16 | dp[i] = Math.max(p1, Math.max(p2, p3)); 17 | } 18 | return dp[n - 1]; 19 | } 20 | 21 | public static int rob(int[] nums) { 22 | if (nums == null || nums.length == 0) { 23 | return 0; 24 | } 25 | if (nums.length == 1) { 26 | return nums[0]; 27 | } 28 | if (nums.length == 2) { 29 | return Math.max(nums[0], nums[1]); 30 | } 31 | int pre2 = nums[0]; 32 | int pre1 = Math.max(nums[0], nums[1]); 33 | for (int i = 2; i < nums.length - 1; i++) { 34 | int tmp = Math.max(pre1, nums[i] + pre2); 35 | pre2 = pre1; 36 | pre1 = tmp; 37 | } 38 | int ans1 = pre1; 39 | pre2 = nums[1]; 40 | pre1 = Math.max(nums[1], nums[2]); 41 | for (int i = 3; i < nums.length; i++) { 42 | int tmp = Math.max(pre1, nums[i] + pre2); 43 | pre2 = pre1; 44 | pre1 = tmp; 45 | } 46 | int ans2 = pre1; 47 | return Math.max(ans1, ans2); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/class33/Problem_0237_DeleteNodeInLinkedList.java: -------------------------------------------------------------------------------- 1 | package class33; 2 | 3 | public class Problem_0237_DeleteNodeInLinkedList { 4 | 5 | public static class ListNode { 6 | int val; 7 | ListNode next; 8 | } 9 | 10 | public void deleteNode(ListNode node) { 11 | node.val = node.next.val; 12 | node.next = node.next.next; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/class33/Problem_0238_ProductOfArrayExceptSelf.java: -------------------------------------------------------------------------------- 1 | package class33; 2 | 3 | public class Problem_0238_ProductOfArrayExceptSelf { 4 | 5 | public int[] productExceptSelf(int[] nums) { 6 | int n = nums.length; 7 | int[] ans = new int[n]; 8 | ans[0] = nums[0]; 9 | for (int i = 1; i < n; i++) { 10 | ans[i] = ans[i - 1] * nums[i]; 11 | } 12 | int right = 1; 13 | for (int i = n - 1; i > 0; i--) { 14 | ans[i] = ans[i - 1] * right; 15 | right *= nums[i]; 16 | } 17 | ans[0] = right; 18 | return ans; 19 | } 20 | 21 | // 扩展 : 如果仅仅是不能用除号,把结果直接填在nums里呢? 22 | // 解法:数一共几个0;每一个位得到结果就是,a / b,位运算替代 /,之前的课讲过(新手班) 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/class33/Problem_0242_ValidAnagram.java: -------------------------------------------------------------------------------- 1 | package class33; 2 | 3 | public class Problem_0242_ValidAnagram { 4 | 5 | public static boolean isAnagram(String s, String t) { 6 | if (s.length() != t.length()) { 7 | return false; 8 | } 9 | char[] str1 = s.toCharArray(); 10 | char[] str2 = t.toCharArray(); 11 | int[] count = new int[256]; 12 | for (char cha : str1) { 13 | count[cha]++; 14 | } 15 | for (char cha : str2) { 16 | if (--count[cha] < 0) { 17 | return false; 18 | } 19 | } 20 | return true; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/class33/Problem_0251_Flatten2DVector.java: -------------------------------------------------------------------------------- 1 | package class33; 2 | 3 | public class Problem_0251_Flatten2DVector { 4 | 5 | public static class Vector2D { 6 | private int[][] matrix; 7 | private int row; 8 | private int col; 9 | private boolean curUse; 10 | 11 | public Vector2D(int[][] v) { 12 | matrix = v; 13 | row = 0; 14 | col = -1; 15 | curUse = true; 16 | hasNext(); 17 | } 18 | 19 | public int next() { 20 | int ans = matrix[row][col]; 21 | curUse = true; 22 | hasNext(); 23 | return ans; 24 | } 25 | 26 | public boolean hasNext() { 27 | if (row == matrix.length) { 28 | return false; 29 | } 30 | if (!curUse) { 31 | return true; 32 | } 33 | // (row,col)用过了 34 | if (col < matrix[row].length - 1) { 35 | col++; 36 | } else { 37 | col = 0; 38 | do { 39 | row++; 40 | } while (row < matrix.length && matrix[row].length == 0); 41 | } 42 | // 新的(row,col) 43 | if (row != matrix.length) { 44 | curUse = false; 45 | return true; 46 | } else { 47 | return false; 48 | } 49 | } 50 | 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/class33/Problem_0269_AlienDictionary.java: -------------------------------------------------------------------------------- 1 | package class33; 2 | 3 | import java.util.HashMap; 4 | import java.util.HashSet; 5 | import java.util.LinkedList; 6 | import java.util.Queue; 7 | 8 | public class Problem_0269_AlienDictionary { 9 | 10 | public static String alienOrder(String[] words) { 11 | if (words == null || words.length == 0) { 12 | return ""; 13 | } 14 | int N = words.length; 15 | HashMap indegree = new HashMap<>(); 16 | for (int i = 0; i < N; i++) { 17 | for (char c : words[i].toCharArray()) { 18 | indegree.put(c, 0); 19 | } 20 | } 21 | HashMap> graph = new HashMap<>(); 22 | for (int i = 0; i < N - 1; i++) { 23 | char[] cur = words[i].toCharArray(); 24 | char[] nex = words[i + 1].toCharArray(); 25 | int len = Math.min(cur.length, nex.length); 26 | int j = 0; 27 | for (; j < len; j++) { 28 | if (cur[j] != nex[j]) { 29 | if (!graph.containsKey(cur[j])) { 30 | graph.put(cur[j], new HashSet<>()); 31 | } 32 | if (!graph.get(cur[j]).contains(nex[j])) { 33 | graph.get(cur[j]).add(nex[j]); 34 | indegree.put(nex[j], indegree.get(nex[j]) + 1); 35 | } 36 | break; 37 | } 38 | } 39 | if (j < cur.length && j == nex.length) { 40 | return ""; 41 | } 42 | } 43 | StringBuilder ans = new StringBuilder(); 44 | Queue q = new LinkedList<>(); 45 | for (Character key : indegree.keySet()) { 46 | if (indegree.get(key) == 0) { 47 | q.offer(key); 48 | } 49 | } 50 | while (!q.isEmpty()) { 51 | char cur = q.poll(); 52 | ans.append(cur); 53 | if (graph.containsKey(cur)) { 54 | for (char next : graph.get(cur)) { 55 | indegree.put(next, indegree.get(next) - 1); 56 | if (indegree.get(next) == 0) { 57 | q.offer(next); 58 | } 59 | } 60 | } 61 | } 62 | return ans.length() == indegree.size() ? ans.toString() : ""; 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/class33/Problem_0277_FindTheCelebrity.java: -------------------------------------------------------------------------------- 1 | package class33; 2 | 3 | public class Problem_0277_FindTheCelebrity { 4 | 5 | // 提交时不要提交这个函数,因为默认系统会给你这个函数 6 | // knows方法,自己不认识自己 7 | public static boolean knows(int x, int i) { 8 | return true; 9 | } 10 | 11 | // 只提交下面的方法 0 ~ n-1 12 | public int findCelebrity(int n) { 13 | // 谁可能成为明星,谁就是cand 14 | int cand = 0; 15 | for (int i = 0; i < n; ++i) { 16 | if (knows(cand, i)) { 17 | cand = i; 18 | } 19 | } 20 | // cand是什么?唯一可能是明星的人! 21 | // 下一步就是验证,它到底是不是明星 22 | // 1) cand是不是不认识所有的人 cand...(右侧cand都不认识) 23 | // 所以,只用验证 ....cand的左侧即可 24 | for (int i = 0; i < cand; ++i) { 25 | if (knows(cand, i)) { 26 | return -1; 27 | } 28 | } 29 | // 2) 是不是所有的人都认识cand 30 | for (int i = 0; i < n; ++i) { 31 | if (!knows(i, cand)) { 32 | return -1; 33 | } 34 | } 35 | return cand; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/class33/Problem_0279_PerfectSquares.java: -------------------------------------------------------------------------------- 1 | package class33; 2 | 3 | public class Problem_0279_PerfectSquares { 4 | 5 | // 暴力解 6 | public static int numSquares1(int n) { 7 | int res = n, num = 2; 8 | while (num * num <= n) { 9 | int a = n / (num * num), b = n % (num * num); 10 | res = Math.min(res, a + numSquares1(b)); 11 | num++; 12 | } 13 | return res; 14 | } 15 | 16 | // 1 : 1, 4, 9, 16, 25, 36, ... 17 | // 4 : 7, 15, 23, 28, 31, 39, 47, 55, 60, 63, 71, ... 18 | // 规律解 19 | // 规律一:个数不超过4 20 | // 规律二:出现1个的时候,显而易见 21 | // 规律三:任何数 % 8 == 7,一定是4个 22 | // 规律四:任何数消去4的因子之后,剩下rest,rest % 8 == 7,一定是4个 23 | public static int numSquares2(int n) { 24 | int rest = n; 25 | while (rest % 4 == 0) { 26 | rest /= 4; 27 | } 28 | if (rest % 8 == 7) { 29 | return 4; 30 | } 31 | int f = (int) Math.sqrt(n); 32 | if (f * f == n) { 33 | return 1; 34 | } 35 | for (int first = 1; first * first <= n; first++) { 36 | int second = (int) Math.sqrt(n - first * first); 37 | if (first * first + second * second == n) { 38 | return 2; 39 | } 40 | } 41 | return 3; 42 | } 43 | 44 | // 数学解 45 | // 1)四平方和定理 46 | // 2)任何数消掉4的因子,结论不变 47 | public static int numSquares3(int n) { 48 | while (n % 4 == 0) { 49 | n /= 4; 50 | } 51 | if (n % 8 == 7) { 52 | return 4; 53 | } 54 | for (int a = 0; a * a <= n; ++a) { 55 | // a * a + b * b = n 56 | int b = (int) Math.sqrt(n - a * a); 57 | if (a * a + b * b == n) { 58 | return (a > 0 && b > 0) ? 2 : 1; 59 | } 60 | } 61 | return 3; 62 | } 63 | 64 | public static void main(String[] args) { 65 | for (int i = 1; i < 1000; i++) { 66 | System.out.println(i + " , " + numSquares1(i)); 67 | } 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/class33/Problem_0283_MoveZeroes.java: -------------------------------------------------------------------------------- 1 | package class33; 2 | 3 | public class Problem_0283_MoveZeroes { 4 | 5 | public static void moveZeroes(int[] nums) { 6 | int to = 0; 7 | for (int i = 0; i < nums.length; i++) { 8 | if (nums[i] != 0) { 9 | swap(nums, to++, i); 10 | } 11 | } 12 | } 13 | 14 | public static void swap(int[] arr, int i, int j) { 15 | int tmp = arr[i]; 16 | arr[i] = arr[j]; 17 | arr[j] = tmp; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/class33/说明: -------------------------------------------------------------------------------- 1 | leetcode高频题 2 | leetcode全题目列表 : https://leetcode.com/problemset/all/ 3 | 在全题目列表的右侧栏,点击Top Interview Questions 4 | 或者直接进入右侧链接 : https://leetcode.com/problemset/all/?listId=wpwgkgt 5 | 即可看到leetcode高频题全列表 6 | 本节课解决leetcode高频题列表中的如下题目 : 7 | 0206 : 太简单,跳过 8 | 0207 : 大厂刷题班, 第33节, 本节 9 | 0208 : 体系学习班, 第8节第1题 10 | 0210 : 大厂刷题班, 第33节, 本节 11 | 0212 : 大厂刷题班, 第26节第1题 12 | 0213 : 大厂刷题班, 第33节, 本节 13 | 0215 : 体系学习班, 第29节第1题 14 | 0217 : 太简单,跳过 15 | 0218 : 大厂刷题班, 第4节第8题 16 | 0227 : 大厂刷题班, 第8节第1题 17 | 0230 : 太简单了,跳过。二叉树基本遍历、Morris遍历都可以解决 18 | 0234 : 体系学习班, 第9节第2题 19 | 0236 : 体系学习班, 第13节第3题 扩展在 大厂刷题班, 第23节第1题 20 | 0237 : 大厂刷题班, 第33节, 本节 21 | 0238 : 大厂刷题班, 第33节, 本节 22 | 0239 : 体系学习班, 第24节第1题 23 | 0240 : 大厂刷题班, 第17节第1题 24 | 0242 : 大厂刷题班, 第33节, 本节 25 | 0251 : 大厂刷题班, 第33节, 本节 26 | 0253 : 体系学习班, 第14节第3题 27 | 0268 : 大厂刷题班, 第14节第6题 28 | 0269 : 大厂刷题班, 第33节, 本节 29 | 0277 : 大厂刷题班, 第33节, 本节 30 | 0279 : 大厂刷题班, 第33节, 本节 31 | 0283 : 大厂刷题班, 第33节, 本节 32 | 0285 : 太简单了,跳过。用二叉树普通遍历或者Morris遍历都可以解决 -------------------------------------------------------------------------------- /src/class34/Problem_0287_FindTheDuplicateNumber.java: -------------------------------------------------------------------------------- 1 | package class34; 2 | 3 | public class Problem_0287_FindTheDuplicateNumber { 4 | 5 | public static int findDuplicate(int[] nums) { 6 | if (nums == null || nums.length < 2) { 7 | return -1; 8 | } 9 | int slow = nums[0]; 10 | int fast = nums[nums[0]]; 11 | while (slow != fast) { 12 | slow = nums[slow]; 13 | fast = nums[nums[fast]]; 14 | } 15 | fast = 0; 16 | while (slow != fast) { 17 | fast = nums[fast]; 18 | slow = nums[slow]; 19 | } 20 | return slow; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/class34/Problem_0289_GameOfLife.java: -------------------------------------------------------------------------------- 1 | package class34; 2 | 3 | // 有关这个游戏更有意思、更完整的内容: 4 | // https://www.bilibili.com/video/BV1rJ411n7ri 5 | // 也推荐这个up主 6 | public class Problem_0289_GameOfLife { 7 | 8 | public static void gameOfLife(int[][] board) { 9 | int N = board.length; 10 | int M = board[0].length; 11 | for (int i = 0; i < N; i++) { 12 | for (int j = 0; j < M; j++) { 13 | int neighbors = neighbors(board, i, j); 14 | if (neighbors == 3 || (board[i][j] == 1 && neighbors == 2)) { 15 | board[i][j] |= 2; 16 | } 17 | } 18 | } 19 | for (int i = 0; i < N; i++) { 20 | for (int j = 0; j < M; j++) { 21 | board[i][j] >>= 1; 22 | } 23 | } 24 | } 25 | 26 | // b[i][j] 这个位置的数,周围有几个1 27 | public static int neighbors(int[][] b, int i, int j) { 28 | return f(b, i - 1, j - 1) 29 | + f(b, i - 1, j) 30 | + f(b, i - 1, j + 1) 31 | + f(b, i, j - 1) 32 | + f(b, i, j + 1) 33 | + f(b, i + 1, j - 1) 34 | + f(b, i + 1, j) 35 | + f(b, i + 1, j + 1); 36 | } 37 | 38 | // b[i][j] 上面有1,就返回1,上面不是1,就返回0 39 | public static int f(int[][] b, int i, int j) { 40 | return (i >= 0 && i < b.length && j >= 0 && j < b[0].length && (b[i][j] & 1) == 1) ? 1 : 0; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/class34/Problem_0295_FindMedianFromDataStream.java: -------------------------------------------------------------------------------- 1 | package class34; 2 | 3 | import java.util.PriorityQueue; 4 | 5 | public class Problem_0295_FindMedianFromDataStream { 6 | 7 | class MedianFinder { 8 | 9 | private PriorityQueue maxh; 10 | private PriorityQueue minh; 11 | 12 | public MedianFinder() { 13 | maxh = new PriorityQueue<>((a, b) -> b - a); 14 | minh = new PriorityQueue<>((a, b) -> a - b); 15 | } 16 | 17 | public void addNum(int num) { 18 | if (maxh.isEmpty() || maxh.peek() >= num) { 19 | maxh.add(num); 20 | } else { 21 | minh.add(num); 22 | } 23 | balance(); 24 | } 25 | 26 | public double findMedian() { 27 | if (maxh.size() == minh.size()) { 28 | return (double) (maxh.peek() + minh.peek()) / 2; 29 | } else { 30 | return maxh.size() > minh.size() ? maxh.peek() : minh.peek(); 31 | } 32 | } 33 | 34 | private void balance() { 35 | if (Math.abs(maxh.size() - minh.size()) == 2) { 36 | if (maxh.size() > minh.size()) { 37 | minh.add(maxh.poll()); 38 | } else { 39 | maxh.add(minh.poll()); 40 | } 41 | } 42 | } 43 | 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /src/class34/Problem_0315_CountOfSmallerNumbersAfterSelf.java: -------------------------------------------------------------------------------- 1 | package class34; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class Problem_0315_CountOfSmallerNumbersAfterSelf { 7 | 8 | public static class Node { 9 | public int value; 10 | public int index; 11 | 12 | public Node(int v, int i) { 13 | value = v; 14 | index = i; 15 | } 16 | } 17 | 18 | public static List countSmaller(int[] nums) { 19 | List ans = new ArrayList<>(); 20 | if (nums == null) { 21 | return ans; 22 | } 23 | for (int i = 0; i < nums.length; i++) { 24 | ans.add(0); 25 | } 26 | if (nums.length < 2) { 27 | return ans; 28 | } 29 | Node[] arr = new Node[nums.length]; 30 | for (int i = 0; i < arr.length; i++) { 31 | arr[i] = new Node(nums[i], i); 32 | } 33 | process(arr, 0, arr.length - 1, ans); 34 | return ans; 35 | } 36 | 37 | public static void process(Node[] arr, int l, int r, List ans) { 38 | if (l == r) { 39 | return; 40 | } 41 | int mid = l + ((r - l) >> 1); 42 | process(arr, l, mid, ans); 43 | process(arr, mid + 1, r, ans); 44 | merge(arr, l, mid, r, ans); 45 | } 46 | 47 | public static void merge(Node[] arr, int l, int m, int r, List ans) { 48 | Node[] help = new Node[r - l + 1]; 49 | int i = help.length - 1; 50 | int p1 = m; 51 | int p2 = r; 52 | while (p1 >= l && p2 >= m + 1) { 53 | if (arr[p1].value > arr[p2].value) { 54 | ans.set(arr[p1].index, ans.get(arr[p1].index) + p2 - m); 55 | } 56 | help[i--] = arr[p1].value > arr[p2].value ? arr[p1--] : arr[p2--]; 57 | } 58 | while (p1 >= l) { 59 | help[i--] = arr[p1--]; 60 | } 61 | while (p2 >= m + 1) { 62 | help[i--] = arr[p2--]; 63 | } 64 | for (i = 0; i < help.length; i++) { 65 | arr[l + i] = help[i]; 66 | } 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/class34/Problem_0326_PowerOfThree.java: -------------------------------------------------------------------------------- 1 | package class34; 2 | 3 | public class Problem_0326_PowerOfThree { 4 | 5 | // 如果一个数字是3的某次幂,那么这个数一定只含有3这个质数因子 6 | // 1162261467是int型范围内,最大的3的幂,它是3的19次方 7 | // 这个1162261467只含有3这个质数因子,如果n也是只含有3这个质数因子,那么 8 | // 1162261467 % n == 0 9 | // 反之如果1162261467 % n != 0 说明n一定含有其他因子 10 | public static boolean isPowerOfThree(int n) { 11 | return (n > 0 && 1162261467 % n == 0); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/class34/Problem_0328_OddEvenLinkedList.java: -------------------------------------------------------------------------------- 1 | package class34; 2 | 3 | public class Problem_0328_OddEvenLinkedList { 4 | 5 | // 提交时不要提交这个类 6 | public static class ListNode { 7 | int val; 8 | ListNode next; 9 | } 10 | 11 | public ListNode oddEvenList(ListNode head) { 12 | ListNode firstOdd = null; 13 | ListNode firstEven = null; 14 | ListNode odd = null; 15 | ListNode even = null; 16 | ListNode next = null; 17 | int count = 1; 18 | while (head != null) { 19 | next = head.next; 20 | head.next = null; 21 | if ((count & 1) == 1) { 22 | firstOdd = firstOdd == null ? head : firstOdd; 23 | if (odd != null) { 24 | odd.next = head; 25 | } 26 | odd = head; 27 | } else { 28 | firstEven = firstEven == null ? head : firstEven; 29 | if (even != null) { 30 | even.next = head; 31 | } 32 | even = head; 33 | } 34 | count++; 35 | head = next; 36 | } 37 | if (odd != null) { 38 | odd.next = firstEven; 39 | } 40 | return firstOdd != null ? firstOdd : firstEven; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/class34/Problem_0340_LongestSubstringWithAtMostKDistinctCharacters.java: -------------------------------------------------------------------------------- 1 | package class34; 2 | 3 | public class Problem_0340_LongestSubstringWithAtMostKDistinctCharacters { 4 | 5 | public static int lengthOfLongestSubstringKDistinct(String s, int k) { 6 | if (s == null || s.length() == 0 || k < 1) { 7 | return 0; 8 | } 9 | char[] str = s.toCharArray(); 10 | int N = str.length; 11 | int[] count = new int[256]; 12 | int diff = 0; 13 | int R = 0; 14 | int ans = 0; 15 | for (int i = 0; i < N; i++) { 16 | // R 窗口的右边界 17 | while (R < N && (diff < k || (diff == k && count[str[R]] > 0))) { 18 | diff += count[str[R]] == 0 ? 1 : 0; 19 | count[str[R++]]++; 20 | } 21 | // R 来到违规的第一个位置 22 | ans = Math.max(ans, R - i); 23 | diff -= count[str[i]] == 1 ? 1 : 0; 24 | count[str[i]]--; 25 | } 26 | return ans; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/class34/Problem_0348_DesignTicTacToe.java: -------------------------------------------------------------------------------- 1 | package class34; 2 | 3 | public class Problem_0348_DesignTicTacToe { 4 | 5 | class TicTacToe { 6 | private int[][] rows; 7 | private int[][] cols; 8 | private int[] leftUp; 9 | private int[] rightUp; 10 | private boolean[][] matrix; 11 | private int N; 12 | 13 | public TicTacToe(int n) { 14 | // rows[a][1] : 1这个人,在a行上,下了几个 15 | // rows[b][2] : 2这个人,在b行上,下了几个 16 | rows = new int[n][3]; //0 1 2 17 | cols = new int[n][3]; 18 | // leftUp[2] = 7 : 2这个人,在左对角线上,下了7个 19 | leftUp = new int[3]; 20 | // rightUp[1] = 9 : 1这个人,在右对角线上,下了9个 21 | rightUp = new int[3]; 22 | matrix = new boolean[n][n]; 23 | N = n; 24 | } 25 | 26 | public int move(int row, int col, int player) { 27 | if (matrix[row][col]) { 28 | return 0; 29 | } 30 | matrix[row][col] = true; 31 | rows[row][player]++; 32 | cols[col][player]++; 33 | if (row == col) { 34 | leftUp[player]++; 35 | } 36 | if (row + col == N - 1) { 37 | rightUp[player]++; 38 | } 39 | if (rows[row][player] == N || cols[col][player] == N || leftUp[player] == N || rightUp[player] == N) { 40 | return player; 41 | } 42 | return 0; 43 | } 44 | 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/class34/Problem_0380_InsertDeleteGetRandom.java: -------------------------------------------------------------------------------- 1 | package class34; 2 | 3 | import java.util.HashMap; 4 | 5 | public class Problem_0380_InsertDeleteGetRandom { 6 | 7 | public class RandomizedSet { 8 | 9 | private HashMap keyIndexMap; 10 | private HashMap indexKeyMap; 11 | private int size; 12 | 13 | public RandomizedSet() { 14 | keyIndexMap = new HashMap(); 15 | indexKeyMap = new HashMap(); 16 | size = 0; 17 | } 18 | 19 | public boolean insert(int val) { 20 | if (!keyIndexMap.containsKey(val)) { 21 | keyIndexMap.put(val, size); 22 | indexKeyMap.put(size++, val); 23 | return true; 24 | } 25 | return false; 26 | } 27 | 28 | public boolean remove(int val) { 29 | if (keyIndexMap.containsKey(val)) { 30 | int deleteIndex = keyIndexMap.get(val); 31 | int lastIndex = --size; 32 | int lastKey = indexKeyMap.get(lastIndex); 33 | keyIndexMap.put(lastKey, deleteIndex); 34 | indexKeyMap.put(deleteIndex, lastKey); 35 | keyIndexMap.remove(val); 36 | indexKeyMap.remove(lastIndex); 37 | return true; 38 | } 39 | return false; 40 | } 41 | 42 | public int getRandom() { 43 | if (size == 0) { 44 | return -1; 45 | } 46 | int randomIndex = (int) (Math.random() * size); 47 | return indexKeyMap.get(randomIndex); 48 | } 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/class34/Problem_0384_ShuffleAnArray.java: -------------------------------------------------------------------------------- 1 | package class34; 2 | 3 | public class Problem_0384_ShuffleAnArray { 4 | 5 | class Solution { 6 | private int[] origin; 7 | private int[] shuffle; 8 | private int N; 9 | 10 | public Solution(int[] nums) { 11 | origin = nums; 12 | N = nums.length; 13 | shuffle = new int[N]; 14 | for (int i = 0; i < N; i++) { 15 | shuffle[i] = origin[i]; 16 | } 17 | } 18 | 19 | public int[] reset() { 20 | return origin; 21 | } 22 | 23 | public int[] shuffle() { 24 | for (int i = N - 1; i >= 0; i--) { 25 | int r = (int) (Math.random() * (i + 1)); 26 | int tmp = shuffle[r]; 27 | shuffle[r] = shuffle[i]; 28 | shuffle[i] = tmp; 29 | } 30 | return shuffle; 31 | } 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/class34/说明: -------------------------------------------------------------------------------- 1 | leetcode高频题 2 | leetcode全题目列表 : https://leetcode.com/problemset/all/ 3 | 在全题目列表的右侧栏,点击Top Interview Questions 4 | 或者直接进入右侧链接 : https://leetcode.com/problemset/all/?listId=wpwgkgt 5 | 即可看到leetcode高频题全列表 6 | 本节课解决leetcode高频题列表中的如下题目 : 7 | 0287 : 大厂刷题班, 第34节, 本节 8 | 0289 : 大厂刷题班, 第34节, 本节 9 | 0295 : 大厂刷题班, 第34节, 本节 10 | 0297 : 体系学习班, 第11节第2题 11 | 0300 : 大厂刷题班, 第9节第3题 12 | 0308 : 体系学习班, 第32节第2题 13 | 0309 : 大厂刷题班, 第15节第5题 14 | 0315 : 大厂刷题班, 第34节, 本节 15 | 0322 : 体系学习班, 硬币找零专题 : 第21节第2、3、4题, 第22节第2题, 第24节第4题 16 | 0324 : 大厂刷题班, 第34节, 本节 17 | 0326 : 大厂刷题班, 第34节, 本节 18 | 0328 : 大厂刷题班, 第34节, 本节 19 | 0329 : 大厂刷题班, 第1节第5题 20 | 0334 : 大厂刷题班, 第9节第3题的变形, 问 : 最长递增子序列长度能否超过2而已, 跳过 21 | 0340 : 大厂刷题班, 第34节, 本节 22 | 0341 : 大厂刷题班, 第34节, 本节 23 | 0344 : 太简单了, 跳过 24 | 0348 : 大厂刷题班, 第34节, 本节 25 | 0350 : 太简单了, 跳过 26 | 0371 : 新手班, 第5节第3题 27 | 0378 : 大厂刷题班, 第17节第2题 28 | 0380 : 大厂刷题班, 第34节, 本节 29 | 0384 : 大厂刷题班, 第34节, 本节 30 | 0387 : 太简单了, 跳过 -------------------------------------------------------------------------------- /src/class35/Code02_MagicStone.java: -------------------------------------------------------------------------------- 1 | package class35; 2 | 3 | import java.util.Arrays; 4 | 5 | // 来自小红书 6 | // [0,4,7] : 0表示这里石头没有颜色,如果变红代价是4,如果变蓝代价是7 7 | // [1,X,X] : 1表示这里石头已经是红,而且不能改颜色,所以后两个数X无意义 8 | // [2,X,X] : 2表示这里石头已经是蓝,而且不能改颜色,所以后两个数X无意义 9 | // 颜色只可能是0、1、2,代价一定>=0 10 | // 给你一批这样的小数组,要求最后必须所有石头都有颜色,且红色和蓝色一样多,返回最小代价 11 | // 如果怎么都无法做到所有石头都有颜色、且红色和蓝色一样多,返回-1 12 | public class Code02_MagicStone { 13 | 14 | public static int minCost(int[][] stones) { 15 | int n = stones.length; 16 | if ((n & 1) != 0) { 17 | return -1; 18 | } 19 | Arrays.sort(stones, (a, b) -> a[0] == 0 && b[0] == 0 ? (b[1] - b[2] - a[1] + a[2]) : (a[0] - b[0])); 20 | int zero = 0; 21 | int red = 0; 22 | int blue = 0; 23 | int cost = 0; 24 | for (int i = 0; i < n; i++) { 25 | if (stones[i][0] == 0) { 26 | zero++; 27 | cost += stones[i][1]; 28 | } else if (stones[i][0] == 1) { 29 | red++; 30 | } else { 31 | blue++; 32 | } 33 | } 34 | if (red > (n >> 1) || blue > (n >> 1)) { 35 | return -1; 36 | } 37 | blue = zero - ((n >> 1) - red); 38 | for (int i = 0; i < blue; i++) { 39 | cost += stones[i][2] - stones[i][1]; 40 | } 41 | return cost; 42 | } 43 | 44 | public static void main(String[] args) { 45 | int[][] stones = { { 1, 5, 3 }, { 2, 7, 9 }, { 0, 6, 4 }, { 0, 7, 9 }, { 0, 2, 1 }, { 0, 5, 9 } }; 46 | System.out.println(minCost(stones)); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/class35/Code04_WalkToEnd.java: -------------------------------------------------------------------------------- 1 | package class35; 2 | 3 | import java.util.PriorityQueue; 4 | 5 | // 来自网易 6 | // map[i][j] == 0,代表(i,j)是海洋,渡过的话代价是2 7 | // map[i][j] == 1,代表(i,j)是陆地,渡过的话代价是1 8 | // map[i][j] == 2,代表(i,j)是障碍,无法渡过 9 | // 每一步上、下、左、右都能走,返回从左上角走到右下角最小代价是多少,如果无法到达返回-1 10 | public class Code04_WalkToEnd { 11 | 12 | public static int minCost(int[][] map) { 13 | if (map[0][0] == 2) { 14 | return -1; 15 | } 16 | int n = map.length; 17 | int m = map[0].length; 18 | PriorityQueue heap = new PriorityQueue<>((a, b) -> a.cost - b.cost); 19 | boolean[][] visited = new boolean[n][m]; 20 | add(map, 0, 0, 0, heap, visited); 21 | while (!heap.isEmpty()) { 22 | Node cur = heap.poll(); 23 | if (cur.row == n - 1 && cur.col == m - 1) { 24 | return cur.cost; 25 | } 26 | add(map, cur.row - 1, cur.col, cur.cost, heap, visited); 27 | add(map, cur.row + 1, cur.col, cur.cost, heap, visited); 28 | add(map, cur.row, cur.col - 1, cur.cost, heap, visited); 29 | add(map, cur.row, cur.col + 1, cur.cost, heap, visited); 30 | } 31 | return -1; 32 | } 33 | 34 | public static void add(int[][] m, int i, int j, int pre, PriorityQueue heap, boolean[][] visited) { 35 | if (i >= 0 && i < m.length && j >= 0 && j < m[0].length && m[i][j] != 2 && !visited[i][j]) { 36 | heap.add(new Node(i, j, pre + (m[i][j] == 0 ? 2 : 1))); 37 | visited[i][j] = true; 38 | } 39 | } 40 | 41 | public static class Node { 42 | public int row; 43 | public int col; 44 | public int cost; 45 | 46 | public Node(int a, int b, int c) { 47 | row = a; 48 | col = b; 49 | cost = c; 50 | } 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/class35/Code05_CircleCandy.java: -------------------------------------------------------------------------------- 1 | package class35; 2 | 3 | // 来自网易 4 | // 给定一个正数数组arr,表示每个小朋友的得分 5 | // 任何两个相邻的小朋友,如果得分一样,怎么分糖果无所谓,但如果得分不一样,分数大的一定要比分数少的多拿一些糖果 6 | // 假设所有的小朋友坐成一个环形,返回在不破坏上一条规则的情况下,需要的最少糖果数 7 | public class Code05_CircleCandy { 8 | 9 | public static int minCandy(int[] arr) { 10 | if (arr == null || arr.length == 0) { 11 | return 0; 12 | } 13 | if (arr.length == 1) { 14 | return 1; 15 | } 16 | int n = arr.length; 17 | int minIndex = 0; 18 | for (int i = 0; i < n; i++) { 19 | if (arr[i] <= arr[lastIndex(i, n)] && arr[i] <= arr[nextIndex(i, n)]) { 20 | minIndex = i; 21 | break; 22 | } 23 | } 24 | int[] nums = new int[n + 1]; 25 | for (int i = 0; i <= n; i++, minIndex = nextIndex(minIndex, n)) { 26 | nums[i] = arr[minIndex]; 27 | } 28 | int[] left = new int[n + 1]; 29 | left[0] = 1; 30 | for (int i = 1; i <= n; i++) { 31 | left[i] = nums[i] > nums[i - 1] ? (left[i - 1] + 1) : 1; 32 | } 33 | int[] right = new int[n + 1]; 34 | right[n] = 1; 35 | for (int i = n - 1; i >= 0; i--) { 36 | right[i] = nums[i] > nums[i + 1] ? (right[i + 1] + 1) : 1; 37 | } 38 | int ans = 0; 39 | for (int i = 0; i < n; i++) { 40 | ans += Math.max(left[i], right[i]); 41 | } 42 | return ans; 43 | } 44 | 45 | public static int nextIndex(int i, int n) { 46 | return i == n - 1 ? 0 : (i + 1); 47 | } 48 | 49 | public static int lastIndex(int i, int n) { 50 | return i == 0 ? (n - 1) : (i - 1); 51 | } 52 | 53 | public static void main(String[] args) { 54 | int[] arr = { 3, 4, 2, 3, 2 }; 55 | System.out.println(minCandy(arr)); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/class35/Problem_0347_TopKFrequentElements.java: -------------------------------------------------------------------------------- 1 | package class35; 2 | 3 | import java.util.Comparator; 4 | import java.util.HashMap; 5 | import java.util.PriorityQueue; 6 | 7 | public class Problem_0347_TopKFrequentElements { 8 | 9 | public static class Node { 10 | public int num; 11 | public int count; 12 | 13 | public Node(int k) { 14 | num = k; 15 | count = 1; 16 | } 17 | } 18 | 19 | public static class CountComparator implements Comparator { 20 | 21 | @Override 22 | public int compare(Node o1, Node o2) { 23 | return o1.count - o2.count; 24 | } 25 | 26 | } 27 | 28 | public static int[] topKFrequent(int[] nums, int k) { 29 | HashMap map = new HashMap<>(); 30 | for (int num : nums) { 31 | if (!map.containsKey(num)) { 32 | map.put(num, new Node(num)); 33 | } else { 34 | map.get(num).count++; 35 | } 36 | } 37 | PriorityQueue heap = new PriorityQueue<>(new CountComparator()); 38 | for (Node node : map.values()) { 39 | if (heap.size() < k || (heap.size() == k && node.count > heap.peek().count)) { 40 | heap.add(node); 41 | } 42 | if (heap.size() > k) { 43 | heap.poll(); 44 | } 45 | } 46 | int[] ans = new int[k]; 47 | int index = 0; 48 | while (!heap.isEmpty()) { 49 | ans[index++] = heap.poll().num; 50 | } 51 | return ans; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/class35/Problem_0412_FizzBuzz.java: -------------------------------------------------------------------------------- 1 | package class35; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class Problem_0412_FizzBuzz { 7 | 8 | public static List fizzBuzz(int n) { 9 | ArrayList ans = new ArrayList<>(); 10 | for (int i = 1; i <= n; i++) { 11 | if (i % 15 == 0) { 12 | ans.add("FizzBuzz"); 13 | } else if (i % 5 == 0) { 14 | ans.add("Buzz"); 15 | } else if (i % 3 == 0) { 16 | ans.add("Fizz"); 17 | } else { 18 | ans.add(String.valueOf(i)); 19 | } 20 | } 21 | return ans; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/class35/Problem_0454_4SumII.java: -------------------------------------------------------------------------------- 1 | package class35; 2 | 3 | import java.util.HashMap; 4 | 5 | public class Problem_0454_4SumII { 6 | 7 | public static int fourSumCount(int[] A, int[] B, int[] C, int[] D) { 8 | HashMap map = new HashMap<>(); 9 | int sum = 0; 10 | for (int i = 0; i < A.length; i++) { 11 | for (int j = 0; j < B.length; j++) { 12 | sum = A[i] + B[j]; 13 | if (!map.containsKey(sum)) { 14 | map.put(sum, 1); 15 | } else { 16 | map.put(sum, map.get(sum) + 1); 17 | } 18 | } 19 | } 20 | int ans = 0; 21 | for (int i = 0; i < C.length; i++) { 22 | for (int j = 0; j < D.length; j++) { 23 | sum = C[i] + D[j]; 24 | if (map.containsKey(-sum)) { 25 | ans += map.get(-sum); 26 | } 27 | } 28 | } 29 | return ans; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/class35/Problem_0687_LongestUnivaluePath.java: -------------------------------------------------------------------------------- 1 | package class35; 2 | 3 | public class Problem_0687_LongestUnivaluePath { 4 | 5 | public static class TreeNode { 6 | public int val; 7 | public TreeNode left; 8 | public TreeNode right; 9 | 10 | public TreeNode(int v) { 11 | val = v; 12 | } 13 | } 14 | 15 | public static int longestUnivaluePath(TreeNode root) { 16 | if (root == null) { 17 | return 0; 18 | } 19 | return process(root).max - 1; 20 | } 21 | 22 | // 建设以x节点为头的树,返回两个信息 23 | public static class Info { 24 | // 在一条路径上:要求每个节点通过且只通过一遍 25 | public int len; // 路径必须从x出发且只能往下走的情况下,路径的最大距离 26 | public int max; // 路径不要求必须从x出发的情况下,整棵树的合法路径最大距离 27 | 28 | public Info(int l, int m) { 29 | len = l; 30 | max = m; 31 | } 32 | } 33 | 34 | private static Info process(TreeNode x) { 35 | if (x == null) { 36 | return new Info(0, 0); 37 | } 38 | TreeNode l = x.left; 39 | TreeNode r = x.right; 40 | // 左树上,不要求从左孩子出发,最大路径 41 | // 左树上,必须从左孩子出发,往下的最大路径 42 | Info linfo = process(l); 43 | // 右树上,不要求从右孩子出发,最大路径 44 | // 右树上,必须从右孩子出发,往下的最大路径 45 | Info rinfo = process(r); 46 | // 必须从x出发的情况下,往下的最大路径 47 | int len = 1; 48 | if (l != null && l.val == x.val) { 49 | len = linfo.len + 1; 50 | } 51 | if (r != null && r.val == x.val) { 52 | len = Math.max(len, rinfo.len + 1); 53 | } 54 | // 不要求从x出发,最大路径 55 | int max = Math.max(Math.max(linfo.max, rinfo.max), len); 56 | if (l != null && r != null && l.val == x.val && r.val == x.val) { 57 | max = Math.max(max, linfo.len + rinfo.len + 1); 58 | } 59 | return new Info(len, max); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/class35/说明: -------------------------------------------------------------------------------- 1 | leetcode高频题 2 | leetcode全题目列表 : https://leetcode.com/problemset/all/ 3 | 在全题目列表的右侧栏,点击Top Interview Questions 4 | 或者直接进入右侧链接 : https://leetcode.com/problemset/all/?listId=wpwgkgt 5 | 即可看到leetcode高频题全列表 6 | 本节课解决leetcode高频题列表中的如下题目 : 7 | 0347 : 大厂刷题班, 第35节, 本节 8 | 0395 : 大厂刷题班, 第35节, 本节 9 | 0412 : 大厂刷题班, 第35节, 本节 10 | 0454 : 大厂刷题班, 第35节, 本节 11 | 0673 : 大厂刷题班, 第35节, 本节 12 | 0687 : 大厂刷题班, 第35节, 本节 13 | 0772 : 大厂刷题班, 第8节第1题 14 | 至此,Leetcode高频题系列完结 15 | 16 | 本节附加题 17 | Code01 : 2021年8月大厂真实笔试题 18 | Code02 : 2021年8月大厂真实笔试题 19 | Code03 : 2021年8月大厂真实笔试题 20 | Code04 : 2021年8月大厂真实笔试题 21 | Code05 : 2021年8月大厂真实笔试题 -------------------------------------------------------------------------------- /src/class36/Code02_Ratio01Split.java: -------------------------------------------------------------------------------- 1 | package class36; 2 | 3 | import java.util.HashMap; 4 | 5 | // 来自京东 6 | // 把一个01字符串切成多个部分,要求每一部分的0和1比例一样,同时要求尽可能多的划分 7 | // 比如 : 01010101 8 | // 01 01 01 01 这是一种切法,0和1比例为 1 : 1 9 | // 0101 0101 也是一种切法,0和1比例为 1 : 1 10 | // 两种切法都符合要求,但是那么尽可能多的划分为第一种切法,部分数为4 11 | // 比如 : 00001111 12 | // 只有一种切法就是00001111整体作为一块,那么尽可能多的划分,部分数为1 13 | // 给定一个01字符串str,假设长度为N,要求返回一个长度为N的数组ans 14 | // 其中ans[i] = str[0...i]这个前缀串,要求每一部分的0和1比例一样,同时要求尽可能多的划分下,部分数是多少 15 | // 输入: str = "010100001" 16 | // 输出: ans = [1, 1, 1, 2, 1, 2, 1, 1, 3] 17 | public class Code02_Ratio01Split { 18 | 19 | // 001010010100... 20 | public static int[] split(int[] arr) { 21 | 22 | // key : 分子 23 | // value : 属于key的分母表, 每一个分母,及其 分子/分母 这个比例,多少个前缀拥有 24 | HashMap> pre = new HashMap<>(); 25 | int n = arr.length; 26 | int[] ans = new int[n]; 27 | int zero = 0; // 0出现的次数 28 | int one = 0; // 1出现的次数 29 | for (int i = 0; i < n; i++) { 30 | if (arr[i] == 0) { 31 | zero++; 32 | } else { 33 | one++; 34 | } 35 | if (zero == 0 || one == 0) { 36 | ans[i] = i + 1; 37 | } else { // 0和1,都有数量 -> 最简分数 38 | int gcd = gcd(zero, one); 39 | int a = zero / gcd; 40 | int b = one / gcd; 41 | // a / b 比例,之前有多少前缀拥有? 3+1 4 5+1 6 42 | if (!pre.containsKey(a)) { 43 | pre.put(a, new HashMap<>()); 44 | } 45 | if (!pre.get(a).containsKey(b)) { 46 | pre.get(a).put(b, 1); 47 | } else { 48 | pre.get(a).put(b, pre.get(a).get(b) + 1); 49 | } 50 | ans[i] = pre.get(a).get(b); 51 | } 52 | } 53 | return ans; 54 | } 55 | 56 | public static int gcd(int m, int n) { 57 | return n == 0 ? m : gcd(n, m % n); 58 | } 59 | 60 | public static void main(String[] args) { 61 | int[] arr = { 0, 1, 0, 1, 0, 1, 1, 0 }; 62 | int[] ans = split(arr); 63 | for (int i = 0; i < ans.length; i++) { 64 | System.out.print(ans[i] + " "); 65 | } 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/class36/Code03_MatchCount.java: -------------------------------------------------------------------------------- 1 | package class36; 2 | 3 | // 来自美团 4 | // 给定两个字符串s1和s2 5 | // 返回在s1中有多少个子串等于s2 6 | public class Code03_MatchCount { 7 | 8 | public static int sa(String s1, String s2) { 9 | if (s1 == null || s2 == null || s1.length() < s2.length()) { 10 | return 0; 11 | } 12 | char[] str1 = s1.toCharArray(); 13 | char[] str2 = s2.toCharArray(); 14 | return count(str1, str2); 15 | } 16 | 17 | // 改写kmp为这道题需要的功能 18 | public static int count(char[] str1, char[] str2) { 19 | int x = 0; 20 | int y = 0; 21 | int count = 0; 22 | int[] next = getNextArray(str2); 23 | while (x < str1.length) { 24 | if (str1[x] == str2[y]) { 25 | x++; 26 | y++; 27 | if (y == str2.length) { 28 | count++; 29 | y = next[y]; 30 | } 31 | } else if (next[y] == -1) { 32 | x++; 33 | } else { 34 | y = next[y]; 35 | } 36 | } 37 | return count; 38 | } 39 | 40 | // next数组多求一位 41 | // 比如:str2 = aaaa 42 | // 那么,next = -1,0,1,2,3 43 | // 最后一个3表示,终止位置之前的字符串最长前缀和最长后缀的匹配长度 44 | // 也就是next数组补一位 45 | public static int[] getNextArray(char[] str2) { 46 | if (str2.length == 1) { 47 | return new int[] { -1, 0 }; 48 | } 49 | int[] next = new int[str2.length + 1]; 50 | next[0] = -1; 51 | next[1] = 0; 52 | int i = 2; 53 | int cn = 0; 54 | while (i < next.length) { 55 | if (str2[i - 1] == str2[cn]) { 56 | next[i++] = ++cn; 57 | } else if (cn > 0) { 58 | cn = next[cn]; 59 | } else { 60 | next[i++] = 0; 61 | } 62 | } 63 | return next; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/class36/Code04_ComputeExpressionValue.java: -------------------------------------------------------------------------------- 1 | package class36; 2 | 3 | // 来自美团 4 | // () 分值为2 5 | // (()) 分值为3 6 | // ((())) 分值为4 7 | // 也就是说,每包裹一层,分数就是里面的分值+1 8 | // ()() 分值为2 * 2 9 | // (())() 分值为3 * 2 10 | // 也就是说,每连接一段,分数就是各部分相乘,以下是一个结合起来的例子 11 | // (()())()(()) -> (2 * 2 + 1) * 2 * 3 -> 30 12 | // 给定一个括号字符串str,已知str一定是正确的括号结合,不会有违规嵌套 13 | // 返回分数 14 | public class Code04_ComputeExpressionValue { 15 | 16 | public static int sores(String s) { 17 | return compute(s.toCharArray(), 0)[0]; 18 | } 19 | 20 | // s[i.....] 遇到 ')' 或者 终止位置 停! 21 | // 返回值:int[] 长度就是2 22 | // 0 :分数是多少 23 | // 1 : 来到了什么位置停的! 24 | public static int[] compute(char[] s, int i) { 25 | if (s[i] == ')') { 26 | return new int[] { 1, i }; 27 | } 28 | int ans = 1; 29 | while (i < s.length && s[i] != ')') { 30 | int[] info = compute(s, i + 1); 31 | ans *= info[0] + 1; 32 | i = info[1] + 1; 33 | } 34 | return new int[] { ans, i }; 35 | } 36 | 37 | public static void main(String[] args) { 38 | 39 | String str1 = "(()())()(())"; 40 | System.out.println(sores(str1)); 41 | 42 | // (()()) + (((()))) + ((())()) 43 | // (()()) -> 2 * 2 + 1 -> 5 44 | // (((()))) -> 5 45 | // ((())()) -> ((2 + 1) * 2) + 1 -> 7 46 | // 所以下面的结果应该是175 47 | String str2 = "(()())(((())))((())())"; 48 | System.out.println(sores(str2)); 49 | 50 | // (()()()) + (()(())) 51 | // (()()()) -> 2 * 2 * 2 + 1 -> 9 52 | // (()(())) -> 2 * 3 + 1 -> 7 53 | // 所以下面的结果应该是63 54 | String str3 = "(()()())(()(()))"; 55 | System.out.println(sores(str3)); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/class36/Code06_NodeWeight.java: -------------------------------------------------------------------------------- 1 | package class36; 2 | 3 | import java.util.HashMap; 4 | 5 | // 来自美团 6 | // 有一棵树,给定头节点h,和结构数组m,下标0弃而不用 7 | // 比如h = 1, m = [ [] , [2,3], [4], [5,6], [], [], []] 8 | // 表示1的孩子是2、3; 2的孩子是4; 3的孩子是5、6; 4、5和6是叶节点,都不再有孩子 9 | // 每一个节点都有颜色,记录在c数组里,比如c[i] = 4, 表示节点i的颜色为4 10 | // 一开始只有叶节点是有权值的,记录在w数组里, 11 | // 比如,如果一开始就有w[i] = 3, 表示节点i是叶节点、且权值是3 12 | // 现在规定非叶节点i的权值计算方式: 13 | // 根据i的所有直接孩子来计算,假设i的所有直接孩子,颜色只有a,b,k 14 | // w[i] = Max { 15 | // (颜色为a的所有孩子个数 + 颜色为a的孩子权值之和), 16 | // (颜色为b的所有孩子个数 + 颜色为b的孩子权值之和), 17 | // (颜色为k的所有孩子个数 + 颜色k的孩子权值之和) 18 | // } 19 | // 请计算所有孩子的权值并返回 20 | public class Code06_NodeWeight { 21 | 22 | // 当前来到h节点, 23 | // h的直接孩子,在哪呢?m[h] = {a,b,c,d,e} 24 | // 每个节点的颜色在哪?比如i号节点,c[i]就是i号节点的颜色 25 | // 每个节点的权值在哪?比如i号节点,w[i]就是i号节点的权值 26 | // void : 把w数组填满就是这个函数的目标 27 | public static void w(int h, int[][] m, int[] w, int[] c) { 28 | if (m[h].length == 0) { // 叶节点 29 | return; 30 | } 31 | // 有若干个直接孩子 32 | // 1 7个 33 | // 3 10个 34 | HashMap colors = new HashMap(); 35 | // 1 20 36 | // 3 45 37 | HashMap weihts = new HashMap(); 38 | for (int child : m[h]) { 39 | w(child, m, w, c); 40 | colors.put(c[child], colors.getOrDefault(c[child], 0) + 1); 41 | weihts.put(c[child], weihts.getOrDefault(c[child], 0) + w[c[child]]); 42 | } 43 | for (int color : colors.keySet()) { 44 | w[h] = Math.max(w[h], colors.get(color) + weihts.get(color)); 45 | } 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/class36/Code07_ModMHeads.java: -------------------------------------------------------------------------------- 1 | package class36; 2 | 3 | import java.util.HashMap; 4 | 5 | // 来自腾讯 6 | // 给定一个单链表的头节点head,每个节点都有value(>0),给定一个正数m 7 | // value%m的值一样的节点算一类 8 | // 请把所有的类根据单链表的方式重新连接好,返回每一类的头节点 9 | public class Code07_ModMHeads { 10 | 11 | public static class Node { 12 | public int value; 13 | public Node next; 14 | } 15 | 16 | public static class Ht { 17 | public Node h; 18 | public Node t; 19 | 20 | public Ht(Node a) { 21 | h = a; 22 | t = a; 23 | } 24 | } 25 | 26 | public static Node[] split(Node h, int m) { 27 | HashMap map = new HashMap<>(); 28 | while (h != null) { 29 | Node next = h.next; 30 | h.next = null; 31 | int mod = h.value % m; 32 | if (!map.containsKey(mod)) { 33 | map.put(mod, new Ht(h)); 34 | } else { 35 | map.get(mod).t.next = h; 36 | map.get(mod).t = h; 37 | } 38 | h = next; 39 | } 40 | Node[] ans = new Node[m]; 41 | for (int mod : map.keySet()) { 42 | ans[mod] = map.get(mod).h; 43 | } 44 | return ans; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/class36/Code09_MinBoatEvenNumbers.java: -------------------------------------------------------------------------------- 1 | package class36; 2 | 3 | import java.util.Arrays; 4 | 5 | // 来自腾讯 6 | // 给定一个正数数组arr,代表每个人的体重。给定一个正数limit代表船的载重,所有船都是同样的载重量 7 | // 每个人的体重都一定不大于船的载重 8 | // 要求: 9 | // 1, 可以1个人单独一搜船 10 | // 2, 一艘船如果坐2人,两个人的体重相加需要是偶数,且总体重不能超过船的载重 11 | // 3, 一艘船最多坐2人 12 | // 返回如果想所有人同时坐船,船的最小数量 13 | public class Code09_MinBoatEvenNumbers { 14 | 15 | public static int minBoat(int[] arr, int limit) { 16 | Arrays.sort(arr); 17 | int odd = 0; 18 | int even = 0; 19 | for (int num : arr) { 20 | if ((num & 1) == 0) { 21 | even++; 22 | } else { 23 | odd++; 24 | } 25 | } 26 | int[] odds = new int[odd]; 27 | int[] evens = new int[even]; 28 | for (int i = arr.length - 1; i >= 0; i--) { 29 | if ((arr[i] & 1) == 0) { 30 | evens[--even] = arr[i]; 31 | } else { 32 | odds[--odd] = arr[i]; 33 | } 34 | } 35 | return min(odds, limit) + min(evens, limit); 36 | } 37 | 38 | public static int min(int[] arr, int limit) { 39 | if (arr == null || arr.length == 0) { 40 | return 0; 41 | } 42 | int N = arr.length; 43 | if (arr[N - 1] > limit) { 44 | return -1; 45 | } 46 | int lessR = -1; 47 | for (int i = N - 1; i >= 0; i--) { 48 | if (arr[i] <= (limit / 2)) { 49 | lessR = i; 50 | break; 51 | } 52 | } 53 | if (lessR == -1) { 54 | return N; 55 | } 56 | int L = lessR; 57 | int R = lessR + 1; 58 | int noUsed = 0; 59 | while (L >= 0) { 60 | int solved = 0; 61 | while (R < N && arr[L] + arr[R] <= limit) { 62 | R++; 63 | solved++; 64 | } 65 | if (solved == 0) { 66 | noUsed++; 67 | L--; 68 | } else { 69 | L = Math.max(-1, L - solved); 70 | } 71 | } 72 | int all = lessR + 1; 73 | int used = all - noUsed; 74 | int moreUnsolved = (N - all) - used; 75 | return used + ((noUsed + 1) >> 1) + moreUnsolved; 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/class36/Code11_StoneGameIV.java: -------------------------------------------------------------------------------- 1 | package class36; 2 | 3 | // 来自哈喽单车 4 | // 本题是leetcode原题 : https://leetcode.com/problems/stone-game-iv/ 5 | public class Code11_StoneGameIV { 6 | 7 | // 当前的!先手,会不会赢 8 | // 打表,不能发现规律 9 | public static boolean winnerSquareGame1(int n) { 10 | if (n == 0) { 11 | return false; 12 | } 13 | // 当前的先手,会尝试所有的情况,1,4,9,16,25,36.... 14 | for (int i = 1; i * i <= n; i++) { 15 | // 当前的先手,决定拿走 i * i 这个平方数 16 | // 它的对手会不会赢? winnerSquareGame1(n - i * i) 17 | if (!winnerSquareGame1(n - i * i)) { 18 | return true; 19 | } 20 | } 21 | return false; 22 | } 23 | 24 | public static boolean winnerSquareGame2(int n) { 25 | int[] dp = new int[n + 1]; 26 | dp[0] = -1; 27 | return process2(n, dp); 28 | } 29 | 30 | public static boolean process2(int n, int[] dp) { 31 | if (dp[n] != 0) { 32 | return dp[n] == 1 ? true : false; 33 | } 34 | boolean ans = false; 35 | for (int i = 1; i * i <= n; i++) { 36 | if (!process2(n - i * i, dp)) { 37 | ans = true; 38 | break; 39 | } 40 | } 41 | dp[n] = ans ? 1 : -1; 42 | return ans; 43 | } 44 | 45 | public static boolean winnerSquareGame3(int n) { 46 | boolean[] dp = new boolean[n + 1]; 47 | for (int i = 1; i <= n; i++) { 48 | for (int j = 1; j * j <= i; j++) { 49 | if (!dp[i - j * j]) { 50 | dp[i] = true; 51 | break; 52 | } 53 | } 54 | } 55 | return dp[n]; 56 | } 57 | 58 | public static void main(String[] args) { 59 | int n = 10000000; 60 | System.out.println(winnerSquareGame3(n)); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/class36/Code12_BusRoutes.java: -------------------------------------------------------------------------------- 1 | package class36; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | 6 | // 来自三七互娱 7 | // Leetcode原题 : https://leetcode.com/problems/bus-routes/ 8 | public class Code12_BusRoutes { 9 | 10 | // 0 : [1,3,7,0] 11 | // 1 : [7,9,6,2] 12 | // .... 13 | // 返回:返回换乘几次+1 -> 返回一共坐了多少条线的公交。 14 | public static int numBusesToDestination(int[][] routes, int source, int target) { 15 | if (source == target) { 16 | return 0; 17 | } 18 | int n = routes.length; 19 | // key : 车站 20 | // value : list -> 该车站拥有哪些线路! 21 | HashMap> map = new HashMap<>(); 22 | for (int i = 0; i < n; i++) { 23 | for (int j = 0; j < routes[i].length; j++) { 24 | if (!map.containsKey(routes[i][j])) { 25 | map.put(routes[i][j], new ArrayList<>()); 26 | } 27 | map.get(routes[i][j]).add(i); 28 | } 29 | } 30 | ArrayList queue = new ArrayList<>(); 31 | boolean[] set = new boolean[n]; 32 | for (int route : map.get(source)) { 33 | queue.add(route); 34 | set[route] = true; 35 | } 36 | int len = 1; 37 | while (!queue.isEmpty()) { 38 | ArrayList nextLevel = new ArrayList<>(); 39 | for (int route : queue) { 40 | int[] bus = routes[route]; 41 | for (int station : bus) { 42 | if (station == target) { 43 | return len; 44 | } 45 | for (int nextRoute : map.get(station)) { 46 | if (!set[nextRoute]) { 47 | nextLevel.add(nextRoute); 48 | set[nextRoute] = true; 49 | } 50 | } 51 | } 52 | } 53 | queue = nextLevel; 54 | len++; 55 | } 56 | return -1; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/class36/说明: -------------------------------------------------------------------------------- 1 | Code01 : 2021年8月大厂真实笔试题 2 | Code02 : 2021年8月大厂真实笔试题 3 | Code03 : 2021年8月大厂真实笔试题 4 | Code04 : 2021年8月大厂真实笔试题 5 | Code05 : 2021年8月大厂真实笔试题 6 | Code06 : 2021年8月大厂真实笔试题 7 | Code07 : 2021年8月大厂真实笔试题 8 | Code08 : 2021年8月大厂真实笔试题 9 | Code09 : 2021年8月大厂真实笔试题 10 | Code10 : 2021年8月大厂真实笔试题 11 | Code11 : 2021年8月大厂真实笔试题 12 | Code12 : 2021年8月大厂真实笔试题 -------------------------------------------------------------------------------- /src/class37/Code01_ArrangeProject.java: -------------------------------------------------------------------------------- 1 | package class37; 2 | 3 | import java.util.ArrayList; 4 | import java.util.LinkedList; 5 | import java.util.Queue; 6 | 7 | // 来自网易 8 | // 刚入职网易互娱,新人mini项目便如火如荼的开展起来。为了更好的项目协作与管理, 9 | // 小易决定将学到的甘特图知识用于mini项目时间预估。小易先把项目中每一项工作以任务的形式列举出来, 10 | // 每项任务有一个预计花费时间与前置任务表,必须完成了该任务的前置任务才能着手去做该任务。 11 | // 作为经验PM,小易把任务划分得井井有条,保证没有前置任务或者前置任务全数完成的任务,都可以同时进行。 12 | // 小易给出了这样一个任务表,请作为程序的你计算需要至少多长时间才能完成所有任务。 13 | // 输入第一行为一个正整数T,表示数据组数。 14 | // 对于接下来每组数据,第一行为一个正整数N,表示一共有N项任务。 15 | // 接下来N行,每行先有两个整数Di和Ki,表示完成第i个任务的预计花费时间为Di天,该任务有Ki个前置任务。 16 | // 之后为Ki个整数Mj,表示第Mj个任务是第i个任务的前置任务。 17 | // 数据范围:对于所有数据,满足1<=T<=3, 1<=N, Mj<=100000, 0<=Di<=1000, 0<=sum(Ki)<=N*2。 18 | public class Code01_ArrangeProject { 19 | 20 | public static int dayCount(ArrayList[] nums, int[] days, int[] headCount) { 21 | Queue head = countHead(headCount); 22 | int maxDay = 0; 23 | int[] countDay = new int[days.length]; 24 | while (!head.isEmpty()) { 25 | int cur = head.poll(); 26 | countDay[cur] += days[cur]; 27 | for (int j = 0; j < nums[cur].size(); j++) { 28 | headCount[nums[cur].get(j)]--; 29 | if (headCount[nums[cur].get(j)] == 0) { 30 | head.offer(nums[cur].get(j)); 31 | } 32 | countDay[nums[cur].get(j)] = Math.max(countDay[nums[cur].get(j)], countDay[cur]); 33 | } 34 | } 35 | for (int i = 0; i < countDay.length; i++) { 36 | maxDay = Math.max(maxDay, countDay[i]); 37 | } 38 | return maxDay; 39 | } 40 | 41 | private static Queue countHead(int[] headCount) { 42 | Queue queue = new LinkedList<>(); 43 | for (int i = 0; i < headCount.length; i++) { 44 | if (headCount[i] == 0) 45 | queue.offer(i); // 没有前驱任务 46 | } 47 | return queue; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/class37/Problem_0221_MaximalSquare.java: -------------------------------------------------------------------------------- 1 | package class37; 2 | 3 | public class Problem_0221_MaximalSquare { 4 | 5 | public static int maximalSquare(char[][] m) { 6 | if (m == null || m.length == 0 || m[0].length == 0) { 7 | return 0; 8 | } 9 | int N = m.length; 10 | int M = m[0].length; 11 | int[][] dp = new int[N + 1][M + 1]; 12 | int max = 0; 13 | for (int i = 0; i < N; i++) { 14 | if (m[i][0] == '1') { 15 | dp[i][0] = 1; 16 | max = 1; 17 | } 18 | } 19 | for (int j = 1; j < M; j++) { 20 | if (m[0][j] == '1') { 21 | dp[0][j] = 1; 22 | max = 1; 23 | } 24 | } 25 | for (int i = 1; i < N; i++) { 26 | for (int j = 1; j < M; j++) { 27 | if (m[i][j] == '1') { 28 | dp[i][j] = Math.min( 29 | Math.min(dp[i - 1][j], 30 | dp[i][j - 1]), 31 | dp[i - 1][j - 1]) 32 | + 1; 33 | max = Math.max(max, dp[i][j]); 34 | } 35 | } 36 | } 37 | return max * max; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/class37/Problem_0226_InvertBinaryTree.java: -------------------------------------------------------------------------------- 1 | package class37; 2 | 3 | public class Problem_0226_InvertBinaryTree { 4 | 5 | public class TreeNode { 6 | public int val; 7 | public TreeNode left; 8 | public TreeNode right; 9 | } 10 | 11 | public static TreeNode invertTree(TreeNode root) { 12 | if (root == null) { 13 | return null; 14 | } 15 | TreeNode left = root.left; 16 | root.left = invertTree(root.right); 17 | root.right = invertTree(left); 18 | return root; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/class37/Problem_0394_DecodeString.java: -------------------------------------------------------------------------------- 1 | package class37; 2 | 3 | public class Problem_0394_DecodeString { 4 | 5 | public static String decodeString(String s) { 6 | char[] str = s.toCharArray(); 7 | return process(str, 0).ans; 8 | } 9 | 10 | public static class Info { 11 | public String ans; 12 | public int stop; 13 | 14 | public Info(String a, int e) { 15 | ans = a; 16 | stop = e; 17 | } 18 | } 19 | 20 | // s[i....] 何时停?遇到 ']' 或者遇到 s的终止位置,停止 21 | // 返回Info 22 | // 0) 串 23 | // 1) 算到了哪 24 | public static Info process(char[] s, int i) { 25 | StringBuilder ans = new StringBuilder(); 26 | int count = 0; 27 | while (i < s.length && s[i] != ']') { 28 | if ((s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z')) { 29 | ans.append(s[i++]); 30 | } else if (s[i] >= '0' && s[i] <= '9') { 31 | count = count * 10 + s[i++] - '0'; 32 | } else { // str[index] = '[' 33 | Info next = process(s, i + 1); 34 | ans.append(timesString(count, next.ans)); 35 | count = 0; 36 | i = next.stop + 1; 37 | } 38 | } 39 | return new Info(ans.toString(), i); 40 | } 41 | 42 | public static String timesString(int times, String str) { 43 | StringBuilder ans = new StringBuilder(); 44 | for (int i = 0; i < times; i++) { 45 | ans.append(str); 46 | } 47 | return ans.toString(); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/class37/Problem_0437_PathSumIII.java: -------------------------------------------------------------------------------- 1 | package class37; 2 | 3 | import java.util.HashMap; 4 | 5 | public class Problem_0437_PathSumIII { 6 | 7 | public class TreeNode { 8 | public int val; 9 | public TreeNode left; 10 | public TreeNode right; 11 | } 12 | 13 | public static int pathSum(TreeNode root, int sum) { 14 | HashMap preSumMap = new HashMap<>(); 15 | preSumMap.put(0, 1); 16 | return process(root, sum, 0, preSumMap); 17 | } 18 | 19 | // 返回方法数 20 | public static int process(TreeNode x, int sum, int preAll, HashMap preSumMap) { 21 | if (x == null) { 22 | return 0; 23 | } 24 | int all = preAll + x.val; 25 | int ans = 0; 26 | if (preSumMap.containsKey(all - sum)) { 27 | ans = preSumMap.get(all - sum); 28 | } 29 | if (!preSumMap.containsKey(all)) { 30 | preSumMap.put(all, 1); 31 | } else { 32 | preSumMap.put(all, preSumMap.get(all) + 1); 33 | } 34 | ans += process(x.left, sum, all, preSumMap); 35 | ans += process(x.right, sum, all, preSumMap); 36 | if (preSumMap.get(all) == 1) { 37 | preSumMap.remove(all); 38 | } else { 39 | preSumMap.put(all, preSumMap.get(all) - 1); 40 | } 41 | return ans; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/class37/说明: -------------------------------------------------------------------------------- 1 | leetcode最受欢迎100题 2 | leetcode全题目列表 : https://leetcode.com/problemset/all/ 3 | 在全题目列表的右侧栏,点击Top 100 Liked Questions 4 | 或者直接进入右侧链接 : https://leetcode.com/problemset/all/?listId=79h8rn6 5 | 即可看到leetcode最受欢迎100题全列表 6 | 7 | 大厂刷题班27节~35节已经讲完leetcode高频题系列 8 | leetcode高频题系列和leetcode最受欢迎100题系列题目有重合 9 | 以下为leetcode最受欢迎100题不和leetcode高频题重合的题号,其他的都重复了,不再讲述 10 | 0032 : 大厂刷题班, 第14节第1题 11 | 0039 : 体系学习班, 硬币找零专题 : 第21节第2、3、4题, 第22节第2题, 第24节第4题。本题就是无限张找零问题,不再重复讲述 12 | 0064 : 体系学习班, 第21节第1题 13 | 0072 : 大厂刷题班, 第5节第3题 14 | 0085 : 体系学习班, 第25节第4题 15 | 0096 : 体系学习班, 第39节第4题, 卡特兰数 16 | 0114 : 大厂刷题班, 第37节, 本节 17 | 0142 : 体系学习班, 第10节第1题 18 | 0221 : 大厂刷题班, 第37节, 本节 19 | 0226 : 大厂刷题班, 第37节, 本节 20 | 0337 : 体系学习班, 第13节, 第4题, 还是这道题的加强版(多叉树) 21 | 0338 : 和leetcode第191题重复, 大厂刷题班第30节讲过了 22 | 0394 : 大厂刷题班, 第37节, 本节 23 | 0406 : 大厂刷题班, 第37节, 本节 24 | 0416 : 体系学习班, 第23节第1题, 还是这道题的加强版 25 | 0437 : 大厂刷题班, 第37节, 本节 26 | 剩余题目在下一节 27 | 28 | 本节附加题 29 | code01 : 2021年8月大厂真实笔试题 30 | code02 : 2021年8月大厂真实笔试题 -------------------------------------------------------------------------------- /src/class38/Problem_0438_FindAllAnagramsInAString.java: -------------------------------------------------------------------------------- 1 | package class38; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | 7 | public class Problem_0438_FindAllAnagramsInAString { 8 | 9 | public static List findAnagrams(String s, String p) { 10 | List ans = new ArrayList<>(); 11 | if (s == null || p == null || s.length() < p.length()) { 12 | return ans; 13 | } 14 | char[] str = s.toCharArray(); 15 | int N = str.length; 16 | char[] pst = p.toCharArray(); 17 | int M = pst.length; 18 | HashMap map = new HashMap<>(); 19 | for (char cha : pst) { 20 | if (!map.containsKey(cha)) { 21 | map.put(cha, 1); 22 | } else { 23 | map.put(cha, map.get(cha) + 1); 24 | } 25 | } 26 | int all = M; 27 | for (int end = 0; end < M - 1; end++) { 28 | if (map.containsKey(str[end])) { 29 | int count = map.get(str[end]); 30 | if (count > 0) { 31 | all--; 32 | } 33 | map.put(str[end], count - 1); 34 | } 35 | } 36 | for (int end = M - 1, start = 0; end < N; end++, start++) { 37 | if (map.containsKey(str[end])) { 38 | int count = map.get(str[end]); 39 | if (count > 0) { 40 | all--; 41 | } 42 | map.put(str[end], count - 1); 43 | } 44 | if (all == 0) { 45 | ans.add(start); 46 | } 47 | if (map.containsKey(str[start])) { 48 | int count = map.get(str[start]); 49 | if (count >= 0) { 50 | all++; 51 | } 52 | map.put(str[start], count + 1); 53 | } 54 | } 55 | return ans; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/class38/Problem_0448_FindAllNumbersDisappearedInAnArray.java: -------------------------------------------------------------------------------- 1 | package class38; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class Problem_0448_FindAllNumbersDisappearedInAnArray { 7 | 8 | public static List findDisappearedNumbers(int[] nums) { 9 | List ans = new ArrayList<>(); 10 | if (nums == null || nums.length == 0) { 11 | return ans; 12 | } 13 | int N = nums.length; 14 | for (int i = 0; i < N; i++) { 15 | // 从i位置出发,去玩下标循环怼 16 | walk(nums, i); 17 | } 18 | for (int i = 0; i < N; i++) { 19 | if (nums[i] != i + 1) { 20 | ans.add(i + 1); 21 | } 22 | } 23 | return ans; 24 | } 25 | 26 | public static void walk(int[] nums, int i) { 27 | while (nums[i] != i + 1) { // 不断从i发货 28 | int nexti = nums[i] - 1; 29 | if (nums[nexti] == nexti + 1) { 30 | break; 31 | } 32 | swap(nums, i, nexti); 33 | } 34 | } 35 | 36 | public static void swap(int[] nums, int i, int j) { 37 | int tmp = nums[i]; 38 | nums[i] = nums[j]; 39 | nums[j] = tmp; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/class38/Problem_0617_MergeTwoBinaryTrees.java: -------------------------------------------------------------------------------- 1 | package class38; 2 | 3 | public class Problem_0617_MergeTwoBinaryTrees { 4 | 5 | public static class TreeNode { 6 | public int val; 7 | public TreeNode left; 8 | public TreeNode right; 9 | 10 | public TreeNode(int val) { 11 | this.val = val; 12 | } 13 | } 14 | 15 | // 当前,一棵树的头是t1,另一颗树的头是t2 16 | // 请返回,整体merge之后的头 17 | public static TreeNode mergeTrees(TreeNode t1, TreeNode t2) { 18 | if (t1 == null) { 19 | return t2; 20 | } 21 | if (t2 == null) { 22 | return t1; 23 | } 24 | // t1和t2都不是空 25 | TreeNode merge = new TreeNode(t1.val + t2.val); 26 | merge.left = mergeTrees(t1.left, t2.left); 27 | merge.right = mergeTrees(t1.right, t2.right); 28 | return merge; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/class38/Problem_0621_TaskScheduler.java: -------------------------------------------------------------------------------- 1 | package class38; 2 | 3 | public class Problem_0621_TaskScheduler { 4 | 5 | // ['A', 'B', 'A'] 6 | public static int leastInterval(char[] tasks, int free) { 7 | int[] count = new int[256]; 8 | // 出现最多次的任务,到底是出现了几次 9 | int maxCount = 0; 10 | for (char task : tasks) { 11 | count[task]++; 12 | maxCount = Math.max(maxCount, count[task]); 13 | } 14 | // 有多少种任务,都出现最多次 15 | int maxKinds = 0; 16 | for (int task = 0; task < 256; task++) { 17 | if (count[task] == maxCount) { 18 | maxKinds++; 19 | } 20 | } 21 | // maxKinds : 有多少种任务,都出现最多次 22 | // maxCount : 最多次,是几次? 23 | // 砍掉最后一组剩余的任务数 24 | int tasksExceptFinalTeam = tasks.length - maxKinds; 25 | int spaces = (free + 1) * (maxCount - 1); 26 | // 到底几个空格最终会留下! 27 | int restSpaces = Math.max(0, spaces - tasksExceptFinalTeam); 28 | return tasks.length + restSpaces; 29 | // return Math.max(tasks.length, ((n + 1) * (maxCount - 1) + maxKinds)); 30 | } 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/class38/Problem_0647_PalindromicSubstrings.java: -------------------------------------------------------------------------------- 1 | package class38; 2 | 3 | public class Problem_0647_PalindromicSubstrings { 4 | 5 | public static int countSubstrings(String s) { 6 | if (s == null || s.length() == 0) { 7 | return 0; 8 | } 9 | int[] dp = getManacherDP(s); 10 | int ans = 0; 11 | for (int i = 0; i < dp.length; i++) { 12 | ans += dp[i] >> 1; 13 | } 14 | return ans; 15 | } 16 | 17 | public static int[] getManacherDP(String s) { 18 | char[] str = manacherString(s); 19 | int[] pArr = new int[str.length]; 20 | int C = -1; 21 | int R = -1; 22 | for (int i = 0; i < str.length; i++) { 23 | pArr[i] = R > i ? Math.min(pArr[2 * C - i], R - i) : 1; 24 | while (i + pArr[i] < str.length && i - pArr[i] > -1) { 25 | if (str[i + pArr[i]] == str[i - pArr[i]]) 26 | pArr[i]++; 27 | else { 28 | break; 29 | } 30 | } 31 | if (i + pArr[i] > R) { 32 | R = i + pArr[i]; 33 | C = i; 34 | } 35 | } 36 | return pArr; 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 | } 50 | -------------------------------------------------------------------------------- /src/class38/Problem_0739_DailyTemperatures.java: -------------------------------------------------------------------------------- 1 | package class38; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Stack; 6 | 7 | public class Problem_0739_DailyTemperatures { 8 | 9 | public static int[] dailyTemperatures(int[] arr) { 10 | if (arr == null || arr.length == 0) { 11 | return new int[0]; 12 | } 13 | int N = arr.length; 14 | int[] ans = new int[N]; 15 | Stack> stack = new Stack<>(); 16 | for (int i = 0; i < N; i++) { 17 | while (!stack.isEmpty() && arr[stack.peek().get(0)] < arr[i]) { 18 | List popIs = stack.pop(); 19 | for (Integer popi : popIs) { 20 | ans[popi] = i - popi; 21 | } 22 | } 23 | if (!stack.isEmpty() && arr[stack.peek().get(0)] == arr[i]) { 24 | stack.peek().add(Integer.valueOf(i)); 25 | } else { 26 | ArrayList list = new ArrayList<>(); 27 | list.add(i); 28 | stack.push(list); 29 | } 30 | } 31 | return ans; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/class38/Problem_0763_PartitionLabels.java: -------------------------------------------------------------------------------- 1 | package class38; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class Problem_0763_PartitionLabels { 7 | 8 | public static List partitionLabels(String S) { 9 | char[] str = S.toCharArray(); 10 | int[] far = new int[26]; 11 | for (int i = 0; i < str.length; i++) { 12 | far[str[i] - 'a'] = i; 13 | } 14 | List ans = new ArrayList<>(); 15 | int left = 0; 16 | int right = far[str[0] - 'a']; 17 | for (int i = 1; i < str.length; i++) { 18 | if (i > right) { 19 | ans.add(right - left + 1); 20 | left = i; 21 | } 22 | right = Math.max(right, far[str[i] - 'a']); 23 | } 24 | ans.add(right - left + 1); 25 | return ans; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/class38/说明: -------------------------------------------------------------------------------- 1 | leetcode最受欢迎100题 2 | leetcode全题目列表 : https://leetcode.com/problemset/all/ 3 | 在全题目列表的右侧栏,点击Top 100 Liked Questions 4 | 或者直接进入右侧链接 : https://leetcode.com/problemset/all/?listId=79h8rn6 5 | 即可看到leetcode最受欢迎100题全列表 6 | 7 | 大厂刷题班27节~35节已经讲完leetcode高频题系列 8 | leetcode高频题系列和leetcode最受欢迎100题系列题目有重合 9 | 以下为leetcode最受欢迎100题不和leetcode高频题重合的题号,其他的都重复了,不再讲述 10 | 0438 : 大厂刷题班, 第38节, 本节 11 | 0448 : 大厂刷题班, 第38节, 本节 12 | 0494 : 大厂刷题班, 第1节第7题 13 | 0543 : 体系学习班, 第12节第6题 14 | 0560 : 大厂刷题班, 第37节, Leetcode题目437与本题思路相同, 课上也讲了该题做法 15 | 0581 : 大厂刷题班, 第1节第6题 16 | 0617 : 大厂刷题班, 第38节, 本节 17 | 0621 : 大厂刷题班, 第38节, 本节 18 | 0647 : 大厂刷题班, 第38节, 本节 19 | 0739 : 大厂刷题班, 第38节, 本节 20 | 0763 : 大厂刷题班, 第38节, 本节 21 | 至此,leetcode最受欢迎100题系列完结 22 | 23 | 本节附加题 24 | code01 : 2021年8月大厂真实笔试题 25 | code02 : 2021年8月大厂真实笔试题 -------------------------------------------------------------------------------- /src/class39/Code01_01AddValue.java: -------------------------------------------------------------------------------- 1 | package class39; 2 | 3 | // 来自腾讯 4 | // 给定一个只由0和1组成的字符串S,假设下标从1开始,规定i位置的字符价值V[i]计算方式如下 : 5 | // 1) i == 1时,V[i] = 1 6 | // 2) i > 1时,如果S[i] != S[i-1],V[i] = 1 7 | // 3) i > 1时,如果S[i] == S[i-1],V[i] = V[i-1] + 1 8 | // 你可以随意删除S中的字符,返回整个S的最大价值 9 | // 字符串长度<=5000 10 | public class Code01_01AddValue { 11 | 12 | public static int max1(String s) { 13 | if (s == null || s.length() == 0) { 14 | return 0; 15 | } 16 | char[] str = s.toCharArray(); 17 | int[] arr = new int[str.length]; 18 | for (int i = 0; i < arr.length; i++) { 19 | arr[i] = str[i] == '0' ? 0 : 1; 20 | } 21 | return process1(arr, 0, 0, 0); 22 | } 23 | 24 | // 递归含义 : 25 | // 目前在arr[index...]上做选择, str[index...]的左边,最近的数字是lastNum 26 | // 并且lastNum所带的价值,已经拉高到baseValue 27 | // 返回在str[index...]上做选择,最终获得的最大价值 28 | // index -> 0 ~ 4999 29 | // lastNum -> 0 or 1 30 | // baseValue -> 1 ~ 5000 31 | // 5000 * 2 * 5000 -> 5 * 10^7(过!) 32 | public static int process1(int[] arr, int index, int lastNum, int baseValue) { 33 | if (index == arr.length) { 34 | return 0; 35 | } 36 | int curValue = lastNum == arr[index] ? (baseValue + 1) : 1; 37 | // 当前index位置的字符保留 38 | int next1 = process1(arr, index + 1, arr[index], curValue); 39 | // 当前index位置的字符不保留 40 | int next2 = process1(arr, index + 1, lastNum, baseValue); 41 | return Math.max(curValue + next1, next2); 42 | } 43 | 44 | // 请看体系学习班,动态规划章节,把上面的递归改成动态规划!看完必会 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/class39/Code03_SequenceKDifferentKinds.java: -------------------------------------------------------------------------------- 1 | package class39; 2 | 3 | // 来自百度 4 | // 给定一个字符串str,和一个正数k 5 | // str子序列的字符种数必须是k种,返回有多少子序列满足这个条件 6 | // 已知str中都是小写字母 7 | // 原始是取mod 8 | // 本节在尝试上,最难的 9 | // 搞出桶来,组合公式 10 | public class Code03_SequenceKDifferentKinds { 11 | 12 | // bu -> {6,7,0,0,6,3} 13 | // 0 1 2 3 4 5 14 | // a b c d e f 15 | // 在桶数组bu[index....] 一定要凑出rest种来!请问几种方法! 16 | public static int f(int[] bu, int index, int rest) { 17 | if (index == bu.length) { 18 | return rest == 0 ? 1 : 0; 19 | } 20 | // 最后形成的子序列,一个index代表的字符也没有! 21 | int p1 = f(bu, index + 1, rest); 22 | // 最后形成的子序列,一定要包含index代表的字符,几个呢?(所有可能性都要算上!) 23 | int p2 = 0; 24 | if (rest > 0) { // 剩余的种数,没耗尽,可以包含当前桶的字符 25 | p2 = (1 << bu[index] - 1) * f(bu, index + 1, rest - 1); 26 | } 27 | return p1 + p2; 28 | } 29 | 30 | public static int nums(String s, int k) { 31 | char[] str = s.toCharArray(); 32 | int[] counts = new int[26]; 33 | for (char c : str) { 34 | counts[c - 97]++; 35 | } 36 | return ways(counts, 0, k); 37 | } 38 | 39 | public static int ways(int[] c, int i, int r) { 40 | if (r == 0) { 41 | return 1; 42 | } 43 | if (i == c.length) { 44 | return 0; 45 | } 46 | // math(n) -> 2 ^ n -1 47 | return math(c[i]) * ways(c, i + 1, r - 1) + ways(c, i + 1, r); 48 | } 49 | 50 | // n个不同的球 51 | // 挑出1个的方法数 + 挑出2个的方法数 + ... + 挑出n个的方法数为: 52 | // C(n,1) + C(n,2) + ... + C(n,n) == (2 ^ n) -1 53 | public static int math(int n) { 54 | return (1 << n) - 1; 55 | } 56 | 57 | public static void main(String[] args) { 58 | String str = "acbbca"; 59 | int k = 3; 60 | System.out.println(nums(str, k)); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/class40/Code04_LetASorted.java: -------------------------------------------------------------------------------- 1 | package class40; 2 | 3 | // 给定两个数组A和B,长度都是N 4 | // A[i]不可以在A中和其他数交换,只可以选择和B[i]交换(0<=i= lastA && process(A, B, i + 1, A[i])) { 21 | return true; 22 | } 23 | // 第一种选择 : A[i]和B[i]交换 24 | if (B[i] >= lastA && process(A, B, i + 1, B[i])) { 25 | return true; 26 | } 27 | return false; 28 | } 29 | 30 | public static boolean process2(int[] A, int[] B, int i, int lastA) { 31 | if (i == A.length) { 32 | return true; 33 | } 34 | // 第一种选择 : A[i]不和B[i]交换 35 | if (A[i] <= lastA && process2(A, B, i + 1, A[i])) { 36 | return true; 37 | } 38 | // 第一种选择 : A[i]和B[i]交换 39 | if (B[i] <= lastA && process2(A, B, i + 1, B[i])) { 40 | return true; 41 | } 42 | return false; 43 | } 44 | 45 | // A B 操作 : A[i] 与 B[i] 交换! 46 | // 目的 : 让A和B都有序,能不能做到 47 | // public static boolean process3(int[] A, int[] B, int i, int lastA, int lastB) { 48 | // 49 | // } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/class40/Code05_AllSame.java: -------------------------------------------------------------------------------- 1 | package class40; 2 | 3 | // 来自腾讯 4 | // 比如arr = {3,1,2,4} 5 | // 下标对应是:0 1 2 3 6 | // 你最开始选择一个下标进行操作,一旦最开始确定了是哪个下标,以后都只能在这个下标上进行操作 7 | // 比如你选定1下标,1下标上面的数字是1,你可以选择变化这个数字,比如你让这个数字变成2 8 | // 那么arr = {3,2,2,4} 9 | // 下标对应是:0 1 2 3 10 | // 因为你最开始确定了1这个下标,所以你以后都只能对这个下标进行操作, 11 | // 但是,和你此时下标上的数字一样的、且位置连成一片的数字,会跟着一起变 12 | // 比如你选择让此时下标1的数字2变成3, 13 | // 那么arr = {3,3,3,4} 可以看到下标1和下标2的数字一起变成3,这是规则!一定会一起变 14 | // 下标对应是:0 1 2 3 15 | // 接下来,你还是只能对1下标进行操作,那么数字一样的、且位置连成一片的数字(arr[0~2]这个范围)都会一起变 16 | // 决定变成4 17 | // 那么arr = {4,4,4,4} 18 | // 下标对应是:0 1 2 3 19 | // 至此,所有数都成一样的了,你在下标1上做了3个决定(第一次变成2,第二次变成3,第三次变成4), 20 | // 因为联动规则,arr全刷成一种数字了 21 | // 给定一个数组arr,最开始选择哪个下标,你随意 22 | // 你的目的是一定要让arr都成为一种数字,注意联动效果会一直生效 23 | // 返回最小的变化数 24 | // arr长度 <= 200, arr中的值 <= 10^6 25 | public class Code05_AllSame { 26 | 27 | public static int allSame(int[] arr) { 28 | int ans = Integer.MAX_VALUE; 29 | for (int i = 0; i < arr.length; i++) { 30 | ans = Math.min(ans, process(arr, i - 1, arr[i], i + 1)); 31 | } 32 | return ans; 33 | } 34 | 35 | // 左边arr[0..left],如果left == -1,说明没有左边了 36 | // 右边arr[right...n-1],如果right == n,说明没有右边了 37 | // 中间的值是midV,中间的值代表中间一整个部分的值,中间部分有可能是一个数,也可能是一堆数,但是值都为midV 38 | // 返回arr都刷成一样的,最小代价是多少 39 | // left 可能性 : N 40 | // right 可能性 : N 41 | // midV 可能性 : arr中的最大值! 42 | public static int process(int[] arr, int left, int midV, int right) { 43 | for (; left >= 0 && arr[left] == midV;) { 44 | left--; 45 | } 46 | for (; right < arr.length && arr[right] == midV;) { 47 | right++; 48 | } 49 | if (left == -1 && right == arr.length) { 50 | return 0; 51 | } 52 | int p1 = Integer.MAX_VALUE; 53 | if (left >= 0) { 54 | p1 = process(arr, left - 1, arr[left], right) + 1; 55 | } 56 | int p2 = Integer.MAX_VALUE; 57 | if (right < arr.length) { 58 | p2 = process(arr, left, arr[right], right + 1) + 1; 59 | } 60 | return Math.min(p1, p2); 61 | } 62 | 63 | // 如上的递归,请改动态规划,具体参考体系学习班,动态规划大章节! 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/class41/Problem_0031_NextPermutation.java: -------------------------------------------------------------------------------- 1 | package class41; 2 | 3 | public class Problem_0031_NextPermutation { 4 | 5 | public static void nextPermutation(int[] nums) { 6 | int N = nums.length; 7 | // 从右往左第一次降序的位置 8 | int firstLess = -1; 9 | for (int i = N - 2; i >= 0; i--) { 10 | if (nums[i] < nums[i + 1]) { 11 | firstLess = i; 12 | break; 13 | } 14 | } 15 | if (firstLess < 0) { 16 | reverse(nums, 0, N - 1); 17 | } else { 18 | int rightClosestMore = -1; 19 | // 找最靠右的、同时比nums[firstLess]大的数,位置在哪 20 | // 这里其实也可以用二分优化,但是这种优化无关紧要了 21 | for (int i = N - 1; i > firstLess; i--) { 22 | if (nums[i] > nums[firstLess]) { 23 | rightClosestMore = i; 24 | break; 25 | } 26 | } 27 | swap(nums, firstLess, rightClosestMore); 28 | reverse(nums, firstLess + 1, N - 1); 29 | } 30 | } 31 | 32 | public static void reverse(int[] nums, int L, int R) { 33 | while (L < R) { 34 | swap(nums, L++, R--); 35 | } 36 | } 37 | 38 | public static void swap(int[] nums, int i, int j) { 39 | int tmp = nums[i]; 40 | nums[i] = nums[j]; 41 | nums[j] = tmp; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/class42/Problem_0265_PaintHouseII.java: -------------------------------------------------------------------------------- 1 | package class42; 2 | 3 | public class Problem_0265_PaintHouseII { 4 | 5 | // costs[i][k] i号房子用k颜色刷的花费 6 | // 要让0...N-1的房子相邻不同色 7 | // 返回最小花费 8 | public static int minCostII(int[][] costs) { 9 | int N = costs.length; 10 | if (N == 0) { 11 | return 0; 12 | } 13 | int K = costs[0].length; 14 | // 之前取得的最小代价、取得最小代价时的颜色 15 | int preMin1 = 0; 16 | int preEnd1 = -1; 17 | // 之前取得的次小代价、取得次小代价时的颜色 18 | int preMin2 = 0; 19 | int preEnd2 = -1; 20 | for (int i = 0; i < N; i++) { // i房子 21 | int curMin1 = Integer.MAX_VALUE; 22 | int curEnd1 = -1; 23 | int curMin2 = Integer.MAX_VALUE; 24 | int curEnd2 = -1; 25 | for (int j = 0; j < K; j++) { // j颜色! 26 | if (j != preEnd1) { 27 | if (preMin1 + costs[i][j] < curMin1) { 28 | curMin2 = curMin1; 29 | curEnd2 = curEnd1; 30 | curMin1 = preMin1 + costs[i][j]; 31 | curEnd1 = j; 32 | } else if (preMin1 + costs[i][j] < curMin2) { 33 | curMin2 = preMin1 + costs[i][j]; 34 | curEnd2 = j; 35 | } 36 | } else if (j != preEnd2) { 37 | if (preMin2 + costs[i][j] < curMin1) { 38 | curMin2 = curMin1; 39 | curEnd2 = curEnd1; 40 | curMin1 = preMin2 + costs[i][j]; 41 | curEnd1 = j; 42 | } else if (preMin2 + costs[i][j] < curMin2) { 43 | curMin2 = preMin2 + costs[i][j]; 44 | curEnd2 = j; 45 | } 46 | } 47 | } 48 | preMin1 = curMin1; 49 | preEnd1 = curEnd1; 50 | preMin2 = curMin2; 51 | preEnd2 = curEnd2; 52 | } 53 | return preMin1; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/class42/Problem_0296_BestMeetingPoint.java: -------------------------------------------------------------------------------- 1 | package class42; 2 | 3 | public class Problem_0296_BestMeetingPoint { 4 | 5 | public static int minTotalDistance(int[][] grid) { 6 | int N = grid.length; 7 | int M = grid[0].length; 8 | int[] iOnes = new int[N]; 9 | int[] jOnes = new int[M]; 10 | for (int i = 0; i < N; i++) { 11 | for (int j = 0; j < M; j++) { 12 | if (grid[i][j] == 1) { 13 | iOnes[i]++; 14 | jOnes[j]++; 15 | } 16 | } 17 | } 18 | int total = 0; 19 | int i = 0; 20 | int j = N - 1; 21 | int iRest = 0; 22 | int jRest = 0; 23 | while (i < j) { 24 | if (iOnes[i] + iRest <= iOnes[j] + jRest) { 25 | total += iOnes[i] + iRest; 26 | iRest += iOnes[i++]; 27 | } else { 28 | total += iOnes[j] + jRest; 29 | jRest += iOnes[j--]; 30 | } 31 | } 32 | i = 0; 33 | j = M - 1; 34 | iRest = 0; 35 | jRest = 0; 36 | while (i < j) { 37 | if (jOnes[i] + iRest <= jOnes[j] + jRest) { 38 | total += jOnes[i] + iRest; 39 | iRest += jOnes[i++]; 40 | } else { 41 | total += jOnes[j] + jRest; 42 | jRest += jOnes[j--]; 43 | } 44 | } 45 | return total; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/class42/Problem_0335_SelfCrossing.java: -------------------------------------------------------------------------------- 1 | package class42; 2 | 3 | public class Problem_0335_SelfCrossing { 4 | 5 | public static boolean isSelfCrossing(int[] x) { 6 | if (x == null || x.length < 4) { 7 | return false; 8 | } 9 | if ((x.length > 3 && x[2] <= x[0] && x[3] >= x[1]) 10 | || (x.length > 4 11 | && ((x[3] <= x[1] && x[4] >= x[2]) || (x[3] == x[1] && x[0] + x[4] >= x[2])))) { 12 | return true; 13 | } 14 | for (int i = 5; i < x.length; i++) { 15 | if (x[i - 1] <= x[i - 3] && ((x[i] >= x[i - 2]) 16 | || (x[i - 2] >= x[i - 4] && x[i - 5] + x[i - 1] >= x[i - 3] && x[i - 4] + x[i] >= x[i - 2]))) { 17 | return true; 18 | } 19 | } 20 | return false; 21 | } 22 | 23 | public static void main(String[] args) { 24 | int[] arr = { 2, 2, 3, 2, 2 }; 25 | System.out.println(isSelfCrossing(arr)); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/class44/Problem_0992_SubarraysWithKDifferentIntegers.java: -------------------------------------------------------------------------------- 1 | package class44; 2 | 3 | import java.util.HashMap; 4 | 5 | public class Problem_0992_SubarraysWithKDifferentIntegers { 6 | 7 | // nums 数组,题目规定,nums中的数字,不会超过nums的长度 8 | // [ ]长度为5,0~5 9 | public static int subarraysWithKDistinct1(int[] nums, int k) { 10 | int n = nums.length; 11 | // k-1种数的窗口词频统计 12 | int[] lessCounts = new int[n + 1]; 13 | // k种数的窗口词频统计 14 | int[] equalCounts = new int[n + 1]; 15 | int lessLeft = 0; 16 | int equalLeft = 0; 17 | int lessKinds = 0; 18 | int equalKinds = 0; 19 | int ans = 0; 20 | for (int r = 0; r < n; r++) { 21 | // 当前刚来到r位置! 22 | if (lessCounts[nums[r]] == 0) { 23 | lessKinds++; 24 | } 25 | if (equalCounts[nums[r]] == 0) { 26 | equalKinds++; 27 | } 28 | lessCounts[nums[r]]++; 29 | equalCounts[nums[r]]++; 30 | while (lessKinds == k) { 31 | if (lessCounts[nums[lessLeft]] == 1) { 32 | lessKinds--; 33 | } 34 | lessCounts[nums[lessLeft++]]--; 35 | } 36 | while (equalKinds > k) { 37 | if (equalCounts[nums[equalLeft]] == 1) { 38 | equalKinds--; 39 | } 40 | equalCounts[nums[equalLeft++]]--; 41 | } 42 | ans += lessLeft - equalLeft; 43 | } 44 | return ans; 45 | } 46 | 47 | public static int subarraysWithKDistinct2(int[] arr, int k) { 48 | return numsMostK(arr, k) - numsMostK(arr, k - 1); 49 | } 50 | 51 | public static int numsMostK(int[] arr, int k) { 52 | int i = 0, res = 0; 53 | HashMap count = new HashMap<>(); 54 | for (int j = 0; j < arr.length; ++j) { 55 | if (count.getOrDefault(arr[j], 0) == 0) { 56 | k--; 57 | } 58 | count.put(arr[j], count.getOrDefault(arr[j], 0) + 1); 59 | while (k < 0) { 60 | count.put(arr[i], count.get(arr[i]) - 1); 61 | if (count.get(arr[i]) == 0) { 62 | k++; 63 | } 64 | i++; 65 | } 66 | res += j - i + 1; 67 | } 68 | return res; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/class45/Problem_0291_WordPatternII.java: -------------------------------------------------------------------------------- 1 | package class45; 2 | 3 | import java.util.HashSet; 4 | 5 | public class Problem_0291_WordPatternII { 6 | 7 | public static boolean wordPatternMatch(String pattern, String str) { 8 | return match(str, pattern, 0, 0, new String[26], new HashSet<>()); 9 | } 10 | 11 | // 题目有限制,str和pattern其中的字符,一定是a~z小写 12 | // p[a] -> "abc" 13 | // p[b] -> "fbf" 14 | // 需要指代的表最多26长度 15 | // String[] map -> new String[26] 16 | // p[a] -> "abc" map[0] -> "abc" 17 | // p[b] -> "fbf" map[1] -> "fbf"; 18 | // p[z] -> "kfk" map[25] -> "kfk" 19 | // HashSet set -> map中指代了哪些字符串 20 | // str[si.......] 是不是符合 p[pi......]?符合返回true,不符合返回false 21 | // 之前的决定!由map和set,告诉我!不能冲突! 22 | public static boolean match(String s, String p, int si, int pi, String[] map, HashSet set) { 23 | if (pi == p.length() && si == s.length()) { 24 | return true; 25 | } 26 | // str和pattern,并没有都结束! 27 | if (pi == p.length() || si == s.length()) { 28 | return false; 29 | } 30 | // str和pattern,都没结束! 31 | 32 | char ch = p.charAt(pi); 33 | String cur = map[ch - 'a']; 34 | if (cur != null) { // 当前p[pi]已经指定过了! 35 | return si + cur.length() <= s.length() // 不能越界! 36 | && cur.equals(s.substring(si, si + cur.length())) 37 | && match(s, p, si + cur.length(), pi + 1, map, set); 38 | } 39 | // p[pi]没指定! 40 | int end = s.length(); 41 | // 剪枝!重要的剪枝! 42 | for (int i = p.length() - 1; i > pi; i--) { 43 | end -= map[p.charAt(i) - 'a'] == null ? 1 : map[p.charAt(i) - 'a'].length(); 44 | } 45 | for (int i = si; i < end; i++) { 46 | // 从si出发的所有前缀串,全试 47 | cur = s.substring(si, i + 1); 48 | // 但是,只有这个前缀串,之前没占过别的坑!才能去尝试 49 | if (!set.contains(cur)) { 50 | set.add(cur); 51 | map[ch - 'a'] = cur; 52 | if (match(s, p, i + 1, pi + 1, map, set)) { 53 | return true; 54 | } 55 | map[ch - 'a'] = null; 56 | set.remove(cur); 57 | } 58 | } 59 | return false; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/class45/Problem_0403_FrogJump.java: -------------------------------------------------------------------------------- 1 | package class45; 2 | 3 | import java.util.HashMap; 4 | import java.util.HashSet; 5 | 6 | public class Problem_0403_FrogJump { 7 | 8 | public static boolean canCross(int[] stones) { 9 | HashSet set = new HashSet<>(); 10 | for (int num : stones) { 11 | set.add(num); 12 | } 13 | HashMap> dp = new HashMap<>(); 14 | return jump(1, 1, stones[stones.length - 1], set, dp); 15 | } 16 | 17 | public static boolean jump(int cur, int pre, int end, HashSet set, 18 | HashMap> dp) { 19 | if (cur == end) { 20 | return true; 21 | } 22 | if (!set.contains(cur)) { 23 | return false; 24 | } 25 | if (dp.containsKey(cur) && dp.get(cur).containsKey(pre)) { 26 | return dp.get(cur).get(pre); 27 | } 28 | boolean ans = (pre > 1 && jump(cur + pre - 1, pre - 1, end, set, dp)) 29 | || jump(cur + pre, pre, end, set, dp) 30 | || jump(cur + pre + 1, pre + 1, end, set, dp); 31 | if (!dp.containsKey(cur)) { 32 | dp.put(cur, new HashMap<>()); 33 | } 34 | if (!dp.get(cur).containsKey(pre)) { 35 | dp.get(cur).put(pre, ans); 36 | } 37 | return ans; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/class45/Problem_2035_PartitionArrayIntoTwoArraysToMinimizeSumDifference.java: -------------------------------------------------------------------------------- 1 | package class45; 2 | 3 | import java.util.HashMap; 4 | import java.util.TreeSet; 5 | 6 | public class Problem_2035_PartitionArrayIntoTwoArraysToMinimizeSumDifference { 7 | 8 | public static int minimumDifference(int[] arr) { 9 | int size = arr.length; 10 | int half = size >> 1; 11 | HashMap> lmap = new HashMap<>(); 12 | process(arr, 0, half, 0, 0, lmap); 13 | HashMap> rmap = new HashMap<>(); 14 | process(arr, half, size, 0, 0, rmap); 15 | int sum = 0; 16 | for (int num : arr) { 17 | sum += num; 18 | } 19 | int ans = Integer.MAX_VALUE; 20 | for (int leftNum : lmap.keySet()) { 21 | for (int leftSum : lmap.get(leftNum)) { 22 | Integer rightSum = rmap.get(half - leftNum).floor((sum >> 1) - leftSum); 23 | if (rightSum != null) { 24 | int pickSum = leftSum + rightSum; 25 | int restSum = sum - pickSum; 26 | ans = Math.min(ans, restSum - pickSum); 27 | } 28 | } 29 | } 30 | return ans; 31 | } 32 | 33 | 34 | // arr -> 8 0 1 2 3 4 5 6 7 35 | // process(arr, 0, 4) [0,4) 36 | // process(arr, 4, 8) [4,8) 37 | // arr[index....end-1]这个范围上,去做选择 38 | // pick挑了几个数! 39 | // sum挑的这些数,累加和是多少! 40 | // map记录结果 41 | // HashMap> map 42 | // key -> 挑了几个数,比如挑了3个数,但是形成累加和可能多个! 43 | // value -> 有序表,都记下来! 44 | // 整个过程,纯暴力!2^15 -> 3万多,纯暴力跑完,依然很快! 45 | public static void process(int[] arr, int index, int end, int pick, int sum, 46 | HashMap> map) { 47 | if (index == end) { 48 | if (!map.containsKey(pick)) { 49 | map.put(pick, new TreeSet<>()); 50 | } 51 | map.get(pick).add(sum); 52 | } else { 53 | process(arr, index + 1, end, pick, sum, map); 54 | process(arr, index + 1, end, pick + 1, sum + arr[index], map); 55 | } 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/class46/Problem_0391_PerfectRectangle.java: -------------------------------------------------------------------------------- 1 | package class46; 2 | 3 | import java.util.HashMap; 4 | 5 | public class Problem_0391_PerfectRectangle { 6 | 7 | public static boolean isRectangleCover(int[][] matrix) { 8 | if (matrix.length == 0 || matrix[0].length == 0) { 9 | return false; 10 | } 11 | int l = Integer.MAX_VALUE; 12 | int r = Integer.MIN_VALUE; 13 | int d = Integer.MAX_VALUE; 14 | int u = Integer.MIN_VALUE; 15 | HashMap> map = new HashMap<>(); 16 | int area = 0; 17 | for (int[] rect : matrix) { 18 | add(map, rect[0], rect[1]); 19 | add(map, rect[0], rect[3]); 20 | add(map, rect[2], rect[1]); 21 | add(map, rect[2], rect[3]); 22 | area += (rect[2] - rect[0]) * (rect[3] - rect[1]); 23 | l = Math.min(rect[0], l); 24 | d = Math.min(rect[1], d); 25 | r = Math.max(rect[2], r); 26 | u = Math.max(rect[3], u); 27 | } 28 | return checkPoints(map, l, d, r, u) && area == (r - l) * (u - d); 29 | } 30 | 31 | public static void add(HashMap> map, int row, int col) { 32 | if (!map.containsKey(row)) { 33 | map.put(row, new HashMap<>()); 34 | } 35 | map.get(row).put(col, map.get(row).getOrDefault(col, 0) + 1); 36 | } 37 | 38 | public static boolean checkPoints(HashMap> map, int l, int d, int r, int u) { 39 | if (map.get(l).getOrDefault(d, 0) != 1 40 | || map.get(l).getOrDefault(u, 0) != 1 41 | || map.get(r).getOrDefault(d, 0) != 1 42 | || map.get(r).getOrDefault(u, 0) != 1) { 43 | return false; 44 | } 45 | map.get(l).remove(d); 46 | map.get(l).remove(u); 47 | map.get(r).remove(d); 48 | map.get(r).remove(u); 49 | for (int key : map.keySet()) { 50 | for (int value : map.get(key).values()) { 51 | if ((value & 1) != 0) { 52 | return false; 53 | } 54 | } 55 | } 56 | return true; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/class47/Problem_0358_RearrangeStringKDistanceApart.java: -------------------------------------------------------------------------------- 1 | package class47; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | 6 | // 本题的解法思路与leetcode 621题 TaskScheduler 问题是一样的 7 | public class Problem_0358_RearrangeStringKDistanceApart { 8 | 9 | public String rearrangeString(String s, int k) { 10 | if (s == null || s.length() < k) { 11 | return s; 12 | } 13 | char[] str = s.toCharArray(); 14 | int[][] cnts = new int[256][2]; 15 | for (int i = 0; i < 256; i++) { 16 | cnts[i] = new int[] { i, 0 }; 17 | } 18 | int maxCount = 0; 19 | for (char task : str) { 20 | cnts[task][1]++; 21 | maxCount = Math.max(maxCount, cnts[task][1]); 22 | } 23 | int maxKinds = 0; 24 | for (int task = 0; task < 256; task++) { 25 | if (cnts[task][1] == maxCount) { 26 | maxKinds++; 27 | } 28 | } 29 | int N = str.length; 30 | if (!isValid(N, k, maxCount, maxKinds)) { 31 | return ""; 32 | } 33 | ArrayList ans = new ArrayList<>(); 34 | for (int i = 0; i < maxCount; i++) { 35 | ans.add(new StringBuilder()); 36 | } 37 | Arrays.sort(cnts, (a, b) -> (b[1] - a[1])); 38 | int i = 0; 39 | for (; i < 256 && cnts[i][1] == maxCount; i++) { 40 | for (int j = 0; j < maxCount; j++) { 41 | ans.get(j).append((char) cnts[i][0]); 42 | } 43 | } 44 | int out = 0; 45 | for (; i < 256; i++) { 46 | for (int j = 0; j < cnts[i][1]; j++) { 47 | ans.get(out).append((char) cnts[i][0]); 48 | out = out == ans.size() - 2 ? 0 : out + 1; 49 | } 50 | } 51 | StringBuilder builder = new StringBuilder(); 52 | for (StringBuilder b : ans) { 53 | builder.append(b.toString()); 54 | } 55 | return builder.toString(); 56 | } 57 | 58 | public static boolean isValid(int N, int k, int maxCount, int maxKinds) { 59 | int restTasks = N - maxKinds; 60 | int spaces = k * (maxCount - 1); 61 | return spaces - restTasks <= 0; 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/class48/Problem_0483_SmallestGoodBase.java: -------------------------------------------------------------------------------- 1 | package class48; 2 | 3 | public class Problem_0483_SmallestGoodBase { 4 | 5 | // ""4651" -> 4651 6 | public static String smallestGoodBase(String n) { 7 | long num = Long.valueOf(n); 8 | // n这个数,需要从m位开始试,固定位数,一定要有m位! 9 | for (int m = (int) (Math.log(num + 1) / Math.log(2)); m > 2; m--) { 10 | // num开m次方 11 | long l = (long) (Math.pow(num, 1.0 / m)); 12 | long r = (long) (Math.pow(num, 1.0 / (m - 1))) + 1L; 13 | while (l <= r) { 14 | long k = l + ((r - l) >> 1); 15 | long sum = 0L; 16 | long base = 1L; 17 | for (int i = 0; i < m && sum <= num; i++) { 18 | sum += base; 19 | base *= k; 20 | } 21 | if (sum < num) { 22 | l = k + 1; 23 | } else if (sum > num) { 24 | r = k - 1; 25 | } else { 26 | return String.valueOf(k); 27 | } 28 | } 29 | } 30 | return String.valueOf(num - 1); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/class49/Problem_0377_CombinationSumIV.java: -------------------------------------------------------------------------------- 1 | package class49; 2 | 3 | import java.util.Arrays; 4 | 5 | public class Problem_0377_CombinationSumIV { 6 | 7 | // 当前剩下的值是rest, 8 | // nums中所有的值,都可能作为分解rest的,第一块!全试一试 9 | // nums, 无重复,都是正 10 | // rest, 11 | public static int ways(int rest, int[] nums) { 12 | if (rest < 0) { 13 | return 0; 14 | } 15 | if (rest == 0) { 16 | return 1; 17 | } 18 | int ways = 0; 19 | for (int num : nums) { 20 | ways += ways(rest - num, nums); 21 | } 22 | return ways; 23 | } 24 | 25 | public static int[] dp = new int[1001]; 26 | 27 | public static int combinationSum41(int[] nums, int target) { 28 | Arrays.fill(dp, 0, target + 1, -1); 29 | return process1(nums, target); 30 | } 31 | 32 | public static int process1(int[] nums, int rest) { 33 | if (rest < 0) { 34 | return 0; 35 | } 36 | if (dp[rest] != -1) { 37 | return dp[rest]; 38 | } 39 | int ans = 0; 40 | if (rest == 0) { 41 | ans = 1; 42 | } else { 43 | for (int num : nums) { 44 | ans += process1(nums, rest - num); 45 | } 46 | } 47 | dp[rest] = ans; 48 | return ans; 49 | } 50 | 51 | // 剪枝 + 严格位置依赖的动态规划 52 | public static int combinationSum42(int[] nums, int target) { 53 | Arrays.sort(nums); 54 | int[] dp = new int[target + 1]; 55 | dp[0] = 1; 56 | for (int rest = 1; rest <= target; rest++) { 57 | for (int i = 0; i < nums.length && nums[i] <= rest; i++) { 58 | dp[rest] += dp[rest - nums[i]]; 59 | } 60 | } 61 | return dp[target]; 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/class49/Problem_0446_ArithmeticSlicesIISubsequence.java: -------------------------------------------------------------------------------- 1 | package class49; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | 6 | public class Problem_0446_ArithmeticSlicesIISubsequence { 7 | 8 | // 时间复杂度是O(N^2),最优解的时间复杂度 9 | public static int numberOfArithmeticSlices(int[] arr) { 10 | int N = arr.length; 11 | int ans = 0; 12 | ArrayList> maps = new ArrayList<>(); 13 | for (int i = 0; i < N; i++) { 14 | maps.add(new HashMap<>()); 15 | // ....j...i(结尾) 16 | for (int j = i - 1; j >= 0; j--) { 17 | long diff = (long) arr[i] - (long) arr[j]; 18 | if (diff <= Integer.MIN_VALUE || diff > Integer.MAX_VALUE) { 19 | continue; 20 | } 21 | int dif = (int) diff; 22 | int count = maps.get(j).getOrDefault(dif, 0); 23 | ans += count; 24 | maps.get(i).put(dif, maps.get(i).getOrDefault(dif, 0) + count + 1); 25 | } 26 | } 27 | return ans; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/class49/Problem_0489_RobotRoomCleaner.java: -------------------------------------------------------------------------------- 1 | package class49; 2 | 3 | import java.util.HashSet; 4 | 5 | public class Problem_0489_RobotRoomCleaner { 6 | 7 | // 不要提交这个接口的内容 8 | interface Robot { 9 | public boolean move(); 10 | 11 | public void turnLeft(); 12 | 13 | public void turnRight(); 14 | 15 | public void clean(); 16 | } 17 | 18 | // 提交下面的内容 19 | public static void cleanRoom(Robot robot) { 20 | clean(robot, 0, 0, 0, new HashSet<>()); 21 | } 22 | 23 | private static final int[][] ds = { { -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 } }; 24 | 25 | // 机器人robot, 26 | // 当前来到的位置(x,y),且之前没来过 27 | // 机器人脸冲什么方向d,0 1 2 3 28 | // visited里记录了机器人走过哪些位置 29 | // 函数的功能:不要重复走visited里面的位置,把剩下的位置,都打扫干净! 30 | // 而且要回去! 31 | public static void clean(Robot robot, int x, int y, int d, HashSet visited) { 32 | robot.clean(); 33 | visited.add(x + "_" + y); 34 | for (int i = 0; i < 4; i++) { 35 | // d = 0 : 0 1 2 3 36 | // d = 1 : 1 2 3 0 37 | // d = 2 : 2 3 0 1 38 | // d = 3 : 3 0 1 2 39 | // 下一步的方向! 40 | int nd = (i + d) % 4; 41 | // 当下一步的方向定了!下一步的位置在哪?(nx, ny) 42 | int nx = ds[nd][0] + x; 43 | int ny = ds[nd][1] + y; 44 | if (!visited.contains(nx + "_" + ny) && robot.move()) { 45 | clean(robot, nx, ny, nd, visited); 46 | } 47 | robot.turnRight(); 48 | } 49 | // 负责回去:之前的位置,怎么到你的!你要回去,而且方向和到你之前,要一致! 50 | robot.turnRight(); 51 | robot.turnRight(); 52 | robot.move(); 53 | robot.turnRight(); 54 | robot.turnRight(); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/class49/Problem_0527_WordAbbreviation.java: -------------------------------------------------------------------------------- 1 | package class49; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | 7 | public class Problem_0527_WordAbbreviation { 8 | 9 | public static List wordsAbbreviation(List words) { 10 | int len = words.size(); 11 | List res = new ArrayList<>(); 12 | HashMap> map = new HashMap<>(); 13 | for (int i = 0; i < len; i++) { 14 | res.add(makeAbbr(words.get(i), 1)); 15 | List list = map.getOrDefault(res.get(i), new ArrayList<>()); 16 | list.add(i); 17 | map.put(res.get(i), list); 18 | } 19 | int[] prefix = new int[len]; 20 | for (int i = 0; i < len; i++) { 21 | if (map.get(res.get(i)).size() > 1) { 22 | List indexes = map.get(res.get(i)); 23 | map.remove(res.get(i)); 24 | for (int j : indexes) { 25 | prefix[j]++; 26 | res.set(j, makeAbbr(words.get(j), prefix[j])); 27 | List list = map.getOrDefault(res.get(j), new ArrayList<>()); 28 | list.add(j); 29 | map.put(res.get(j), list); 30 | } 31 | i--; 32 | } 33 | } 34 | return res; 35 | } 36 | 37 | public static String makeAbbr(String s, int k) { 38 | if (k >= s.length() - 2) { 39 | return s; 40 | } 41 | StringBuilder builder = new StringBuilder(); 42 | builder.append(s.substring(0, k)); 43 | builder.append(s.length() - 1 - k); 44 | builder.append(s.charAt(s.length() - 1)); 45 | return builder.toString(); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/class49/Problem_0548_SplitArrayEithEqualSum.java: -------------------------------------------------------------------------------- 1 | package class49; 2 | 3 | public class Problem_0548_SplitArrayEithEqualSum { 4 | 5 | public static boolean splitArray(int[] nums) { 6 | if (nums.length < 7) { 7 | return false; 8 | } 9 | int[] sumLeftToRight = new int[nums.length]; 10 | int[] sumRightToLeft = new int[nums.length]; 11 | int s = 0; 12 | for (int i = 0; i < nums.length; i++) { 13 | sumLeftToRight[i] = s; 14 | s += nums[i]; 15 | } 16 | s = 0; 17 | for (int i = nums.length - 1; i >= 0; i--) { 18 | sumRightToLeft[i] = s; 19 | s += nums[i]; 20 | } 21 | for (int i = 1; i < nums.length - 5; i++) { 22 | for (int j = nums.length - 2; j > i + 3; j--) { 23 | if (sumLeftToRight[i] == sumRightToLeft[j] && find(sumLeftToRight, sumRightToLeft, i, j)) { 24 | return true; 25 | } 26 | } 27 | } 28 | return false; 29 | } 30 | 31 | public static boolean find(int[] sumLeftToRight, int[] sumRightToLeft, int l, int r) { 32 | int s = sumLeftToRight[l]; 33 | int prefix = sumLeftToRight[l + 1]; 34 | int suffix = sumRightToLeft[r - 1]; 35 | for (int i = l + 2; i < r - 1; i++) { 36 | int s1 = sumLeftToRight[i] - prefix; 37 | int s2 = sumRightToLeft[i] - suffix; 38 | if (s1 == s2 && s1 == s) { 39 | return true; 40 | } 41 | } 42 | return false; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/class50/Problem_0568_MaximumVacationDays.java: -------------------------------------------------------------------------------- 1 | package class50; 2 | 3 | public class Problem_0568_MaximumVacationDays { 4 | 5 | public static int maxVacationDays(int[][] fly, int[][] day) { 6 | int n = fly.length; 7 | int k = day[0].length; 8 | // pas[i] = {a, b, c} 9 | // 从a、b、c能飞到i 10 | int[][] pass = new int[n][]; 11 | for (int i = 0; i < n; i++) { 12 | int s = 0; 13 | for (int j = 0; j < n; j++) { 14 | if (fly[j][i] != 0) { 15 | s++; 16 | } 17 | } 18 | pass[i] = new int[s]; 19 | for (int j = n - 1; j >= 0; j--) { 20 | if (fly[j][i] != 0) { 21 | pass[i][--s] = j; 22 | } 23 | } 24 | } 25 | // dp[i][j] -> 第i周必须在j这座城,0~i-1周(随意),最大休假天数 26 | int[][] dp = new int[k][n]; 27 | // 飞的时机,是周一早上飞,认为对时间没有影响,直接到某个城,然后过一周 28 | dp[0][0] = day[0][0]; 29 | for (int j = 1; j < n; j++) { 30 | dp[0][j] = fly[0][j] != 0 ? day[j][0] : -1; 31 | } 32 | for (int i = 1; i < k; i++) { // 第i周 33 | for (int j = 0; j < n; j++) { // 在j号城过! 34 | // 第i周,要怎么到j号城 35 | // 下面max的初始值,我第i-1周,就在j号城,选择不动地方,进入第i周 36 | int max = dp[i - 1][j]; 37 | for (int p : pass[j]) { // 枚举什么?能到j号城的城市p 38 | max = Math.max(max, dp[i - 1][p]); 39 | } 40 | dp[i][j] = max != -1 ? max + day[j][i] : -1; 41 | } 42 | } 43 | int ans = 0; 44 | for (int i = 0; i < n; i++) { 45 | ans = Math.max(ans, dp[k - 1][i]); 46 | } 47 | return ans; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/class50/Problem_0587_ErectTheFence.java: -------------------------------------------------------------------------------- 1 | package class50; 2 | 3 | import java.util.Arrays; 4 | 5 | public class Problem_0587_ErectTheFence { 6 | 7 | public static int[][] outerTrees(int[][] points) { 8 | int n = points.length; 9 | int s = 0; 10 | int[][] stack = new int[n << 1][]; 11 | // x小的排前面,x一样的,y小的排前面 12 | Arrays.sort(points, (a, b) -> a[0] != b[0] ? a[0] - b[0] : a[1] - b[1]); 13 | for (int i = 0; i < n; i++) { 14 | while (s > 1 && cross(stack[s - 2], stack[s - 1], points[i]) > 0) { 15 | s--; 16 | } 17 | stack[s++] = points[i]; 18 | } 19 | for (int i = n - 2; i >= 0; i--) { 20 | while (s > 1 && cross(stack[s - 2], stack[s - 1], points[i]) > 0) { 21 | s--; 22 | } 23 | stack[s++] = points[i]; 24 | } 25 | // 去重返回 26 | Arrays.sort(stack, 0, s, (a, b) -> b[0] == a[0] ? b[1] - a[1] : b[0] - a[0]); 27 | n = 1; 28 | for (int i = 1; i < s; i++) { 29 | // 如果i点,x和y,与i-1点,x和y都一样 30 | // i点与i-1点,在同一个位置,此时,i点不保留 31 | if (stack[i][0] != stack[i - 1][0] || stack[i][1] != stack[i - 1][1]) { 32 | stack[n++] = stack[i]; 33 | } 34 | } 35 | return Arrays.copyOf(stack, n); 36 | } 37 | 38 | // 叉乘的实现 39 | // 假设有a、b、c三个点,并且给出每个点的(x,y)位置 40 | // 从a到c的向量,在从a到b的向量的哪一侧? 41 | // 如果a到c的向量,在从a到b的向量右侧,返回正数 42 | // 如果a到c的向量,在从a到b的向量左侧,返回负数 43 | // 如果a到c的向量,和从a到b的向量重合,返回0 44 | public static int cross(int[] a, int[] b, int[] c) { 45 | return (b[1] - a[1]) * (c[0] - b[0]) - (b[0] - a[0]) * (c[1] - b[1]); 46 | } 47 | 48 | public static void main(String[] args) { 49 | int[] a = { 4, 4 }; 50 | int[] b = { 1, 1 }; 51 | int[] c = { 1, 5 }; 52 | System.out.println(cross(a, b, c)); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/class51/Problem_0630_CourseScheduleIII.java: -------------------------------------------------------------------------------- 1 | package class51; 2 | 3 | import java.util.Arrays; 4 | import java.util.PriorityQueue; 5 | 6 | public class Problem_0630_CourseScheduleIII { 7 | 8 | public static int scheduleCourse(int[][] courses) { 9 | // courses[i] = {花费,截止} 10 | Arrays.sort(courses, (a, b) -> a[1] - b[1]); 11 | // 花费时间的大根堆 12 | PriorityQueue heap = new PriorityQueue<>((a, b) -> b - a); 13 | // 时间点 14 | int time = 0; 15 | for (int[] c : courses) { 16 | // 17 | if (time + c[0] <= c[1]) { // 当前时间 + 花费 <= 截止时间的 18 | heap.add(c[0]); 19 | time += c[0]; 20 | } else { // 当前时间 + 花费 > 截止时间的, 只有淘汰掉某课,当前的课才能进来! 21 | // 22 | 23 | 24 | if (!heap.isEmpty() && heap.peek() > c[0]) { 25 | // time -= heap.poll(); 26 | // heap.add(c[0]); 27 | // time += c[0]; 28 | heap.add(c[0]); 29 | time += c[0] - heap.poll(); 30 | } 31 | } 32 | } 33 | return heap.size(); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/class51/Problem_0875_KokoEatingBananas.java: -------------------------------------------------------------------------------- 1 | package class51; 2 | 3 | public class Problem_0875_KokoEatingBananas { 4 | 5 | public static int minEatingSpeed(int[] piles, int h) { 6 | int L = 1; 7 | int R = 0; 8 | for (int pile : piles) { 9 | R = Math.max(R, pile); 10 | } 11 | int ans = 0; 12 | int M = 0; 13 | while (L <= R) { 14 | M = L + ((R - L) >> 1); 15 | if (hours(piles, M) <= h) { 16 | ans = M; 17 | R = M - 1; 18 | } else { 19 | L = M + 1; 20 | } 21 | } 22 | return ans; 23 | } 24 | 25 | public static int hours(int[] piles, int speed) { 26 | int ans = 0; 27 | int offset = speed - 1; 28 | for (int pile : piles) { 29 | ans += (pile + offset) / speed; 30 | } 31 | return ans; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/class52/Problem_0656_CoinPath.java: -------------------------------------------------------------------------------- 1 | package class52; 2 | 3 | import java.util.Arrays; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | 7 | public class Problem_0656_CoinPath { 8 | 9 | // arr 0 -> n-1 10 | // arr[i] = -1 死了! 11 | public static int minCost(int[] arr, int jump) { 12 | if (arr == null || arr.length == 0) { 13 | return 0; 14 | } 15 | int n = arr.length; 16 | if (arr[0] == -1 || arr[n - 1] == -1) { 17 | return -1; 18 | } 19 | // dp[i] : 从0位置开始出发,到达i位置的最小代价 20 | int[] dp = new int[n]; 21 | dp[0] = arr[0]; 22 | for (int i = 1; i < n; i++) { 23 | dp[i] = Integer.MAX_VALUE; 24 | if (arr[i] != -1) { 25 | for (int pre = Math.max(0, i - jump); pre < i; pre++) { 26 | if (dp[pre] != -1) { 27 | dp[i] = Math.min(dp[i], dp[pre] + arr[i]); 28 | } 29 | } 30 | } 31 | dp[i] = dp[i] == Integer.MAX_VALUE ? -1 : dp[i]; 32 | } 33 | return dp[n - 1]; 34 | } 35 | 36 | public static List cheapestJump(int[] arr, int jump) { 37 | int n = arr.length; 38 | int[] best = new int[n]; 39 | int[] last = new int[n]; 40 | int[] size = new int[n]; 41 | Arrays.fill(best, Integer.MAX_VALUE); 42 | Arrays.fill(last, -1); 43 | best[0] = 0; 44 | for (int i = 0; i < n; i++) { 45 | if (arr[i] != -1) { 46 | for (int j = Math.max(0, i - jump); j < i; j++) { 47 | if (arr[j] != -1) { 48 | int cur = best[j] + arr[i]; 49 | // 1) 代价低换方案! 50 | // 2) 代价一样,但是点更多,换方案! 51 | if (cur < best[i] || (cur == best[i] && size[i] - 1 < size[j])) { 52 | best[i] = cur; 53 | last[i] = j; 54 | size[i] = size[j] + 1; 55 | } 56 | } 57 | } 58 | } 59 | } 60 | List path = new LinkedList<>(); 61 | for (int cur = n - 1; cur >= 0; cur = last[cur]) { 62 | path.add(0, cur + 1); 63 | } 64 | return path.get(0) != 1 ? new LinkedList<>() : path; 65 | } 66 | 67 | } 68 | --------------------------------------------------------------------------------