From 0dfd08357a8affde86e8706896965a10a65b0760 Mon Sep 17 00:00:00 2001 From: algorithmzuo Date: Wed, 11 Jan 2023 15:23:20 +0800 Subject: [PATCH] modify code --- 公开课/class001/Code01_PosArrayToBST.java | 224 ------------- .../Code02_ContainAllCharExactly.java | 115 ------- 公开课/class002/Code01_MakeNo.java | 50 --- 公开课/class002/Code02_KthMinPair.java | 214 ------------ .../Code01_LongestNoRepeatSubstring.java | 77 ----- 公开课/class003/Code02_HowManyTypes.java | 82 ----- .../class003/Code03_SubsquenceMaxModM.java | 144 --------- 公开课/class004/Code01_QueryHobby.java | 115 ------- 公开课/class004/Code02_MergeRecord.java | 216 ------------- 公开课/class005/Code01_RotateString.java | 93 ------ 公开课/class005/Code02_RestoreWays.java | 237 -------------- 公开课/class006/Code01_Power2Diffs.java | 97 ------ 公开课/class006/Code02_Water.java | 121 ------- 公开课/class007/Code01_RandToRand.java | 93 ------ .../Code02_EqualProbabilityRandom.java | 46 --- .../class007/Code03_FindHalfMajority.java | 77 ----- 公开课/class007/Code04_FindKMajor.java | 135 -------- 公开课/class008/Code01_JumpGameII.java | 27 -- .../Code02_LongestConsecutiveSequence.java | 24 -- .../class009/Code01_SetMatrixZeroes.java | 84 ----- .../class009/Code02_SearchA2DMatrixII.java | 30 -- 公开课/class009/Code03_LongestOnes.java | 155 --------- 公开课/class010/Code01_SwapWithoutTmp.java | 17 - 公开课/class010/Code02_GetMax.java | 53 --- .../class010/Code03_EvenTimesOddTimes.java | 89 ----- .../class011/Code01_CopyListWithRandom.java | 133 -------- 公开课/class011/Code02_JumpMinTimes.java | 201 ------------ 公开课/class012/Code01_MoneyProblem.java | 200 ------------ .../class013/Code01_PalindromeNumber.java | 24 -- .../Code03_LongestNoRepeatSubstring.java | 70 ---- 公开课/class014/Code01_CoverMax.java | 133 -------- 公开课/class014/Code02_MaxDistance.java | 154 --------- .../class015/Code01_CordCoverMaxPoint.java | 88 ----- 公开课/class015/Code02_ColorLeftRight.java | 72 ----- .../Code03_MaxABSBetweenLeftAndRight.java | 72 ----- .../class015/Code04_TrappingRainWater.java | 121 ------- 公开课/class016/Code01_RandToRand.java | 138 -------- .../Code02_EqualProbabilityRandom.java | 46 --- .../class016/Code03_FindHalfMajority.java | 77 ----- 公开课/class016/Code04_FindKMajor.java | 135 -------- 公开课/class017/Code01_SubArrayMaxSum.java | 111 ------- .../class017/Code02_SubMatrixMaxSum.java | 83 ----- 公开课/class018/Code01_SqrtX.java | 31 -- 公开课/class018/Code02_PowXN.java | 54 ---- .../Code03_ContainerWithMostWater.java | 31 -- 公开课/class019/Code01_RotateImage.java | 27 -- .../class019/Code02_ZigZagPrintMatrix.java | 48 --- 公开课/class019/Code03_PrintStar.java | 46 --- 公开课/class020/Code01_RotateString.java | 93 ------ 公开课/class020/Code02_HowManyTypes.java | 111 ------- .../Code03_LongestNoRepeatSubstring.java | 77 ----- 公开课/class020/Code04_CoverMax.java | 133 -------- 公开课/class020/Code05_MakeNo.java | 60 ---- 公开课/class021/Code01_SwapWithoutTmp.java | 17 - 公开课/class021/Code02_GetMax.java | 55 ---- .../class021/Code03_EvenTimesOddTimes.java | 71 ---- 公开课/class022/Code01_MinSwapStep.java | 53 --- 公开课/class022/Code02_CountFiles.java | 42 --- 公开课/class022/Code03_Cola.java | 146 --------- .../class023/Code01_FindHalfMajority.java | 78 ----- 公开课/class024/Code01_RotateImage.java | 61 ---- .../class024/Code02_ZigZagPrintMatrix.java | 52 --- 公开课/class024/Code03_PrintStar.java | 46 --- 公开课/class025/Code01_Water.java | 120 ------- 公开课/class025/Code02_RandToRand.java | 134 -------- .../Code03_EqualProbabilityRandom.java | 67 ---- 公开课/class026/Code01_SubArrayMaxSum.java | 161 ---------- .../Code02_SubArrayMaxSumFollowUp.java | 58 ---- .../class026/Code03_SubMatrixMaxSum.java | 83 ----- 公开课/class027/Code01_MinSwapStep.java | 71 ---- 公开课/class027/Code02_CountFiles.java | 42 --- 公开课/class027/Code03_Cola.java | 148 --------- 公开课/class028/Code01_RotateString.java | 93 ------ 公开课/class028/Code02_HowManyTypes.java | 111 ------- .../Code03_LongestNoRepeatSubstring.java | 83 ----- 公开课/class028/Code04_CoverMax.java | 133 -------- 公开课/class029/Code01_AppleMinBags.java | 77 ----- 公开课/class029/Code02_EatGrass.java | 40 --- .../class029/Code03_MaxLeftMaxRight.java | 80 ----- 公开课/class030/Code01_IsPalindrome.java | 25 -- 公开课/class030/Code02_MySqrt.java | 30 -- 公开课/class030/Code03_UglyNumber.java | 51 --- 公开课/class030/Code04_EnterLoopNode.java | 34 -- 公开课/class031/Code01_SwapWithoutTmp.java | 24 -- 公开课/class031/Code02_AddMinus.java | 29 -- 公开课/class031/Code03_GetMax.java | 49 --- 公开课/class031/Code04_MissingNumber.java | 27 -- .../Code01_BinaryTreeLevelOrderTraversal.java | 46 --- ...ode01_BinaryTreeLevelOrderTraversalII.java | 45 --- ...ryTreeFromPreorderAndInorderTraversal.java | 74 ----- 公开课/class032/Code03_PaperFolding.java | 26 -- .../class032/Code04_DiameterOfBinaryTree.java | 38 --- .../class033/Code01_FindHalfMajority.java | 76 ----- 公开课/class033/Code02_RotateImage.java | 52 --- .../class033/Code03_ZigZagPrintMatrix.java | 48 --- 公开课/class033/Code04_PrintStar.java | 46 --- 公开课/class034/Code01_Water.java | 118 ------- 公开课/class034/Code02_RandToRand.java | 134 -------- .../Code03_EqualProbabilityRandom.java | 67 ---- .../class034/Code04_EvenTimesOddTimes.java | 52 --- 公开课/class034/Code05_MakeNo.java | 50 --- 公开课/class035/Code01_UglyNumber.java | 62 ---- 公开课/class035/Code02_MakeNo.java | 50 --- 公开课/class035/Code03_CoverMax.java | 131 -------- .../Code01_LongestNoRepeatSubstring.java | 76 ----- .../class036/Code02_CordCoverMaxPoint.java | 88 ----- 公开课/class036/Code03_ColorLeftRight.java | 72 ----- .../Code01_MaxABSBetweenLeftAndRight.java | 72 ----- 公开课/class037/Code02_JumpGameII.java | 23 -- .../class037/Code03_FindHalfMajority.java | 76 ----- 公开课/class038/Code01_SubArrayMaxSum.java | 195 ----------- 公开课/class038/Code02_MaxSumFollowUp.java | 83 ----- 公开课/class038/Code03_MaxSumNoAdjoin.java | 58 ---- 公开课/class038/Code04_MissingNumber.java | 27 -- 公开课/class039/Code01_Water.java | 120 ------- 公开课/class039/Code02_RandToRand.java | 134 -------- .../Code03_EqualProbabilityRandom.java | 67 ---- .../class039/Code04_EvenTimesOddTimes.java | 52 --- 公开课/class039/Code05_KM.java | 144 --------- .../class040/Code01_PalindromeNumber.java | 23 -- .../Code02_MaximumProductSubarray.java | 24 -- 公开课/class040/Code03_CoverMax.java | 135 -------- 公开课/class040/Code04_KM.java | 144 --------- .../Code01_LongestNoRepeatSubstring.java | 76 ----- .../class041/Code02_CordCoverMaxPoint.java | 88 ----- .../Code03_MaxABSBetweenLeftAndRight.java | 72 ----- 公开课/class041/Code04_KM.java | 143 -------- .../Code02_ContainAllCharExactly.java | 114 ------- .../class042/Code03_FindHalfMajority.java | 137 -------- 公开课/class043/Code01_AppleMinBags.java | 69 ---- 公开课/class043/Code02_SplitNumber.java | 49 --- 公开课/class043/Code03_EatGrass.java | 44 --- .../class043/Code04_FindOddTimesNumber.java | 18 -- 公开课/class044/Code01_SubArrayMaxSum.java | 95 ------ 公开课/class044/Code02_MaxSumFollowUp.java | 119 ------- 公开课/class044/Code03_MaxSumNoAdjoin.java | 97 ------ .../class045/Code01_MaxLeftMaxRight.java | 80 ----- 公开课/class045/Code02_RotateImage.java | 52 --- .../class045/Code03_ZigZagPrintMatrix.java | 48 --- 公开课/class045/Code04_MissingNumber.java | 29 -- .../class046/Code01_MergeKSortedLists.java | 52 --- .../Code02_LongestNoRepeatSubstring.java | 97 ------ .../class046/Code03_CordCoverMaxPoint.java | 88 ----- 公开课/class047/Code01_Water.java | 120 ------- 公开课/class047/Code02_RandToRand.java | 137 -------- .../Code03_EqualProbabilityRandom.java | 67 ---- .../class047/Code04_EvenTimesOddTimes.java | 52 --- 公开课/class048/Code01_SubArrayMaxSum.java | 137 -------- 公开课/class048/Code02_MaxSumFollowUp.java | 119 ------- 公开课/class048/Code03_MaxSumNoAdjoin.java | 118 ------- 公开课/class049/Code01_AppleMinBags.java | 114 ------- 公开课/class049/Code02_SplitNumber.java | 48 --- 公开课/class049/Code03_EatGrass.java | 41 --- 公开课/class050/Code01_HowManyTypes.java | 83 ----- .../class050/Code02_CordCoverMaxPoint.java | 88 ----- .../class050/Code03_FindHalfMajority.java | 138 -------- .../class050/Code04_ZigZagPrintMatrix.java | 55 ---- 公开课/class050/Code05_RotateImage.java | 52 --- .../Code01_LongestNoRepeatSubstring.java | 124 ------- 公开课/class051/Code02_CoverMax.java | 204 ------------ .../class052/Code01_EvenTimesOddTimes.java | 75 ----- 公开课/class052/Code02_KM.java | 176 ---------- 公开课/class052/Code03_UglyNumber.java | 63 ---- 公开课/class052/Code04_MakeNo.java | 52 --- .../Code01_BestTimeToBuyAndSellStock.java | 18 -- .../Code02_BestTimeToBuyAndSellStockII.java | 17 - .../Code03_BestTimeToBuyAndSellStockIII.java | 23 -- .../class053/Code04_RabbitsInForest.java | 28 -- 公开课/class053/Code05_LIS.java | 58 ---- .../class053/Code06_EnvelopesProblem.java | 60 ---- .../class054/Code01_FindHalfMajority.java | 104 ------ .../class054/Code02_PalindromeNumber.java | 30 -- 公开课/class054/Code03_Water.java | 120 ------- 公开课/class054/Code04_JumpGameII.java | 24 -- .../Code01_LongestNoRepeatSubstring.java | 26 -- 公开课/class055/Code02_SubArrayMaxSum.java | 22 -- .../Code03_MaximumProductSubarray.java | 40 --- 公开课/class055/Code04_PaperFolding.java | 26 -- 公开课/class056/Code01_MissingNumber.java | 34 -- .../class056/Code02_RabbitsInForest.java | 30 -- 公开课/class056/Code03_LIS.java | 58 ---- .../class056/Code04_EnvelopesProblem.java | 60 ---- 公开课/class057/Code01_MagicStone.java | 49 --- 公开课/class057/Code02_CircleCandy.java | 58 ---- .../Code03_ComputeExpressionValue.java | 58 ---- 公开课/class057/Code04_Ratio01Split.java | 67 ---- .../class058/Code01_MinBoatEvenNumbers.java | 78 ----- .../class058/Code02_MaxKLenSequence.java | 87 ----- 公开课/class058/Code03_StoneGameIV.java | 99 ------ 公开课/class059/Code01_MagicStone.java | 49 --- 公开课/class059/Code02_CircleCandy.java | 58 ---- .../class059/Code03_MinBoatEvenNumbers.java | 78 ----- 公开课/class059/Code04_StringKth.java | 97 ------ .../class059/Code05_SubarraySumEqualsK.java | 34 -- 公开课/class059/Code06_Ratio01Split.java | 68 ---- 公开课/class060/Code01_MinSwapTimes.java | 88 ----- .../class060/Code02_MaxMeetingScore.java | 114 ------- .../class060/Code03_NextPermutation.java | 46 --- .../Code04_SequenceKDifferentKinds.java | 111 ------- 公开课/class061/Code01_HashFunction.java | 51 --- 公开课/class061/Code02_FillGapMinStep.java | 103 ------ 公开课/class061/Code03_Mod3Max.java | 160 --------- .../class062/Code01_MonotonousStack.java | 172 ---------- .../Code02_LargestRectangleInHistogram.java | 58 ---- 公开课/class062/Code03_ValidSequence.java | 113 ------- .../class062/Code04_MaxKLenSequence.java | 92 ------ .../class063/Code01_SumNoPositiveMinCost.java | 138 -------- .../class063/Code02_SplitBuildingBlock.java | 61 ---- 公开课/class064/Code01_LIS.java | 58 ---- .../class064/Code02_EnvelopesProblem.java | 60 ---- 公开课/class064/Code03_MinSwapTimes.java | 95 ------ 公开课/class064/Code04_PoemProblem.java | 149 --------- 公开课/class065/Code01_CoverMax.java | 157 --------- 公开课/class065/Code02_Heaters.java | 114 ------- .../class065/Code03_TrappingRainWater.java | 121 ------- .../class065/Code04_CombinationSumIV.java | 65 ---- .../Code01_BestTimeToBuyAndSellStock.java | 25 -- .../Code02_BestTimeToBuyAndSellStockII.java | 17 - .../Code03_BestTimeToBuyAndSellStockIII.java | 123 ------- .../class066/Code04_SplitArrayLargestSum.java | 47 --- .../class066/Code05_KokoEatingBananas.java | 50 --- 公开课/class067/Code01_IsStepSum.java | 68 ---- .../class067/Code02_KokoEatingBananas.java | 40 --- .../class067/Code03_SplitArrayLargestSum.java | 49 --- .../Code04_MinimumWindowSubstring.java | 53 --- ...ode05_SubarraysWithKDifferentIntegers.java | 66 ---- 公开课/class068/Code01_MagicStone.java | 100 ------ 公开课/class068/Code02_CircleCandy.java | 58 ---- .../class068/Code03_MinBoatEvenNumbers.java | 78 ----- 公开课/class069/Code01_Hash.java | 52 --- 公开课/class069/Code02_BitMap.java | 87 ----- .../class070/Code01_FindTheCelebrity.java | 40 --- .../class070/Code02_AvoidFloodInTheCity.java | 82 ----- 公开课/class070/Code03_BurstBalloons.java | 154 --------- 公开课/class070/SuperWaterKing.java | 50 --- 公开课/class071/Code01_CoverMax.java | 90 ------ 公开课/class071/Code02_Heaters.java | 114 ------- .../class071/Code03_TrappingRainWater.java | 121 ------- .../class071/Code04_ExpressionCompute.java | 57 ---- 公开课/class072/Code01_SplitApples.java | 163 ---------- .../class072/Code02_SplitBuildingBlock.java | 61 ---- .../class072/Code03_BestMeetingPoint.java | 50 --- .../class072/Code04_CombinationSumIV.java | 47 --- 公开课/class073/Code01_CoverMax.java | 155 --------- 公开课/class073/Code02_4KeysKeyboard.java | 38 --- .../Code03_MinContinuousFragment.java | 162 ---------- 公开课/class073/Code04_MaxGap.java | 101 ------ 公开课/class074/Code01_Mod3Max.java | 247 -------------- 公开课/class074/Code02_LetASorted.java | 97 ------ .../class074/Code03_AwayFromBlackHole.java | 122 ------- 公开课/class074/Code04_AllSame.java | 65 ---- .../class075/Code01_BattleshipsInABoard.java | 21 -- ...ode02_ShortestSubarrayWithSumAtLeastK.java | 74 ----- .../Code03_BuyThingsAboutCollocation.java | 103 ------ 公开课/class075/Code04_BrickAll.java | 50 --- 公开课/class076/Code01_SetAll.java | 48 --- 公开课/class076/Code02_4KeysKeyboard.java | 24 -- 公开课/class076/Code03_BrickAll.java | 50 --- .../Code04_InsertDeleteGetRandom.java | 51 --- 公开课/class076/Code05_SplitApples.java | 161 ---------- 公开课/class076/Code06_SplitStrings.java | 11 - ...ode07_ShortestSubarrayWithSumAtLeastK.java | 74 ----- .../class077/Code01_MonotonousStack.java | 178 ---------- .../class077/Code02_AllTimesMinToMax.java | 101 ------ .../Code03_LargestRectangleInHistogram.java | 58 ---- 公开课/class077/Code04_ValidSequence.java | 113 ------- .../class078/Code01_SplitSameNumberWays.java | 36 --- .../Code02_NearBiggerNoSameNeighbour.java | 67 ---- 公开课/class078/Code03_MaxTeamNumber.java | 129 -------- ...de04_MinimumNumberOfDaysToEatNOranges.java | 59 ---- .../class078/Code05_MaxKLenSequence.java | 92 ------ 公开课/class078/Code06_StringCheck.java | 65 ---- ...ode07_ShortestSubarrayWithSumAtLeastK.java | 74 ----- 公开课/class079/Code01_StringCheck.java | 65 ---- .../class079/Code02_NumberOfDivisibleByM.java | 69 ---- 公开课/class079/Code03_MinWaitingTime.java | 95 ------ .../Code04_LongestUncontinuousSet.java | 39 --- 公开课/class079/Code05_CutDouFu.java | 52 --- .../class080/Code01_FinancialProduct.java | 51 --- 公开课/class080/Code02_EatFish.java | 106 ------ .../class080/Code03_BuyGoodsHaveDiscount.java | 89 ----- 公开课/class080/Code04_JumpToTargets.java | 56 ---- 公开课/class081/Code01_ArrangeJob.java | 62 ---- .../class081/Code02_MinTowNumberSumABS.java | 159 --------- .../Code03_HowManyWaysFromBottomToTop.java | 81 ----- 公开课/class082/Code01_JumpToTargets.java | 45 --- .../Code02_ArrangeMeetingPosCancelPre.java | 210 ------------ .../class082/Code03_MaxScoreMoveInBoard.java | 71 ---- .../class082/Code04_FourNumbersMinusOne.java | 58 ---- .../class082/Code05_MaxSumOnReverseArray.java | 105 ------ 公开课/class083/Code01_MaxOneNumbers.java | 114 ------- .../class083/Code02_PerfectPairNumber.java | 52 --- .../class083/Code03_TopMinSubsquenceSum.java | 114 ------- .../class083/Code04_TopMaxSubsquenceSum.java | 124 ------- 公开课/class084/Code01_MinDepth.java | 116 ------- .../class084/Code02_DiameterOfBinarytree.java | 70 ---- .../class084/Code03_AllJobFinishTime.java | 51 --- 公开课/class084/Code04_ClassicDP.java | 56 ---- 公开课/class085/Code01_WhoWin21Balls.java | 100 ------ ...ode02_ShortestSubarrayWithSumAtLeastK.java | 122 ------- .../class086/Code01_TwoObjectMaxValue.java | 225 ------------- .../Code02_ModifyOneNumberModXWays.java | 84 ----- .../class086/Code03_BattleshipsInABoard.java | 21 -- 公开课/class086/Code04_BrickAll.java | 50 --- .../class087/Code01_RedAndWhiteSquares.java | 211 ------------ .../class087/Code02_MaxNumberUnderLimit.java | 203 ------------ 公开课/class087/Code03_NumberOfCannon.java | 104 ------ .../class088/Code01_FourNumbersMinusOne.java | 74 ----- 公开课/class088/Code02_MinWaitingTime.java | 97 ------ ...03_UniqueSubstringsInWraparoundString.java | 34 -- ..._MostStonesRemovedWithSameRowOrColumn.java | 95 ------ 公开课/class089/Code02_ReachingPoints.java | 49 --- ...e03_NumberOfDifferentSubsequencesGCDs.java | 64 ---- 公开课/class090/Code01_LIS.java | 94 ------ .../class090/Code02_MaxAnimalNumber.java | 116 ------- .../class090/Code03_EnvelopesProblem.java | 61 ---- 公开课/class091/Code01_SetAll.java | 57 ---- 公开课/class091/Code02_Heaters.java | 132 -------- .../class091/Code03_TrappingRainWater.java | 116 ------- 公开课/class091/Code04_SplitApples.java | 124 ------- .../class092/Code01_ValidParentheses.java | 102 ------ .../class092/Code02_LongestParentheses.java | 84 ----- .../Code03_CompleteTreeNodeNumber.java | 105 ------ .../class093/Code01_FindDuplicateOnlyOne.java | 117 ------- .../class093/Code02_SellingPiecesOfWood.java | 165 ---------- .../Code01_SortStackUsingRecursive.java | 205 ------------ .../Code02_ReversePolishNotation.java | 101 ------ 公开课/class094/Code03_RightView.java | 97 ------ .../Code01_NumberOfPeopleAwareOfASecret.java | 63 ---- .../class095/Code02_MaxNumberUnderLimit.java | 213 ------------ .../class095/Code03_SwimInRisingWater.java | 155 --------- 公开课/class096/Code01_ParenthesesDye.java | 169 ---------- ...e02_ShortestImpossibleSequenceOfRolls.java | 38 --- .../class096/Code03_SwimInRisingWater.java | 155 --------- ...de04_LongestOneLetterManyNumberString.java | 108 ------- 公开课/class097/Code01_Cakes.java | 116 ------- 公开课/class097/Code02_MinAddToMatch.java | 121 ------- 公开课/class098/Code01_ChangeToSame.java | 115 ------- 公开课/class098/Code02_MinCostMostE.java | 203 ------------ 公开课/class098/Code03_TravelMinFuel.java | 82 ----- .../class099/Code01_MatchsticksToSquare.java | 96 ------ 公开课/class099/Code02_CutOrPoison.java | 122 ------- .../Code03_CorporateFlightBookings.java | 33 -- .../Code01_EvenTimesMaxSubstring.java | 103 ------ .../Code02_MaxLengthSameCharMChanges.java | 124 ------- .../class100/Code03_ExaminationPaperWays.java | 119 ------- .../Code01_SlidingWindowMaxArray.java | 177 ---------- 公开课/class101/Code02_WindPrevent.java | 110 ------- 公开课/class101/Code03_DreamCity.java | 70 ---- 公开课/class102/Code01_SortGame.java | 189 ----------- .../class102/Code02_NLengthMValueLIS3.java | 176 ---------- 公开课/class102/Code03_LIS.java | 55 ---- .../class103/Code01_SoldierFindEnemy.java | 185 ----------- .../Code02_RedPalindromeGoodStrings.java | 93 ------ .../Code01_RedPalindromeGoodStrings.java | 134 -------- .../class104/Code02_MaxSumOnReverseArray.java | 96 ------ .../class104/Code03_ExaminationPaperWays.java | 120 ------- .../class104/Code04_TopMinSubsquenceSum.java | 116 ------- .../Code05_MaxLengthSameCharMChanges.java | 130 -------- .../Code06_EvenTimesMaxSubstring.java | 118 ------- 公开课/class104/Code07_SortGame.java | 189 ----------- .../class105/Code01_EveryQueryUsers.java | 213 ------------ .../Code02_TwoTeamsSortedMinSwap.java | 146 --------- .../class106/Code01_MaximumWidthRamp.java | 50 --- .../class106/Code02_MakeASortedMinSwaps.java | 169 ---------- 公开课/class107/Code01_ScoreAllMatrix.java | 75 ----- .../class107/Code02_HappyLimitLessGap.java | 124 ------- .../class107/Code03_RobotAndClothes.java | 304 ------------------ .../class108/Code01_CordCoverMaxPoint.java | 92 ------ ...ngestSumSubArrayLengthInPositiveArray.java | 94 ------ .../Code03_LongestSumSubArrayLength.java | 104 ------ .../Code04_SlidingWindowMaxArray.java | 145 --------- 公开课/class108/Code05_WindPrevent.java | 149 --------- ...de06_RemoveMostKContinuousSameLongest.java | 105 ------ .../Code07_RangesHasDominateNumber.java | 88 ----- .../class108/Code08_LastStoneWeightII.java | 40 --- 公开课/class108/Code09_ScoreAllMatrix.java | 78 ----- .../class109/Code01_ThreeEqualParts.java | 80 ----- .../Code02_LongestSumSubArrayLength.java | 114 ------- .../Code03_EvenTimesMaxSubstring.java | 103 ------ ...de04_RemoveMostKContinuousSameLongest.java | 113 ------- .../class110/Code01_MoveCityGetMoney.java | 236 -------------- .../class110/Code02_EntryRoomGetMoney.java | 199 ------------ ...ode01_ComplementaryPairsInStringArray.java | 145 --------- .../class111/Code02_CouplesHoldingHands.java | 76 ----- ...01_SortArrayByMovingItemsToEmptySpace.java | 106 ------ .../class112/Code02_ZigZagConversion.java | 37 --- 公开课/class113/Code01_TravelMinFuel.java | 79 ----- .../class113/Code02_MakingALargeIsland.java | 124 ------- .../Code03_MinimumCostToHireKWorkers.java | 54 ---- .../Code01_KthMissingPositiveNumber.java | 26 -- .../class114/Code02_ZigZagConversion.java | 40 --- .../class114/Code03_MaximumWidthRamp.java | 42 --- .../class114/Code04_ThreeEqualParts.java | 80 ----- .../class114/Code05_CouplesHoldingHands.java | 74 ----- .../Code06_AbsToArrayFinalLength.java | 130 -------- .../Code07_HeightAfterSubtreeRemoval.java | 75 ----- .../Code08_AsFarFromLandAsPossible.java | 84 ----- 公开课/class114/Code09_OrderlyQueue.java | 181 ----------- .../class115/Code01_StampingTheGrid.java | 69 ---- .../Code02_SumOfSubSequenceWidths.java | 32 -- .../class115/Code03_SumOfDistancesInTree.java | 54 ---- ...de01_MinimumNumberOfDaysToEatNOranges.java | 81 ----- .../class116/Code02_HowManyObtuseAngles.java | 44 --- 公开课/class116/Code03_CherryPickup.java | 84 ----- .../class117/Code01_BoatsToSavePeople.java | 34 -- .../Code02_MaximumProductSubarray.java | 28 -- 公开课/class117/Code03_RotateImage.java | 30 -- ...allestRangeCoveringElementsfromKLists.java | 75 ----- 公开课/class117/Code05_CandyProblem.java | 74 ----- .../class117/Code06_MinWindowLength.java | 44 --- .../Code07_RangesHasDominateNumber.java | 107 ------ .../class118/Code01_ExpressionCompute.java | 68 ---- .../Code02_ComputeExpressionValue.java | 58 ---- .../Code03_RegularExpressionMatch.java | 65 ---- 415 files changed, 36818 deletions(-) delete mode 100644 公开课/class001/Code01_PosArrayToBST.java delete mode 100644 公开课/class001/Code02_ContainAllCharExactly.java delete mode 100644 公开课/class002/Code01_MakeNo.java delete mode 100644 公开课/class002/Code02_KthMinPair.java delete mode 100644 公开课/class003/Code01_LongestNoRepeatSubstring.java delete mode 100644 公开课/class003/Code02_HowManyTypes.java delete mode 100644 公开课/class003/Code03_SubsquenceMaxModM.java delete mode 100644 公开课/class004/Code01_QueryHobby.java delete mode 100644 公开课/class004/Code02_MergeRecord.java delete mode 100644 公开课/class005/Code01_RotateString.java delete mode 100644 公开课/class005/Code02_RestoreWays.java delete mode 100644 公开课/class006/Code01_Power2Diffs.java delete mode 100644 公开课/class006/Code02_Water.java delete mode 100644 公开课/class007/Code01_RandToRand.java delete mode 100644 公开课/class007/Code02_EqualProbabilityRandom.java delete mode 100644 公开课/class007/Code03_FindHalfMajority.java delete mode 100644 公开课/class007/Code04_FindKMajor.java delete mode 100644 公开课/class008/Code01_JumpGameII.java delete mode 100644 公开课/class008/Code02_LongestConsecutiveSequence.java delete mode 100644 公开课/class009/Code01_SetMatrixZeroes.java delete mode 100644 公开课/class009/Code02_SearchA2DMatrixII.java delete mode 100644 公开课/class009/Code03_LongestOnes.java delete mode 100644 公开课/class010/Code01_SwapWithoutTmp.java delete mode 100644 公开课/class010/Code02_GetMax.java delete mode 100644 公开课/class010/Code03_EvenTimesOddTimes.java delete mode 100644 公开课/class011/Code01_CopyListWithRandom.java delete mode 100644 公开课/class011/Code02_JumpMinTimes.java delete mode 100644 公开课/class012/Code01_MoneyProblem.java delete mode 100644 公开课/class013/Code01_PalindromeNumber.java delete mode 100644 公开课/class013/Code03_LongestNoRepeatSubstring.java delete mode 100644 公开课/class014/Code01_CoverMax.java delete mode 100644 公开课/class014/Code02_MaxDistance.java delete mode 100644 公开课/class015/Code01_CordCoverMaxPoint.java delete mode 100644 公开课/class015/Code02_ColorLeftRight.java delete mode 100644 公开课/class015/Code03_MaxABSBetweenLeftAndRight.java delete mode 100644 公开课/class015/Code04_TrappingRainWater.java delete mode 100644 公开课/class016/Code01_RandToRand.java delete mode 100644 公开课/class016/Code02_EqualProbabilityRandom.java delete mode 100644 公开课/class016/Code03_FindHalfMajority.java delete mode 100644 公开课/class016/Code04_FindKMajor.java delete mode 100644 公开课/class017/Code01_SubArrayMaxSum.java delete mode 100644 公开课/class017/Code02_SubMatrixMaxSum.java delete mode 100644 公开课/class018/Code01_SqrtX.java delete mode 100644 公开课/class018/Code02_PowXN.java delete mode 100644 公开课/class018/Code03_ContainerWithMostWater.java delete mode 100644 公开课/class019/Code01_RotateImage.java delete mode 100644 公开课/class019/Code02_ZigZagPrintMatrix.java delete mode 100644 公开课/class019/Code03_PrintStar.java delete mode 100644 公开课/class020/Code01_RotateString.java delete mode 100644 公开课/class020/Code02_HowManyTypes.java delete mode 100644 公开课/class020/Code03_LongestNoRepeatSubstring.java delete mode 100644 公开课/class020/Code04_CoverMax.java delete mode 100644 公开课/class020/Code05_MakeNo.java delete mode 100644 公开课/class021/Code01_SwapWithoutTmp.java delete mode 100644 公开课/class021/Code02_GetMax.java delete mode 100644 公开课/class021/Code03_EvenTimesOddTimes.java delete mode 100644 公开课/class022/Code01_MinSwapStep.java delete mode 100644 公开课/class022/Code02_CountFiles.java delete mode 100644 公开课/class022/Code03_Cola.java delete mode 100644 公开课/class023/Code01_FindHalfMajority.java delete mode 100644 公开课/class024/Code01_RotateImage.java delete mode 100644 公开课/class024/Code02_ZigZagPrintMatrix.java delete mode 100644 公开课/class024/Code03_PrintStar.java delete mode 100644 公开课/class025/Code01_Water.java delete mode 100644 公开课/class025/Code02_RandToRand.java delete mode 100644 公开课/class025/Code03_EqualProbabilityRandom.java delete mode 100644 公开课/class026/Code01_SubArrayMaxSum.java delete mode 100644 公开课/class026/Code02_SubArrayMaxSumFollowUp.java delete mode 100644 公开课/class026/Code03_SubMatrixMaxSum.java delete mode 100644 公开课/class027/Code01_MinSwapStep.java delete mode 100644 公开课/class027/Code02_CountFiles.java delete mode 100644 公开课/class027/Code03_Cola.java delete mode 100644 公开课/class028/Code01_RotateString.java delete mode 100644 公开课/class028/Code02_HowManyTypes.java delete mode 100644 公开课/class028/Code03_LongestNoRepeatSubstring.java delete mode 100644 公开课/class028/Code04_CoverMax.java delete mode 100644 公开课/class029/Code01_AppleMinBags.java delete mode 100644 公开课/class029/Code02_EatGrass.java delete mode 100644 公开课/class029/Code03_MaxLeftMaxRight.java delete mode 100644 公开课/class030/Code01_IsPalindrome.java delete mode 100644 公开课/class030/Code02_MySqrt.java delete mode 100644 公开课/class030/Code03_UglyNumber.java delete mode 100644 公开课/class030/Code04_EnterLoopNode.java delete mode 100644 公开课/class031/Code01_SwapWithoutTmp.java delete mode 100644 公开课/class031/Code02_AddMinus.java delete mode 100644 公开课/class031/Code03_GetMax.java delete mode 100644 公开课/class031/Code04_MissingNumber.java delete mode 100644 公开课/class032/Code01_BinaryTreeLevelOrderTraversal.java delete mode 100644 公开课/class032/Code01_BinaryTreeLevelOrderTraversalII.java delete mode 100644 公开课/class032/Code02_ConstructBinaryTreeFromPreorderAndInorderTraversal.java delete mode 100644 公开课/class032/Code03_PaperFolding.java delete mode 100644 公开课/class032/Code04_DiameterOfBinaryTree.java delete mode 100644 公开课/class033/Code01_FindHalfMajority.java delete mode 100644 公开课/class033/Code02_RotateImage.java delete mode 100644 公开课/class033/Code03_ZigZagPrintMatrix.java delete mode 100644 公开课/class033/Code04_PrintStar.java delete mode 100644 公开课/class034/Code01_Water.java delete mode 100644 公开课/class034/Code02_RandToRand.java delete mode 100644 公开课/class034/Code03_EqualProbabilityRandom.java delete mode 100644 公开课/class034/Code04_EvenTimesOddTimes.java delete mode 100644 公开课/class034/Code05_MakeNo.java delete mode 100644 公开课/class035/Code01_UglyNumber.java delete mode 100644 公开课/class035/Code02_MakeNo.java delete mode 100644 公开课/class035/Code03_CoverMax.java delete mode 100644 公开课/class036/Code01_LongestNoRepeatSubstring.java delete mode 100644 公开课/class036/Code02_CordCoverMaxPoint.java delete mode 100644 公开课/class036/Code03_ColorLeftRight.java delete mode 100644 公开课/class037/Code01_MaxABSBetweenLeftAndRight.java delete mode 100644 公开课/class037/Code02_JumpGameII.java delete mode 100644 公开课/class037/Code03_FindHalfMajority.java delete mode 100644 公开课/class038/Code01_SubArrayMaxSum.java delete mode 100644 公开课/class038/Code02_MaxSumFollowUp.java delete mode 100644 公开课/class038/Code03_MaxSumNoAdjoin.java delete mode 100644 公开课/class038/Code04_MissingNumber.java delete mode 100644 公开课/class039/Code01_Water.java delete mode 100644 公开课/class039/Code02_RandToRand.java delete mode 100644 公开课/class039/Code03_EqualProbabilityRandom.java delete mode 100644 公开课/class039/Code04_EvenTimesOddTimes.java delete mode 100644 公开课/class039/Code05_KM.java delete mode 100644 公开课/class040/Code01_PalindromeNumber.java delete mode 100644 公开课/class040/Code02_MaximumProductSubarray.java delete mode 100644 公开课/class040/Code03_CoverMax.java delete mode 100644 公开课/class040/Code04_KM.java delete mode 100644 公开课/class041/Code01_LongestNoRepeatSubstring.java delete mode 100644 公开课/class041/Code02_CordCoverMaxPoint.java delete mode 100644 公开课/class041/Code03_MaxABSBetweenLeftAndRight.java delete mode 100644 公开课/class041/Code04_KM.java delete mode 100644 公开课/class042/Code02_ContainAllCharExactly.java delete mode 100644 公开课/class042/Code03_FindHalfMajority.java delete mode 100644 公开课/class043/Code01_AppleMinBags.java delete mode 100644 公开课/class043/Code02_SplitNumber.java delete mode 100644 公开课/class043/Code03_EatGrass.java delete mode 100644 公开课/class043/Code04_FindOddTimesNumber.java delete mode 100644 公开课/class044/Code01_SubArrayMaxSum.java delete mode 100644 公开课/class044/Code02_MaxSumFollowUp.java delete mode 100644 公开课/class044/Code03_MaxSumNoAdjoin.java delete mode 100644 公开课/class045/Code01_MaxLeftMaxRight.java delete mode 100644 公开课/class045/Code02_RotateImage.java delete mode 100644 公开课/class045/Code03_ZigZagPrintMatrix.java delete mode 100644 公开课/class045/Code04_MissingNumber.java delete mode 100644 公开课/class046/Code01_MergeKSortedLists.java delete mode 100644 公开课/class046/Code02_LongestNoRepeatSubstring.java delete mode 100644 公开课/class046/Code03_CordCoverMaxPoint.java delete mode 100644 公开课/class047/Code01_Water.java delete mode 100644 公开课/class047/Code02_RandToRand.java delete mode 100644 公开课/class047/Code03_EqualProbabilityRandom.java delete mode 100644 公开课/class047/Code04_EvenTimesOddTimes.java delete mode 100644 公开课/class048/Code01_SubArrayMaxSum.java delete mode 100644 公开课/class048/Code02_MaxSumFollowUp.java delete mode 100644 公开课/class048/Code03_MaxSumNoAdjoin.java delete mode 100644 公开课/class049/Code01_AppleMinBags.java delete mode 100644 公开课/class049/Code02_SplitNumber.java delete mode 100644 公开课/class049/Code03_EatGrass.java delete mode 100644 公开课/class050/Code01_HowManyTypes.java delete mode 100644 公开课/class050/Code02_CordCoverMaxPoint.java delete mode 100644 公开课/class050/Code03_FindHalfMajority.java delete mode 100644 公开课/class050/Code04_ZigZagPrintMatrix.java delete mode 100644 公开课/class050/Code05_RotateImage.java delete mode 100644 公开课/class051/Code01_LongestNoRepeatSubstring.java delete mode 100644 公开课/class051/Code02_CoverMax.java delete mode 100644 公开课/class052/Code01_EvenTimesOddTimes.java delete mode 100644 公开课/class052/Code02_KM.java delete mode 100644 公开课/class052/Code03_UglyNumber.java delete mode 100644 公开课/class052/Code04_MakeNo.java delete mode 100644 公开课/class053/Code01_BestTimeToBuyAndSellStock.java delete mode 100644 公开课/class053/Code02_BestTimeToBuyAndSellStockII.java delete mode 100644 公开课/class053/Code03_BestTimeToBuyAndSellStockIII.java delete mode 100644 公开课/class053/Code04_RabbitsInForest.java delete mode 100644 公开课/class053/Code05_LIS.java delete mode 100644 公开课/class053/Code06_EnvelopesProblem.java delete mode 100644 公开课/class054/Code01_FindHalfMajority.java delete mode 100644 公开课/class054/Code02_PalindromeNumber.java delete mode 100644 公开课/class054/Code03_Water.java delete mode 100644 公开课/class054/Code04_JumpGameII.java delete mode 100644 公开课/class055/Code01_LongestNoRepeatSubstring.java delete mode 100644 公开课/class055/Code02_SubArrayMaxSum.java delete mode 100644 公开课/class055/Code03_MaximumProductSubarray.java delete mode 100644 公开课/class055/Code04_PaperFolding.java delete mode 100644 公开课/class056/Code01_MissingNumber.java delete mode 100644 公开课/class056/Code02_RabbitsInForest.java delete mode 100644 公开课/class056/Code03_LIS.java delete mode 100644 公开课/class056/Code04_EnvelopesProblem.java delete mode 100644 公开课/class057/Code01_MagicStone.java delete mode 100644 公开课/class057/Code02_CircleCandy.java delete mode 100644 公开课/class057/Code03_ComputeExpressionValue.java delete mode 100644 公开课/class057/Code04_Ratio01Split.java delete mode 100644 公开课/class058/Code01_MinBoatEvenNumbers.java delete mode 100644 公开课/class058/Code02_MaxKLenSequence.java delete mode 100644 公开课/class058/Code03_StoneGameIV.java delete mode 100644 公开课/class059/Code01_MagicStone.java delete mode 100644 公开课/class059/Code02_CircleCandy.java delete mode 100644 公开课/class059/Code03_MinBoatEvenNumbers.java delete mode 100644 公开课/class059/Code04_StringKth.java delete mode 100644 公开课/class059/Code05_SubarraySumEqualsK.java delete mode 100644 公开课/class059/Code06_Ratio01Split.java delete mode 100644 公开课/class060/Code01_MinSwapTimes.java delete mode 100644 公开课/class060/Code02_MaxMeetingScore.java delete mode 100644 公开课/class060/Code03_NextPermutation.java delete mode 100644 公开课/class060/Code04_SequenceKDifferentKinds.java delete mode 100644 公开课/class061/Code01_HashFunction.java delete mode 100644 公开课/class061/Code02_FillGapMinStep.java delete mode 100644 公开课/class061/Code03_Mod3Max.java delete mode 100644 公开课/class062/Code01_MonotonousStack.java delete mode 100644 公开课/class062/Code02_LargestRectangleInHistogram.java delete mode 100644 公开课/class062/Code03_ValidSequence.java delete mode 100644 公开课/class062/Code04_MaxKLenSequence.java delete mode 100644 公开课/class063/Code01_SumNoPositiveMinCost.java delete mode 100644 公开课/class063/Code02_SplitBuildingBlock.java delete mode 100644 公开课/class064/Code01_LIS.java delete mode 100644 公开课/class064/Code02_EnvelopesProblem.java delete mode 100644 公开课/class064/Code03_MinSwapTimes.java delete mode 100644 公开课/class064/Code04_PoemProblem.java delete mode 100644 公开课/class065/Code01_CoverMax.java delete mode 100644 公开课/class065/Code02_Heaters.java delete mode 100644 公开课/class065/Code03_TrappingRainWater.java delete mode 100644 公开课/class065/Code04_CombinationSumIV.java delete mode 100644 公开课/class066/Code01_BestTimeToBuyAndSellStock.java delete mode 100644 公开课/class066/Code02_BestTimeToBuyAndSellStockII.java delete mode 100644 公开课/class066/Code03_BestTimeToBuyAndSellStockIII.java delete mode 100644 公开课/class066/Code04_SplitArrayLargestSum.java delete mode 100644 公开课/class066/Code05_KokoEatingBananas.java delete mode 100644 公开课/class067/Code01_IsStepSum.java delete mode 100644 公开课/class067/Code02_KokoEatingBananas.java delete mode 100644 公开课/class067/Code03_SplitArrayLargestSum.java delete mode 100644 公开课/class067/Code04_MinimumWindowSubstring.java delete mode 100644 公开课/class067/Code05_SubarraysWithKDifferentIntegers.java delete mode 100644 公开课/class068/Code01_MagicStone.java delete mode 100644 公开课/class068/Code02_CircleCandy.java delete mode 100644 公开课/class068/Code03_MinBoatEvenNumbers.java delete mode 100644 公开课/class069/Code01_Hash.java delete mode 100644 公开课/class069/Code02_BitMap.java delete mode 100644 公开课/class070/Code01_FindTheCelebrity.java delete mode 100644 公开课/class070/Code02_AvoidFloodInTheCity.java delete mode 100644 公开课/class070/Code03_BurstBalloons.java delete mode 100644 公开课/class070/SuperWaterKing.java delete mode 100644 公开课/class071/Code01_CoverMax.java delete mode 100644 公开课/class071/Code02_Heaters.java delete mode 100644 公开课/class071/Code03_TrappingRainWater.java delete mode 100644 公开课/class071/Code04_ExpressionCompute.java delete mode 100644 公开课/class072/Code01_SplitApples.java delete mode 100644 公开课/class072/Code02_SplitBuildingBlock.java delete mode 100644 公开课/class072/Code03_BestMeetingPoint.java delete mode 100644 公开课/class072/Code04_CombinationSumIV.java delete mode 100644 公开课/class073/Code01_CoverMax.java delete mode 100644 公开课/class073/Code02_4KeysKeyboard.java delete mode 100644 公开课/class073/Code03_MinContinuousFragment.java delete mode 100644 公开课/class073/Code04_MaxGap.java delete mode 100644 公开课/class074/Code01_Mod3Max.java delete mode 100644 公开课/class074/Code02_LetASorted.java delete mode 100644 公开课/class074/Code03_AwayFromBlackHole.java delete mode 100644 公开课/class074/Code04_AllSame.java delete mode 100644 公开课/class075/Code01_BattleshipsInABoard.java delete mode 100644 公开课/class075/Code02_ShortestSubarrayWithSumAtLeastK.java delete mode 100644 公开课/class075/Code03_BuyThingsAboutCollocation.java delete mode 100644 公开课/class075/Code04_BrickAll.java delete mode 100644 公开课/class076/Code01_SetAll.java delete mode 100644 公开课/class076/Code02_4KeysKeyboard.java delete mode 100644 公开课/class076/Code03_BrickAll.java delete mode 100644 公开课/class076/Code04_InsertDeleteGetRandom.java delete mode 100644 公开课/class076/Code05_SplitApples.java delete mode 100644 公开课/class076/Code06_SplitStrings.java delete mode 100644 公开课/class076/Code07_ShortestSubarrayWithSumAtLeastK.java delete mode 100644 公开课/class077/Code01_MonotonousStack.java delete mode 100644 公开课/class077/Code02_AllTimesMinToMax.java delete mode 100644 公开课/class077/Code03_LargestRectangleInHistogram.java delete mode 100644 公开课/class077/Code04_ValidSequence.java delete mode 100644 公开课/class078/Code01_SplitSameNumberWays.java delete mode 100644 公开课/class078/Code02_NearBiggerNoSameNeighbour.java delete mode 100644 公开课/class078/Code03_MaxTeamNumber.java delete mode 100644 公开课/class078/Code04_MinimumNumberOfDaysToEatNOranges.java delete mode 100644 公开课/class078/Code05_MaxKLenSequence.java delete mode 100644 公开课/class078/Code06_StringCheck.java delete mode 100644 公开课/class078/Code07_ShortestSubarrayWithSumAtLeastK.java delete mode 100644 公开课/class079/Code01_StringCheck.java delete mode 100644 公开课/class079/Code02_NumberOfDivisibleByM.java delete mode 100644 公开课/class079/Code03_MinWaitingTime.java delete mode 100644 公开课/class079/Code04_LongestUncontinuousSet.java delete mode 100644 公开课/class079/Code05_CutDouFu.java delete mode 100644 公开课/class080/Code01_FinancialProduct.java delete mode 100644 公开课/class080/Code02_EatFish.java delete mode 100644 公开课/class080/Code03_BuyGoodsHaveDiscount.java delete mode 100644 公开课/class080/Code04_JumpToTargets.java delete mode 100644 公开课/class081/Code01_ArrangeJob.java delete mode 100644 公开课/class081/Code02_MinTowNumberSumABS.java delete mode 100644 公开课/class081/Code03_HowManyWaysFromBottomToTop.java delete mode 100644 公开课/class082/Code01_JumpToTargets.java delete mode 100644 公开课/class082/Code02_ArrangeMeetingPosCancelPre.java delete mode 100644 公开课/class082/Code03_MaxScoreMoveInBoard.java delete mode 100644 公开课/class082/Code04_FourNumbersMinusOne.java delete mode 100644 公开课/class082/Code05_MaxSumOnReverseArray.java delete mode 100644 公开课/class083/Code01_MaxOneNumbers.java delete mode 100644 公开课/class083/Code02_PerfectPairNumber.java delete mode 100644 公开课/class083/Code03_TopMinSubsquenceSum.java delete mode 100644 公开课/class083/Code04_TopMaxSubsquenceSum.java delete mode 100644 公开课/class084/Code01_MinDepth.java delete mode 100644 公开课/class084/Code02_DiameterOfBinarytree.java delete mode 100644 公开课/class084/Code03_AllJobFinishTime.java delete mode 100644 公开课/class084/Code04_ClassicDP.java delete mode 100644 公开课/class085/Code01_WhoWin21Balls.java delete mode 100644 公开课/class085/Code02_ShortestSubarrayWithSumAtLeastK.java delete mode 100644 公开课/class086/Code01_TwoObjectMaxValue.java delete mode 100644 公开课/class086/Code02_ModifyOneNumberModXWays.java delete mode 100644 公开课/class086/Code03_BattleshipsInABoard.java delete mode 100644 公开课/class086/Code04_BrickAll.java delete mode 100644 公开课/class087/Code01_RedAndWhiteSquares.java delete mode 100644 公开课/class087/Code02_MaxNumberUnderLimit.java delete mode 100644 公开课/class087/Code03_NumberOfCannon.java delete mode 100644 公开课/class088/Code01_FourNumbersMinusOne.java delete mode 100644 公开课/class088/Code02_MinWaitingTime.java delete mode 100644 公开课/class088/Code03_UniqueSubstringsInWraparoundString.java delete mode 100644 公开课/class089/Code01_MostStonesRemovedWithSameRowOrColumn.java delete mode 100644 公开课/class089/Code02_ReachingPoints.java delete mode 100644 公开课/class089/Code03_NumberOfDifferentSubsequencesGCDs.java delete mode 100644 公开课/class090/Code01_LIS.java delete mode 100644 公开课/class090/Code02_MaxAnimalNumber.java delete mode 100644 公开课/class090/Code03_EnvelopesProblem.java delete mode 100644 公开课/class091/Code01_SetAll.java delete mode 100644 公开课/class091/Code02_Heaters.java delete mode 100644 公开课/class091/Code03_TrappingRainWater.java delete mode 100644 公开课/class091/Code04_SplitApples.java delete mode 100644 公开课/class092/Code01_ValidParentheses.java delete mode 100644 公开课/class092/Code02_LongestParentheses.java delete mode 100644 公开课/class092/Code03_CompleteTreeNodeNumber.java delete mode 100644 公开课/class093/Code01_FindDuplicateOnlyOne.java delete mode 100644 公开课/class093/Code02_SellingPiecesOfWood.java delete mode 100644 公开课/class094/Code01_SortStackUsingRecursive.java delete mode 100644 公开课/class094/Code02_ReversePolishNotation.java delete mode 100644 公开课/class094/Code03_RightView.java delete mode 100644 公开课/class095/Code01_NumberOfPeopleAwareOfASecret.java delete mode 100644 公开课/class095/Code02_MaxNumberUnderLimit.java delete mode 100644 公开课/class095/Code03_SwimInRisingWater.java delete mode 100644 公开课/class096/Code01_ParenthesesDye.java delete mode 100644 公开课/class096/Code02_ShortestImpossibleSequenceOfRolls.java delete mode 100644 公开课/class096/Code03_SwimInRisingWater.java delete mode 100644 公开课/class096/Code04_LongestOneLetterManyNumberString.java delete mode 100644 公开课/class097/Code01_Cakes.java delete mode 100644 公开课/class097/Code02_MinAddToMatch.java delete mode 100644 公开课/class098/Code01_ChangeToSame.java delete mode 100644 公开课/class098/Code02_MinCostMostE.java delete mode 100644 公开课/class098/Code03_TravelMinFuel.java delete mode 100644 公开课/class099/Code01_MatchsticksToSquare.java delete mode 100644 公开课/class099/Code02_CutOrPoison.java delete mode 100644 公开课/class099/Code03_CorporateFlightBookings.java delete mode 100644 公开课/class100/Code01_EvenTimesMaxSubstring.java delete mode 100644 公开课/class100/Code02_MaxLengthSameCharMChanges.java delete mode 100644 公开课/class100/Code03_ExaminationPaperWays.java delete mode 100644 公开课/class101/Code01_SlidingWindowMaxArray.java delete mode 100644 公开课/class101/Code02_WindPrevent.java delete mode 100644 公开课/class101/Code03_DreamCity.java delete mode 100644 公开课/class102/Code01_SortGame.java delete mode 100644 公开课/class102/Code02_NLengthMValueLIS3.java delete mode 100644 公开课/class102/Code03_LIS.java delete mode 100644 公开课/class103/Code01_SoldierFindEnemy.java delete mode 100644 公开课/class103/Code02_RedPalindromeGoodStrings.java delete mode 100644 公开课/class104/Code01_RedPalindromeGoodStrings.java delete mode 100644 公开课/class104/Code02_MaxSumOnReverseArray.java delete mode 100644 公开课/class104/Code03_ExaminationPaperWays.java delete mode 100644 公开课/class104/Code04_TopMinSubsquenceSum.java delete mode 100644 公开课/class104/Code05_MaxLengthSameCharMChanges.java delete mode 100644 公开课/class104/Code06_EvenTimesMaxSubstring.java delete mode 100644 公开课/class104/Code07_SortGame.java delete mode 100644 公开课/class105/Code01_EveryQueryUsers.java delete mode 100644 公开课/class105/Code02_TwoTeamsSortedMinSwap.java delete mode 100644 公开课/class106/Code01_MaximumWidthRamp.java delete mode 100644 公开课/class106/Code02_MakeASortedMinSwaps.java delete mode 100644 公开课/class107/Code01_ScoreAllMatrix.java delete mode 100644 公开课/class107/Code02_HappyLimitLessGap.java delete mode 100644 公开课/class107/Code03_RobotAndClothes.java delete mode 100644 公开课/class108/Code01_CordCoverMaxPoint.java delete mode 100644 公开课/class108/Code02_LongestSumSubArrayLengthInPositiveArray.java delete mode 100644 公开课/class108/Code03_LongestSumSubArrayLength.java delete mode 100644 公开课/class108/Code04_SlidingWindowMaxArray.java delete mode 100644 公开课/class108/Code05_WindPrevent.java delete mode 100644 公开课/class108/Code06_RemoveMostKContinuousSameLongest.java delete mode 100644 公开课/class108/Code07_RangesHasDominateNumber.java delete mode 100644 公开课/class108/Code08_LastStoneWeightII.java delete mode 100644 公开课/class108/Code09_ScoreAllMatrix.java delete mode 100644 公开课/class109/Code01_ThreeEqualParts.java delete mode 100644 公开课/class109/Code02_LongestSumSubArrayLength.java delete mode 100644 公开课/class109/Code03_EvenTimesMaxSubstring.java delete mode 100644 公开课/class109/Code04_RemoveMostKContinuousSameLongest.java delete mode 100644 公开课/class110/Code01_MoveCityGetMoney.java delete mode 100644 公开课/class110/Code02_EntryRoomGetMoney.java delete mode 100644 公开课/class111/Code01_ComplementaryPairsInStringArray.java delete mode 100644 公开课/class111/Code02_CouplesHoldingHands.java delete mode 100644 公开课/class112/Code01_SortArrayByMovingItemsToEmptySpace.java delete mode 100644 公开课/class112/Code02_ZigZagConversion.java delete mode 100644 公开课/class113/Code01_TravelMinFuel.java delete mode 100644 公开课/class113/Code02_MakingALargeIsland.java delete mode 100644 公开课/class113/Code03_MinimumCostToHireKWorkers.java delete mode 100644 公开课/class114/Code01_KthMissingPositiveNumber.java delete mode 100644 公开课/class114/Code02_ZigZagConversion.java delete mode 100644 公开课/class114/Code03_MaximumWidthRamp.java delete mode 100644 公开课/class114/Code04_ThreeEqualParts.java delete mode 100644 公开课/class114/Code05_CouplesHoldingHands.java delete mode 100644 公开课/class114/Code06_AbsToArrayFinalLength.java delete mode 100644 公开课/class114/Code07_HeightAfterSubtreeRemoval.java delete mode 100644 公开课/class114/Code08_AsFarFromLandAsPossible.java delete mode 100644 公开课/class114/Code09_OrderlyQueue.java delete mode 100644 公开课/class115/Code01_StampingTheGrid.java delete mode 100644 公开课/class115/Code02_SumOfSubSequenceWidths.java delete mode 100644 公开课/class115/Code03_SumOfDistancesInTree.java delete mode 100644 公开课/class116/Code01_MinimumNumberOfDaysToEatNOranges.java delete mode 100644 公开课/class116/Code02_HowManyObtuseAngles.java delete mode 100644 公开课/class116/Code03_CherryPickup.java delete mode 100644 公开课/class117/Code01_BoatsToSavePeople.java delete mode 100644 公开课/class117/Code02_MaximumProductSubarray.java delete mode 100644 公开课/class117/Code03_RotateImage.java delete mode 100644 公开课/class117/Code04_SmallestRangeCoveringElementsfromKLists.java delete mode 100644 公开课/class117/Code05_CandyProblem.java delete mode 100644 公开课/class117/Code06_MinWindowLength.java delete mode 100644 公开课/class117/Code07_RangesHasDominateNumber.java delete mode 100644 公开课/class118/Code01_ExpressionCompute.java delete mode 100644 公开课/class118/Code02_ComputeExpressionValue.java delete mode 100644 公开课/class118/Code03_RegularExpressionMatch.java diff --git a/公开课/class001/Code01_PosArrayToBST.java b/公开课/class001/Code01_PosArrayToBST.java deleted file mode 100644 index f873fc0..0000000 --- a/公开课/class001/Code01_PosArrayToBST.java +++ /dev/null @@ -1,224 +0,0 @@ -package class001; - -import java.util.ArrayList; - -public class Code01_PosArrayToBST { - - public static class Node { - public int value; - public Node left; - public Node right; - - public Node(int v) { - value = v; - } - } - - public static Node posArrayToBST1(int[] posArr) { - // 0~N-1 - return process1(posArr, 0, posArr.length - 1); - } - - // 目前,我们在使用posArr[L..R]这些数字,来建树 - // 建出的每一个节点都连好,然后把整棵树的头节点返回 - public static Node process1(int[] posArr, int L, int R) { - if (L > R) { - return null; - } - Node head = new Node(posArr[R]); - if (L == R) { - return head; - } - int M = L - 1; - for (int i = L; i < R; i++) { // i -> L..R-1 - if (posArr[i] < posArr[R]) { - M = i; - } - } - head.left = process1(posArr, L, M); - head.right = process1(posArr, M + 1, R - 1); - return head; - } - - - public static Node process3(int[] posArr, int L, int R) { - Node head = new Node(posArr[R]); - if (L == R) { - return head; - } - int M = -1; - for (int i = L; i < R; i++) { // i -> L..R-1 - if (posArr[i] < posArr[R]) { - M = i; - } - } - // > - if(M==-1) { - head.right = process3(posArr, L, R - 1); - }else if(M == R-1) { - head.left = process3(posArr, L, R - 1); - }else { - head.left = process3(posArr, L, M); - head.right = process3(posArr, M + 1, R - 1); - } - return head; - } - - - - - - - - - - - public static Node posArrayToBST2(int[] posArr) { - return process2(posArr, 0, posArr.length - 1); - } - - public static Node process2(int[] posArr, int L, int R) { - if (L > R) { - return null; - } - Node head = new Node(posArr[R]); - if (L == R) { - return head; - } - - int M = L - 1; - int left = L; - int right = R - 1; - while (left <= right) { - int mid = left + ((right - left) >> 1); - if (posArr[mid] < posArr[R]) { - M = mid; - left = mid + 1; - } else { - right = mid - 1; - } - } - head.left = process2(posArr, L, M); - head.right = process2(posArr, M + 1, R - 1); - return head; - } - - // for test - public static int[] getBstPosArray(Node head) { - ArrayList posList = new ArrayList<>(); - pos(head, posList); - int[] ans = new int[posList.size()]; - for (int i = 0; i < ans.length; i++) { - ans[i] = posList.get(i); - } - return ans; - } - - // for test - public static void pos(Node head, ArrayList posList) { - if (head != null) { - pos(head.left, posList); - pos(head.right, posList); - posList.add(head.value); - } - } - - // for test [0~1000] - // N - public static Node generateRandomBST(int min, int max, int N) { - if (min > max) { - return null; - } - return createTree(min, max, 1, N); - } - - // for test - public static Node createTree(int min, int max, int level, int N) { - if (min > max || level > N) { - return null; - } - Node head = new Node(random(min, max)); - head.left = createTree(min, head.value - 1, level + 1, N); - head.right = createTree(head.value + 1, max, level + 1, N); - return head; - } - - // for test - public static int random(int min, int max) { - return min + (int) (Math.random() * (max - min + 1)); - } - - // for test - public static boolean isSameValueStructure(Node head1, Node head2) { - if (head1 == null && head2 != null) { - return false; - } - if (head1 != null && head2 == null) { - return false; - } - if (head1 == null && head2 == null) { - return true; - } - return head1.value == head2.value && isSameValueStructure(head1.left, head2.left) - && isSameValueStructure(head1.right, head2.right); - } - - // for test - public static void printTree(Node head) { - System.out.println("Binary Tree:"); - printInOrder(head, 0, "H", 17); - System.out.println(); - } - - // for test - public static void printInOrder(Node head, int height, String to, int len) { - if (head == null) { - return; - } - printInOrder(head.right, height + 1, "v", len); - String val = to + head.value + to; - int lenM = val.length(); - int lenL = (len - lenM) / 2; - int lenR = len - lenM - lenL; - val = getSpace(lenL) + val + getSpace(lenR); - System.out.println(getSpace(height * len) + val); - printInOrder(head.left, height + 1, "^", len); - } - - // for test - public static String getSpace(int num) { - String space = " "; - StringBuffer buf = new StringBuffer(""); - for (int i = 0; i < num; i++) { - buf.append(space); - } - return buf.toString(); - } - - // for test - public static void main(String[] args) { - int min = 0; - int max = 12; - int level = 4; - Node head = generateRandomBST(min, max, level); - int[] pos = getBstPosArray(head); - printTree(head); - printTree(posArrayToBST1(pos)); - printTree(posArrayToBST2(pos)); - System.out.println(isSameValueStructure(head, posArrayToBST1(pos))); - System.out.println(isSameValueStructure(head, posArrayToBST2(pos))); - - int testTimes = 5000000; - System.out.println("test begin, time time : " + testTimes); - for (int i = 0; i < testTimes; i++) { - head = generateRandomBST(min, max, level); - pos = getBstPosArray(head); - if (!isSameValueStructure(head, posArrayToBST1(pos)) || !isSameValueStructure(head, posArrayToBST2(pos))) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - - } - -} diff --git a/公开课/class001/Code02_ContainAllCharExactly.java b/公开课/class001/Code02_ContainAllCharExactly.java deleted file mode 100644 index 1e67b59..0000000 --- a/公开课/class001/Code02_ContainAllCharExactly.java +++ /dev/null @@ -1,115 +0,0 @@ -package class001; - -import java.util.Arrays; - -public class Code02_ContainAllCharExactly { - - public static int containExactly1(String s, String a) { - if (s == null || a == null || s.length() < a.length()) { - return -1; - } - char[] aim = a.toCharArray(); - Arrays.sort(aim); - String aimSort = String.valueOf(aim); - for (int L = 0; L < s.length(); L++) { - for (int R = L; R < s.length(); R++) { - char[] cur = s.substring(L, R + 1).toCharArray(); - Arrays.sort(cur); - String curSort = String.valueOf(cur); - if (curSort.equals(aimSort)) { - return L; - } - } - } - return -1; - } - - public static int containExactly2(String s, String a) { - if (s == null || a == null || s.length() < a.length()) { - return -1; - } - char[] str = s.toCharArray(); - char[] aim = a.toCharArray(); - for (int L = 0; L <= str.length - aim.length; L++) { - if (isCountEqual(str, L, aim)) { - return L; - } - } - return -1; - } - - public static boolean isCountEqual(char[] str, int L, char[] aim) { - int[] count = new int[256]; - for (int i = 0; i < aim.length; i++) { - count[aim[i]]++; - } - for (int i = 0; i < aim.length; i++) { - if (count[str[L + i]]-- == 0) { - return false; - } - } - return true; - } - - public static int containExactly3(String s, String a) { - if (s == null || a == null || s.length() < a.length()) { - return -1; - } - char[] aim = a.toCharArray(); - int[] count = new int[256]; - for (int i = 0; i < aim.length; i++) { - count[aim[i]]++; - } - int M = aim.length; - char[] str = s.toCharArray(); - int inValidTimes = 0; - int R = 0; - for (; R < M; R++) { - if (count[str[R]]-- <= 0) { - inValidTimes++; - } - } - for (; R < str.length; R++) { - if (inValidTimes == 0) { - return R - M; - } - if (count[str[R]]-- <= 0) { - inValidTimes++; - } - if (count[str[R - M]]++ < 0) { - inValidTimes--; - } - } - return inValidTimes == 0 ? R - M : -1; - } - - // for test - public static String getRandomString(int possibilities, int maxSize) { - char[] ans = new char[(int) (Math.random() * maxSize) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (char) ((int) (Math.random() * possibilities) + 'a'); - } - return String.valueOf(ans); - } - - public static void main(String[] args) { - int possibilities = 5; - int strMaxSize = 20; - int aimMaxSize = 5; - int testTimes = 500000; - System.out.println("test begin, test time : " + testTimes); - for (int i = 0; i < testTimes; i++) { - String str = getRandomString(possibilities, strMaxSize); - String aim = getRandomString(possibilities, aimMaxSize); - int ans1 = containExactly1(str, aim); - int ans2 = containExactly2(str, aim); - int ans3 = containExactly3(str, aim); - if (ans1 != ans2 || ans2 != ans3) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - - } - -} diff --git a/公开课/class002/Code01_MakeNo.java b/公开课/class002/Code01_MakeNo.java deleted file mode 100644 index 82f769c..0000000 --- a/公开课/class002/Code01_MakeNo.java +++ /dev/null @@ -1,50 +0,0 @@ -package class002; - -public class Code01_MakeNo { - - public static int[] makeNo(int size) { - if (size == 1) { - return new int[] { 1 }; - } - int halfSize = (size + 1) / 2; - int[] base = makeNo(halfSize); - int[] ans = new int[size]; - int index = 0; - for (; index < halfSize; index++) { - ans[index] = base[index] * 2 + 1; - } - for (int i = 0; index < size; index++, i++) { - ans[index] = base[i] * 2; - } - return ans; - } - - // 检验函数 - public static boolean isValid(int[] arr) { - int N = arr.length; - for (int i = 0; i < N; i++) { - for (int k = i + 1; k < N; k++) { - for (int j = k + 1; j < N; j++) { - if (arr[i] + arr[j] == 2 * arr[k]) { - return false; - } - } - } - } - return true; - } - - public static void main(String[] args) { - System.out.println("test begin"); - for (int N = 1; N < 1000; N++) { - int[] arr = makeNo(N); - if (!isValid(arr)) { - System.out.println("Oops!"); - } - } - System.out.println("test end"); - System.out.println(isValid(makeNo(1042))); - System.out.println(isValid(makeNo(2981))); - } - -} diff --git a/公开课/class002/Code02_KthMinPair.java b/公开课/class002/Code02_KthMinPair.java deleted file mode 100644 index 56655c0..0000000 --- a/公开课/class002/Code02_KthMinPair.java +++ /dev/null @@ -1,214 +0,0 @@ -package class002; - -import java.util.Arrays; -import java.util.Comparator; - -public class Code02_KthMinPair { - - public static class Pair { - public int x; - public int y; - - Pair(int x, int y) { - this.x = x; - this.y = y; - } - } - - public static class PairComparator implements Comparator { - - @Override - public int compare(Pair arg0, Pair arg1) { - return arg0.x != arg1.x ? arg0.x - arg1.x : arg0.y - arg1.y; - } - - } - - // O(N^2 * log (N^2))的复杂度,你肯定过不了 - // 返回的int[] 长度是2,{3,1} int[2] = [3,1] - public static int[] kthMinPair1(int[] arr, int k) { - int N = arr.length; - if (k > N * N) { - return null; - } - Pair[] pairs = new Pair[N * N]; - int index = 0; - for (int i = 0; i < N; i++) { - for (int j = 0; j < N; j++) { - pairs[index++] = new Pair(arr[i], arr[j]); - } - } - Arrays.sort(pairs, new PairComparator()); - return new int[] { pairs[k - 1].x, pairs[k - 1].y }; - } - - // O(N*logN)的复杂度,你肯定过了 - public static int[] kthMinPair2(int[] arr, int k) { - int N = arr.length; - if (k > N * N) { - return null; - } - // O(N*logN) - Arrays.sort(arr); - // 第K小的数值对,第一维数字,是什么 是arr中 - int fristNum = arr[(k - 1) / N]; - int lessFristNumSize = 0;// 数出比fristNum小的数有几个 - int fristNumSize = 0; // 数出==fristNum的数有几个 - // <= fristNum - for (int i = 0; i < N && arr[i] <= fristNum; i++) { - if (arr[i] < fristNum) { - lessFristNumSize++; - } else { - fristNumSize++; - } - } - int rest = k - (lessFristNumSize * N); - return new int[] { fristNum, arr[(rest - 1) / fristNumSize] }; - } - - // O(N)的复杂度,你肯定蒙了 - public static int[] kthMinPair3(int[] arr, int k) { - int N = arr.length; - if (k > N * N) { - return null; - } - // 在无序数组中,找到第K小的数,返回值 - // 第K小,以1作为开始 - int fristNum = getMinKthByBFPRT(arr, ((k - 1) / N) + 1); - int lessFristNumSize = 0; - int fristNumSize = 0; - for (int i = 0; i < N; i++) { - if (arr[i] < fristNum) { - lessFristNumSize++; - } - if (arr[i] == fristNum) { - fristNumSize++; - } - } - int rest = k - (lessFristNumSize * N); - return new int[] { fristNum, getMinKthByBFPRT(arr, ((rest - 1) / fristNumSize) + 1) }; - } - - // 利用bfprt算法求解,是O(N)的过程 - // 在arr上,找到第K小的数,并返回。K范围是[1,N],范围不是[0,N-1] - // 对你来讲,它可能永远不会被你想起,但确实本题最优解的算法原型 - public static int getMinKthByBFPRT(int[] arr, int K) { - return select(arr, 0, arr.length - 1, K - 1); - } - - public static int select(int[] arr, int begin, int end, int i) { - if (begin == end) { - return arr[begin]; - } - int pivot = medianOfMedians(arr, begin, end); - int[] pivotRange = partition(arr, begin, end, pivot); - if (i >= pivotRange[0] && i <= pivotRange[1]) { - return arr[i]; - } else if (i < pivotRange[0]) { - return select(arr, begin, pivotRange[0] - 1, i); - } else { - return select(arr, pivotRange[1] + 1, end, i); - } - } - - public static int medianOfMedians(int[] arr, int begin, int end) { - int num = end - begin + 1; - int offset = num % 5 == 0 ? 0 : 1; - int[] mArr = new int[num / 5 + offset]; - for (int i = 0; i < mArr.length; i++) { - int beginI = begin + i * 5; - int endI = beginI + 4; - mArr[i] = getMedian(arr, beginI, Math.min(end, endI)); - } - return select(mArr, 0, mArr.length - 1, mArr.length / 2); - } - - public static int[] partition(int[] arr, int begin, int end, int pivotValue) { - int small = begin - 1; - int cur = begin; - int big = end + 1; - while (cur != big) { - if (arr[cur] < pivotValue) { - swap(arr, ++small, cur++); - } else if (arr[cur] > pivotValue) { - swap(arr, cur, --big); - } else { - cur++; - } - } - int[] range = new int[2]; - range[0] = small + 1; - range[1] = big - 1; - return range; - } - - public static int getMedian(int[] arr, int begin, int end) { - insertionSort(arr, begin, end); - int sum = end + begin; - int mid = (sum / 2) + (sum % 2); - return arr[mid]; - } - - public static void insertionSort(int[] arr, int begin, int end) { - for (int i = begin + 1; i != end + 1; i++) { - for (int j = i; j != begin; j--) { - if (arr[j - 1] > arr[j]) { - swap(arr, j - 1, j); - } else { - break; - } - } - } - } - - public static void swap(int[] arr, int index1, int index2) { - int tmp = arr[index1]; - arr[index1] = arr[index2]; - arr[index2] = tmp; - } - - // 为了测试,生成值也随机,长度也随机的随机数组 - public static int[] getRandomArray(int max, int len) { - int[] arr = new int[(int) (Math.random() * len) + 1]; - for (int i = 0; i < arr.length; i++) { - arr[i] = (int) (Math.random() * max) - (int) (Math.random() * max); - } - return arr; - } - - // 为了测试 - public static int[] copyArray(int[] arr) { - if (arr == null) { - return null; - } - int[] res = new int[arr.length]; - for (int i = 0; i < arr.length; i++) { - res[i] = arr[i]; - } - return res; - } - - // 随机测试了百万组,保证三种方法都是对的 - public static void main(String[] args) { - int max = 100; - int len = 30; - int testTimes = 100000; - System.out.println("test bagin, time times : " + testTimes); - for (int i = 0; i < testTimes; i++) { - int[] arr = getRandomArray(max, len); - int[] arr1 = copyArray(arr); - int[] arr2 = copyArray(arr); - int[] arr3 = copyArray(arr); - int N = arr.length * arr.length; - int k = (int) (Math.random() * N) + 1; - int[] ans1 = kthMinPair1(arr1, k); - int[] ans2 = kthMinPair2(arr2, k); - int[] ans3 = kthMinPair3(arr3, k); - if (ans1[0] != ans2[0] || ans2[0] != ans3[0] || ans1[1] != ans2[1] || ans2[1] != ans3[1]) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - } - -} diff --git a/公开课/class003/Code01_LongestNoRepeatSubstring.java b/公开课/class003/Code01_LongestNoRepeatSubstring.java deleted file mode 100644 index 979609b..0000000 --- a/公开课/class003/Code01_LongestNoRepeatSubstring.java +++ /dev/null @@ -1,77 +0,0 @@ -package class003; - -public class Code01_LongestNoRepeatSubstring { - - /* - * 给定一个只由小写字母(a~z)组成的字符串str, 返回其中最长无重复字符的子串长度 - * - */ - - public static int lnrs1(String s) { - if (s == null || s.length() == 0) { - return 0; - } - char[] str = s.toCharArray(); - int N = str.length; - int max = 0; - for (int i = 0; i < N; i++) { - boolean[] set = new boolean[26]; - for (int j = i; j < N; j++) { - if (set[str[j] - 'a']) { - break; - } - set[str[j] - 'a'] = true; - max = Math.max(max, j - i + 1); - } - } - return max; - } - - public static int lnrs2(String s) { - if (s == null || s.length() == 0) { - return 0; - } - char[] str = s.toCharArray(); - int N = str.length; - int[] last = new int[26]; - for (int i = 0; i < 26; i++) { - last[i] = -1; - } - last[str[0] - 'a'] = 0; - int max = 1; - int preMaxLen = 1; - for (int i = 1; i < N; i++) { - preMaxLen = Math.min(i - last[str[i] - 'a'], preMaxLen + 1); - max = Math.max(max, preMaxLen); - last[str[i] - 'a'] = i; - } - return max; - } - - // for test - public static String getRandomString(int possibilities, int maxSize) { - char[] ans = new char[(int) (Math.random() * maxSize) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (char) ((int) (Math.random() * possibilities) + 'a'); - } - return String.valueOf(ans); - } - - public static void main(String[] args) { - int possibilities = 26; - int strMaxSize = 100; - int testTimes = 1000000; - System.out.println("test begin, test time : " + testTimes); - for (int i = 0; i < testTimes; i++) { - String str = getRandomString(possibilities, strMaxSize); - int ans1 = lnrs1(str); - int ans2 = lnrs2(str); - if (ans1 != ans2) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - - } - -} diff --git a/公开课/class003/Code02_HowManyTypes.java b/公开课/class003/Code02_HowManyTypes.java deleted file mode 100644 index 884e8eb..0000000 --- a/公开课/class003/Code02_HowManyTypes.java +++ /dev/null @@ -1,82 +0,0 @@ -package class003; - -import java.util.HashSet; - -public class Code02_HowManyTypes { - - /* - * 只由小写字母(a~z)组成的一批字符串,都放在字符类型的数组String[] arr中, - * 如果其中某两个字符串,所含有的字符种类完全一样,就将两个字符串算作一类 比如:baacba和bac就算作一类 - * 虽然长度不一样,但是所含字符的种类完全一样(a、b、c) 返回arr中有多少类? - * - */ - - public static int types1(String[] arr) { - HashSet types = new HashSet<>(); - for (String str : arr) { - char[] chs = str.toCharArray(); - boolean[] map = new boolean[26]; - for (int i = 0; i < chs.length; i++) { - map[chs[i] - 'a'] = true; - } - String key = ""; - for (int i = 0; i < 26; i++) { - if (map[i]) { - key += String.valueOf((char) (i + 'a')); - } - } - types.add(key); - } - return types.size(); - } - - public static int types2(String[] arr) { - HashSet types = new HashSet<>(); - for (String str : arr) { - char[] chs = str.toCharArray(); - int key = 0; - for(int i = 0 ; i < chs.length;i++) { - key |= (1 << (chs[i] - 'a')); - } - types.add(key); - } - return types.size(); - } - - // for test - public static String[] getRandomStringArray(int possibilities, int strMaxSize, int arrMaxSize) { - String[] ans = new String[(int) (Math.random() * arrMaxSize) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = getRandomString(possibilities, strMaxSize); - } - return ans; - } - - // for test - public static String getRandomString(int possibilities, int strMaxSize) { - char[] ans = new char[(int) (Math.random() * strMaxSize) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (char) ((int) (Math.random() * possibilities) + 'a'); - } - return String.valueOf(ans); - } - - public static void main(String[] args) { - int possibilities = 5; - int strMaxSize = 10; - int arrMaxSize = 100; - int testTimes = 500000; - System.out.println("test begin, test time : " + testTimes); - for (int i = 0; i < testTimes; i++) { - String[] arr = getRandomStringArray(possibilities, strMaxSize, arrMaxSize); - int ans1 = types1(arr); - int ans2 = types2(arr); - if (ans1 != ans2) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - - } - -} diff --git a/公开课/class003/Code03_SubsquenceMaxModM.java b/公开课/class003/Code03_SubsquenceMaxModM.java deleted file mode 100644 index 3c5bed5..0000000 --- a/公开课/class003/Code03_SubsquenceMaxModM.java +++ /dev/null @@ -1,144 +0,0 @@ -package class003; - -import java.util.HashSet; -import java.util.TreeSet; - -public class Code03_SubsquenceMaxModM { - - /* - * 给定一个非负数组arr,和一个正数m。 返回arr的所有子序列中累加和%m之后的最大值。 - * - */ - - public static int max1(int[] arr, int m) { - HashSet set = new HashSet<>(); - process(arr, 0, 0, set); - int max = 0; - for (Integer sum : set) { - max = Math.max(max, sum % m); - } - return max; - } - - public static void process(int[] arr, int index, int sum, HashSet set) { - if (index == arr.length) { - set.add(sum); - } else { - process(arr, index + 1, sum, set); - process(arr, index + 1, sum + arr[index], set); - } - } - - public static int max2(int[] arr, int m) { - int sum = 0; - int N = arr.length; - for (int i = 0; i < N; i++) { - sum += arr[i]; - } - boolean[][] dp = new boolean[N][sum + 1]; - for (int i = 0; i < N; i++) { - dp[i][0] = true; - } - dp[0][arr[0]] = true; - for (int i = 1; i < N; i++) { - for (int j = 1; j <= sum; j++) { - dp[i][j] = dp[i - 1][j]; - if (j - arr[i] >= 0) { - dp[i][j] = dp[i][j] | dp[i - 1][j - arr[i]]; - } - } - } - int ans = 0; - for (int j = 0; j <= sum; j++) { - if (dp[N - 1][j]) { - ans = Math.max(ans, j % m); - } - } - return ans; - - } - - public static int max3(int[] arr, int m) { - int N = arr.length; - boolean[][] dp = new boolean[N][m]; - for (int i = 0; i < N; i++) { - dp[i][0] = true; - } - dp[0][arr[0] % m] = true; - for (int i = 1; i < N; i++) { - for (int j = 1; j < m; j++) { - dp[i][j] = dp[i - 1][j]; - int cur = arr[i] % m; - if (j - cur >= 0) { - dp[i][j] = dp[i][j] | dp[i - 1][j - cur]; - } - if (m + j - cur < m) { - dp[i][j] = dp[i][j] | dp[i - 1][m + j - cur]; - } - } - } - int ans = 0; - for (int i = 0; i < m; i++) { - if (dp[N - 1][i]) { - ans = i; - } - } - return ans; - } - - // 如果arr的累加和很大,m也很大 - // 但是arr的长度相对不大 - public static int max4(int[] arr, int m) { - if (arr.length == 1) { - return arr[0] % m; - } - int mid = (arr.length - 1) / 2; - TreeSet sortSet1 = new TreeSet<>(); - process4(arr, 0, 0, mid, m, sortSet1); - TreeSet sortSet2 = new TreeSet<>(); - process4(arr, mid + 1, 0, arr.length - 1, m, sortSet2); - int ans = 0; - for (Integer left : sortSet1) { - ans = Math.max(ans, left + sortSet2.floor(m - 1 - left)); - } - return ans; - } - - public static void process4(int[] arr, int index, int sum, int end, int m, TreeSet sortSet) { - if (index == end + 1) { - sortSet.add(sum % m); - } else { - process4(arr, index + 1, sum, end, m, sortSet); - process4(arr, index + 1, sum + arr[index], end, m, sortSet); - } - } - - public static int[] generateRandomArray(int len, int value) { - int[] ans = new int[(int) (Math.random() * len) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * value); - } - return ans; - } - - public static void main(String[] args) { - int len = 10; - int value = 100; - int m = 76; - int testTime = 500000; - System.out.println("test begin"); - for (int i = 0; i < testTime; i++) { - int[] arr = generateRandomArray(len, value); - int ans1 = max1(arr, m); - int ans2 = max2(arr, m); - int ans3 = max3(arr, m); - int ans4 = max4(arr, m); - if (ans1 != ans2 || ans2 != ans3 || ans3 != ans4) { - System.out.print("Oops!"); - } - } - System.out.println("test finish!"); - - } - -} diff --git a/公开课/class004/Code01_QueryHobby.java b/公开课/class004/Code01_QueryHobby.java deleted file mode 100644 index 076e0bc..0000000 --- a/公开课/class004/Code01_QueryHobby.java +++ /dev/null @@ -1,115 +0,0 @@ -package class004; - -import java.util.ArrayList; -import java.util.HashMap; - -public class Code01_QueryHobby { - - /* - * 今日头条原题 - * - * 数组为{3, 2, 2, 3, 1},查询为(0, 3, 2)。意思是在数组里下标0~3这个范围上,有几个2?返回2。 - * 假设给你一个数组arr,对这个数组的查询非常频繁,请返回所有查询的结果 - * - */ - - public static class QueryBox1 { - private int[] arr; - - public QueryBox1(int[] array) { - arr = new int[array.length]; - for (int i = 0; i < arr.length; i++) { - arr[i] = array[i]; - } - } - - public int query(int L, int R, int v) { - int ans = 0; - for (; L <= R; L++) { - if (arr[L] == v) { - ans++; - } - } - return ans; - } - } - - public static class QueryBox2 { - private HashMap> map; - - public QueryBox2(int[] arr) { - map = new HashMap<>(); - for (int i = 0; i < arr.length; i++) { - if (!map.containsKey(arr[i])) { - map.put(arr[i], new ArrayList<>()); - } - map.get(arr[i]).add(i); - } - } - - public int query(int L, int R, int value) { - if (!map.containsKey(value)) { - return 0; - } - ArrayList indexArr = map.get(value); - // 查询 < L 的下标有几个 - int a = countLess(indexArr, L); - // 查询 < R+1 的下标有几个 - int b = countLess(indexArr, R + 1); - return b - a; - } - - // 在有序数组arr中,用二分的方法数出 arr, int limit) { - int L = 0; - int R = arr.size() - 1; - int mostRight = -1; - while (L <= R) { - int mid = L + ((R - L) >> 1); - if (arr.get(mid) < limit) { - mostRight = mid; - L = mid + 1; - } else { - R = mid - 1; - } - } - return mostRight + 1; - } - - } - - public static int[] generateRandomArray(int len, int value) { - int[] ans = new int[(int) (Math.random() * len) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * value) + 1; - } - return ans; - } - - public static void main(String[] args) { - int len = 300; - int value = 20; - int testTimes = 1000; - int queryTimes = 1000; - System.out.println("test begin"); - for (int i = 0; i < testTimes; i++) { - int[] arr = generateRandomArray(len, value); - int N = arr.length; - QueryBox1 box1 = new QueryBox1(arr); - QueryBox2 box2 = new QueryBox2(arr); - for (int j = 0; j < queryTimes; j++) { - int a = (int) (Math.random() * N); - int b = (int) (Math.random() * N); - int L = Math.min(a, b); - int R = Math.max(a, b); - int v = (int) (Math.random() * value) + 1; - if (box1.query(L, R, v) != box2.query(L, R, v)) { - System.out.println("Oops!"); - } - } - } - System.out.println("test end"); - } - -} diff --git a/公开课/class004/Code02_MergeRecord.java b/公开课/class004/Code02_MergeRecord.java deleted file mode 100644 index fbd3e0f..0000000 --- a/公开课/class004/Code02_MergeRecord.java +++ /dev/null @@ -1,216 +0,0 @@ -package class004; - -public class Code02_MergeRecord { - - /* - * 腾讯原题 - * - * 给定整数power,给定一个数组arr,给定一个数组reverse。含义如下: - * arr的长度一定是2的power次方,reverse中的每个值一定都在0~power范围。 - * 例如power = 2, arr = {3, 1, 4, 2},reverse = {0, 1, 0, 2} - * 任何一个在前的数字可以和任何一个在后的数组,构成一对数。可能是升序关系、相等关系或者降序关系。 - * 比如arr开始时有如下的降序对:(3,1)、(3,2)、(4,2),一共3个。 - * 接下来根据reverse对arr进行调整: - * reverse[0] = 0, 表示在arr中,划分每1(2的0次方)个数一组,然后每个小组内部逆序,那么arr变成 - * [3,1,4,2],此时有3个逆序对。 - * reverse[1] = 1, 表示在arr中,划分每2(2的1次方)个数一组,然后每个小组内部逆序,那么arr变成 - * [1,3,2,4],此时有1个逆序对 - * reverse[2] = 0, 表示在arr中,划分每1(2的0次方)个数一组,然后每个小组内部逆序,那么arr变成 - * [1,3,2,4],此时有1个逆序对。 - * reverse[3] = 2, 表示在arr中,划分每4(2的2次方)个数一组,然后每个小组内部逆序,那么arr变成 - * [4,2,3,1],此时有4个逆序对。 - * 所以返回[3,1,1,4],表示每次调整之后的逆序对数量。 - * - * 输入数据状况: - * power的范围[0,20] - * arr长度范围[1,10的7次方] - * reverse长度范围[1,10的6次方] - * - * */ - - public static int[] reversePair1(int[] originArr, int[] reverseArr, int power) { - int[] ans = new int[reverseArr.length]; - for (int i = 0; i < reverseArr.length; i++) { - reverseArray(originArr, 1 << (reverseArr[i])); - ans[i] = countReversePair(originArr); - } - return ans; - } - - public static void reverseArray(int[] originArr, int teamSize) { - if (teamSize < 2) { - return; - } - for (int i = 0; i < originArr.length; i += teamSize) { - reversePart(originArr, i, i + teamSize - 1); - } - } - - public static void reversePart(int[] arr, int L, int R) { - while (L < R) { - int tmp = arr[L]; - arr[L++] = arr[R]; - arr[R--] = tmp; - } - } - - public static int countReversePair(int[] originArr) { - int ans = 0; - for (int i = 0; i < originArr.length; i++) { - for (int j = i + 1; j < originArr.length; j++) { - if (originArr[i] > originArr[j]) { - ans++; - } - } - } - return ans; - } - - public static int[] reversePair2(int[] originArr, int[] reverseArr, int power) { - int[] reverse = copyArray(originArr); - reversePart(reverse, 0, reverse.length - 1); - int[] recordDown = new int[power + 1]; - int[] recordUp = new int[power + 1]; - process(originArr, 0, originArr.length - 1, power, recordDown); - process(reverse, 0, reverse.length - 1, power, recordUp); - int[] ans = new int[reverseArr.length]; - for (int i = 0; i < reverseArr.length; i++) { - int curPower = reverseArr[i]; - for (int p = 1; p <= curPower; p++) { - int tmp = recordDown[p]; - recordDown[p] = recordUp[p]; - recordUp[p] = tmp; - } - for (int p = 1; p <= power; p++) { - ans[i] += recordDown[p]; - } - } - return ans; - } - - public static void process(int[] originArr, int L, int R, int power, int[] record) { - if (L == R) { - return; - } - int mid = L + ((R - L) >> 1); - process(originArr, L, mid, power - 1, record); - process(originArr, mid + 1, R, power - 1, record); - record[power] += merge(originArr, L, mid, R); - } - - public static int merge(int[] arr, int L, int m, int r) { - int[] help = new int[r - L + 1]; - int i = 0; - int p1 = L; - int p2 = m + 1; - int ans = 0; - while (p1 <= m && p2 <= r) { - ans += arr[p1] > arr[p2] ? (m - p1 + 1) : 0; - help[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++]; - } - while (p1 <= m) { - help[i++] = arr[p1++]; - } - while (p2 <= r) { - help[i++] = arr[p2++]; - } - for (i = 0; i < help.length; i++) { - arr[L + i] = help[i]; - } - return ans; - } - - // for test - public static int[] generateRandomOriginArray(int power, int value) { - int[] ans = new int[1 << power]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * value); - } - return ans; - } - - // for test - public static int[] generateRandomReverseArray(int len, int power) { - int[] ans = new int[len]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * (power + 1)); - } - return ans; - } - - // for test - public static void printArray(int[] arr) { - System.out.println("arr size : " + arr.length); - for (int i = 0; i < arr.length; i++) { - System.out.print(arr[i] + " "); - } - System.out.println(); - } - - // for test - public static int[] copyArray(int[] arr) { - if (arr == null) { - return null; - } - int[] res = new int[arr.length]; - for (int i = 0; i < arr.length; i++) { - res[i] = arr[i]; - } - return res; - } - - // for test - public static boolean isEqual(int[] arr1, int[] arr2) { - if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) { - return false; - } - if (arr1 == null && arr2 == null) { - return true; - } - if (arr1.length != arr2.length) { - return false; - } - for (int i = 0; i < arr1.length; i++) { - if (arr1[i] != arr2[i]) { - return false; - } - } - return true; - } - - public static void main(String[] args) { - int powerMax = 8; - int msizeMax = 10; - int value = 30; - int testTime = 50000; - System.out.println("test begin"); - for (int i = 0; i < testTime; i++) { - int power = (int) (Math.random() * powerMax) + 1; - int msize = (int) (Math.random() * msizeMax) + 1; - int[] originArr = generateRandomOriginArray(power, value); - int[] originArr1 = copyArray(originArr); - int[] originArr2 = copyArray(originArr); - int[] reverseArr = generateRandomReverseArray(msize, power); - int[] reverseArr1 = copyArray(reverseArr); - int[] reverseArr2 = copyArray(reverseArr); - int[] ans1 = reversePair1(originArr1, reverseArr1, power); - int[] ans2 = reversePair2(originArr2, reverseArr2, power); - if (!isEqual(ans1, ans2)) { - System.out.println("Oops!"); - } - } - System.out.println("test finish!"); - - powerMax = 20; - msizeMax = 1000000; - value = 1000; - int[] originArr = generateRandomOriginArray(powerMax, value); - int[] reverseArr = generateRandomReverseArray(msizeMax, powerMax); - // int[] ans1 = reversePair1(originArr1, reverseArr1, powerMax); - long start = System.currentTimeMillis(); - reversePair2(originArr, reverseArr, powerMax); - long end = System.currentTimeMillis(); - System.out.println("run time : " + (end - start) + " ms"); - } - -} diff --git a/公开课/class005/Code01_RotateString.java b/公开课/class005/Code01_RotateString.java deleted file mode 100644 index e3979e7..0000000 --- a/公开课/class005/Code01_RotateString.java +++ /dev/null @@ -1,93 +0,0 @@ -package class005; - -public class Code01_RotateString { - - public static String rotate1(String s, int leftSize) { - if (leftSize <= 0 || leftSize >= s.length()) { - return s; - } - return process1(s.toCharArray(), 0, leftSize - 1, s.length() - 1); - } - - public static String process1(char[] str, int L, int M, int R) { - reverse(str, L, M); - reverse(str, M + 1, R); - reverse(str, L, R); - return String.valueOf(str); - } - - public static void reverse(char[] str, int L, int R) { - while (L < R) { - char tmp = str[L]; - str[L++] = str[R]; - str[R--] = tmp; - } - } - - public static String rotate2(String s, int leftSize) { - if (leftSize <= 0 || leftSize >= s.length()) { - return s; - } - char[] str = s.toCharArray(); - int L = 0; - int R = str.length - 1; - int lpart = leftSize; - int rpart = str.length - leftSize; - int same = Math.min(lpart, rpart); - int diff = lpart - rpart; - exchange(str, L, R, same); - while (diff != 0) { - if (diff > 0) { - L += same; - lpart = diff; - } else { - R -= same; - rpart = -diff; - } - same = Math.min(lpart, rpart); - diff = lpart - rpart; - exchange(str, L, R, same); - } - return String.valueOf(str); - } - - public static void exchange(char[] chas, int start, int end, int size) { - int i = end - size + 1; - char tmp = 0; - while (size-- != 0) { - tmp = chas[start]; - chas[start] = chas[i]; - chas[i] = tmp; - start++; - i++; - } - } - - // for test - public static String getRandomString(int possibilities, int strMaxSize) { - char[] ans = new char[(int) (Math.random() * strMaxSize) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (char) ((int) (Math.random() * possibilities) + 'a'); - } - return String.valueOf(ans); - } - - public static void main(String[] args) { - int possibilities = 5; - int strMaxSize = 10; - int testTimes = 5000000; - System.out.println("test begin, test time : " + testTimes); - for (int i = 0; i < testTimes; i++) { - String str = getRandomString(possibilities, strMaxSize); - int leftSize = (int) (Math.random() * (str.length() + 1)); - String ans1 = rotate1(str, leftSize); - String ans2 = rotate2(str, leftSize); - if (!ans1.equals(ans2)) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - - } - -} diff --git a/公开课/class005/Code02_RestoreWays.java b/公开课/class005/Code02_RestoreWays.java deleted file mode 100644 index e1766ef..0000000 --- a/公开课/class005/Code02_RestoreWays.java +++ /dev/null @@ -1,237 +0,0 @@ -package class005; - -public class Code02_RestoreWays { - - /* - * 整型数组arr长度为n(3 <= n <= 10^4),最初每个数字是<=200的正数且满足如下条件: 1. arr[0] <= arr[1] 2. - * arr[n-1] <= arr[n-2] 3. arr[i] <= max(arr[i-1], arr[i+1]) - * 但是在arr有些数字丢失了,比如k位置的数字之前是正数,丢失之后k位置的数字为0。 请你根据上述条件, 计算可能有多少种不同的arr可以满足以上条件。 - * 比如 [6,0,9] 只有还原成 [6,9,9]满足全部三个条件,所以返回1种。 - * - */ - - public static int ways0(int[] arr) { - return process0(arr, 0); - } - - public static int process0(int[] arr, int index) { - if (index == arr.length) { - return isValid(arr) ? 1 : 0; - } else { - if (arr[index] != 0) { - return process0(arr, index + 1); - } else { - int ways = 0; - for (int v = 1; v < 201; v++) { - arr[index] = v; - ways += process0(arr, index + 1); - } - arr[index] = 0; - return ways; - } - } - } - - public static boolean isValid(int[] arr) { - if (arr[0] > arr[1]) { - return false; - } - if (arr[arr.length - 1] > arr[arr.length - 2]) { - return false; - } - for (int i = 1; i < arr.length - 1; i++) { - if (arr[i] > Math.max(arr[i - 1], arr[i + 1])) { - return false; - } - } - return true; - } - - public static int ways1(int[] arr) { - int N = arr.length; - if (arr[N - 1] != 0) { - return process1(arr, N - 1, arr[N - 1], 2); - } else { - int ways = 0; - for (int v = 1; v < 201; v++) { - ways += process1(arr, N - 1, v, 2); - } - return ways; - } - } - - // 如果index位置的数字变成了v, - // 并且arr[index]和arr[index+1]的关系为s, - // s==0,代表arr[index] < arr[index+1] - // s==1,代表arr[index] = arr[index+1] - // s==2,代表arr[index] > arr[index+1] - // 返回有多少种转化方式? - public static int process1(int[] arr, int i, int v, int s) { - if (i == 0) { - return ((s == 0 || s == 1) && (arr[i] == 0 || v == arr[i])) ? 1 : 0; - } - if (arr[i] != 0 && v != arr[i]) { - return 0; - } - int ways = 0; - if (s == 0 || s == 1) { - for (int pre = 1; pre < 201; pre++) { - ways += process1(arr, i - 1, pre, pre < v ? 0 : (pre == v ? 1 : 2)); - } - } else { - for (int pre = v; pre < 201; pre++) { - ways += process1(arr, i - 1, pre, pre < v ? 0 : (pre == v ? 1 : 2)); - } - } - return ways; - } - - public static int ways2(int[] arr) { - int N = arr.length; - int[][][] dp = new int[N][201][3]; - if (arr[0] != 0) { - dp[0][arr[0]][0] = 1; - dp[0][arr[0]][1] = 1; - } else { - for (int v = 1; v < 201; v++) { - dp[0][v][0] = 1; - dp[0][v][1] = 1; - } - } - for (int i = 1; i < N; i++) { - for (int v = 1; v < 201; v++) { - for (int s = 0; s < 3; s++) { - if (arr[i] == 0 || v == arr[i]) { - if (s == 0 || s == 1) { - // A[i] = dp[i-1][0~v-1][0] - // A[0] = dp[i-1][0][0] - - - // dp[i-1][1~v-1][0] A[v-1] - A[0] - // dp[i-1][v][1] - // dp[i-1][v+1~200][2] - for (int pre = 1; pre < 201; pre++) { - dp[i][v][s] += dp[i - 1][pre][pre < v ? 0 : (pre == v ? 1 : 2)]; - } - } else { - for (int pre = v; pre < 201; pre++) { - dp[i][v][s] += dp[i - 1][pre][pre < v ? 0 : (pre == v ? 1 : 2)]; - } - } - } - } - } - } - if (arr[N - 1] != 0) { - return dp[N - 1][arr[N - 1]][2]; - } else { - int ways = 0; - for (int v = 1; v < 201; v++) { - ways += dp[N - 1][v][2]; - } - return ways; - } - } - - public static int ways3(int[] arr) { - int N = arr.length; - int[][][] dp = new int[N][201][3]; - if (arr[0] != 0) { - dp[0][arr[0]][0] = 1; - dp[0][arr[0]][1] = 1; - } else { - for (int v = 1; v < 201; v++) { - dp[0][v][0] = 1; - dp[0][v][1] = 1; - } - } - // presum[0~V][0] -> A - // presum[0~V][1] -> B - // presum[0~V][2] -> C - int[][] presum = new int[201][3]; - // presum -> dp[0][..][..] 三张表 - for (int v = 1; v < 201; v++) { - for (int s = 0; s < 3; s++) { - presum[v][s] = presum[v - 1][s] + dp[0][v][s]; - } - } - for (int i = 1; i < N; i++) { - for (int v = 1; v < 201; v++) { - for (int s = 0; s < 3; s++) { - if (arr[i] == 0 || v == arr[i]) { - if (s == 0 || s == 1) { - // dp[i][..][..] -> dp[i-1][..][..] - dp[i][v][s] += sum(1, v - 1, 0, presum); - dp[i][v][s] += dp[i - 1][v][1]; - dp[i][v][s] += sum(v + 1, 200, 2, presum); - } else { - dp[i][v][s] += dp[i - 1][v][1]; - dp[i][v][s] += sum(v + 1, 200, 2, presum); - } - } - } - } - for (int v = 1; v < 201; v++) { - for (int s = 0; s < 3; s++) { - presum[v][s] = presum[v - 1][s] + dp[i][v][s]; - } - } - } - if (arr[N - 1] != 0) { - return dp[N - 1][arr[N - 1]][2]; - } else { - return sum(1, 200, 2, presum); - } - } - - public static int sum(int begin, int end, int relation, int[][] presum) { - return presum[end][relation] - presum[begin - 1][relation]; - } - - // for test - public static int[] generateRandomArray(int len) { - int[] ans = new int[(int) (Math.random() * len) + 2]; - for (int i = 0; i < ans.length; i++) { - if (Math.random() < 0.5) { - ans[i] = 0; - } else { - ans[i] = (int) (Math.random() * 200) + 1; - } - } - return ans; - } - - // for test - public static void printArray(int[] arr) { - System.out.println("arr size : " + arr.length); - for (int i = 0; i < arr.length; i++) { - System.out.print(arr[i] + " "); - } - System.out.println(); - } - - public static void main(String[] args) { - int len = 3; - int testTime = 10; - System.out.println("test begin"); - for (int i = 0; i < testTime; i++) { - int[] arr = generateRandomArray(len); - int ans0 = ways0(arr); - int ans1 = ways1(arr); - int ans2 = ways2(arr); - int ans3 = ways3(arr); - if (ans0 != ans1 || ans2 != ans3 || ans0 != ans2) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - int[] arr = generateRandomArray(100000); - System.out.println(arr.length); - long begin = System.currentTimeMillis(); - ways3(arr); - long end = System.currentTimeMillis(); - System.out.println("run time : " + (end - begin) + " ms"); - - } - -} diff --git a/公开课/class006/Code01_Power2Diffs.java b/公开课/class006/Code01_Power2Diffs.java deleted file mode 100644 index b7de461..0000000 --- a/公开课/class006/Code01_Power2Diffs.java +++ /dev/null @@ -1,97 +0,0 @@ -package class006; - -import java.util.Arrays; -import java.util.HashSet; - -public class Code01_Power2Diffs { - - /* - * 给定一个有序数组arr,其中值可能为正、负、0。 返回arr中每个数都平方之后不同的结果有多少种? - * - * 给定一个数组arr,先递减然后递增,返回arr中有多少个不同的数字? - * - */ - - // 时间复杂度O(N),额外空间复杂度O(N) - public static int diff1(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - HashSet set = new HashSet<>(); - for (int cur : arr) { - set.add(cur * cur); - } - return set.size(); - } - - // 时间复杂度O(N),额外空间复杂度O(1) - public static int diff2(int[] arr) { - int N = arr.length; - int L = 0; - int R = N - 1; - int count = 0; - int leftAbs = 0; - int rightAbs = 0; - while (L <= R) { - count++; - leftAbs = Math.abs(arr[L]); - rightAbs = Math.abs(arr[R]); - if (leftAbs < rightAbs) { - while (R >= 0 && Math.abs(arr[R]) == rightAbs) { - R--; - } - } else if (leftAbs > rightAbs) { - while (L < N && Math.abs(arr[L]) == leftAbs) { - L++; - } - } else { - while (L < N && Math.abs(arr[L]) == leftAbs) { - L++; - } - while (R >= 0 && Math.abs(arr[R]) == rightAbs) { - R--; - } - } - } - return count; - } - - // for test - public static int[] randomSortedArray(int len, int value) { - int[] ans = new int[(int) (Math.random() * len) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * value) - (int) (Math.random() * value); - } - Arrays.sort(ans); - return ans; - } - - // for test - public static void printArray(int[] arr) { - for (int cur : arr) { - System.out.print(cur + " "); - } - System.out.println(); - } - - public static void main(String[] args) { - int len = 100; - int value = 500; - int testTimes = 200000; - System.out.println("test begin"); - for (int i = 0; i < testTimes; i++) { - int[] arr = randomSortedArray(len, value); - int ans1 = diff1(arr); - int ans2 = diff2(arr); - if (ans1 != ans2) { - printArray(arr); - System.out.println(ans1); - System.out.println(ans2); - System.out.println("Oops!"); - break; - } - } - System.out.println("test finish"); - } - -} diff --git a/公开课/class006/Code02_Water.java b/公开课/class006/Code02_Water.java deleted file mode 100644 index 1173051..0000000 --- a/公开课/class006/Code02_Water.java +++ /dev/null @@ -1,121 +0,0 @@ -package class006; - -public class Code02_Water { - - /* - * 给定一个正整数数组arr,把arr想象成一个直方图。返回这个直方图如果装水,能装下几格水? - * - */ - - public static int water1(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int water = 0; - for (int i = 1; i < N - 1; i++) { - int leftMax = Integer.MIN_VALUE; - for (int j = 0; j < i; j++) { - leftMax = Math.max(leftMax, arr[j]); - } - int rightMax = Integer.MIN_VALUE; - for (int j = i + 1; j < N; j++) { - rightMax = Math.max(rightMax, arr[j]); - } - water += Math.max(Math.min(leftMax, rightMax) - arr[i], 0); - } - return water; - } - - public static int water2(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int[] leftMaxs = new int[N]; - leftMaxs[0] = arr[0]; - for (int i = 1; i < N; i++) { - leftMaxs[i] = Math.max(leftMaxs[i - 1], arr[i]); - } - - int[] rightMaxs = new int[N]; - rightMaxs[N - 1] = arr[N - 1]; - for (int i = N - 2; i >= 0; i--) { - rightMaxs[i] = Math.max(rightMaxs[i + 1], arr[i]); - } - int water = 0; - for (int i = 1; i < N - 1; i++) { - water += Math.max(Math.min(leftMaxs[i - 1], rightMaxs[i + 1]) - arr[i], 0); - } - return water; - } - - public static int water3(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int[] rightMaxs = new int[N]; - rightMaxs[N - 1] = arr[N - 1]; - for (int i = N - 2; i >= 0; i--) { - rightMaxs[i] = Math.max(rightMaxs[i + 1], arr[i]); - } - int water = 0; - int leftMax = arr[0]; - for (int i = 1; i < N - 1; i++) { - water += Math.max(Math.min(leftMax, rightMaxs[i + 1]) - arr[i], 0); - leftMax = Math.max(leftMax, arr[i]); - } - return water; - } - - public static int water4(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int L = 1; - int leftMax = arr[0]; - int R = N - 2; - int rightMax = arr[N - 1]; - int water = 0; - while (L <= R) { - if (leftMax <= rightMax) { - water += Math.max(0, leftMax - arr[L]); - leftMax = Math.max(leftMax, arr[L++]); - } else { - water += Math.max(0, rightMax - arr[R]); - rightMax = Math.max(rightMax, arr[R--]); - } - } - return water; - } - - // for test - public static int[] generateRandomArray(int len, int value) { - int[] ans = new int[(int) (Math.random() * len) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * value) + 1; - } - return ans; - } - - public static void main(String[] args) { - int len = 100; - int value = 200; - int testTimes = 100000; - System.out.println("test begin"); - for (int i = 0; i < testTimes; i++) { - int[] arr = generateRandomArray(len, value); - int ans1 = water1(arr); - int ans2 = water2(arr); - int ans3 = water3(arr); - int ans4 = water4(arr); - if (ans1 != ans2 || ans3 != ans4 || ans1 != ans3) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - } - -} diff --git a/公开课/class007/Code01_RandToRand.java b/公开课/class007/Code01_RandToRand.java deleted file mode 100644 index ec95702..0000000 --- a/公开课/class007/Code01_RandToRand.java +++ /dev/null @@ -1,93 +0,0 @@ -package class007; - -public class Code01_RandToRand { - - // 这个结构是唯一的随机机制 - // 你只能初始化并使用,不可修改 - public static class RandomBox { - private final int min; - private final int max; - - // 初始化时请一定不要让mi==ma - public RandomBox(int mi, int ma) { - min = mi; - max = ma; - } - - // 13 ~ 17 - // 13 + [0,4] - public int random() { - return min + (int) (Math.random() * (max - min + 1)); - } - - public int min() { - return min; - } - - public int max() { - return max; - } - } - - // 利用条件RandomBox,如何等概率返回0和1 - public static int rand01(RandomBox randomBox) { - int min = randomBox.min(); - int max = randomBox.max(); - // min ~ max - int size = max - min + 1; - // size是不是奇数,odd 奇数 - boolean odd = (size & 1) != 0; - int mid = size / 2; - int ans = 0; - do { - ans = randomBox.random() - min; - } while (odd && ans == mid); - return ans < mid ? 0 : 1; - } - - // 给你一个RandomBox,这是唯一能借助的随机机制 - // 等概率返回from~to范围上任何一个数 - // 要求from<=to - public static int random(RandomBox randomBox, int from, int to) { - if (from == to) { - return from; - } - // 3 ~ 9 - // 0 ~ 6 - // 0 ~ range - int range = to - from; - int num = 1; - // 求0~range需要几个2进制位 - while ((1 << num) - 1 < range) { - num++; - } - - // 我们一共需要num位 - // 最终的累加和,首先+0位上是1还是0,1位上是1还是0,2位上是1还是0... - int ans = 0; - do { - ans = 0; - for (int i = 0; i < num; i++) { - ans |= (rand01(randomBox) << i); - } - } while (ans > range); - return ans + from; - } - - public static void main(String[] args) { - RandomBox randomBox = new RandomBox(3, 9); - int from = 17; - int to = 29; - int[] ans = new int[to + 1]; - int testTime1 = 1000000; - for (int i = 0; i < testTime1; i++) { - ans[random(randomBox, from, to)]++; - } - for (int i = 0; i < ans.length; i++) { - System.out.println(ans[i]); - } - System.out.println("=========="); - - } - -} diff --git a/公开课/class007/Code02_EqualProbabilityRandom.java b/公开课/class007/Code02_EqualProbabilityRandom.java deleted file mode 100644 index ed54603..0000000 --- a/公开课/class007/Code02_EqualProbabilityRandom.java +++ /dev/null @@ -1,46 +0,0 @@ -package class007; - -public class Code02_EqualProbabilityRandom { - - // 这个结构是唯一的随机机制 - // 你只能初始化并使用,不可修改 - public static class RandomBox { - private final double p; - - // 初始化时请一定满足:0 < zeroP < 1 - public RandomBox(double zeroP) { - p = zeroP; - } - - public int random() { - return Math.random() < p ? 0 : 1; - } - - } - - // 底层依赖一个以p概率返回0,以1-p概率返回1的随机函数rand01p - // 如何加工出等概率返回0和1的函数 - public static int rand01(RandomBox randomBox) { - int num; - do { - num = randomBox.random(); - } while (num == randomBox.random()); - return num; - } - - public static void main(String[] args) { - double zeroP = 0.88; - RandomBox randomBox = new RandomBox(zeroP); - - int testTime = 10000000; - int count = 0; - for (int i = 0; i < testTime; i++) { - if (rand01(randomBox) == 0) { - count++; - } - } - System.out.println((double) count / (double) testTime); - - } - -} diff --git a/公开课/class007/Code03_FindHalfMajority.java b/公开课/class007/Code03_FindHalfMajority.java deleted file mode 100644 index 6a2afc4..0000000 --- a/公开课/class007/Code03_FindHalfMajority.java +++ /dev/null @@ -1,77 +0,0 @@ -package class007; - -import java.util.HashMap; -import java.util.Map.Entry; - -public class Code03_FindHalfMajority { - - public static int halfMajor(int[] arr) { - int cand = 0; - int HP = 0; - // 遍历一遍数组arr,一次删掉两个不同的数,谁会剩下来,谁就是cand - for (int i = 0; i != arr.length; i++) { - if (HP == 0) { // 如果没有候选 - cand = arr[i]; - HP = 1; - } else if (arr[i] == cand) { - HP++; - } else { - HP--; - } - } - if (HP == 0) { - return -1; - } - HP = 0; - for (int i = 0; i != arr.length; i++) { - if (arr[i] == cand) { - HP++; - } - } - return HP > arr.length / 2 ? cand : -1; - } - - // for test - public static int right(int[] arr) { - HashMap map = new HashMap<>(); - for (int cur : arr) { - if (!map.containsKey(cur)) { - map.put(cur, 0); - } - map.put(cur, map.get(cur) + 1); - } - for (Entry entry : map.entrySet()) { - if (entry.getValue() > arr.length / 2) { - return entry.getKey(); - } - } - return -1; - } - - // for test - public static int[] genareteRandomArray(int len, int max) { - int[] ans = new int[(int) (Math.random() * len) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * max) + 1; - } - return ans; - } - - public static void main(String[] args) { - int len = 100; - int max = 10; - int testTime = 100000; - System.out.println("test begin"); - for (int i = 0; i < testTime; i++) { - int[] arr = genareteRandomArray(len, max); - int ans1 = halfMajor(arr); - int ans2 = right(arr); - if (ans1 != ans2) { - System.out.println("Oops!"); - break; - } - } - System.out.println("test end"); - } - -} diff --git a/公开课/class007/Code04_FindKMajor.java b/公开课/class007/Code04_FindKMajor.java deleted file mode 100644 index a6079d7..0000000 --- a/公开课/class007/Code04_FindKMajor.java +++ /dev/null @@ -1,135 +0,0 @@ -package class007; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map.Entry; - -public class Code04_FindKMajor { - - public static List kMajor(int[] arr, int K) { - List ans = new ArrayList<>(); - if (K < 2) { - return ans; - } - // 候选表,记录数一定是O(K) > N/K k-1 - HashMap cands = new HashMap(); - for (int i = 0; i != arr.length; i++) { - if (cands.containsKey(arr[i])) { - cands.put(arr[i], cands.get(arr[i]) + 1); - } else { - if (cands.size() == K - 1) { - allCandsMinusOne(cands); - } else { - cands.put(arr[i], 1); - } - } - } - HashMap reals = getReals(arr, cands); - for (Entry set : cands.entrySet()) { - Integer key = set.getKey(); - if (reals.get(key) > arr.length / K) { - ans.add(key); - } - } - return ans; - } - - public static void allCandsMinusOne(HashMap map) { - List removeList = new LinkedList(); - for (Entry set : map.entrySet()) { - Integer key = set.getKey(); - Integer value = set.getValue(); - if (value == 1) { - removeList.add(key); - } - map.put(key, value - 1); - } - for (Integer removeKey : removeList) { - map.remove(removeKey); - } - } - - // for test - public static List right(int[] arr, int K) { - List ans = new ArrayList<>(); - if (K < 2) { - return ans; - } - HashMap times = new HashMap<>(); - for (int num : arr) { - if (!times.containsKey(num)) { - times.put(num, 1); - } else { - times.put(num, times.get(num) + 1); - } - } - for (Entry entry : times.entrySet()) { - if (entry.getValue() > arr.length / K) { - ans.add(entry.getKey()); - } - } - return ans; - } - - public static HashMap getReals(int[] arr, HashMap cands) { - HashMap reals = new HashMap(); - for (int i = 0; i != arr.length; i++) { - int curNum = arr[i]; - if (cands.containsKey(curNum)) { - if (reals.containsKey(curNum)) { - reals.put(curNum, reals.get(curNum) + 1); - } else { - reals.put(curNum, 1); - } - } - } - return reals; - } - - public static int[] genareteRandomArray(int len, int max) { - int[] ans = new int[(int) (Math.random() * len) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * max) + 1; - } - return ans; - } - - public static boolean isEqual(List ans1, List ans2) { - if (ans1.size() != ans2.size()) { - return false; - } - HashSet set1 = new HashSet<>(); - for (Integer num : ans1) { - set1.add(num); - } - if (set1.size() != ans1.size()) { - return false; - } - for (Integer num : ans2) { - set1.remove(num); - } - return set1.size() == 0; - } - - public static void main(String[] args) { - int len = 100; - int max = 10; - int K = 5; - int testTime = 100000; - System.out.println("test begin"); - for (int i = 0; i < testTime; i++) { - int[] arr = genareteRandomArray(len, max); - List ans1 = kMajor(arr, K); - List ans2 = right(arr, K); - if (!isEqual(ans1, ans2)) { - System.out.println("Oops!"); - break; - } - } - System.out.println("test end"); - } - -} diff --git a/公开课/class008/Code01_JumpGameII.java b/公开课/class008/Code01_JumpGameII.java deleted file mode 100644 index 70bbfc5..0000000 --- a/公开课/class008/Code01_JumpGameII.java +++ /dev/null @@ -1,27 +0,0 @@ -package class008; - -public class Code01_JumpGameII { - - /* - * 评测代码可以直接去leetcode搜索:Jump Game II - * - */ - - public static int jump(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int jump = 0; - int cur = 0; - int next = 0; - for (int i = 0; i < arr.length; i++) { - if (cur < i) { - jump++; - cur = next; - } - next = Math.max(next, i + arr[i]); - } - return jump; - } - -} diff --git a/公开课/class008/Code02_LongestConsecutiveSequence.java b/公开课/class008/Code02_LongestConsecutiveSequence.java deleted file mode 100644 index ad545fa..0000000 --- a/公开课/class008/Code02_LongestConsecutiveSequence.java +++ /dev/null @@ -1,24 +0,0 @@ -package class008; - -import java.util.HashMap; - -public class Code02_LongestConsecutiveSequence { - - public static int longestConsecutive(int[] nums) { - HashMap map = new HashMap<>(); - int len = 0; - for (int num : nums) { - if (!map.containsKey(num)) { - map.put(num, 1); - int preLen = map.containsKey(num - 1) ? map.get(num - 1) : 0; - int posLen = map.containsKey(num + 1) ? map.get(num + 1) : 0; - int all = preLen + posLen + 1; - map.put(num - preLen, all); - map.put(num + posLen, all); - len = Math.max(len, all); - } - } - return len; - } - -} diff --git a/公开课/class009/Code01_SetMatrixZeroes.java b/公开课/class009/Code01_SetMatrixZeroes.java deleted file mode 100644 index 355be75..0000000 --- a/公开课/class009/Code01_SetMatrixZeroes.java +++ /dev/null @@ -1,84 +0,0 @@ -package class009; - -public class Code01_SetMatrixZeroes { - - /* - * 评测代码可以直接去leetcode搜索:Set Matrix Zeroes - * - */ - public static void setZeroes1(int[][] matrix) { - boolean row0Zero = false; - boolean col0Zero = false; - int i = 0; - int j = 0; - for (i = 0; i < matrix[0].length; i++) { - if (matrix[0][i] == 0) { - row0Zero = true; - break; - } - } - for (i = 0; i < matrix.length; i++) { - if (matrix[i][0] == 0) { - col0Zero = true; - break; - } - } - // 跳过了所有0行、0列的数据 - for (i = 1; i < matrix.length; i++) { - for (j = 1; j < matrix[0].length; j++) { - if (matrix[i][j] == 0) { - matrix[i][0] = 0; - matrix[0][j] = 0; - } - } - } - for (i = 1; i < matrix.length; i++) { - for (j = 1; j < matrix[0].length; j++) { - if (matrix[i][0] == 0 || matrix[0][j] == 0) { - matrix[i][j] = 0; - } - } - } - if (row0Zero) { - for (i = 0; i < matrix[0].length; i++) { - matrix[0][i] = 0; - } - } - if (col0Zero) { - for (i = 0; i < matrix.length; i++) { - matrix[i][0] = 0; - } - } - } - - public static void setZeroes2(int[][] matrix) { - boolean col0 = false; - int i = 0; - int j = 0; - for (i = 0; i < matrix.length; i++) { - for (j = 0; j < matrix[0].length; j++) { - if (matrix[i][j] == 0) { - matrix[i][0] = 0; - if (j == 0) { - col0 = true; - } else { - matrix[0][j] = 0; - } - } - } - } - for (i = matrix.length - 1; i >= 0; i--) { - for (j = 1; j < matrix[0].length; j++) { - if (matrix[i][0] == 0 || matrix[0][j] == 0) { - matrix[i][j] = 0; - } - } - } - if (col0) { - for (i = 0; i < matrix.length; i++) { - matrix[i][0] = 0; - } - } - } - -} diff --git a/公开课/class009/Code02_SearchA2DMatrixII.java b/公开课/class009/Code02_SearchA2DMatrixII.java deleted file mode 100644 index 3fa803e..0000000 --- a/公开课/class009/Code02_SearchA2DMatrixII.java +++ /dev/null @@ -1,30 +0,0 @@ -package class009; - -public class Code02_SearchA2DMatrixII { - - /* - * 评测代码可以直接去leetcode搜索:Search a 2D Matrix II - * - */ - - public static boolean searchMatrix(int[][] m, int target) { - if (m == null || m.length == 0 || m[0] == null || m[0].length == 0) { - return false; - } - int N = m.length; - int M = m[0].length; - int row = 0; - int col = M - 1; - while (row < N && col >= 0) { - if (m[row][col] > target) { - col--; - } else if (m[row][col] < target) { - row++; - } else { - return true; - } - } - return false; - } - -} diff --git a/公开课/class009/Code03_LongestOnes.java b/公开课/class009/Code03_LongestOnes.java deleted file mode 100644 index fafbd55..0000000 --- a/公开课/class009/Code03_LongestOnes.java +++ /dev/null @@ -1,155 +0,0 @@ -package class009; - -import java.util.ArrayList; -import java.util.List; - -public class Code03_LongestOnes { - - public static List longestOnes1(int[][] matrix) { - int N = matrix.length; - int M = matrix[0].length; - List ans = new ArrayList<>(); - int maxLen = 0; - for (int i = 0; i < N; i++) { // 每一行的答案,i - int j = M; // 最左发现的1的位置 - while (j > 0 && matrix[i][j - 1] == 1) { - j--; - } - if (maxLen < M - j) { - maxLen = M - j; - ans.clear(); - } - if (maxLen == M - j) { - ans.add(i); - } - } - return ans; - } - - public static List longestOnes2(int[][] matrix) { - int N = matrix.length; - int M = matrix[0].length; - List ans = new ArrayList<>(); - int maxLen = 0; - int col = M; - for (int i = 0; i < N; i++) { - while (col > 0 && matrix[i][col - 1] == 1) { - col--; - } - // col来到当前i行最左侧的1的位置 - if (maxLen < M - col) { - maxLen = M - col; - ans.clear(); - } - if (matrix[i][col] == 1) { - ans.add(i); - } - } - return ans; - } - - public static List longestOnes3(int[][] matrix) { - int N = matrix.length; - int M = matrix[0].length; - List ans = new ArrayList<>(); - int maxLen = 0; - for (int i = 0; i < N; i++) { - int j = mostLeftOne(matrix[i], 0, M - 1); - if (maxLen < M - j) { - maxLen = M - j; - ans.clear(); - } - if (maxLen == M - j) { - ans.add(i); - } - } - return ans; - } - - public static List longestOnes4(int[][] matrix) { - int N = matrix.length; - int M = matrix[0].length; - List ans = new ArrayList<>(); - int maxLen = 0; - int col = M; - for (int i = 0; i < N; i++) { - col = mostLeftOne(matrix[i], 0, col - 1); - if (maxLen < M - col) { - maxLen = M - col; - ans.clear(); - } - if (matrix[i][col] == 1) { - ans.add(i); - } - } - return ans; - } - - // arr[L..R]上,一定有一个前期:要么都是0,要么都是1,如果0和1都有,0在左侧,1在右侧 - public static int mostLeftOne(int[] arr, int L, int R) { - int ans = R + 1; // R + 1 -> [L..R] 没有1的 - int M = 0; - while (L <= R) { - M = (L + R) / 2; - if (arr[M] == 1) { - ans = M; - R = M - 1; - } else { - L = M + 1; - } - } - return ans; - } - - // for test - // 随机生成一个最大规模达到rowSize * colSize的矩阵 - // 确保每一行都是0在左侧,1在右侧 - public static int[][] generateRandomMatrix(int rowSize, int colSize) { - int N = (int) (Math.random() * rowSize) + 1; - int M = (int) (Math.random() * colSize) + 1; - int[][] matrix = new int[N][M]; - for (int i = 0; i < N; i++) { - int[] arr = new int[M]; - int rightStart = (int) (Math.random() * M); - for (int j = rightStart; j < M; j++) { - arr[j] = 1; - } - matrix[i] = arr; - } - return matrix; - } - - public static boolean equal(List ans1, List ans2) { - if (ans1.size() != ans2.size()) { - return false; - } - int N = ans1.size(); - for (int i = 0; i < N; i++) { - if (!ans1.get(i).equals(ans2.get(i))) { - return false; - } - } - return true; - } - - public static void main(String[] args) { - System.out.println("Hello!"); - int rowSize = 30; - int colSize = 100; - int testTimes = 300000; - System.out.println("test begin"); - for (int i = 0; i < testTimes; i++) { - int[][] matrix = generateRandomMatrix(rowSize, colSize); - List ans1 = longestOnes1(matrix); - List ans2 = longestOnes2(matrix); - List ans3 = longestOnes3(matrix); - List ans4 = longestOnes4(matrix); - if (!equal(ans1, ans2) || !equal(ans3, ans4) || !equal(ans1, ans3)) { - System.out.println("Oops"); - } - } - System.out.println("test end"); - - } - -} diff --git a/公开课/class010/Code01_SwapWithoutTmp.java b/公开课/class010/Code01_SwapWithoutTmp.java deleted file mode 100644 index 47a6da2..0000000 --- a/公开课/class010/Code01_SwapWithoutTmp.java +++ /dev/null @@ -1,17 +0,0 @@ -package class010; - -public class Code01_SwapWithoutTmp { - - public static void main(String[] args) { - int a = 111; - int b = 111; - System.out.println(a); - System.out.println(b); - a = a ^ b; - b = a ^ b; - a = a ^ b; - System.out.println(a); - System.out.println(b); - } - -} diff --git a/公开课/class010/Code02_GetMax.java b/公开课/class010/Code02_GetMax.java deleted file mode 100644 index 478ff13..0000000 --- a/公开课/class010/Code02_GetMax.java +++ /dev/null @@ -1,53 +0,0 @@ -package class010; - -public class Code02_GetMax { - - // 请确保,n不是0,就是1 - // 0 -> 1 1 -> 0 - public static int flip(int n) { - return n ^ 1; - } - - // 如果n是非负数,返回1 - // 如果n是负数,返回0 - public static int sign(int n) { - // (n >> 31) & 1 0(int 非负数) 1(int 负数) - // >>> >> - return flip((n >> 31) & 1); - } - - // 确保 a-b 是不会溢出的 - public static int getMax1(int a, int b) { - int c = a - b; - int scA = sign(c); // scA == 1 a - b >= 0 a返回 sca == 0 a-b < 0 b返回 - int scB = flip(scA); - return a * scA + b * scB; - } - - public static int getMax2(int a, int b) { - int c = a - b; - int sa = sign(a); - int sb = sign(b); - int sc = sign(c); - int difSab = sa ^ sb; - int sameSab = flip(difSab); - // 返回a的条件 returnA == 1 应该返回a; - // returnA == 0,不应该返回a - int returnA = difSab * sa + sameSab * sc; - int returnB = flip(returnA); - return a * returnA + b * returnB; - } - - public static void main(String[] args) { - int a = -16; - int b = 1; - System.out.println(getMax1(a, b)); - System.out.println(getMax2(a, b)); - a = 2147483647; - b = -2147480000; - System.out.println(getMax1(a, b)); // wrong answer because of overflow - System.out.println(getMax2(a, b)); - - } - -} diff --git a/公开课/class010/Code03_EvenTimesOddTimes.java b/公开课/class010/Code03_EvenTimesOddTimes.java deleted file mode 100644 index b54d8d6..0000000 --- a/公开课/class010/Code03_EvenTimesOddTimes.java +++ /dev/null @@ -1,89 +0,0 @@ -package class010; - -public class Code03_EvenTimesOddTimes { - - // arr中,只有一种数,出现奇数次 - public static void printOddTimesNum1(int[] arr) { - int eor = 0; - for (int i = 0; i < arr.length; i++) { - eor ^= arr[i]; - } - System.out.println(eor); - } - - // arr中,有两种数,出现奇数次 - public static void printOddTimesNum2(int[] arr) { - int eor = 0; - for (int i = 0; i < arr.length; i++) { - eor ^= arr[i]; - } - // eor = a ^ b - // eor != 0 - // eor必然有一个位置上是1 - // 0110010000 - // 0000010000 - int rightOne = eor & (~eor + 1); // 提取出最右的1 - int onlyOne = 0; // e' - for (int i = 0 ; i < arr.length;i++) { - // arr[1] = 111100011110000 - // rightOne= 000000000010000 - if ((arr[i] & rightOne) != 0) { - onlyOne ^= arr[i]; - } - } - System.out.println(onlyOne + " " + (eor ^ onlyOne)); - } - - - public static int bit1counts(int N) { - int count = 0; - while(N != 0) { - int rightOne = N & ((~N) + 1); - count++; - N -= rightOne; - } - return count; - } - - - public static int add(int a, int b) { - int t = 0; - while( b != 0) { - t = a; - a = a ^ b; - b = ((t & b) << 1); - } - return a; - } - - public static int minus(int a, int b) { - // -b ~b + 1 - return add(a, add(~b , 1)); - } - - - - - public static void main(String[] args) { - int a = 5; - int b = 7; - - - System.out.println(minus(a,b)); - - a = a ^ b; - b = a ^ b; - a = a ^ b; - - System.out.println(a); - System.out.println(b); - - int[] arr1 = { 3, 3, 2, 3, 1, 1, 1, 3, 1, 1, 1 }; - printOddTimesNum1(arr1); - - int[] arr2 = { 4, 3, 4, 2, 2, 2, 4, 1, 1, 1, 3, 3, 1, 1, 1, 4, 2, 2 }; - printOddTimesNum2(arr2); - - } - -} diff --git a/公开课/class011/Code01_CopyListWithRandom.java b/公开课/class011/Code01_CopyListWithRandom.java deleted file mode 100644 index 62e7c53..0000000 --- a/公开课/class011/Code01_CopyListWithRandom.java +++ /dev/null @@ -1,133 +0,0 @@ -package class011; - -import java.util.HashMap; - -public class Code01_CopyListWithRandom { - - public static class Node { - public int value; - public Node next; - public Node rand; - - public Node(int data) { - this.value = data; - } - } - - public static Node copyListWithRand1(Node head) { - HashMap map = new HashMap(); - Node cur = head; - while (cur != null) { - map.put(cur, new Node(cur.value)); - cur = cur.next; - } - cur = head; - while (cur != null) { - // cur 老 - // map.get(cur) 新 - map.get(cur).next = map.get(cur.next); - map.get(cur).rand = map.get(cur.rand); - cur = cur.next; - } - return map.get(head); - } - - public static Node copyListWithRand2(Node head) { - if (head == null) { - return null; - } - Node cur = head; - Node next = null; - // copy node and link to every node - // 1 -> 2 - // 1 -> 1' -> 2 - while (cur != null) { - // 1 -> 2 -> 3 - // cur next - // 1 -> 1' -> 2 -> 2' - next = cur.next; - cur.next = new Node(cur.value); - cur.next.next = next; - cur = next; - } - cur = head; - Node curCopy = null; - // set copy node rand - // 1 -> 1' -> 2 -> 2' - while (cur != null) { - // 1 -> 1' -> 2 -> 2' - // cur next - // cur 老 cur.next 新 - next = cur.next.next; - curCopy = cur.next; - curCopy.rand = cur.rand != null ? cur.rand.next : null; - cur = next; - } - // head head.next - Node res = head.next; - cur = head; - // split - while (cur != null) { - next = cur.next.next; - curCopy = cur.next; - cur.next = next; - curCopy.next = next != null ? next.next : null; - cur = next; - } - return res; - } - - public static void printRandLinkedList(Node head) { - Node cur = head; - System.out.print("order: "); - while (cur != null) { - System.out.print(cur.value + " "); - cur = cur.next; - } - System.out.println(); - cur = head; - System.out.print("rand: "); - while (cur != null) { - System.out.print(cur.rand == null ? "- " : cur.rand.value + " "); - cur = cur.next; - } - System.out.println(); - } - - public static void main(String[] args) { - Node head = null; - Node res1 = null; - Node res2 = null; - printRandLinkedList(head); - res1 = copyListWithRand1(head); - printRandLinkedList(res1); - res2 = copyListWithRand2(head); - printRandLinkedList(res2); - printRandLinkedList(head); - System.out.println("========================="); - - head = new Node(1); - head.next = new Node(2); - head.next.next = new Node(3); - head.next.next.next = new Node(4); - head.next.next.next.next = new Node(5); - head.next.next.next.next.next = new Node(6); - - head.rand = head.next.next.next.next.next; // 1 -> 6 - head.next.rand = head.next.next.next.next.next; // 2 -> 6 - head.next.next.rand = head.next.next.next.next; // 3 -> 5 - head.next.next.next.rand = head.next.next; // 4 -> 3 - head.next.next.next.next.rand = null; // 5 -> null - head.next.next.next.next.next.rand = head.next.next.next; // 6 -> 4 - - printRandLinkedList(head); - res1 = copyListWithRand1(head); - printRandLinkedList(res1); - res2 = copyListWithRand2(head); - printRandLinkedList(res2); - printRandLinkedList(head); - System.out.println("========================="); - - } - -} diff --git a/公开课/class011/Code02_JumpMinTimes.java b/公开课/class011/Code02_JumpMinTimes.java deleted file mode 100644 index 41f3b56..0000000 --- a/公开课/class011/Code02_JumpMinTimes.java +++ /dev/null @@ -1,201 +0,0 @@ -package class011; - -import java.util.HashMap; -import java.util.LinkedList; -import java.util.Queue; - -public class Code02_JumpMinTimes { - - public static int jumpMinTimes1(int N, int start, int end, int[] arr) { - boolean[] map = new boolean[N + 1]; - - return f1(N, start, end, 0, arr, map); - } - - // 一共有N个位置, 每个位置如何跳,记录在arr中 - // 之前一共走了步数是step步 - // 当前来到cur位置,最终想去aim位置, - // 返回从start开始到aim,最少的步数 - // 如果map[i] == true 表示i位置,之前来过 - // 如果map[i] == false 表示i位置,之前没来过 - public static int f1(int N, int cur, int aim, int step, int[] arr, boolean[] map) { - if (cur < 1 || cur > N) { - return -1; - } - if (map[cur]) { - return -1; - } - // 有效的位置,又没来过 - if (cur == aim) { - return step; - } - map[cur] = true; - int ans1 = f1(N, cur + arr[cur - 1], aim, step + 1, arr, map); - int ans2 = f1(N, cur - arr[cur - 1], aim, step + 1, arr, map); - map[cur] = false; - if (ans1 != -1 && ans2 != -1) { - return Math.min(ans1, ans2); - } - if (ans1 != -1 && ans2 == -1) { - return ans1; - } - if (ans1 == -1 && ans2 != -1) { - return ans2; - } - return -1; - } - - // 一共有N个位置 - // 最终要去aim位置 - // arr中,描述怎么跳 - // 当前,来到了i位置 - // 已经走了k步 - // 最后到达aim,至少几步? - public static int process(int N, int aim, int[] arr, int i, int k) { - if (i < 1 || i > N || k > N - 1) { - return -1; - } - if (i == aim) { - return k; - } - // 请注意,arr的下标是从0开始的,但是题目规定的下标从1开始 - // 所以,拿出i位置能跳的距离,需要拿arr[i-1]位置的值 - int ans1 = process(N, aim, arr, i + arr[i - 1], k + 1); - int ans2 = process(N, aim, arr, i - arr[i - 1], k + 1); - int ans = -1; - if (ans1 != -1 && ans2 != -1) { - ans = Math.min(ans1, ans2); - } - if (ans1 != -1 && ans2 == -1) { - ans = ans1; - } - if (ans1 == -1 && ans2 != -1) { - ans = ans2; - } - return ans; - } - - public static int jumpMinTimes2(int N, int start, int end, int[] arr) { - int[][] dp = new int[N + 1][N + 1]; - for (int i = 0; i < dp.length; i++) { - for (int j = 0; j < dp[0].length; j++) { - dp[i][j] = -2; - } - } - // dp[i][k] == -2表示这个过程没算过 - // dp[i][k] != -2表示这个过程算过了 - return f2(N, end, arr, start, 0, dp); - } - - // 一共有N个位置,跳的过程中,如果你又跳回到某个位置,其实这已经说明不是最优步数了 - // 也就是说,如果存在最优的跳法,那么这个最优跳法一定不会大于N-1步 - // 所以,增加了一个参数k,表示已经跳了多少步 - // 整个函数的含义: - // 一共有1~N个位置,目标是aim位置 - // 所有位置能跳的距离都记录在arr中,并且对任意的arr[i] > 0 - // 当前来到的位置是i, 之前已经跳过了k步, - // 返回最后到达aim位置,跳的最少的步数 - // 如果返回-1表示怎么也无法到达 - public static int f2(int N, int aim, int[] arr, int i, int k, int[][] dp) { - if (i < 1 || i > N || k > N - 1) { - return -1; - } - if (dp[i][k] != -2) { - return dp[i][k]; - } - if (i == aim) { - dp[i][k] = k; - return k; - } - // 请注意,arr的下标是从0开始的,但是题目规定的下标从1开始 - // 所以,拿出i位置能跳的距离,需要拿arr[i-1]位置的值 - int ans1 = f2(N, aim, arr, i + arr[i - 1], k + 1, dp); - int ans2 = f2(N, aim, arr, i - arr[i - 1], k + 1, dp); - int ans = -1; - if (ans1 != -1 && ans2 != -1) { - ans = Math.min(ans1, ans2); - } - if (ans1 != -1 && ans2 == -1) { - ans = ans1; - } - if (ans1 == -1 && ans2 != -1) { - ans = ans2; - } - dp[i][k] = ans; - return ans; - } - - // bfs - public static int jumpMinTimes3(int N, int start, int end, int[] arr) { - if (start < 1 || start > N || end < 1 || end > N) { - return -1; - } - Queue queue = new LinkedList<>(); - HashMap levelMap = new HashMap<>(); - queue.add(start); - levelMap.put(start, 0); - while (!queue.isEmpty()) { - int cur = queue.poll(); - int level = levelMap.get(cur); - if (cur == end) { - return level; - } else { - int left = cur - arr[cur - 1]; - int right = cur + arr[cur - 1]; - if (left > 0 && !levelMap.containsKey(left)) { - queue.add(left); - levelMap.put(left, level + 1); - } - if (right <= N && !levelMap.containsKey(right)) { - queue.add(right); - levelMap.put(right, level + 1); - } - } - } - return -1; - } - - // for test - public static int[] gerRandomArray(int N, int R) { - int[] arr = new int[N]; - for (int i = 0; i < N; i++) { - arr[i] = (int) (Math.random() * R); - } - return arr; - } - - public static void printArray(int[] arr) { - for (int i = 0; i < arr.length; i++) { - System.out.print(arr[i] + " "); - } - System.out.println(); - } - - public static void main(String[] args) { - int maxN = 20; - int maxV = 10; - int testTimes = 200000; - System.out.println("test begin"); - for (int i = 0; i < testTimes; i++) { - int[] arr = gerRandomArray(maxN, maxV); - int N = arr.length; - int start = (int) (Math.random() * N) + 1; - int end = (int) (Math.random() * N) + 1; - int ans1 = jumpMinTimes1(N, start, end, arr); - int ans2 = jumpMinTimes2(N, start, end, arr); - int ans3 = jumpMinTimes3(N, start, end, arr); - if (ans1 != ans2 || ans2 != ans3) { - printArray(arr); - System.out.println("start : " + start); - System.out.println("end : " + end); - System.out.println("ans1 : " + ans1); - System.out.println("ans2 : " + ans2); - System.out.println("ans3 : " + ans2); - System.out.println("Oops!"); - break; - } - } - System.out.println("test end"); - } - -} diff --git a/公开课/class012/Code01_MoneyProblem.java b/公开课/class012/Code01_MoneyProblem.java deleted file mode 100644 index 80c721c..0000000 --- a/公开课/class012/Code01_MoneyProblem.java +++ /dev/null @@ -1,200 +0,0 @@ -package class012; - -import java.util.HashMap; - -public class Code01_MoneyProblem { - - public static long func1(int[] d, int[] p) { - return process(d, p, 0, 0); - } - - // int[] d d[i]:i号怪兽的武力 - // int[] p p[i]:i号怪兽要求的钱 - // hp 当前你所具有的能力 - // index 来到了第index个怪兽的面前 - - // 目前,你的能力是hp,你来到了index号怪兽的面前,如果要通过后续所有的怪兽, - // 请返回需要花的最少钱数 - public static long process(int[] d, int[] p, int hp, int index) { - if (index == d.length) { // base case - return 0; - } - // index < d.length 还有怪兽要面对 - if (hp < d[index]) { - return p[index] + process(d, p, hp + d[index], index + 1); - } else { // hp >= d[index] 可以贿赂,也可以不贿赂 - return Math.min(p[index] + process(d, p, hp + d[index], index + 1), - - process(d, p, hp, index + 1)); - } - } - - // 正数数组 d p - public static int dp1(int[] d, int[] p) { - if (d == null || d.length == 0) { - return 0; - } - - int sum = 0; - for (int ability : d) { - sum += ability; - } - int N = d.length; - - int[][] dp = new int[N + 1][sum + 1]; - - // dp[N][...] = 0; - for (int i = N - 1; i >= 0; i--) { - for (int j = 0; j <= sum; j++) { - // j 能力 i 怪兽号 - if (j + d[i] > sum) { - continue; - } - if (j < d[i]) { - dp[i][j] = p[i] + dp[i + 1][j + d[i]]; - } else { - dp[i][j] = Math.min(p[i] + dp[i + 1][j + d[i]], dp[i + 1][j]); - } - } - } - - return dp[0][0]; - - } - - public static long func2(int[] d, int[] p) { - int sum = 0; - for (int num : d) { - sum += num; - } - long[][] dp = new long[d.length + 1][sum + 1]; - for (int i = 0; i <= sum; i++) { - dp[0][i] = 0; - } - for (int cur = d.length - 1; cur >= 0; cur--) { - for (int hp = 0; hp <= sum; hp++) { - // 如果这种情况发生,那么这个hp必然是递归过程中不会出现的状态 - // 既然动态规划是尝试过程的优化,尝试过程碰不到的状态,不必计算 - if (hp + d[cur] > sum) { - continue; - } - if (hp < d[cur]) { - dp[cur][hp] = p[cur] + dp[cur + 1][hp + d[cur]]; - } else { - dp[cur][hp] = Math.min(p[cur] + dp[cur + 1][hp + d[cur]], dp[cur + 1][hp]); - } - } - } - return dp[0][0]; - } - - - - public static long func1dp(int[] d, int[] p) { - HashMap dp = new HashMap<>(); - return processdp(d, p, 0, 0, dp); - } - - // int[] d d[i]:i号怪兽的武力 - // int[] p p[i]:i号怪兽要求的钱 - // hp 当前你所具有的能力 - // index 来到了第index个怪兽的面前 - - // 目前,你的能力是hp,你来到了index号怪兽的面前,如果要通过后续所有的怪兽, - // 请返回需要花的最少钱数 - public static long processdp(int[] d, int[] p, int hp, int index,HashMap dp) { - String key = String.valueOf(hp) + "_" + String.valueOf(index); - if(dp.containsKey(key)) { - return dp.get(key); - } - long ans = 0; - if(index < d.length) { - if (hp < d[index]) { - ans = p[index] + process(d, p, hp + d[index], index + 1); - } else { // hp >= d[index] 可以贿赂,也可以不贿赂 - ans = Math.min(p[index] + process(d, p, hp + d[index], index + 1), - - process(d, p, hp, index + 1)); - } - } - dp.put(key, ans); - return ans; - - } - - - public static long func3(int[] d, int[] p) { - int sum = 0; - for (int num : p) { - sum += num; - } - // dp[i][j]含义: - // 能经过0~i的怪兽,且花钱为j(花钱的严格等于j)时的武力值最大是多少? - // 如果dp[i][j]==-1,表示经过0~i的怪兽,花钱为j是无法通过的,或者之前的钱怎么组合也得不到正好为j的钱数 - int[][] dp = new int[d.length][sum + 1]; - for (int i = 0; i < dp.length; i++) { - for (int j = 0; j <= sum; j++) { - dp[i][j] = -1; - } - } - // 经过0~i的怪兽,花钱数一定为p[0],达到武力值d[0]的地步。其他第0行的状态一律是无效的 - dp[0][p[0]] = d[0]; - for (int i = 1; i < d.length; i++) { - for (int j = 0; j <= sum; j++) { - // 可能性一,为当前怪兽花钱 - // 存在条件: - // j - p[i]要不越界,并且在钱数为j - p[i]时,要能通过0~i-1的怪兽,并且钱数组合是有效的。 - if (j >= p[i] && dp[i - 1][j - p[i]] != -1) { - dp[i][j] = dp[i - 1][j - p[i]] + d[i]; - } - // 可能性二,不为当前怪兽花钱 - // 存在条件: - // 0~i-1怪兽在花钱为j的情况下,能保证通过当前i位置的怪兽 - if (dp[i - 1][j] >= d[i]) { - // 两种可能性中,选武力值最大的 - dp[i][j] = Math.max(dp[i][j], dp[i - 1][j]); - } - } - } - int ans = 0; - // dp表最后一行上,dp[N-1][j]代表: - // 能经过0~N-1的怪兽,且花钱为j(花钱的严格等于j)时的武力值最大是多少? - // 那么最后一行上,最左侧的不为-1的列数(j),就是答案 - for (int j = 0; j <= sum; j++) { - if (dp[d.length - 1][j] != -1) { - ans = j; - break; - } - } - return ans; - } - - public static int[][] generateTwoRandomArray(int len, int value) { - int size = (int) (Math.random() * len) + 1; - int[][] arrs = new int[2][size]; - for (int i = 0; i < size; i++) { - arrs[0][i] = (int) (Math.random() * value) + 1; - arrs[1][i] = (int) (Math.random() * value) + 1; - } - return arrs; - } - - public static void main(String[] args) { - int len = 10; - int value = 20; - int testTimes = 1000000; - for (int i = 0; i < testTimes; i++) { - int[][] arrs = generateTwoRandomArray(len, value); - int[] d = arrs[0]; - int[] p = arrs[1]; - long ans1 = func1(d, p); - long ans2 = func2(d, p); - long ans3 = func3(d, p); - if (ans1 != ans2 || ans2 != ans3) { - System.out.println("oops!"); - } - } - - } - -} diff --git a/公开课/class013/Code01_PalindromeNumber.java b/公开课/class013/Code01_PalindromeNumber.java deleted file mode 100644 index a682247..0000000 --- a/公开课/class013/Code01_PalindromeNumber.java +++ /dev/null @@ -1,24 +0,0 @@ -package class013; - -public class Code01_PalindromeNumber { - - public static boolean isPalindrome(int n) { - if (n < 0) { - return false; - } - n = Math.abs(n); - int help = 1; - while (n / help >= 10) { - help *= 10; - } - while (n != 0) { - if (n / help != n % 10) { - return false; - } - n = (n % help) / 10; - help /= 100; - } - return true; - } - -} diff --git a/公开课/class013/Code03_LongestNoRepeatSubstring.java b/公开课/class013/Code03_LongestNoRepeatSubstring.java deleted file mode 100644 index e3c1d87..0000000 --- a/公开课/class013/Code03_LongestNoRepeatSubstring.java +++ /dev/null @@ -1,70 +0,0 @@ -package class013; - -public class Code03_LongestNoRepeatSubstring { - - public static int maxUnique(String str) { - if (str == null || str.equals("")) { - return 0; - } - char[] chas = str.toCharArray(); - // map 替代了哈希表 假设字符的码是0~255 - int[] map = new int[256]; - for (int i = 0; i < 256; i++) { - map[i] = -1; - } - int len = 0; - int pre = -1; - int cur = 0; - for (int i = 0; i != chas.length; i++) { - pre = Math.max(pre, map[chas[i]]); - cur = i - pre; - len = Math.max(len, cur); - map[chas[i]] = i; - } - return len; - } - - // for test - public static String getRandomString(int len) { - char[] str = new char[len]; - int base = 'a'; - int range = 'z' - 'a' + 1; - for (int i = 0; i != len; i++) { - str[i] = (char) ((int) (Math.random() * range) + base); - } - return String.valueOf(str); - } - - // for test - public static String maxUniqueString(String str) { - if (str == null || str.equals("")) { - return str; - } - char[] chas = str.toCharArray(); - int[] map = new int[256]; - for (int i = 0; i < 256; i++) { - map[i] = -1; - } - int len = -1; - int pre = -1; - int cur = 0; - int end = -1; - for (int i = 0; i != chas.length; i++) { - pre = Math.max(pre, map[chas[i]]); - cur = i - pre; - if (cur > len) { - len = cur; - end = i; - } - map[chas[i]] = i; - } - return str.substring(end - len + 1, end + 1); - } - - public static void main(String[] args) { - String str = getRandomString(20); - System.out.println(str); - System.out.println(maxUnique(str)); - System.out.println(maxUniqueString(str)); - } -} diff --git a/公开课/class014/Code01_CoverMax.java b/公开课/class014/Code01_CoverMax.java deleted file mode 100644 index 5267691..0000000 --- a/公开课/class014/Code01_CoverMax.java +++ /dev/null @@ -1,133 +0,0 @@ -package class014; - -import java.util.Arrays; -import java.util.Comparator; -import java.util.PriorityQueue; - -public class Code01_CoverMax { - - public static int maxCover1(int[][] lines) { - int min = Integer.MAX_VALUE; - int max = Integer.MIN_VALUE; - for (int i = 0; i < lines.length; i++) { - min = Math.min(min, lines[i][0]); - max = Math.max(max, lines[i][1]); - } - int cover = 0; - for (double p = min + 0.5; p < max; p += 1) { - int cur = 0; - for (int i = 0; i < lines.length; i++) { - if (lines[i][0] < p && lines[i][1] > p) { - cur++; - } - } - cover = Math.max(cover, cur); - } - return cover; - } - - public static int maxCover2(int[][] m) { - Line[] lines = new Line[m.length]; - for (int i = 0; i < m.length; i++) { - lines[i] = new Line(m[i][0], m[i][1]); - } - Arrays.sort(lines, new StartComparator()); - // lines - // - PriorityQueue heap = new PriorityQueue<>(); - int max = 0; - for (int i = 0; i < lines.length; i++) { - // lines[i] -> cur 在黑盒中,把<=cur.start 东西都弹出 - while (!heap.isEmpty() && heap.peek() <= lines[i].start) { - heap.poll(); - } - heap.add(lines[i].end); - max = Math.max(max, heap.size()); - } - return max; - } - - public static class Line { - public int start; - public int end; - - public Line(int s, int e) { - start = s; - end = e; - } - } - - public static class EndComparator implements Comparator { - - @Override - public int compare(Line o1, Line o2) { - return o1.end - o2.end; - } - - } - - // for test - public static int[][] generateLines(int N, int L, int R) { - int size = (int) (Math.random() * N) + 1; - int[][] ans = new int[size][2]; - for (int i = 0; i < size; i++) { - int a = L + (int) (Math.random() * (R - L + 1)); - int b = L + (int) (Math.random() * (R - L + 1)); - if (a == b) { - b = a + 1; - } - ans[i][0] = Math.min(a, b); - ans[i][1] = Math.max(a, b); - } - return ans; - } - - public static class StartComparator implements Comparator { - - @Override - public int compare(Line o1, Line o2) { - return o1.start - o2.start; - } - - } - - public static void main(String[] args) { - - Line l1 = new Line(4, 9); - Line l2 = new Line(1, 4); - Line l3 = new Line(7, 15); - Line l4 = new Line(2, 4); - Line l5 = new Line(4, 6); - Line l6 = new Line(3, 7); - - // 底层堆结构,heap - PriorityQueue heap = new PriorityQueue<>(new StartComparator()); - heap.add(l1); - heap.add(l2); - heap.add(l3); - heap.add(l4); - heap.add(l5); - heap.add(l6); - - while (!heap.isEmpty()) { - Line cur = heap.poll(); - System.out.println(cur.start + "," + cur.end); - } - - System.out.println("test begin"); - int N = 100; - int L = 0; - int R = 200; - int testTimes = 200000; - for (int i = 0; i < testTimes; i++) { - int[][] lines = generateLines(N, L, R); - int ans1 = maxCover1(lines); - int ans2 = maxCover2(lines); - if (ans1 != ans2) { - System.out.println("Oops!"); - } - } - System.out.println("test end"); - } - -} diff --git a/公开课/class014/Code02_MaxDistance.java b/公开课/class014/Code02_MaxDistance.java deleted file mode 100644 index 7076c8d..0000000 --- a/公开课/class014/Code02_MaxDistance.java +++ /dev/null @@ -1,154 +0,0 @@ -package class014; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; - -public class Code02_MaxDistance { - - public static class Node { - public int value; - public Node left; - public Node right; - - public Node(int data) { - this.value = data; - } - } - - public static int maxDistance2(Node head) { - return f(head).allTreeMaxDis; - } - - // 左:最大距离、高 - // 右:最大距离、高 - public static class Info { - public int allTreeMaxDis; - public int height; - - public Info(int all, int h) { - allTreeMaxDis = all; - height = h; - } - } - - // 以x为头情况下,两个结果 - public static Info f(Node x) { - if (x == null) { - return new Info(0, 0); - } - Info leftInfo = f(x.left); - Info rightInfo = f(x.right); - int allTreeMaxDis = Math.max(Math.max(leftInfo.allTreeMaxDis, rightInfo.allTreeMaxDis), - leftInfo.height + rightInfo.height + 1); - int height = Math.max(leftInfo.height, rightInfo.height) + 1; - return new Info(allTreeMaxDis, height); - } - - public static int maxDistance1(Node head) { - if (head == null) { - return 0; - } - ArrayList arr = getPrelist(head); - HashMap parentMap = getParentMap(head); - int max = 0; - for (int i = 0; i < arr.size(); i++) { - for (int j = i; j < arr.size(); j++) { - max = Math.max(max, distance(parentMap, arr.get(i), arr.get(j))); - } - } - return max; - } - - public static ArrayList getPrelist(Node head) { - ArrayList arr = new ArrayList<>(); - fillPrelist(head, arr); - return arr; - } - - public static void fillPrelist(Node head, ArrayList arr) { - if (head == null) { - return; - } - arr.add(head); - fillPrelist(head.left, arr); - fillPrelist(head.right, arr); - } - - public static HashMap getParentMap(Node head) { - HashMap map = new HashMap<>(); - map.put(head, null); - fillParentMap(head, map); - return map; - } - - public static void fillParentMap(Node head, HashMap parentMap) { - if (head.left != null) { - parentMap.put(head.left, head); - fillParentMap(head.left, parentMap); - } - if (head.right != null) { - parentMap.put(head.right, head); - fillParentMap(head.right, parentMap); - } - } - - public static int distance(HashMap parentMap, Node o1, Node o2) { - HashSet o1Set = new HashSet<>(); - Node cur = o1; - o1Set.add(cur); - while (parentMap.get(cur) != null) { - cur = parentMap.get(cur); - o1Set.add(cur); - } - cur = o2; - while (!o1Set.contains(cur)) { - cur = parentMap.get(cur); - } - Node lowestAncestor = cur; - cur = o1; - int distance1 = 1; - while (cur != lowestAncestor) { - cur = parentMap.get(cur); - distance1++; - } - cur = o2; - int distance2 = 1; - while (cur != lowestAncestor) { - cur = parentMap.get(cur); - distance2++; - } - return distance1 + distance2 - 1; - } - - // for test - public static Node generateRandomBST(int maxLevel, int maxValue) { - return generate(1, maxLevel, maxValue); - } - - // for test - public static Node generate(int level, int maxLevel, int maxValue) { - if (level > maxLevel || Math.random() < 0.5) { - return null; - } - Node head = new Node((int) (Math.random() * maxValue)); - head.left = generate(level + 1, maxLevel, maxValue); - head.right = generate(level + 1, maxLevel, maxValue); - return head; - } - - public static void main(String[] args) { - int maxLevel = 4; - int maxValue = 100; - int testTimes = 1000000; - System.out.println("test begin"); - for (int i = 0; i < testTimes; i++) { - Node head = generateRandomBST(maxLevel, maxValue); - if (maxDistance1(head) != maxDistance2(head)) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - } - -} diff --git a/公开课/class015/Code01_CordCoverMaxPoint.java b/公开课/class015/Code01_CordCoverMaxPoint.java deleted file mode 100644 index 9248055..0000000 --- a/公开课/class015/Code01_CordCoverMaxPoint.java +++ /dev/null @@ -1,88 +0,0 @@ -package class015; - -import java.util.Arrays; - -public class Code01_CordCoverMaxPoint { - - public static int maxPoint1(int[] arr, int L) { - int res = 1; - for (int i = 0; i < arr.length; i++) { - int nearest = nearestIndex(arr, i, arr[i] - L); - res = Math.max(res, i - nearest + 1); - } - return res; - } - - public static int nearestIndex(int[] arr, int R, int value) { - int L = 0; - int index = R; - while (L <= R) { - int mid = L + ((R - L) >> 1); - if (arr[mid] >= value) { - index = mid; - R = mid - 1; - } else { - L = mid + 1; - } - } - return index; - } - - public static int maxPoint2(int[] arr, int L) { - int left = 0; - int right = 0; - int N = arr.length; - int max = 0; - while (left < N) { - while (right < N && arr[right] - arr[left] <= L) { - right++; - } - max = Math.max(max, right - (left++)); - } - return max; - } - - // for test - public static int test(int[] arr, int L) { - int max = 0; - for (int i = 0; i < arr.length; i++) { - int pre = i - 1; - while (pre >= 0 && arr[i] - arr[pre] <= L) { - pre--; - } - max = Math.max(max, i - pre); - } - return max; - } - - // for test - public static int[] generateArray(int len, int max) { - int[] ans = new int[(int) (Math.random() * len) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * max); - } - Arrays.sort(ans); - return ans; - } - - public static void main(String[] args) { - int len = 100; - int max = 1000; - int testTime = 100000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int L = (int) (Math.random() * max); - int[] arr = generateArray(len, max); - int ans1 = maxPoint1(arr, L); - int ans2 = maxPoint2(arr, L); - int ans3 = test(arr, L); - if (ans1 != ans2 || ans2 != ans3) { - System.out.println("oops!"); - break; - } - } - System.out.println("测试结束"); - - } - -} diff --git a/公开课/class015/Code02_ColorLeftRight.java b/公开课/class015/Code02_ColorLeftRight.java deleted file mode 100644 index 3185cc3..0000000 --- a/公开课/class015/Code02_ColorLeftRight.java +++ /dev/null @@ -1,72 +0,0 @@ -package class015; - -public class Code02_ColorLeftRight { - - // RGRGR -> RRRGG - public static int minPaint(String s) { - if (s == null || s.length() < 2) { - return 0; - } - char[] str = s.toCharArray(); - int N = str.length; - int rAll = 0; - for (int i = 0; i < N; i++) { - rAll += str[i] == 'R' ? 1 : 0; - } - int ans = rAll; // 如果数组所有的范围,都是右侧范围,都变成G - int left = 0; - for (int i = 0; i < N - 1; i++) { // 0..i 左侧 n-1..N-1 - left += str[i] == 'G' ? 1 : 0; - rAll -= str[i] == 'R' ? 1 : 0; - ans = Math.min(ans, left + rAll); - } - // 0...N-1 左全部 右无 - ans = Math.min(ans, left + (str[N - 1] == 'G' ? 1 : 0)); - return ans; - } - - // RGRGR -> RRRGG - public static int test(String s) { - if (s == null || s.length() < 2) { - return 0; - } - char[] str = s.toCharArray(); - int ans = Integer.MAX_VALUE; - for (int leftEnd = -1; leftEnd < str.length; leftEnd++) { - int left = 0; - for (int i = 0; i <= leftEnd; i++) { - left += str[i] == 'G' ? 1 : 0; - } - int right = 0; - for (int i = leftEnd + 1; i < str.length; i++) { - right += str[i] == 'R' ? 1 : 0; - } - ans = Math.min(ans, left + right); - } - return ans; - } - - public static String generateString(int len) { - char[] str = new char[(int) (Math.random() * len) + 1]; - for (int i = 0; i < str.length; i++) { - str[i] = Math.random() < 0.5 ? 'R' : 'G'; - } - return String.valueOf(str); - } - - public static void main(String[] args) { - int len = 100; - int testTime = 100000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - String str = generateString(len); - int ans1 = minPaint(str); - int ans2 = test(str); - if (ans1 != ans2) { - System.out.println("Oops!"); - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class015/Code03_MaxABSBetweenLeftAndRight.java b/公开课/class015/Code03_MaxABSBetweenLeftAndRight.java deleted file mode 100644 index 0b69740..0000000 --- a/公开课/class015/Code03_MaxABSBetweenLeftAndRight.java +++ /dev/null @@ -1,72 +0,0 @@ -package class015; - -public class Code03_MaxABSBetweenLeftAndRight { - - public static int maxABS1(int[] arr) { - int res = Integer.MIN_VALUE; - int maxLeft = 0; - int maxRight = 0; - for (int i = 0; i != arr.length - 1; i++) { - maxLeft = Integer.MIN_VALUE; - for (int j = 0; j != i + 1; j++) { - maxLeft = Math.max(arr[j], maxLeft); - } - maxRight = Integer.MIN_VALUE; - for (int j = i + 1; j != arr.length; j++) { - maxRight = Math.max(arr[j], maxRight); - } - res = Math.max(Math.abs(maxLeft - maxRight), res); - } - return res; - } - - public static int maxABS2(int[] arr) { - int[] lArr = new int[arr.length]; - int[] rArr = new int[arr.length]; - lArr[0] = arr[0]; - rArr[arr.length - 1] = arr[arr.length - 1]; - for (int i = 1; i < arr.length; i++) { - lArr[i] = Math.max(lArr[i - 1], arr[i]); - } - for (int i = arr.length - 2; i > -1; i--) { - rArr[i] = Math.max(rArr[i + 1], arr[i]); - } - int max = 0; - for (int i = 0; i < arr.length - 1; i++) { - max = Math.max(max, Math.abs(lArr[i] - rArr[i + 1])); - } - return max; - } - - public static int maxABS3(int[] arr) { - int max = Integer.MIN_VALUE; - for (int i = 0; i < arr.length; i++) { - max = Math.max(arr[i], max); - } - return max - Math.min(arr[0], arr[arr.length - 1]); - } - - public static int[] generateRandomArray(int length) { - int[] arr = new int[length]; - for (int i = 0; i != arr.length; i++) { - arr[i] = (int) (Math.random() * 1000) - 499; - } - return arr; - } - - public static void main(String[] args) { - int len = 100; - int testTime = 100000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int[] arr = generateRandomArray(len); - int ans1 = maxABS1(arr); - int ans2 = maxABS2(arr); - int ans3 = maxABS3(arr); - if (ans1 != ans2 || ans1 != ans3) { - System.out.println("Oops!"); - } - } - System.out.println("测试结束"); - } -} diff --git a/公开课/class015/Code04_TrappingRainWater.java b/公开课/class015/Code04_TrappingRainWater.java deleted file mode 100644 index fd8145d..0000000 --- a/公开课/class015/Code04_TrappingRainWater.java +++ /dev/null @@ -1,121 +0,0 @@ -package class015; - -public class Code04_TrappingRainWater { - - /* - * 给定一个正整数数组arr,把arr想象成一个直方图。返回这个直方图如果装水,能装下几格水? - * - */ - - public static int water1(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int water = 0; - for (int i = 1; i < N - 1; i++) { - int leftMax = Integer.MIN_VALUE; - for (int j = 0; j < i; j++) { - leftMax = Math.max(leftMax, arr[j]); - } - int rightMax = Integer.MIN_VALUE; - for (int j = i + 1; j < N; j++) { - rightMax = Math.max(rightMax, arr[j]); - } - water += Math.max(Math.min(leftMax, rightMax) - arr[i], 0); - } - return water; - } - - public static int water2(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int[] leftMaxs = new int[N]; - leftMaxs[0] = arr[0]; - for (int i = 1; i < N; i++) { - leftMaxs[i] = Math.max(leftMaxs[i - 1], arr[i]); - } - - int[] rightMaxs = new int[N]; - rightMaxs[N - 1] = arr[N - 1]; - for (int i = N - 2; i >= 0; i--) { - rightMaxs[i] = Math.max(rightMaxs[i + 1], arr[i]); - } - int water = 0; - for (int i = 1; i < N - 1; i++) { - water += Math.max(Math.min(leftMaxs[i - 1], rightMaxs[i + 1]) - arr[i], 0); - } - return water; - } - - public static int water3(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int[] rightMaxs = new int[N]; - rightMaxs[N - 1] = arr[N - 1]; - for (int i = N - 2; i >= 0; i--) { - rightMaxs[i] = Math.max(rightMaxs[i + 1], arr[i]); - } - int water = 0; - int leftMax = arr[0]; - for (int i = 1; i < N - 1; i++) { - water += Math.max(Math.min(leftMax, rightMaxs[i + 1]) - arr[i], 0); - leftMax = Math.max(leftMax, arr[i]); - } - return water; - } - - public static int water4(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int L = 1; - int leftMax = arr[0]; - int R = N - 2; - int rightMax = arr[N - 1]; - int water = 0; - while (L <= R) { - if (leftMax <= rightMax) { - water += Math.max(0, leftMax - arr[L]); - leftMax = Math.max(leftMax, arr[L++]); - } else { - water += Math.max(0, rightMax - arr[R]); - rightMax = Math.max(rightMax, arr[R--]); - } - } - return water; - } - - // for test - public static int[] generateRandomArray(int len, int value) { - int[] ans = new int[(int) (Math.random() * len) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * value) + 1; - } - return ans; - } - - public static void main(String[] args) { - int len = 100; - int value = 200; - int testTimes = 100000; - System.out.println("测试开始"); - for (int i = 0; i < testTimes; i++) { - int[] arr = generateRandomArray(len, value); - int ans1 = water1(arr); - int ans2 = water2(arr); - int ans3 = water3(arr); - int ans4 = water4(arr); - if (ans1 != ans2 || ans3 != ans4 || ans1 != ans3) { - System.out.println("Oops!"); - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class016/Code01_RandToRand.java b/公开课/class016/Code01_RandToRand.java deleted file mode 100644 index 8804b59..0000000 --- a/公开课/class016/Code01_RandToRand.java +++ /dev/null @@ -1,138 +0,0 @@ -package class016; - -public class Code01_RandToRand { - - // 条件,且代码不可修改,1~5 - public static int f() { - return (int) (Math.random() * 5) + 1; - } - - // 等概率返回 0~4 - public static int a() { - return f() - 1; - } - - // 等概率返回 0 ~ 24 - public static int b() { - return a() * 5 + a(); - } - - // 等概率返回 1~7 - public static int g1() { - int t = 0; - do { - t = b(); - } while (t > 20); - // t 0 ~ 20 - return (t % 7) + 1; - } - - // 利用f函数,请等概率生成0和1 - public static int c() { - int t = 0; - do { - t = f(); - } while (t == 3); - return t < 3 ? 0 : 1; - } - - // 等概率返回 1~7 - public static int g2() { - int t = 0; - do { - t = (c() << 2) + (c() << 1) + c(); - } while (t == 7); - return t + 1; - } - - // 这个结构是唯一的随机机制 - // 你只能初始化并使用,不可修改 - public static class RandomBox { - private final int min; - private final int max; - - // 初始化时请一定不要让mi==ma - public RandomBox(int mi, int ma) { - min = mi; - max = ma; - } - - public int random() { - return min + (int) (Math.random() * (max - min + 1)); - } - - public int min() { - return min; - } - - public int max() { - return max; - } - } - - // 利用条件RandomBox,如何等概率返回0和1 - public static int rand01(RandomBox randomBox) { - int min = randomBox.min(); - int max = randomBox.max(); - // min ~ max - int size = max - min + 1; - // size是不是奇数,odd 奇数 - boolean odd = (size & 1) != 0; - int mid = size / 2; - int ans = 0; - do { - ans = randomBox.random() - min; - } while (odd && ans == mid); - return ans < mid ? 0 : 1; - } - - // 给你一个RandomBox,这是唯一能借助的随机机制 - // 等概率返回from~to范围上任何一个数 - // 要求from<=to - public static int random(RandomBox randomBox, int from, int to) { - if (from == to) { - return from; - } - // 3 ~ 9 - // 0 ~ 6 - // 0 ~ range - int range = to - from; - int num = 1; - // 求0~range需要几个2进制位 - while ((1 << num) - 1 < range) { - num++; - } - - // 我们一共需要num位 - // 最终的累加和,首先+0位上是1还是0,1位上是1还是0,2位上是1还是0... - int ans = 0; - do { - ans = 0; - for (int i = 0; i < num; i++) { - ans |= (rand01(randomBox) << i); - } - } while (ans > range); - return ans + from; - } - - public static void main(String[] args) { - int hasFrom = 1; - int hasTo = 19; - - int from = 7; - int to = 29; - - RandomBox randomBox = new RandomBox(hasFrom, hasTo); - int[] ans = new int[to + 1]; - int testTime1 = 1000000; - for (int i = 0; i < testTime1; i++) { - ans[random(randomBox, from, to)]++; - } - for (int i = 0; i < ans.length; i++) { - System.out.println(i + " 出现了 : " + ans[i]); - } - System.out.println("=========="); - - } - -} diff --git a/公开课/class016/Code02_EqualProbabilityRandom.java b/公开课/class016/Code02_EqualProbabilityRandom.java deleted file mode 100644 index 3d8ed13..0000000 --- a/公开课/class016/Code02_EqualProbabilityRandom.java +++ /dev/null @@ -1,46 +0,0 @@ -package class016; - -public class Code02_EqualProbabilityRandom { - - // 这个结构是唯一的随机机制 - // 你只能初始化并使用,不可修改 - public static class RandomBox { - private final double p; - - // 初始化时请一定满足:0 < zeroP < 1 - public RandomBox(double zeroP) { - p = zeroP; - } - - public int random() { - return Math.random() < p ? 0 : 1; - } - - } - - // 底层依赖一个以p概率返回0,以1-p概率返回1的随机函数rand01p - // 如何加工出等概率返回0和1的函数 - public static int rand01(RandomBox randomBox) { - int num; - do { - num = randomBox.random(); - } while (num == randomBox.random()); - return num; - } - - public static void main(String[] args) { - double zeroP = 0.88; - RandomBox randomBox = new RandomBox(zeroP); - - int testTime = 10000000; - int count = 0; - for (int i = 0; i < testTime; i++) { - if (rand01(randomBox) == 0) { - count++; - } - } - System.out.println((double) count / (double) testTime); - - } - -} diff --git a/公开课/class016/Code03_FindHalfMajority.java b/公开课/class016/Code03_FindHalfMajority.java deleted file mode 100644 index acadae6..0000000 --- a/公开课/class016/Code03_FindHalfMajority.java +++ /dev/null @@ -1,77 +0,0 @@ -package class016; - -import java.util.HashMap; -import java.util.Map.Entry; - -public class Code03_FindHalfMajority { - - public static int halfMajor(int[] arr) { - int cand = 0; - int HP = 0; - // 遍历一遍数组arr,一次删掉两个不同的数,谁会剩下来,谁就是cand - for (int i = 0; i != arr.length; i++) { - if (HP == 0) { - cand = arr[i]; - HP = 1; - } else if (arr[i] == cand) { - HP++; - } else { - HP--; - } - } - if (HP == 0) { - return -1; - } - HP = 0; - for (int i = 0; i != arr.length; i++) { - if (arr[i] == cand) { - HP++; - } - } - return HP > arr.length / 2 ? cand : -1; - } - - // for test - public static int right(int[] arr) { - HashMap map = new HashMap<>(); - for (int cur : arr) { - if (!map.containsKey(cur)) { - map.put(cur, 0); - } - map.put(cur, map.get(cur) + 1); - } - for (Entry entry : map.entrySet()) { - if (entry.getValue() > arr.length / 2) { - return entry.getKey(); - } - } - return -1; - } - - // for test - public static int[] genareteRandomArray(int len, int max) { - int[] ans = new int[(int) (Math.random() * len) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * max) + 1; - } - return ans; - } - - public static void main(String[] args) { - int len = 100; - int max = 10; - int testTime = 100000; - System.out.println("test begin"); - for (int i = 0; i < testTime; i++) { - int[] arr = genareteRandomArray(len, max); - int ans1 = halfMajor(arr); - int ans2 = right(arr); - if (ans1 != ans2) { - System.out.println("Oops!"); - break; - } - } - System.out.println("test end"); - } - -} diff --git a/公开课/class016/Code04_FindKMajor.java b/公开课/class016/Code04_FindKMajor.java deleted file mode 100644 index a76ab1b..0000000 --- a/公开课/class016/Code04_FindKMajor.java +++ /dev/null @@ -1,135 +0,0 @@ -package class016; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map.Entry; - -public class Code04_FindKMajor { - - public static List kMajor(int[] arr, int K) { - List ans = new ArrayList<>(); - if (K < 2) { - return ans; - } - // 候选表,记录数一定是O(K) > N/K k-1 - HashMap cands = new HashMap(); - for (int i = 0; i != arr.length; i++) { - if (cands.containsKey(arr[i])) { - cands.put(arr[i], cands.get(arr[i]) + 1); - } else { - if (cands.size() == K - 1) { - allCandsMinusOne(cands); - } else { - cands.put(arr[i], 1); - } - } - } - HashMap reals = getReals(arr, cands); - for (Entry set : cands.entrySet()) { - Integer key = set.getKey(); - if (reals.get(key) > arr.length / K) { - ans.add(key); - } - } - return ans; - } - - public static void allCandsMinusOne(HashMap map) { - List removeList = new LinkedList(); - for (Entry set : map.entrySet()) { - Integer key = set.getKey(); - Integer value = set.getValue(); - if (value == 1) { - removeList.add(key); - } - map.put(key, value - 1); - } - for (Integer removeKey : removeList) { - map.remove(removeKey); - } - } - - // for test - public static List right(int[] arr, int K) { - List ans = new ArrayList<>(); - if (K < 2) { - return ans; - } - HashMap times = new HashMap<>(); - for (int num : arr) { - if (!times.containsKey(num)) { - times.put(num, 1); - } else { - times.put(num, times.get(num) + 1); - } - } - for (Entry entry : times.entrySet()) { - if (entry.getValue() > arr.length / K) { - ans.add(entry.getKey()); - } - } - return ans; - } - - public static HashMap getReals(int[] arr, HashMap cands) { - HashMap reals = new HashMap(); - for (int i = 0; i != arr.length; i++) { - int curNum = arr[i]; - if (cands.containsKey(curNum)) { - if (reals.containsKey(curNum)) { - reals.put(curNum, reals.get(curNum) + 1); - } else { - reals.put(curNum, 1); - } - } - } - return reals; - } - - public static int[] genareteRandomArray(int len, int max) { - int[] ans = new int[(int) (Math.random() * len) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * max) + 1; - } - return ans; - } - - public static boolean isEqual(List ans1, List ans2) { - if (ans1.size() != ans2.size()) { - return false; - } - HashSet set1 = new HashSet<>(); - for (Integer num : ans1) { - set1.add(num); - } - if (set1.size() != ans1.size()) { - return false; - } - for (Integer num : ans2) { - set1.remove(num); - } - return set1.size() == 0; - } - - public static void main(String[] args) { - int len = 100; - int max = 10; - int K = 5; - int testTime = 100000; - System.out.println("test begin"); - for (int i = 0; i < testTime; i++) { - int[] arr = genareteRandomArray(len, max); - List ans1 = kMajor(arr, K); - List ans2 = right(arr, K); - if (!isEqual(ans1, ans2)) { - System.out.println("Oops!"); - break; - } - } - System.out.println("test end"); - } - -} diff --git a/公开课/class017/Code01_SubArrayMaxSum.java b/公开课/class017/Code01_SubArrayMaxSum.java deleted file mode 100644 index 05895f4..0000000 --- a/公开课/class017/Code01_SubArrayMaxSum.java +++ /dev/null @@ -1,111 +0,0 @@ -package class017; - -import java.util.ArrayList; -import java.util.List; - -public class Code01_SubArrayMaxSum { - - public static int test(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int N = arr.length; - int max = Integer.MIN_VALUE; - for (int L = 0; L < N; L++) { - for (int R = L; R < N; R++) { - // arr[L...R] - int sum = 0; - for (int i = L; i <= R; i++) { - sum += arr[i]; - } - max = Math.max(max, sum); - } - } - return max; - } - - public static int maxSum1(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - // 0结尾时候的答案 - int pre = arr[0]; - int max = arr[0]; - for (int i = 1; i < arr.length; i++) { - // i结尾时候的答案 - pre = arr[i] + (pre > 0 ? pre : 0); - max = Math.max(max, pre); - } - return max; - } - - public static List> maxSum2(int[] arr) { - List> ans = new ArrayList<>(); - if (arr == null || arr.length == 0) { - return ans; - } - int L = 0; - int maxLen = 0; - int maxSum = Integer.MIN_VALUE; - int cur = 0; - for (int i = 0; i < arr.length; i++) { - // L...i sum - cur += arr[i]; - if (cur == maxSum && (i - L + 1) == maxLen) { - List curAns = new ArrayList<>(); - curAns.add(L); - curAns.add(i); - ans.add(curAns); - } - if (cur > maxSum || (cur == maxSum && (i - L + 1) > maxLen)) { - ans.clear(); - List curAns = new ArrayList<>(); - curAns.add(L); - curAns.add(i); - ans.add(curAns); - maxLen = i - L + 1; - } - maxSum = Math.max(maxSum, cur); - if (cur < 0) { - cur = 0; - L = i + 1; - } - } - return ans; - } - - public static int[] generateArray(int N, int V) { - int n = (int) (Math.random() * N) + 1; - int[] arr = new int[n]; - for (int i = 0; i < n; i++) { - arr[i] = (int) (Math.random() * V) - (int) (Math.random() * V); - } - return arr; - } - - public static void main(String[] args) { -// int N = 100; -// int V = 100; -// int testTime = 1000000; -// System.out.println("test begin"); -// for (int i = 0; i < testTime; i++) { -// int[] arr = generateArray(N, V); -// int ans1 = maxSum1(arr); -// int ans2 = maxSum2(arr); -// if (ans1 != ans2) { -// System.out.println("Oops!"); -// } -// } -// System.out.println("test finish"); - - int[] test = { 2, 2, 1, -9, 2, 3, -9, 6, -9, 2, 2, 2, -9, 2, 2, 2, -9, 1, 4, 1 }; - - List> ans = maxSum2(test); - - for (List cur : ans) { - System.out.println("start : " + cur.get(0) + ", end : " + cur.get(1)); - } - - } - -} diff --git a/公开课/class017/Code02_SubMatrixMaxSum.java b/公开课/class017/Code02_SubMatrixMaxSum.java deleted file mode 100644 index 442471b..0000000 --- a/公开课/class017/Code02_SubMatrixMaxSum.java +++ /dev/null @@ -1,83 +0,0 @@ -package class017; - -public class Code02_SubMatrixMaxSum { - - public static int maxSum1(int[][] matrix) { - int n = matrix.length; - int m = matrix[0].length; - int max = Integer.MIN_VALUE; - for (int ai = 0; ai < n; ai++) { - for (int aj = 0; aj < m; aj++) { - for (int bi = ai; bi < n; bi++) { - for (int bj = aj; bj < m; bj++) { - max = Math.max(max, sum(matrix, ai, aj, bi, bj)); - } - } - } - } - return max; - } - - public static int sum(int[][] matrix, int ai, int aj, int bi, int bj) { - int sum = 0; - for (int i = ai; i <= bi; i++) { - for (int j = aj; j <= bj; j++) { - sum += matrix[i][j]; - } - } - return sum; - } - - public static int maxSum2(int[][] matrix) { - if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { - return 0; - } - int max = Integer.MIN_VALUE; - int cur = 0; - int[] s = null; - for (int i = 0; i != matrix.length; i++) { - s = new int[matrix[0].length]; - for (int j = i; j != matrix.length; j++) { - cur = 0; - for (int k = 0; k != s.length; k++) { - s[k] += matrix[j][k]; - cur += s[k]; - max = Math.max(max, cur); - cur = cur < 0 ? 0 : cur; - } - } - } - return max; - } - - public static int[][] generateMatrix(int N, int M, int V) { - int n = (int) (Math.random() * N) + 1; - int m = (int) (Math.random() * M) + 1; - int[][] matrix = new int[n][m]; - for (int i = 0; i < n; i++) { - for (int j = 0; j < m; j++) { - matrix[i][j] = (int) (Math.random() * V) - (int) (Math.random() * V); - } - } - return matrix; - } - - public static void main(String[] args) { - int N = 20; - int M = 20; - int V = 100; - int testTime = 50000; - System.out.println("test begin"); - for (int i = 0; i < testTime; i++) { - int[][] matrix = generateMatrix(N, M, V); - int ans1 = maxSum1(matrix); - int ans2 = maxSum2(matrix); - if (ans1 != ans2) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - - } - -} diff --git a/公开课/class018/Code01_SqrtX.java b/公开课/class018/Code01_SqrtX.java deleted file mode 100644 index 15bb042..0000000 --- a/公开课/class018/Code01_SqrtX.java +++ /dev/null @@ -1,31 +0,0 @@ -package class018; - -public class Code01_SqrtX { - - // x一定非负,输入可以保证 - public static int mySqrt(int x) { - if (x == 0) { - return 0; - } - // x != 0 1 2 - if (x < 3) { - return 1; - } - // x >= 3 - long ans = 1; - long L = 1; - long R = x; - long M = 0; - while (L <= R) { - M = (L + R) / 2; - if (M * M <= x) { - ans = M; - L = M + 1; - } else { - R = M - 1; - } - } - return (int) ans; - } - -} diff --git a/公开课/class018/Code02_PowXN.java b/公开课/class018/Code02_PowXN.java deleted file mode 100644 index 03e7fa0..0000000 --- a/公开课/class018/Code02_PowXN.java +++ /dev/null @@ -1,54 +0,0 @@ -package class018; - -public class Code02_PowXN { - - public static void main(String[] args) { - long a = 2; - long n = 13; // 1101 - long t = a; - long res = 1; - while (n != 0) { - // n = 110111011111 - // & 1 = 000000000001 - // 000000000000 - // n & (n-1) - // 把n抹掉最右侧的1 - // n = 10010101100010000 - // n-1 = 10010101100001111 - // & = 10010101100000000 - if ((n & 1) == 1) { - res *= t; - } - t = t * t; - n = n >> 1; - } - System.out.println(res); - System.out.println(Math.pow(2.0, 13)); - System.out.println(-Integer.MIN_VALUE); - System.out.println(Math.abs(Integer.MIN_VALUE)); - - } - - // 求x的n次方 - public static double myPow(double x, int n) { - if (n == 0) { - return 1D; - } - if (n == Integer.MIN_VALUE) { - return (x == 1D || x == -1D) ? 1D : 0; - } - // 4.5 -3 - int pow = Math.abs(n); - double t = x; - double ans = 1D; - while (pow != 0) { - if ((pow & 1) != 0) { - ans *= t; - } - pow >>= 1; - t = t * t; - } - return n < 0 ? (1D / ans) : ans; - } - -} diff --git a/公开课/class018/Code03_ContainerWithMostWater.java b/公开课/class018/Code03_ContainerWithMostWater.java deleted file mode 100644 index 9c4f60d..0000000 --- a/公开课/class018/Code03_ContainerWithMostWater.java +++ /dev/null @@ -1,31 +0,0 @@ -package class018; - -public class Code03_ContainerWithMostWater { - - public static int maxArea1(int[] h) { - int max = 0; - int N = h.length; - for (int i = 0; i < N; i++) { // h[i] - for (int j = i + 1; j < N; j++) { // h[j] - max = Math.max(max, Math.min(h[i], h[j]) * (j - i)); - } - } - return max; - } - - public static int maxArea2(int[] h) { - int max = 0; - int l = 0; - int r = h.length - 1; - while (l < r) { - max = Math.max(max, Math.min(h[l], h[r]) * (r - l)); - if (h[l] > h[r]) { - r--; - } else { - l++; - } - } - return max; - } - -} diff --git a/公开课/class019/Code01_RotateImage.java b/公开课/class019/Code01_RotateImage.java deleted file mode 100644 index 5cecb1d..0000000 --- a/公开课/class019/Code01_RotateImage.java +++ /dev/null @@ -1,27 +0,0 @@ -package class019; - -public class Code01_RotateImage { - - public static void rotate(int[][] matrix) { - // matrix.length == matrix[0].length - int a = 0; - int b = 0; - int c = matrix.length - 1; - int d = matrix[0].length - 1; - while (a < c) { - rotateEdge(matrix, a++, b++, c--, d--); - } - } - - public static void rotateEdge(int[][] m, int a, int b, int c, int d) { - int tmp = 0; - for (int i = 0; i < d - b; i++) { - tmp = m[a][b + i]; - m[a][b + i] = m[c - i][b]; - m[c - i][b] = m[c][d - i]; - m[c][d - i] = m[a + i][d]; - m[a + i][d] = tmp; - } - } - -} diff --git a/公开课/class019/Code02_ZigZagPrintMatrix.java b/公开课/class019/Code02_ZigZagPrintMatrix.java deleted file mode 100644 index 069e84d..0000000 --- a/公开课/class019/Code02_ZigZagPrintMatrix.java +++ /dev/null @@ -1,48 +0,0 @@ -package class019; - -public class Code02_ZigZagPrintMatrix { - - public static void printMatrixZigZag(int[][] matrix) { - int aRow = 0; - int aCol = 0; - int bRow = 0; - int bCol = 0; - // A和B一定会共同走到右下角的位置 - int endR = matrix.length - 1; - int endC = matrix[0].length - 1; - // fromUp = true 斜线打印方向应该从右上走到左下 - // fromUp = false 斜线打印方向应该从左下走到右上 - boolean fromUp = false; - while (aRow != endR + 1) { - printLevel(matrix, aRow, aCol, bRow, bCol, fromUp); - aRow = aCol == endC ? aRow + 1 : aRow; - aCol = aCol == endC ? aCol : aCol + 1; - bCol = bRow == endR ? bCol + 1 : bCol; - bRow = bRow == endR ? bRow : bRow + 1; - fromUp = !fromUp; - } - System.out.println(); - } - - public static void printLevel(int[][] m, int aRow, int aCol, int bRow, int bCol, boolean f) { - if (f) { - while (aRow != bRow + 1) { - System.out.print(m[aRow++][aCol--] + " "); - } - } else { - while (bRow != aRow - 1) { - System.out.print(m[bRow--][bCol++] + " "); - } - } - } - - public static void main(String[] args) { - int[][] matrix = { - { 1, 2, 3, 4 }, - { 5, 6, 7, 8 }, - { 9, 10, 11, 12 } }; - printMatrixZigZag(matrix); - - } - -} diff --git a/公开课/class019/Code03_PrintStar.java b/公开课/class019/Code03_PrintStar.java deleted file mode 100644 index 286b6dc..0000000 --- a/公开课/class019/Code03_PrintStar.java +++ /dev/null @@ -1,46 +0,0 @@ -package class019; - -public class Code03_PrintStar { - - public static void printStar(int N) { - int leftUp = 0; - int rightDown = N - 1; - char[][] m = new char[N][N]; - for (int i = 0; i < N; i++) { - for (int j = 0; j < N; j++) { - m[i][j] = ' '; - } - } - while (leftUp <= rightDown) { - set(m, leftUp, rightDown); - leftUp += 2; - rightDown -= 2; - } - for (int i = 0; i < N; i++) { - for (int j = 0; j < N; j++) { - System.out.print(m[i][j] + " "); - } - System.out.println(); - } - } - - public static void set(char[][] m, int leftUp, int rightDown) { - for (int col = leftUp; col <= rightDown; col++) { - m[leftUp][col] = '*'; - } - for (int row = leftUp + 1; row <= rightDown; row++) { - m[row][rightDown] = '*'; - } - for (int col = rightDown - 1; col > leftUp; col--) { - m[rightDown][col] = '*'; - } - for (int row = rightDown - 1; row > leftUp + 1; row--) { - m[row][leftUp + 1] = '*'; - } - } - - public static void main(String[] args) { - printStar(8); - } - -} diff --git a/公开课/class020/Code01_RotateString.java b/公开课/class020/Code01_RotateString.java deleted file mode 100644 index 826ba5a..0000000 --- a/公开课/class020/Code01_RotateString.java +++ /dev/null @@ -1,93 +0,0 @@ -package class020; - -public class Code01_RotateString { - - public static String rotate1(String s, int leftSize) { - if (leftSize <= 0 || leftSize >= s.length()) { - return s; - } - return process1(s.toCharArray(), 0, leftSize - 1, s.length() - 1); - } - - public static String process1(char[] str, int L, int M, int R) { - reverse(str, L, M); - reverse(str, M + 1, R); - reverse(str, L, R); - return String.valueOf(str); - } - - public static void reverse(char[] str, int L, int R) { - while (L < R) { - char tmp = str[L]; - str[L++] = str[R]; - str[R--] = tmp; - } - } - - public static String rotate2(String s, int leftSize) { - if (leftSize <= 0 || leftSize >= s.length()) { - return s; - } - char[] str = s.toCharArray(); - int L = 0; - int R = str.length - 1; - int lpart = leftSize; - int rpart = str.length - leftSize; - int same = Math.min(lpart, rpart); - int diff = lpart - rpart; - exchange(str, L, R, same); - while (diff != 0) { - if (diff > 0) { - L += same; - lpart = diff; - } else { - R -= same; - rpart = -diff; - } - same = Math.min(lpart, rpart); - diff = lpart - rpart; - exchange(str, L, R, same); - } - return String.valueOf(str); - } - - public static void exchange(char[] chas, int start, int end, int size) { - int i = end - size + 1; - char tmp = 0; - while (size-- != 0) { - tmp = chas[start]; - chas[start] = chas[i]; - chas[i] = tmp; - start++; - i++; - } - } - - // for test - public static String getRandomString(int possibilities, int strMaxSize) { - char[] ans = new char[(int) (Math.random() * strMaxSize) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (char) ((int) (Math.random() * possibilities) + 'a'); - } - return String.valueOf(ans); - } - - public static void main(String[] args) { - int possibilities = 5; - int strMaxSize = 10; - int testTimes = 5000000; - System.out.println("test begin, test time : " + testTimes); - for (int i = 0; i < testTimes; i++) { - String str = getRandomString(possibilities, strMaxSize); - int leftSize = (int) (Math.random() * (str.length() + 1)); - String ans1 = rotate1(str, leftSize); - String ans2 = rotate2(str, leftSize); - if (!ans1.equals(ans2)) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - - } - -} diff --git a/公开课/class020/Code02_HowManyTypes.java b/公开课/class020/Code02_HowManyTypes.java deleted file mode 100644 index 193b242..0000000 --- a/公开课/class020/Code02_HowManyTypes.java +++ /dev/null @@ -1,111 +0,0 @@ -package class020; - -import java.util.HashSet; - -public class Code02_HowManyTypes { - - /* - * 只由小写字母(a~z)组成的一批字符串,都放在字符类型的数组String[] arr中, - * 如果其中某两个字符串,所含有的字符种类完全一样,就将两个字符串算作一类 比如:baacba和bac就算作一类 - * 虽然长度不一样,但是所含字符的种类完全一样(a、b、c) 返回arr中有多少类? - * - */ - - public static int types1(String[] arr) { - HashSet types = new HashSet<>(); - for (String str : arr) { - char[] chs = str.toCharArray(); - boolean[] map = new boolean[26]; - for (int i = 0; i < chs.length; i++) { - map[chs[i] - 'a'] = true; - } - String key = ""; - for (int i = 0; i < 26; i++) { - if (map[i]) { - key += String.valueOf((char) (i + 'a')); - } - } - types.add(key); - } - return types.size(); - } - - public static int types2(String[] arr) { - HashSet types = new HashSet<>(); - for (String str : arr) { - char[] chs = str.toCharArray(); - int key = 0; - for (int i = 0; i < chs.length; i++) { - key |= (1 << (chs[i] - 'a')); - } - types.add(key); - } - return types.size(); - } - - // for test - public static String[] getRandomStringArray(int possibilities, int strMaxSize, int arrMaxSize) { - String[] ans = new String[(int) (Math.random() * arrMaxSize) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = getRandomString(possibilities, strMaxSize); - } - return ans; - } - - // for test - public static String getRandomString(int possibilities, int strMaxSize) { - char[] ans = new char[(int) (Math.random() * strMaxSize) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (char) ((int) (Math.random() * possibilities) + 'a'); - } - return String.valueOf(ans); - } - - public static void printIntegerBinary(int num) { - StringBuilder builder = new StringBuilder(); - for (int i = 31; i >= 0; i--) { - // 依次提取出num从0位~31位的状态来 - int status = ((num >> i) & 1); - builder.append(status); - - } - System.out.println(builder.toString()); - } - - public static void main(String[] args) { - int num = 3; - printIntegerBinary(num); - - char[] str = { 'b', 'b', 'z', 'k', 'o' }; - - int key = 0; - // 如何生成str的摘要? - // 00000000000000000000000000000000 - - for (int i = 0; i < str.length; i++) { - char cha = str[i]; - // cha = a - // cha - 'a' ? 0 - // 1 << (cha - 'a') -> 1 << 0 - key = key | (1 << (cha - 'a')); - } - printIntegerBinary(key); - - int possibilities = 5; - int strMaxSize = 10; - int arrMaxSize = 100; - int testTimes = 500000; - System.out.println("test begin, test time : " + testTimes); - for (int i = 0; i < testTimes; i++) { - String[] arr = getRandomStringArray(possibilities, strMaxSize, arrMaxSize); - int ans1 = types1(arr); - int ans2 = types2(arr); - if (ans1 != ans2) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - - } - -} diff --git a/公开课/class020/Code03_LongestNoRepeatSubstring.java b/公开课/class020/Code03_LongestNoRepeatSubstring.java deleted file mode 100644 index 1bbbdb9..0000000 --- a/公开课/class020/Code03_LongestNoRepeatSubstring.java +++ /dev/null @@ -1,77 +0,0 @@ -package class020; - -public class Code03_LongestNoRepeatSubstring { - - /* - * 给定一个只由小写字母(a~z)组成的字符串str, 返回其中最长无重复字符的子串长度 - * - */ - - public static int lnrs1(String s) { - if (s == null || s.length() == 0) { - return 0; - } - char[] str = s.toCharArray(); - int N = str.length; - int max = 0; - for (int i = 0; i < N; i++) { - boolean[] set = new boolean[26]; - for (int j = i; j < N; j++) { - if (set[str[j] - 'a']) { - break; - } - set[str[j] - 'a'] = true; - max = Math.max(max, j - i + 1); - } - } - return max; - } - - public static int lnrs2(String s) { - if (s == null || s.length() == 0) { - return 0; - } - char[] str = s.toCharArray(); - int N = str.length; - int[] last = new int[26]; - for (int i = 0; i < 26; i++) { - last[i] = -1; - } - last[str[0] - 'a'] = 0; - int max = 1; - int preMaxLen = 1; - for (int i = 1; i < N; i++) { - preMaxLen = Math.min(i - last[str[i] - 'a'], preMaxLen + 1); - max = Math.max(max, preMaxLen); - last[str[i] - 'a'] = i; - } - return max; - } - - // for test - public static String getRandomString(int possibilities, int maxSize) { - char[] ans = new char[(int) (Math.random() * maxSize) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (char) ((int) (Math.random() * possibilities) + 'a'); - } - return String.valueOf(ans); - } - - public static void main(String[] args) { - int possibilities = 26; - int strMaxSize = 100; - int testTimes = 1000000; - System.out.println("test begin, test time : " + testTimes); - for (int i = 0; i < testTimes; i++) { - String str = getRandomString(possibilities, strMaxSize); - int ans1 = lnrs1(str); - int ans2 = lnrs2(str); - if (ans1 != ans2) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - - } - -} diff --git a/公开课/class020/Code04_CoverMax.java b/公开课/class020/Code04_CoverMax.java deleted file mode 100644 index 30f5274..0000000 --- a/公开课/class020/Code04_CoverMax.java +++ /dev/null @@ -1,133 +0,0 @@ -package class020; - -import java.util.Arrays; -import java.util.Comparator; -import java.util.PriorityQueue; - -public class Code04_CoverMax { - - public static int maxCover1(int[][] lines) { - int min = Integer.MAX_VALUE; - int max = Integer.MIN_VALUE; - for (int i = 0; i < lines.length; i++) { - min = Math.min(min, lines[i][0]); - max = Math.max(max, lines[i][1]); - } - int cover = 0; - for (double p = min + 0.5; p < max; p += 1) { - int cur = 0; - for (int i = 0; i < lines.length; i++) { - if (lines[i][0] < p && lines[i][1] > p) { - cur++; - } - } - cover = Math.max(cover, cur); - } - return cover; - } - - public static int maxCover2(int[][] m) { - Line[] lines = new Line[m.length]; - for (int i = 0; i < m.length; i++) { - lines[i] = new Line(m[i][0], m[i][1]); - } - Arrays.sort(lines, new StartComparator()); - // lines - // - PriorityQueue heap = new PriorityQueue<>(); - int max = 0; - for (int i = 0; i < lines.length; i++) { - // lines[i] -> cur 在黑盒中,把<=cur.start 东西都弹出 - while (!heap.isEmpty() && heap.peek() <= lines[i].start) { - heap.poll(); - } - heap.add(lines[i].end); - max = Math.max(max, heap.size()); - } - return max; - } - - public static class Line { - public int start; - public int end; - - public Line(int s, int e) { - start = s; - end = e; - } - } - - public static class EndComparator implements Comparator { - - @Override - public int compare(Line o1, Line o2) { - return o1.end - o2.end; - } - - } - - // for test - public static int[][] generateLines(int N, int L, int R) { - int size = (int) (Math.random() * N) + 1; - int[][] ans = new int[size][2]; - for (int i = 0; i < size; i++) { - int a = L + (int) (Math.random() * (R - L + 1)); - int b = L + (int) (Math.random() * (R - L + 1)); - if (a == b) { - b = a + 1; - } - ans[i][0] = Math.min(a, b); - ans[i][1] = Math.max(a, b); - } - return ans; - } - - public static class StartComparator implements Comparator { - - @Override - public int compare(Line o1, Line o2) { - return o1.start - o2.start; - } - - } - - public static void main(String[] args) { - - Line l1 = new Line(4, 9); - Line l2 = new Line(1, 4); - Line l3 = new Line(7, 15); - Line l4 = new Line(2, 4); - Line l5 = new Line(4, 6); - Line l6 = new Line(3, 7); - - // 底层堆结构,heap - PriorityQueue heap = new PriorityQueue<>(new StartComparator()); - heap.add(l1); - heap.add(l2); - heap.add(l3); - heap.add(l4); - heap.add(l5); - heap.add(l6); - - while (!heap.isEmpty()) { - Line cur = heap.poll(); - System.out.println(cur.start + "," + cur.end); - } - - System.out.println("test begin"); - int N = 100; - int L = 0; - int R = 200; - int testTimes = 200000; - for (int i = 0; i < testTimes; i++) { - int[][] lines = generateLines(N, L, R); - int ans1 = maxCover1(lines); - int ans2 = maxCover2(lines); - if (ans1 != ans2) { - System.out.println("Oops!"); - } - } - System.out.println("test end"); - } - -} diff --git a/公开课/class020/Code05_MakeNo.java b/公开课/class020/Code05_MakeNo.java deleted file mode 100644 index fc7d49c..0000000 --- a/公开课/class020/Code05_MakeNo.java +++ /dev/null @@ -1,60 +0,0 @@ -package class020; - -public class Code05_MakeNo { - - // 生成长度为size的达标数组 - // 达标:对于任意的 i 等长奇数达标来 - // base -> 等长偶数达标来 - int[] ans = new int[size]; - int index = 0; - for(; index < halfSize;index++) { - ans[index] = base[index] * 2 + 1; - } - for(int i = 0 ;index < size;index++,i++) { - ans[index] = base[i] * 2; - } - return ans; - } - - - // 检验函数 - public static boolean isValid(int[] arr) { - int N = arr.length; - for (int i = 0; i < N; i++) { - for (int k = i + 1; k < N; k++) { - for (int j = k + 1; j < N; j++) { - if (arr[i] + arr[j] == 2 * arr[k]) { - return false; - } - } - } - } - return true; - } - - public static void main(String[] args) { - System.out.println("test begin"); - for (int N = 1; N < 1000; N++) { - int[] arr = makeNo(N); - if (!isValid(arr)) { - System.out.println("Oops!"); - } - } - System.out.println("test end"); - System.out.println(isValid(makeNo(1042))); - System.out.println(isValid(makeNo(2981))); - } - -} diff --git a/公开课/class021/Code01_SwapWithoutTmp.java b/公开课/class021/Code01_SwapWithoutTmp.java deleted file mode 100644 index df7b9c9..0000000 --- a/公开课/class021/Code01_SwapWithoutTmp.java +++ /dev/null @@ -1,17 +0,0 @@ -package class021; - -public class Code01_SwapWithoutTmp { - - public static void main(String[] args) { - int a = 123; - int b = -898121; - System.out.println(a); - System.out.println(b); - a = a ^ b; - b = a ^ b; - a = a ^ b; - System.out.println(a); - System.out.println(b); - } - -} diff --git a/公开课/class021/Code02_GetMax.java b/公开课/class021/Code02_GetMax.java deleted file mode 100644 index 339f796..0000000 --- a/公开课/class021/Code02_GetMax.java +++ /dev/null @@ -1,55 +0,0 @@ -package class021; - -public class Code02_GetMax { - - // 输入参数:n,一定要保证,n不是1就是0 - // n == 0 -> 1 - // n == 1 -> 0 - public static int flip(int n) { - return n ^ 1; - } - - // 输入参数n,可以是任何一个整数 - // 如果n是非负数,返回1(int) - // 如果n是负数,返回0(int) - public static int sign(int n) { - return flip((n >> 31) & 1); - } - - // a和b中,谁大返回谁 - public static int getMax1(int a, int b) { - int c = a - b; - int scA = sign(c); // c >= 0 scA = 1; c < 0 scA = 0 - int scB = flip(scA); - return a * scA + b * scB; - } - - public static int getMax2(int a, int b) { - int c = a - b; // c是a-b的差值,有可能溢出,也有可能不溢出 - int sa = sign(a); // a的符号,求出,a>=0 1, a<0 0 - int sb = sign(b); // b的符号,求出,b>=0 1, b<0 0 - int sc = sign(c); // c的符号,求出,c>=0 1, c<0 0 - // 如果a和b的符号,不一样,difSab == 1 - // 如果a和b的符号, 一样,difSab == 0 - int difSab = sa ^ sb; - // 如果a和b的符号,一样,sameSab == 1 - // 如果a和b的符号,不一样,sameSab == 0 - int sameSab = flip(difSab); - int returnA = difSab * sa + sameSab * sc; - int returnB = flip(returnA); - return a * returnA + b * returnB; - } - - public static void main(String[] args) { - int a = -16; - int b = 1; - System.out.println(getMax1(a, b)); - System.out.println(getMax2(a, b)); - a = 2147483647; - b = -2147480000; - System.out.println(getMax1(a, b)); // wrong answer because of overflow - System.out.println(getMax2(a, b)); - - } - -} diff --git a/公开课/class021/Code03_EvenTimesOddTimes.java b/公开课/class021/Code03_EvenTimesOddTimes.java deleted file mode 100644 index b93fe1a..0000000 --- a/公开课/class021/Code03_EvenTimesOddTimes.java +++ /dev/null @@ -1,71 +0,0 @@ -package class021; - -public class Code03_EvenTimesOddTimes { - - // arr中,只有一种数,出现奇数次 - public static void printOddTimesNum1(int[] arr) { - int eor = 0; - for (int i = 0; i < arr.length; i++) { - eor ^= arr[i]; - } - System.out.println(eor); - } - - // arr中,有两种数,出现奇数次 - public static void printOddTimesNum2(int[] arr) { - int eor = 0; - for (int i = 0; i < arr.length; i++) { - eor ^= arr[i]; - } - // eor = a ^ b - // eor != 0 - // eor必然有一个位置上是1 - // 0110010000 - // 0000010000 - int rightOne = eor & (~eor + 1); // 提取出最右的1 - int onlyOne = 0; // e' - for (int i = 0; i < arr.length; i++) { - // arr[1] = 111100011110000 - // rightOne= 000000000010000 - if ((arr[i] & rightOne) != 0) { - onlyOne ^= arr[i]; - } - } - System.out.println(onlyOne + " " + (eor ^ onlyOne)); - } - - public static int bit1counts(int N) { - int count = 0; - while (N != 0) { - int rightOne = N & ((~N) + 1); - count++; - N -= rightOne; - } - return count; - } - - public static int add(int a, int b) { - int t = 0; - while (b != 0) { - t = a; - a = a ^ b; - b = ((t & b) << 1); - } - return a; - } - - public static int minus(int a, int b) { - // -b ~b + 1 - return add(a, add(~b, 1)); - } - - public static void main(String[] args) { - int[] arr1 = { 3, 3, 4, 2, 3, 1, 1, 2, 1, 3, 4, 1, 1, 1, 4, 2, 2 }; - printOddTimesNum1(arr1); - - int[] arr2 = { 4, 3, 4, 2, 2, 2, 4, 1, 1, 1, 3, 3, 1, 1, 1, 4, 2, 2 }; - printOddTimesNum2(arr2); - - } - -} diff --git a/公开课/class022/Code01_MinSwapStep.java b/公开课/class022/Code01_MinSwapStep.java deleted file mode 100644 index 9766e2d..0000000 --- a/公开课/class022/Code01_MinSwapStep.java +++ /dev/null @@ -1,53 +0,0 @@ -package class022; - -public class Code01_MinSwapStep { - - - public static int minSteps1(String s) { - if (s == null || s.equals("")) { - return 0; - } - char[] str = s.toCharArray(); - int step1 = 0; - int gi = 0; - // 想让G都放在左侧,请问至少需要交换几次,需要算出step1来。 - for (int i = 0; i < str.length; i++) { - if (str[i] == 'G') { - step1 += i - (gi++); - } - } - int step2 = 0; - int bi = 0; - for (int i = 0; i < str.length; i++) { - if (str[i] == 'B') { - step2 += i - (bi++); - } - } - return Math.min(step1, step2); - } - - - public static int minSteps(String s) { - if (s == null || s.equals("")) { - return 0; - } - char[] str = s.toCharArray(); - int step1 = 0; - int step2 = 0; - int gi = 0; - int bi = 0; - for (int i = 0; i < str.length; i++) { - if (str[i] == 'G') { - step1 += i - (gi++); - } else { - step2 += i - (bi++); - } - } - return Math.min(step1, step2); - } - - public static void main(String[] args) { - String s = "BGGBB"; - System.out.println(minSteps(s)); - } -} \ No newline at end of file diff --git a/公开课/class022/Code02_CountFiles.java b/公开课/class022/Code02_CountFiles.java deleted file mode 100644 index 2302728..0000000 --- a/公开课/class022/Code02_CountFiles.java +++ /dev/null @@ -1,42 +0,0 @@ -package class022; - -import java.io.File; -import java.util.Stack; - -public class Code02_CountFiles { - - // 注意这个函数也会统计隐藏文件 - public static int getFileNumber(String folderPath) { - // File (文件夹、文件) - File root = new File(folderPath); - if (!root.isDirectory() && !root.isFile()) { - return 0; - } - if (root.isFile()) { - return 1; - } - // File 文件夹 文件 stack只放文件夹 - Stack stack = new Stack<>(); - stack.add(root); - int files = 0; - while (!stack.isEmpty()) { - File folder = stack.pop(); - for (File next : folder.listFiles()) { - if (next.isFile() && next.getName().endsWith("java")) { - files++; - } - if (next.isDirectory()) { - stack.push(next); - } - } - } - return files; - } - - public static void main(String[] args) { - // 你可以自己更改目录 - String path = "/Users/zuochengyun/Desktop/"; - System.out.println(getFileNumber(path)); - } - -} diff --git a/公开课/class022/Code03_Cola.java b/公开课/class022/Code03_Cola.java deleted file mode 100644 index a6eb7c5..0000000 --- a/公开课/class022/Code03_Cola.java +++ /dev/null @@ -1,146 +0,0 @@ -package class022; - -public class Code03_Cola { - /* - * 买饮料 时间限制: 3000MS 内存限制: 589824KB 题目描述: - * 游游今年就要毕业了,和同学们在携程上定制了日本毕业旅行。愉快的一天行程结束后大家回到了酒店房间,这时候同学们都很口渴, - * 石头剪刀布选出游游去楼下的自动贩卖机给大家买可乐。 贩卖机只支持硬币支付,且收退都只支持10 ,50,100 - * 三种面额。一次购买行为只能出一瓶可乐,且每次购买后总是找零最小枚数的硬币。(例如投入100圆,可乐30圆,则找零50圆一枚,10圆两枚) - * 游游需要购买的可乐数量是 m,其中手头拥有的 10,50,100 面额硬币的枚数分别是 a,b,c,可乐的价格是x(x是10的倍数)。 - * 如果游游优先使用大面额购买且钱是够的情况下,请计算出需要投入硬币次数? 输入描述 依次输入, 需要可乐的数量为 m 10元的张数为 a 50元的张数为 b - * 100元的张树为 c 1瓶可乐的价格为 x 输出描述 输出当前金额下需要投入硬币的次数 - * 例如需要购买2瓶可乐,每瓶可乐250圆,手里有100圆3枚,50圆4枚,10圆1枚。 购买第1瓶投递100圆3枚,找50圆 购买第2瓶投递50圆5枚 - * 所以是总共需要操作8次金额投递操作 样例输入 2 1 4 3 250 样例输出 8 - */ - - // 暴力尝试,为了验证正式方法而已 - public static int right(int m, int a, int b, int c, int x) { - int[] qian = { 100, 50, 10 }; - int[] zhang = { c, b, a }; - int puts = 0; - while (m != 0) { - int cur = buy(qian, zhang, x); - if (cur == -1) { - return -1; - } - puts += cur; - m--; - } - return puts; - } - - public static int buy(int[] qian, int[] zhang, int rest) { - int first = -1; - for (int i = 0; i < 3; i++) { - if (zhang[i] != 0) { - first = i; - break; - } - } - if (first == -1) { - return -1; - } - if (qian[first] >= rest) { - zhang[first]--; - giveRest(qian, zhang, first + 1, qian[first] - rest, 1); - return 1; - } else { - zhang[first]--; - int next = buy(qian, zhang, rest - qian[first]); - if (next == -1) { - return -1; - } - return 1 + next; - } - } - - // 正式的方法 - public static int putTimes(int m, int a, int b, int c, int x) { - // 0 1 2 - int[] qian = { 100, 50, 10 }; - int[] zhang = { c, b, a }; - // 总共需要多少次投币 - int puts = 0; - // 之前面值的钱还剩下多少总钱数 - int preQianRest = 0; - // 之前面值的钱还剩下多少总张数 - int preQianZhang = 0; - for (int i = 0; i < 3 && m != 0; i++) { - // 要用之前剩下的钱、当前面值的钱,共同买第一瓶可乐 - // 之前的面值剩下多少钱,是preQianRest - // 之前的面值剩下多少张,是preQianZhang - // 之所以之前的面值会剩下来,一定是剩下的钱,一直攒不出一瓶可乐的单价 - // 当前的面值付出一些钱+之前剩下的钱,此时有可能凑出一瓶可乐来 - // 那么当前面值参与搞定第一瓶可乐,需要掏出多少张呢?就是curQianFirstBuyZhang - int curQianFirstBuyZhang = (x - preQianRest + qian[i] - 1) / qian[i]; - if (zhang[i] >= curQianFirstBuyZhang) { // 如果之前的钱和当前面值的钱,能凑出第一瓶可乐 - // 凑出来了一瓶可乐也可能存在找钱的情况, - giveRest(qian, zhang, i + 1, (preQianRest + qian[i] * curQianFirstBuyZhang) - x, 1); - puts += curQianFirstBuyZhang + preQianZhang; - zhang[i] -= curQianFirstBuyZhang; - m--; - } else { // 如果之前的钱和当前面值的钱,不能凑出第一瓶可乐 - preQianRest += qian[i] * zhang[i]; - preQianZhang += zhang[i]; - continue; - } - // 凑出第一瓶可乐之后,当前的面值有可能能继续买更多的可乐 - // 以下过程就是后续的可乐怎么用当前面值的钱来买 - // 用当前面值的钱,买一瓶可乐需要几张 - int curQianBuyOneColaZhang = (x + qian[i] - 1) / qian[i]; - // 用当前面值的钱,一共可以搞定几瓶可乐 - int curQianBuyColas = Math.min(zhang[i] / curQianBuyOneColaZhang, m); - // 用当前面值的钱,每搞定一瓶可乐,收货机会吐出多少零钱 - int oneTimeRest = qian[i] * curQianBuyOneColaZhang - x; - // 每次买一瓶可乐,吐出的找零总钱数是oneTimeRest - // 一共买的可乐数是curQianBuyColas,所以把零钱去提升后面几种面值的硬币数, - // 就是giveRest的含义 - giveRest(qian, zhang, i + 1, oneTimeRest, curQianBuyColas); - // 当前面值去搞定可乐这件事,一共投了几次币 - puts += curQianBuyOneColaZhang * curQianBuyColas; - // 还剩下多少瓶可乐需要去搞定,继续用后面的面值搞定去吧 - m -= curQianBuyColas; - // 当前面值可能剩下若干张,要参与到后续买可乐的过程中去, - // 所以要更新preQianRest和preQianZhang - zhang[i] -= curQianBuyOneColaZhang * curQianBuyColas; - preQianRest = qian[i] * zhang[i]; - preQianZhang = zhang[i]; - } - return m == 0 ? puts : -1; - } - - public static void giveRest(int[] qian, int[] zhang, int i, int oneTimeRest, int times) { - for (; i < 3; i++) { - zhang[i] += (oneTimeRest / qian[i]) * times; - oneTimeRest %= qian[i]; - } - } - - public static void main(String[] args) { - int testTime = 1000; - int zhangMax = 10; - int colaMax = 10; - int priceMax = 20; - System.out.println("如果错误会打印错误数据,否则就是正确"); - System.out.println("test begin"); - for (int i = 0; i < testTime; i++) { - int m = (int) (Math.random() * colaMax); - int a = (int) (Math.random() * zhangMax); - int b = (int) (Math.random() * zhangMax); - int c = (int) (Math.random() * zhangMax); - int x = ((int) (Math.random() * priceMax) + 1) * 10; - int ans1 = putTimes(m, a, b, c, x); - int ans2 = right(m, a, b, c, x); - if (ans1 != ans2) { - System.out.println("int m = " + m + ";"); - System.out.println("int a = " + a + ";"); - System.out.println("int b = " + b + ";"); - System.out.println("int c = " + c + ";"); - System.out.println("int x = " + x + ";"); - break; - } - } - System.out.println("test end"); - } - -} diff --git a/公开课/class023/Code01_FindHalfMajority.java b/公开课/class023/Code01_FindHalfMajority.java deleted file mode 100644 index a50dd2a..0000000 --- a/公开课/class023/Code01_FindHalfMajority.java +++ /dev/null @@ -1,78 +0,0 @@ -package class023; - -import java.util.HashMap; -import java.util.Map.Entry; - -public class Code01_FindHalfMajority { - - public static int halfMajor(int[] arr) { - int cand = 0; - int HP = 0; - // 遍历一遍数组arr,一次删掉两个不同的数,谁会剩下来,谁就是cand - for (int i = 0; i != arr.length; i++) { - if (HP == 0) { // 无候选 - cand = arr[i]; - HP = 1; - } else if (arr[i] == cand) { - HP++; - } else { - HP--; - } - } - if (HP == 0) { - System.out.println("你他妈在逗我,没水王"); - return -1; - } - HP = 0; - for (int i = 0; i != arr.length; i++) { - if (arr[i] == cand) { - HP++; - } - } - return HP > arr.length / 2 ? cand : -1; - } - - // for test - public static int right(int[] arr) { - HashMap map = new HashMap<>(); - for (int cur : arr) { - if (!map.containsKey(cur)) { - map.put(cur, 0); - } - map.put(cur, map.get(cur) + 1); - } - for (Entry entry : map.entrySet()) { - if (entry.getValue() > arr.length / 2) { - return entry.getKey(); - } - } - return -1; - } - - // for test - public static int[] genareteRandomArray(int len, int max) { - int[] ans = new int[(int) (Math.random() * len) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * max) + 1; - } - return ans; - } - - public static void main(String[] args) { - int len = 100; - int max = 10; - int testTime = 100000; - System.out.println("test begin"); - for (int i = 0; i < testTime; i++) { - int[] arr = genareteRandomArray(len, max); - int ans1 = halfMajor(arr); - int ans2 = right(arr); - if (ans1 != ans2) { - System.out.println("Oops!"); - break; - } - } - System.out.println("test end"); - } - -} diff --git a/公开课/class024/Code01_RotateImage.java b/公开课/class024/Code01_RotateImage.java deleted file mode 100644 index bdba6de..0000000 --- a/公开课/class024/Code01_RotateImage.java +++ /dev/null @@ -1,61 +0,0 @@ -package class024; - -import java.util.HashMap; - -public class Code01_RotateImage { - - public static void rotate(int[][] matrix) { - // matrix.length == matrix[0].length - // (a,b) 左上角的点,在a行b列上 - int a = 0; - int b = 0; - // (a,b) 右下角的点,在c行d列上 - int c = matrix.length - 1; - int d = matrix[0].length - 1; - while (a < c) { // 一定是正方形, - rotateEdge(matrix, a++, b++, c--, d--); - } - } - - public static void rotateEdge(int[][] m, int a, int b, int c, int d) { - int tmp = 0; - for (int i = 0; i < d - b; i++) { - tmp = m[a][b + i]; - m[a][b + i] = m[c - i][b]; - m[c - i][b] = m[c][d - i]; - m[c][d - i] = m[a + i][d]; - m[a + i][d] = tmp; - } - } - - - - public static HashMap map = new HashMap<>(); - - public static void generateMap() { - for(int i = 0 ;i < 32;i++) { - map.put(1 << i , i); - } - } - - // 返回num最右侧的1,在第几位 - // 高 ...... 低 - public static int f(int num) { - // num = 24 - // num = 00000..0000011000 - // 00000..0000001000 - if(map.size() == 0) { - generateMap(); - } - int rightOne = num & (-num); // num & (~num + 1) - return map.get(rightOne); - } - - - public static void main(String[] args) { - - } - - - -} diff --git a/公开课/class024/Code02_ZigZagPrintMatrix.java b/公开课/class024/Code02_ZigZagPrintMatrix.java deleted file mode 100644 index f69863c..0000000 --- a/公开课/class024/Code02_ZigZagPrintMatrix.java +++ /dev/null @@ -1,52 +0,0 @@ -package class024; - -public class Code02_ZigZagPrintMatrix { - - public static void printMatrixZigZag(int[][] matrix) { - // x -> (a,b) 先往右,再往下 - int a = 0; - int b = 0; - - // y -> (c,d) 先往下,再往右 - int c = 0; - int d = 0; - // (endR, endC) 是最右下角的位置 - int endR = matrix.length - 1; - int endC = matrix[0].length - 1; - // fromUp = true 斜线打印方向应该从右上走到左下 - // fromUp = false 斜线打印方向应该从左下走到右上 - boolean fromUp = false; - while (a != endR + 1) { - // (a,b) (c,d) 方向 - printLevel(matrix, a, b, c, d, fromUp); - a = b == endC ? a + 1 : a; - b = b == endC ? b : b + 1; - d = c == endR ? d + 1 : d; - c = c == endR ? c : c + 1; - fromUp = !fromUp; - } - System.out.println(); - } - - public static void printLevel(int[][] m, int aRow, int aCol, int bRow, int bCol, boolean f) { - if (f) { - while (aRow != bRow + 1) { - System.out.print(m[aRow++][aCol--] + " "); - } - } else { - while (bRow != aRow - 1) { - System.out.print(m[bRow--][bCol++] + " "); - } - } - } - - public static void main(String[] args) { - int[][] matrix = { - { 1, 2, 3, 4 }, - { 5, 6, 7, 8 }, - { 9, 10, 11, 12 } }; - printMatrixZigZag(matrix); - - } - -} diff --git a/公开课/class024/Code03_PrintStar.java b/公开课/class024/Code03_PrintStar.java deleted file mode 100644 index c451924..0000000 --- a/公开课/class024/Code03_PrintStar.java +++ /dev/null @@ -1,46 +0,0 @@ -package class024; - -public class Code03_PrintStar { - - public static void printStar(int N) { - int leftUp = 0; - int rightDown = N - 1; - char[][] m = new char[N][N]; - for (int i = 0; i < N; i++) { - for (int j = 0; j < N; j++) { - m[i][j] = ' '; - } - } - while (leftUp <= rightDown) { - set(m, leftUp, rightDown); - leftUp += 2; - rightDown -= 2; - } - for (int i = 0; i < N; i++) { - for (int j = 0; j < N; j++) { - System.out.print(m[i][j] + " "); - } - System.out.println(); - } - } - - public static void set(char[][] m, int leftUp, int rightDown) { - for (int col = leftUp; col <= rightDown; col++) { - m[leftUp][col] = '*'; - } - for (int row = leftUp + 1; row <= rightDown; row++) { - m[row][rightDown] = '*'; - } - for (int col = rightDown - 1; col > leftUp; col--) { - m[rightDown][col] = '*'; - } - for (int row = rightDown - 1; row > leftUp + 1; row--) { - m[row][leftUp + 1] = '*'; - } - } - - public static void main(String[] args) { - printStar(8); - } - -} diff --git a/公开课/class025/Code01_Water.java b/公开课/class025/Code01_Water.java deleted file mode 100644 index da68816..0000000 --- a/公开课/class025/Code01_Water.java +++ /dev/null @@ -1,120 +0,0 @@ -package class025; - -public class Code01_Water { - - /* - * 给定一个正整数数组arr,把arr想象成一个直方图。返回这个直方图如果装水,能装下几格水? - * */ - - public static int water1(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int water = 0; - for (int i = 1; i < N - 1; i++) { - int leftMax = Integer.MIN_VALUE; - for (int j = 0; j < i; j++) { - leftMax = Math.max(leftMax, arr[j]); - } - int rightMax = Integer.MIN_VALUE; - for (int j = i + 1; j < N; j++) { - rightMax = Math.max(rightMax, arr[j]); - } - water += Math.max(Math.min(leftMax, rightMax) - arr[i], 0); - } - return water; - } - - public static int water2(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int[] leftMaxs = new int[N]; - leftMaxs[0] = arr[0]; - for (int i = 1; i < N; i++) { - leftMaxs[i] = Math.max(leftMaxs[i - 1], arr[i]); - } - - int[] rightMaxs = new int[N]; - rightMaxs[N - 1] = arr[N - 1]; - for (int i = N - 2; i >= 0; i--) { - rightMaxs[i] = Math.max(rightMaxs[i + 1], arr[i]); - } - int water = 0; - for (int i = 1; i < N - 1; i++) { - water += Math.max(Math.min(leftMaxs[i - 1], rightMaxs[i + 1]) - arr[i], 0); - } - return water; - } - - public static int water3(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int[] rightMaxs = new int[N]; - rightMaxs[N - 1] = arr[N - 1]; - for (int i = N - 2; i >= 0; i--) { - rightMaxs[i] = Math.max(rightMaxs[i + 1], arr[i]); - } - int water = 0; - int leftMax = arr[0]; - for (int i = 1; i < N - 1; i++) { - water += Math.max(Math.min(leftMax, rightMaxs[i + 1]) - arr[i], 0); - leftMax = Math.max(leftMax, arr[i]); - } - return water; - } - - public static int water4(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int L = 1; - int leftMax = arr[0]; - int R = N - 2; - int rightMax = arr[N - 1]; - int water = 0; - while (L <= R) { - if (leftMax <= rightMax) { - water += Math.max(0, leftMax - arr[L]); - leftMax = Math.max(leftMax, arr[L++]); - } else { - water += Math.max(0, rightMax - arr[R]); - rightMax = Math.max(rightMax, arr[R--]); - } - } - return water; - } - - // for test - public static int[] generateRandomArray(int len, int value) { - int[] ans = new int[(int) (Math.random() * len) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * value) + 1; - } - return ans; - } - - public static void main(String[] args) { - int len = 100; - int value = 200; - int testTimes = 100000; - System.out.println("test begin"); - for (int i = 0; i < testTimes; i++) { - int[] arr = generateRandomArray(len, value); - int ans1 = water1(arr); - int ans2 = water2(arr); - int ans3 = water3(arr); - int ans4 = water4(arr); - if (ans1 != ans2 || ans3 != ans4 || ans1 != ans3) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - } - -} diff --git a/公开课/class025/Code02_RandToRand.java b/公开课/class025/Code02_RandToRand.java deleted file mode 100644 index 84a352c..0000000 --- a/公开课/class025/Code02_RandToRand.java +++ /dev/null @@ -1,134 +0,0 @@ -package class025; - -public class Code02_RandToRand { - - // 此函数只能用,不能修改 - // 等概率返回1~5 - public static int f() { - return (int) (Math.random() * 5) + 1; - } - - // 等概率得到0和1 - public static int a() { - int ans = 0; - do { - ans = f(); - } while (ans == 3); - return ans < 3 ? 0 : 1; - } - - // 等概率返回0~6 - public static int b() { - int ans = 0; - do { - ans = (a() << 2) + (a() << 1) + a(); - } while (ans == 7); - return ans; - } - - // 等概率返回1~7 - public static int c() { - return b() + 1; - } - - // 这个结构是唯一的随机机制 - // 你只能初始化并使用,不可修改 - public static class RandomBox { - private final int min; - private final int max; - - // 初始化时请一定不要让mi==ma - public RandomBox(int mi, int ma) { - min = mi; - max = ma; - } - - // 13 ~ 17 - // 13 + [0,4] - public int random() { - return min + (int) (Math.random() * (max - min + 1)); - } - - public int min() { - return min; - } - - public int max() { - return max; - } - } - - // 利用条件RandomBox,如何等概率返回0和1 - public static int rand01(RandomBox randomBox) { - int min = randomBox.min(); - int max = randomBox.max(); - // min ~ max - int size = max - min + 1; - // size是不是奇数,odd 奇数 - boolean odd = (size & 1) != 0; - int mid = size / 2; - int ans = 0; - do { - ans = randomBox.random() - min; - } while (odd && ans == mid); - return ans < mid ? 0 : 1; - } - - // 给你一个RandomBox,这是唯一能借助的随机机制 - // 等概率返回from~to范围上任何一个数 - // 要求from<=to - public static int random(RandomBox randomBox, int from, int to) { - if (from == to) { - return from; - } - // 3 ~ 9 - // 0 ~ 6 - // 0 ~ range - int range = to - from; - int num = 1; - // 求0~range需要几个2进制位 - while ((1 << num) - 1 < range) { - num++; - } - - // 我们一共需要num位 - // 最终的累加和,首先+0位上是1还是0,1位上是1还是0,2位上是1还是0... - int ans = 0; - do { - ans = 0; - for (int i = 0; i < num; i++) { - ans |= (rand01(randomBox) << i); - } - } while (ans > range); - return ans + from; - } - - public static void main(String[] args) { - - int[] count = new int[8]; // 0 1 2 .. 7 - int testTime = 10000000; - for (int i = 0; i < testTime; i++) { - int ans = c(); - count[ans]++; - } - - for (int i = 0; i < 8; i++) { - System.out.println(i + " : " + count[i]); - } - -// RandomBox randomBox = new RandomBox(3, 9); -// int from = 17; -// int to = 29; -// int[] ans = new int[to + 1]; -// int testTime1 = 1000000; -// for (int i = 0; i < testTime1; i++) { -// ans[random(randomBox, from, to)]++; -// } -// for (int i = 0; i < ans.length; i++) { -// System.out.println(ans[i]); -// } -// System.out.println("=========="); - - } - -} diff --git a/公开课/class025/Code03_EqualProbabilityRandom.java b/公开课/class025/Code03_EqualProbabilityRandom.java deleted file mode 100644 index 9d2d8da..0000000 --- a/公开课/class025/Code03_EqualProbabilityRandom.java +++ /dev/null @@ -1,67 +0,0 @@ -package class025; - -public class Code03_EqualProbabilityRandom { - - // 内部内容不可见 - public static int f() { - return Math.random() < 0.8 ? 0 : 1; - } - - // 等概率返回0和1 - public static int g() { - int first = 0; - do { - first = f(); // 0 1 - } while (first == f()); - return first; - } - - // 这个结构是唯一的随机机制 - // 你只能初始化并使用,不可修改 - public static class RandomBox { - private final double p; - - // 初始化时请一定满足:0 < zeroP < 1 - public RandomBox(double zeroP) { - p = zeroP; - } - - public int random() { - return Math.random() < p ? 0 : 1; - } - - } - - // 底层依赖一个以p概率返回0,以1-p概率返回1的随机函数rand01p - // 如何加工出等概率返回0和1的函数 - public static int rand01(RandomBox randomBox) { - int num; - do { - num = randomBox.random(); - } while (num == randomBox.random()); - return num; - } - - public static void main(String[] args) { - int[] count = new int[2];// 0 1 - for (int i = 0; i < 1000000; i++) { - int ans = g(); - count[ans]++; - } - System.out.println(count[0] + " , " + count[1]); - -// double zeroP = 0.88; -// RandomBox randomBox = new RandomBox(zeroP); -// -// int testTime = 10000000; -// int count = 0; -// for (int i = 0; i < testTime; i++) { -// if (rand01(randomBox) == 0) { -// count++; -// } -// } -// System.out.println((double) count / (double) testTime); - - } - -} diff --git a/公开课/class026/Code01_SubArrayMaxSum.java b/公开课/class026/Code01_SubArrayMaxSum.java deleted file mode 100644 index 7861912..0000000 --- a/公开课/class026/Code01_SubArrayMaxSum.java +++ /dev/null @@ -1,161 +0,0 @@ -package class026; - -import java.util.ArrayList; -import java.util.List; - -public class Code01_SubArrayMaxSum { - - public static int test(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int N = arr.length; - int max = Integer.MIN_VALUE; - for (int L = 0; L < N; L++) { - for (int R = L; R < N; R++) { - // arr[L...R] - int sum = 0; - for (int i = L; i <= R; i++) { - sum += arr[i]; - } - max = Math.max(max, sum); - } - } - return max; - } - - public static int dp1(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int[] dp = new int[arr.length]; - // dp[i] 子数组必须以i位置结尾的情况下,能得到的最大累加和 - dp[0] = arr[0]; - for (int i = 1; i < arr.length; i++) { - int p1 = arr[i]; - int p2 = dp[i - 1] + arr[i]; - dp[i] = Math.max(p1, p2); - } - int max = Integer.MIN_VALUE; - for (int i = 0; i < dp.length; i++) { - max = Math.max(max, dp[i]); - } - return max; - } - - public static int dp2(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int preDp = arr[0]; - int max = preDp; - for (int i = 1; i < arr.length; i++) { - int p1 = arr[i]; - int p2 = preDp + arr[i]; - int dp = Math.max(p1, p2); - max = Math.max(max, dp); - preDp = dp; - } - return max; - } - - public static int maxSum(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int cur = 0; - int max = Integer.MIN_VALUE; - for (int i = 0; i < arr.length; i++) { - cur += arr[i]; - max = Math.max(max, cur); - cur = cur < 0 ? 0 : cur; - } - return max; - } - - public static int maxSum1(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - // 0结尾时候的答案 - int pre = arr[0]; - int max = arr[0]; - for (int i = 1; i < arr.length; i++) { - // i结尾时候的答案 - pre = arr[i] + (pre > 0 ? pre : 0); - max = Math.max(max, pre); - } - return max; - } - - public static List> maxSum2(int[] arr) { - List> ans = new ArrayList<>(); - if (arr == null || arr.length == 0) { - return ans; - } - int L = 0; - int maxLen = 0; - int maxSum = Integer.MIN_VALUE; - int cur = 0; - for (int i = 0; i < arr.length; i++) { - // L...i sum - cur += arr[i]; - if (cur == maxSum && (i - L + 1) == maxLen) { - List curAns = new ArrayList<>(); - curAns.add(L); - curAns.add(i); - ans.add(curAns); - } - if (cur > maxSum || (cur == maxSum && (i - L + 1) > maxLen)) { - ans.clear(); - List curAns = new ArrayList<>(); - curAns.add(L); - curAns.add(i); - ans.add(curAns); - maxLen = i - L + 1; - } - maxSum = Math.max(maxSum, cur); - if (cur < 0) { - cur = 0; - L = i + 1; - } - } - return ans; - } - - public static int[] generateArray(int N, int V) { - int n = (int) (Math.random() * N) + 1; - int[] arr = new int[n]; - for (int i = 0; i < n; i++) { - arr[i] = (int) (Math.random() * V) - (int) (Math.random() * V); - } - return arr; - } - - public static void main(String[] args) { - int N = 100; - int V = 100; - int testTime = 10000; - System.out.println("test begin"); - for (int i = 0; i < testTime; i++) { - int[] arr = generateArray(N, V); - int ans1 = test(arr); - int ans2 = dp1(arr); - int ans3 = dp2(arr); - if (ans1 != ans2 || ans1 != ans3) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - - int[] test = { 2, 2, 1, -9, 2, 3, -9, 6, -9, 2, 2, 2, -9, 2, 2, 2, -9, 1, 4, 1 }; - - List> ans = maxSum2(test); - - for (List cur : ans) { - System.out.println("start : " + cur.get(0) + ", end : " + cur.get(1)); - } - - } - -} diff --git a/公开课/class026/Code02_SubArrayMaxSumFollowUp.java b/公开课/class026/Code02_SubArrayMaxSumFollowUp.java deleted file mode 100644 index 7e806b5..0000000 --- a/公开课/class026/Code02_SubArrayMaxSumFollowUp.java +++ /dev/null @@ -1,58 +0,0 @@ -package class026; - -public class Code02_SubArrayMaxSumFollowUp { - - public static int subSqeMaxSumNoNext(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - if (arr.length == 1) { - return arr[0]; - } - int[] dp = new int[arr.length]; - // dp[i] : arr[0..i]挑选,满足不相邻设定的情况下,随意挑选,最大的累加和 - dp[0] = arr[0]; - dp[1] = Math.max(arr[0], arr[1]); - for (int i = 2; i < arr.length; i++) { - int p1 = dp[i - 1]; - int p2 = arr[i] + Math.max(dp[i - 2], 0); - dp[i] = Math.max(p1, p2); - } - return dp[arr.length - 1]; - } - - // 给定一个数组arr,在不能取相邻数的情况下,返回所有组合中的最大累加和 - // 思路: - // 定义dp[i] : 表示arr[0...i]范围上,在不能取相邻数的情况下,返回所有组合中的最大累加和 - // 在arr[0...i]范围上,在不能取相邻数的情况下,得到的最大累加和,可能性分类: - // 可能性 1) 选出的组合,不包含arr[i]。那么dp[i] = dp[i-1] - // 比如,arr[0...i] = {3,4,-4},最大累加和是不包含i位置数的时候 - // - // 可能性 2) 选出的组合,只包含arr[i]。那么dp[i] = arr[i] - // 比如,arr[0...i] = {-3,-4,4},最大累加和是只包含i位置数的时候 - // - // 可能性 3) 选出的组合,包含arr[i], 且包含arr[0...i-2]范围上的累加和。那么dp[i] = arr[i] + dp[i-2] - // 比如,arr[0...i] = {3,1,4},最大累加和是3和4组成的7,因为相邻不能选,所以i-1位置的数要跳过 - // - // 综上所述:dp[i] = Max { dp[i-1], arr[i] , arr[i] + dp[i-2] } - public static int maxSum(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int N = arr.length; - if (N == 1) { - return arr[0]; - } - if (N == 2) { - return Math.max(arr[0], arr[1]); - } - int[] dp = new int[N]; - dp[0] = arr[0]; - dp[1] = Math.max(arr[0], arr[1]); - for (int i = 2; i < N; i++) { - dp[i] = Math.max(Math.max(dp[i - 1], arr[i]), arr[i] + dp[i - 2]); - } - return dp[N - 1]; - } - -} diff --git a/公开课/class026/Code03_SubMatrixMaxSum.java b/公开课/class026/Code03_SubMatrixMaxSum.java deleted file mode 100644 index fafa1fe..0000000 --- a/公开课/class026/Code03_SubMatrixMaxSum.java +++ /dev/null @@ -1,83 +0,0 @@ -package class026; - -public class Code03_SubMatrixMaxSum { - - public static int maxSum1(int[][] matrix) { - int n = matrix.length; - int m = matrix[0].length; - int max = Integer.MIN_VALUE; - for (int ai = 0; ai < n; ai++) { - for (int aj = 0; aj < m; aj++) { - for (int bi = ai; bi < n; bi++) { - for (int bj = aj; bj < m; bj++) { - max = Math.max(max, sum(matrix, ai, aj, bi, bj)); - } - } - } - } - return max; - } - - public static int sum(int[][] matrix, int ai, int aj, int bi, int bj) { - int sum = 0; - for (int i = ai; i <= bi; i++) { - for (int j = aj; j <= bj; j++) { - sum += matrix[i][j]; - } - } - return sum; - } - - public static int maxSum2(int[][] matrix) { - if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { - return 0; - } - int max = Integer.MIN_VALUE; - int cur = 0; - int[] s = null; - for (int i = 0; i != matrix.length; i++) { - s = new int[matrix[0].length]; - for (int j = i; j != matrix.length; j++) { - cur = 0; - for (int k = 0; k != s.length; k++) { - s[k] += matrix[j][k]; - cur += s[k]; - max = Math.max(max, cur); - cur = cur < 0 ? 0 : cur; - } - } - } - return max; - } - - public static int[][] generateMatrix(int N, int M, int V) { - int n = (int) (Math.random() * N) + 1; - int m = (int) (Math.random() * M) + 1; - int[][] matrix = new int[n][m]; - for (int i = 0; i < n; i++) { - for (int j = 0; j < m; j++) { - matrix[i][j] = (int) (Math.random() * V) - (int) (Math.random() * V); - } - } - return matrix; - } - - public static void main(String[] args) { - int N = 20; - int M = 20; - int V = 100; - int testTime = 50000; - System.out.println("test begin"); - for (int i = 0; i < testTime; i++) { - int[][] matrix = generateMatrix(N, M, V); - int ans1 = maxSum1(matrix); - int ans2 = maxSum2(matrix); - if (ans1 != ans2) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - - } - -} diff --git a/公开课/class027/Code01_MinSwapStep.java b/公开课/class027/Code01_MinSwapStep.java deleted file mode 100644 index be9ee0a..0000000 --- a/公开课/class027/Code01_MinSwapStep.java +++ /dev/null @@ -1,71 +0,0 @@ -package class027; - -public class Code01_MinSwapStep { - - // 一个数组中只有两种字符'G'和'B',想让所有的G都放在左侧,所有的B都放在右侧 - // 但是只能在相邻字符之间进行交换操作,请问请问至少需要交换几次, - public static int minSteps1(String s) { - if (s == null || s.equals("")) { - return 0; - } - char[] str = s.toCharArray(); - int step1 = 0; - int gi = 0; - for (int i = 0; i < str.length; i++) { - if (str[i] == 'G') { - step1 += i - (gi++); - } - } - int step2 = 0; - int bi = 0; - for (int i = 0; i < str.length; i++) { - if (str[i] == 'B') { - step2 += i - (bi++); - } - } - return Math.min(step1, step2); - } - - public static int minSteps2(String s) { - if (s == null || s.equals("")) { - return 0; - } - char[] str = s.toCharArray(); - int step1 = 0; - int step2 = 0; - int gi = 0; - int bi = 0; - for (int i = 0; i < str.length; i++) { - if (str[i] == 'G') { - step1 += i - (gi++); - } else { - step2 += i - (bi++); - } - } - return Math.min(step1, step2); - } - - // 为了测试 - public static String randomString(int maxLen) { - char[] str = new char[(int) (Math.random() * maxLen)]; - for (int i = 0; i < str.length; i++) { - str[i] = Math.random() < 0.5 ? 'G' : 'B'; - } - return String.valueOf(str); - } - - public static void main(String[] args) { - int maxLen = 100; - int testTime = 1000000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - String str = randomString(maxLen); - int ans1 = minSteps1(str); - int ans2 = minSteps2(str); - if (ans1 != ans2) { - System.out.println("Oops!"); - } - } - System.out.println("测试结束"); - } -} \ No newline at end of file diff --git a/公开课/class027/Code02_CountFiles.java b/公开课/class027/Code02_CountFiles.java deleted file mode 100644 index e318671..0000000 --- a/公开课/class027/Code02_CountFiles.java +++ /dev/null @@ -1,42 +0,0 @@ -package class027; - -import java.io.File; -import java.util.Stack; - -public class Code02_CountFiles { - - // 注意这个函数也会统计隐藏文件 - public static int getFileNumber(String folderPath) { - File root = new File(folderPath); - if (!root.isDirectory() && !root.isFile()) { - return 0; - } - if (root.isFile()) { - return 1; - } - // File分为文件夹和文件 - // 而stack只放文件夹 - Stack stack = new Stack<>(); - stack.add(root); - int files = 0; - while (!stack.isEmpty()) { - File folder = stack.pop(); - for (File next : folder.listFiles()) { - if (next.isFile()) { - files++; - } - if (next.isDirectory()) { - stack.push(next); - } - } - } - return files; - } - - public static void main(String[] args) { - // 你可以自己更改目录来查看这个目录下的文件个数 - String path = "/Users/zuochengyun/Desktop"; - System.out.println(getFileNumber(path)); - } - -} diff --git a/公开课/class027/Code03_Cola.java b/公开课/class027/Code03_Cola.java deleted file mode 100644 index c53414a..0000000 --- a/公开课/class027/Code03_Cola.java +++ /dev/null @@ -1,148 +0,0 @@ -package class027; - -public class Code03_Cola { - /* - * 买饮料 时间限制: 3000MS 内存限制: 589824KB 题目描述: - * 游游今年就要毕业了,和同学们在携程上定制了日本毕业旅行。愉快的一天行程结束后大家回到了酒店房间,这时候同学们都很口渴, - * 石头剪刀布选出游游去楼下的自动贩卖机给大家买可乐。 贩卖机只支持硬币支付,且收退都只支持10 ,50,100 - * 三种面额。一次购买行为只能出一瓶可乐,且每次购买后总是找零最小枚数的硬币。(例如投入100圆,可乐30圆,则找零50圆一枚,10圆两枚) - * 游游需要购买的可乐数量是 m,其中手头拥有的 10,50,100 面额硬币的枚数分别是 a,b,c,可乐的价格是x(x是10的倍数)。 - * 如果游游优先使用大面额购买且钱是够的情况下,请计算出需要投入硬币次数? 输入描述 依次输入, 需要可乐的数量为 m 10元的张数为 a 50元的张数为 b - * 100元的张树为 c 1瓶可乐的价格为 x 输出描述 输出当前金额下需要投入硬币的次数 - * 例如需要购买2瓶可乐,每瓶可乐250圆,手里有100圆3枚,50圆4枚,10圆1枚。 购买第1瓶投递100圆3枚,找50圆 购买第2瓶投递50圆5枚 - * 所以是总共需要操作8次金额投递操作 样例输入 2 1 4 3 250 样例输出 8 - */ - - // 暴力尝试,为了验证正式方法而已 - public static int right(int m, int a, int b, int c, int x) { - int[] qian = { 100, 50, 10 }; - int[] zhang = { c, b, a }; - int puts = 0; - while (m != 0) { - int cur = buy(qian, zhang, x); - if (cur == -1) { - return -1; - } - puts += cur; - m--; - } - return puts; - } - - public static int buy(int[] qian, int[] zhang, int rest) { - int first = -1; - for (int i = 0; i < 3; i++) { - if (zhang[i] != 0) { - first = i; - break; - } - } - if (first == -1) { - return -1; - } - if (qian[first] >= rest) { - zhang[first]--; - giveRest(qian, zhang, first + 1, qian[first] - rest, 1); - return 1; - } else { - zhang[first]--; - int next = buy(qian, zhang, rest - qian[first]); - if (next == -1) { - return -1; - } - return 1 + next; - } - } - - // 正式的方法 - public static int putTimes(int m, int a, int b, int c, int x) { - // 0 1 2 - int[] qian = { 100, 50, 10 }; - int[] zhang = { c, b, a }; - // 总共需要多少次投币 - int puts = 0; - // 之前面值的钱还剩下多少总钱数 - int preQianRest = 0; - // 之前面值的钱还剩下多少总张数 - int preQianZhang = 0; - for (int i = 0; i < qian.length && m != 0; i++) { - // 要用之前剩下的钱、当前面值的钱,共同买第一瓶可乐 - // 之前的面值剩下多少钱,是preQianRest - // 之前的面值剩下多少张,是preQianZhang - // 之所以之前的面值会剩下来,一定是剩下的钱,一直攒不出一瓶可乐的单价 - // 当前的面值付出一些钱+之前剩下的钱,此时有可能凑出一瓶可乐来 - // 那么当前面值参与搞定第一瓶可乐,需要掏出多少张呢?就是curQianFirstBuyZhang - int curQianFirstBuyZhang = (x - preQianRest + qian[i] - 1) / qian[i]; - if (zhang[i] >= curQianFirstBuyZhang) { // 如果之前的钱和当前面值的钱,能凑出第一瓶可乐 - // 凑出来了一瓶可乐也可能存在找钱的情况, - giveRest(qian, zhang, i + 1, (preQianRest + qian[i] * curQianFirstBuyZhang) - x, 1); - puts += curQianFirstBuyZhang + preQianZhang; - zhang[i] -= curQianFirstBuyZhang; - m--; - } else { // 如果之前的钱和当前面值的钱,不能凑出第一瓶可乐 - preQianRest += qian[i] * zhang[i]; - preQianZhang += zhang[i]; - continue; - } - // 凑出第一瓶可乐之后,当前的面值有可能能继续买更多的可乐 - // 以下过程就是后续的可乐怎么用当前面值的钱来买 - // 用当前面值的钱,买一瓶可乐需要几张 - int curQianBuyOneColaZhang = (x + qian[i] - 1) / qian[i]; - // 用当前面值的钱,一共可以搞定几瓶可乐 - int curQianBuyColas = Math.min(zhang[i] / curQianBuyOneColaZhang, m); - // 用当前面值的钱,每搞定一瓶可乐,收货机会吐出多少零钱 - int oneTimeRest = qian[i] * curQianBuyOneColaZhang - x; - // 每次买一瓶可乐,吐出的找零总钱数是oneTimeRest - // 一共买的可乐数是curQianBuyColas,所以把零钱去提升后面几种面值的硬币数, - // 就是giveRest的含义 - giveRest(qian, zhang, i + 1, oneTimeRest, curQianBuyColas); - // 当前面值去搞定可乐这件事,一共投了几次币 - puts += curQianBuyOneColaZhang * curQianBuyColas; - // 还剩下多少瓶可乐需要去搞定,继续用后面的面值搞定去吧 - m -= curQianBuyColas; - // 当前面值可能剩下若干张,要参与到后续买可乐的过程中去, - // 所以要更新preQianRest和preQianZhang - zhang[i] -= curQianBuyOneColaZhang * curQianBuyColas; - preQianRest = qian[i] * zhang[i]; - preQianZhang = zhang[i]; - } - return m == 0 ? puts : -1; - } - - // qian [100, 50, 10] - // zhang [ 2, 10, 5] - public static void giveRest(int[] qian, int[] zhang, int i, int oneTimeRest, int times) { - for (; i < 3; i++) { - zhang[i] += (oneTimeRest / qian[i]) * times; - oneTimeRest %= qian[i]; - } - } - - public static void main(String[] args) { - int testTime = 1000; - int zhangMax = 10; - int colaMax = 10; - int priceMax = 20; - System.out.println("如果错误会打印错误数据,否则就是正确"); - System.out.println("test begin"); - for (int i = 0; i < testTime; i++) { - int m = (int) (Math.random() * colaMax); - int a = (int) (Math.random() * zhangMax); - int b = (int) (Math.random() * zhangMax); - int c = (int) (Math.random() * zhangMax); - int x = ((int) (Math.random() * priceMax) + 1) * 10; - int ans1 = putTimes(m, a, b, c, x); - int ans2 = right(m, a, b, c, x); - if (ans1 != ans2) { - System.out.println("int m = " + m + ";"); - System.out.println("int a = " + a + ";"); - System.out.println("int b = " + b + ";"); - System.out.println("int c = " + c + ";"); - System.out.println("int x = " + x + ";"); - break; - } - } - System.out.println("test end"); - } - -} diff --git a/公开课/class028/Code01_RotateString.java b/公开课/class028/Code01_RotateString.java deleted file mode 100644 index e717068..0000000 --- a/公开课/class028/Code01_RotateString.java +++ /dev/null @@ -1,93 +0,0 @@ -package class028; - -public class Code01_RotateString { - - public static String rotate1(String s, int leftSize) { - if (leftSize <= 0 || leftSize >= s.length()) { - return s; - } - return process1(s.toCharArray(), 0, leftSize - 1, s.length() - 1); - } - - public static String process1(char[] str, int L, int M, int R) { - reverse(str, L, M); - reverse(str, M + 1, R); - reverse(str, L, R); - return String.valueOf(str); - } - - public static void reverse(char[] str, int L, int R) { - while (L < R) { - char tmp = str[L]; - str[L++] = str[R]; - str[R--] = tmp; - } - } - - public static String rotate2(String s, int leftSize) { - if (leftSize <= 0 || leftSize >= s.length()) { - return s; - } - char[] str = s.toCharArray(); - int L = 0; - int R = str.length - 1; - int lpart = leftSize; - int rpart = str.length - leftSize; - int same = Math.min(lpart, rpart); - int diff = lpart - rpart; - exchange(str, L, R, same); - while (diff != 0) { - if (diff > 0) { - L += same; - lpart = diff; - } else { - R -= same; - rpart = -diff; - } - same = Math.min(lpart, rpart); - diff = lpart - rpart; - exchange(str, L, R, same); - } - return String.valueOf(str); - } - - public static void exchange(char[] chas, int start, int end, int size) { - int i = end - size + 1; - char tmp = 0; - while (size-- != 0) { - tmp = chas[start]; - chas[start] = chas[i]; - chas[i] = tmp; - start++; - i++; - } - } - - // for test - public static String getRandomString(int possibilities, int strMaxSize) { - char[] ans = new char[(int) (Math.random() * strMaxSize) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (char) ((int) (Math.random() * possibilities) + 'a'); - } - return String.valueOf(ans); - } - - public static void main(String[] args) { - int possibilities = 5; - int strMaxSize = 10; - int testTimes = 5000000; - System.out.println("test begin, test time : " + testTimes); - for (int i = 0; i < testTimes; i++) { - String str = getRandomString(possibilities, strMaxSize); - int leftSize = (int) (Math.random() * (str.length() + 1)); - String ans1 = rotate1(str, leftSize); - String ans2 = rotate2(str, leftSize); - if (!ans1.equals(ans2)) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - - } - -} diff --git a/公开课/class028/Code02_HowManyTypes.java b/公开课/class028/Code02_HowManyTypes.java deleted file mode 100644 index e6d6802..0000000 --- a/公开课/class028/Code02_HowManyTypes.java +++ /dev/null @@ -1,111 +0,0 @@ -package class028; - -import java.util.HashSet; - -public class Code02_HowManyTypes { - - /* - * 只由小写字母(a~z)组成的一批字符串,都放在字符类型的数组String[] arr中, - * 如果其中某两个字符串,所含有的字符种类完全一样,就将两个字符串算作一类 比如:baacba和bac就算作一类 - * 虽然长度不一样,但是所含字符的种类完全一样(a、b、c) 返回arr中有多少类? - * - */ - - public static int types1(String[] arr) { - HashSet types = new HashSet<>(); - for (String str : arr) { - char[] chs = str.toCharArray(); - boolean[] map = new boolean[26]; - for (int i = 0; i < chs.length; i++) { - map[chs[i] - 'a'] = true; - } - String key = ""; - for (int i = 0; i < 26; i++) { - if (map[i]) { - key += String.valueOf((char) (i + 'a')); - } - } - types.add(key); - } - return types.size(); - } - - public static int types2(String[] arr) { - HashSet types = new HashSet<>(); - for (String str : arr) { - char[] chs = str.toCharArray(); - int key = 0; - for (int i = 0; i < chs.length; i++) { - key = key | (1 << (chs[i] - 'a')); - } - types.add(key); - } - return types.size(); - } - - // for test - public static String[] getRandomStringArray(int possibilities, int strMaxSize, int arrMaxSize) { - String[] ans = new String[(int) (Math.random() * arrMaxSize) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = getRandomString(possibilities, strMaxSize); - } - return ans; - } - - // for test - public static String getRandomString(int possibilities, int strMaxSize) { - char[] ans = new char[(int) (Math.random() * strMaxSize) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (char) ((int) (Math.random() * possibilities) + 'a'); - } - return String.valueOf(ans); - } - - public static void printIntegerBinary(int num) { - StringBuilder builder = new StringBuilder(); - for (int i = 31; i >= 0; i--) { - // 依次提取出num从0位~31位的状态来 - int status = ((num >> i) & 1); - builder.append(status); - - } - System.out.println(builder.toString()); - } - - public static void main(String[] args) { - int num = 3; - printIntegerBinary(num); - - char[] str = { 'b', 'b', 'z', 'k', 'o' }; - - int key = 0; - // 如何生成str的摘要? - // 00000000000000000000000000000000 - - for (int i = 0; i < str.length; i++) { - char cha = str[i]; - // cha = a - // cha - 'a' ? 0 - // 1 << (cha - 'a') -> 1 << 0 - key = key | (1 << (cha - 'a')); - } - printIntegerBinary(key); - - int possibilities = 5; - int strMaxSize = 10; - int arrMaxSize = 100; - int testTimes = 500000; - System.out.println("test begin, test time : " + testTimes); - for (int i = 0; i < testTimes; i++) { - String[] arr = getRandomStringArray(possibilities, strMaxSize, arrMaxSize); - int ans1 = types1(arr); - int ans2 = types2(arr); - if (ans1 != ans2) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - - } - -} diff --git a/公开课/class028/Code03_LongestNoRepeatSubstring.java b/公开课/class028/Code03_LongestNoRepeatSubstring.java deleted file mode 100644 index 1730279..0000000 --- a/公开课/class028/Code03_LongestNoRepeatSubstring.java +++ /dev/null @@ -1,83 +0,0 @@ -package class028; - -import java.util.HashMap; -import java.util.HashSet; - -public class Code03_LongestNoRepeatSubstring { - - /* - * 给定一个只由小写字母(a~z)组成的字符串str, 返回其中最长无重复字符的子串长度 - * - */ - - public static int maxNoRepeatSubstringLen1(char[] str) { - int len = 0; - for (int L = 0; L < str.length; L++) { - for (int R = L; R < str.length; R++) { - HashSet set = new HashSet<>(); - boolean noRepeat = true; - for (int i = L; i <= R; i++) { - if (set.contains(str[i])) { - noRepeat = false; - break; - } - set.add(str[i]); - } - if (noRepeat) { - int cur = R - L + 1; - len = Math.max(len, cur); - } - } - } - return len; - } - - public static int maxNoRepeatSubstringLen2(char[] str) { - if (str == null || str.length == 0) { - return 0; - } - int N = str.length; - int[] dp = new int[N]; - HashMap lastMap = new HashMap<>(); - dp[0] = 1; - lastMap.put(str[0], 0); - int max = 1; - for (int i = 1; i < N; i++) { - int lastIndex = lastMap.containsKey(str[i]) ? lastMap.get(str[i]) : -1; - int preNo = i - 1 - dp[i - 1]; - int no = Math.max(lastIndex, preNo); - int curAns = i - no; - dp[i] = curAns; - lastMap.put(str[i], i); - max = Math.max(max, dp[i]); - } - return max; - } - - // for test - public static String getRandomString(int possibilities, int maxSize) { - char[] ans = new char[(int) (Math.random() * maxSize) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (char) ((int) (Math.random() * possibilities) + 'a'); - } - return String.valueOf(ans); - } - - public static void main(String[] args) { - int possibilities = 26; - int strMaxSize = 100; - int testTimes = 10000; - System.out.println("test begin, test time : " + testTimes); - for (int i = 0; i < testTimes; i++) { - String str = getRandomString(possibilities, strMaxSize); - int ans1 = maxNoRepeatSubstringLen1(str.toCharArray()); - int ans2 = maxNoRepeatSubstringLen2(str.toCharArray()); - if (ans1 != ans2) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - - } - -} diff --git a/公开课/class028/Code04_CoverMax.java b/公开课/class028/Code04_CoverMax.java deleted file mode 100644 index 5ccbc2f..0000000 --- a/公开课/class028/Code04_CoverMax.java +++ /dev/null @@ -1,133 +0,0 @@ -package class028; - -import java.util.Arrays; -import java.util.Comparator; -import java.util.PriorityQueue; - -public class Code04_CoverMax { - - public static int maxCover1(int[][] lines) { - int min = Integer.MAX_VALUE; - int max = Integer.MIN_VALUE; - for (int i = 0; i < lines.length; i++) { - min = Math.min(min, lines[i][0]); - max = Math.max(max, lines[i][1]); - } - int cover = 0; - for (double p = min + 0.5; p < max; p += 1) { - int cur = 0; - for (int i = 0; i < lines.length; i++) { - if (lines[i][0] < p && lines[i][1] > p) { - cur++; - } - } - cover = Math.max(cover, cur); - } - return cover; - } - - public static int maxCover2(int[][] m) { - Line[] lines = new Line[m.length]; - for (int i = 0; i < m.length; i++) { - lines[i] = new Line(m[i][0], m[i][1]); - } - Arrays.sort(lines, new StartComparator()); - // lines - // - PriorityQueue heap = new PriorityQueue<>(); - int max = 0; - for (int i = 0; i < lines.length; i++) { - // lines[i] -> cur 在黑盒中,把<=cur.start 东西都弹出 - while (!heap.isEmpty() && heap.peek() <= lines[i].start) { - heap.poll(); - } - heap.add(lines[i].end); - max = Math.max(max, heap.size()); - } - return max; - } - - public static class Line { - public int start; - public int end; - - public Line(int s, int e) { - start = s; - end = e; - } - } - - public static class EndComparator implements Comparator { - - @Override - public int compare(Line o1, Line o2) { - return o1.end - o2.end; - } - - } - - // for test - public static int[][] generateLines(int N, int L, int R) { - int size = (int) (Math.random() * N) + 1; - int[][] ans = new int[size][2]; - for (int i = 0; i < size; i++) { - int a = L + (int) (Math.random() * (R - L + 1)); - int b = L + (int) (Math.random() * (R - L + 1)); - if (a == b) { - b = a + 1; - } - ans[i][0] = Math.min(a, b); - ans[i][1] = Math.max(a, b); - } - return ans; - } - - public static class StartComparator implements Comparator { - - @Override - public int compare(Line o1, Line o2) { - return o1.start - o2.start; - } - - } - - public static void main(String[] args) { - - Line l1 = new Line(4, 9); - Line l2 = new Line(1, 4); - Line l3 = new Line(7, 15); - Line l4 = new Line(2, 4); - Line l5 = new Line(4, 6); - Line l6 = new Line(3, 7); - - // 底层堆结构,heap - PriorityQueue heap = new PriorityQueue<>(new StartComparator()); - heap.add(l1); - heap.add(l2); - heap.add(l3); - heap.add(l4); - heap.add(l5); - heap.add(l6); - - while (!heap.isEmpty()) { - Line cur = heap.poll(); - System.out.println(cur.start + "," + cur.end); - } - - System.out.println("test begin"); - int N = 100; - int L = 0; - int R = 200; - int testTimes = 200000; - for (int i = 0; i < testTimes; i++) { - int[][] lines = generateLines(N, L, R); - int ans1 = maxCover1(lines); - int ans2 = maxCover2(lines); - if (ans1 != ans2) { - System.out.println("Oops!"); - } - } - System.out.println("test end"); - } - -} diff --git a/公开课/class029/Code01_AppleMinBags.java b/公开课/class029/Code01_AppleMinBags.java deleted file mode 100644 index ffbc657..0000000 --- a/公开课/class029/Code01_AppleMinBags.java +++ /dev/null @@ -1,77 +0,0 @@ -package class029; - -public class Code01_AppleMinBags { - - public static int minBag1(int apple) { - if (apple < 0) { - return -1; - } - if (apple == 0) { - return 0; - } - // 最多的8号袋开始试, - for (int max = (apple / 8); max >= 0; max--) { - int rest = apple - (max * 8); - if (rest % 6 == 0) { - return max + rest / 6; - } - } - return -1; - } - - // 18 ~ - // 18 ~ 25 0组 奇数 -1 偶数 3 - // 26 ~ 33 1组 奇数 -1 偶数 4 - // 34 ~ 41 2组 奇数 -1 偶数 5 - // X - // i组 奇数 -1 偶数 i+3 - - // 规律解 通过 - public static int minBag2(int apple) { - if (apple < 18) { - if (apple < 0) { - return -1; - } - if (apple == 0) { - return 0; - } - if (apple == 6 || apple == 8) { - return 1; - } - if (apple == 12 || apple == 14 || apple == 16) { - return 2; - } - return -1; - } - int team = (apple - 18) / 8; - return (apple & 1) == 0 ? (team + 3) : -1; - } - - public static int minBagAwesome(int apple) { - if (apple < 0 || (apple & 1) != 0) { - return -1; - } - if (apple == 0) { - return 0; - } - if (apple < 18) { - if (apple == 6 || apple == 8) { - return 1; - } else if (apple == 12 || apple == 14 || apple == 16) { - return 2; - } else { - return -1; - } - } else { - return (apple - 18) / 8 + 3; - } - } - - public static void main(String[] args) { - for (int apple = 0; apple <= 100; apple++) { - System.out.println(minBag1(apple) == minBag2(apple)); - } - - } - -} diff --git a/公开课/class029/Code02_EatGrass.java b/公开课/class029/Code02_EatGrass.java deleted file mode 100644 index a3e3704..0000000 --- a/公开课/class029/Code02_EatGrass.java +++ /dev/null @@ -1,40 +0,0 @@ -package class029; - -public class Code02_EatGrass { - - // 当前有N份草,当前轮到先手先吃,然后后手再吃 - // 1,4,16,64,... - // 返回 String "先手" "后手" - public static String winner1(int n) { - if (n < 5) { - return (n == 0 || n == 2) ? "后手" : "先手"; - } - // 先手吃的草数 - int eat = 1; - while (eat <= n) { - if (winner1(n - eat).equals("后手")) { - return "先手"; - } - if (eat > n / 4) { // 防止溢出 - break; - } - eat *= 4; - } - return "后手"; - } - - public static String winner2(int n) { - if (n % 5 == 0 || n % 5 == 2) { - return "后手"; - } else { - return "先手"; - } - } - - public static void main(String[] args) { - for (int i = 0; i <= 50; i++) { - System.out.println(i + " : " + winner1(i)); - } - } - -} diff --git a/公开课/class029/Code03_MaxLeftMaxRight.java b/公开课/class029/Code03_MaxLeftMaxRight.java deleted file mode 100644 index 0b1a82a..0000000 --- a/公开课/class029/Code03_MaxLeftMaxRight.java +++ /dev/null @@ -1,80 +0,0 @@ -package class029; - -public class Code03_MaxLeftMaxRight { - - // 笨办法,但是好想 - public static int solution1(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int ans = Integer.MIN_VALUE; - for (int leftEnd = 0; leftEnd < N - 1; leftEnd++) { - int leftMax = arr[0]; - for (int i = 1; i <= leftEnd; i++) { - leftMax = Math.max(leftMax, arr[i]); - } - int rightMax = arr[leftEnd + 1]; - for (int i = leftEnd + 2; i < N; i++) { - rightMax = Math.max(rightMax, arr[i]); - } - ans = Math.max(ans, Math.abs(leftMax - rightMax)); - } - return ans; - } - - // 好办法,是我们真正想测试的 - public static int solution2(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int max = arr[0]; - for (int i = 1; i < N; i++) { - max = Math.max(max, arr[i]); - } - return max - Math.min(arr[0], arr[N - 1]); - } - - public static int[] randomArray(int maxLen, int maxValue) { - int len = (int) (Math.random() * (maxLen + 1)); - int[] arr = new int[len]; - for (int i = 0; i < arr.length; i++) { - arr[i] = (int) (Math.random() * (maxValue + 1)) - (int) (Math.random() * (maxValue + 1)); - } - return arr; - } - - public static void main(String[] args) { - // 随机数组的最大长度 - int maxLen = 6; - // 随机数组值的范围 - int maxValue = 30; - // 测试次数 - int testTime = 3000000; - System.out.println("如果没有错误信息打印,说明所有测试通过"); - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - // 随机得到一个数组,长度也随机,每个值也随机 - int[] arr = randomArray(maxLen, maxValue); - // 用方法1跑出答案1 - int ans1 = solution1(arr); - // 用方法2跑出答案2 - int ans2 = solution2(arr); - // 如果答案1和答案2不一样,提示出错了 - if (ans1 != ans2) { - System.out.println("出错了!"); - System.out.println(ans1 + " , " + ans2); - - for (int k = 0; k < arr.length; k++) { - System.out.print(arr[k] + " "); - } - System.out.println(); - - break; - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class030/Code01_IsPalindrome.java b/公开课/class030/Code01_IsPalindrome.java deleted file mode 100644 index d41667c..0000000 --- a/公开课/class030/Code01_IsPalindrome.java +++ /dev/null @@ -1,25 +0,0 @@ -package class030; - -// 测试链接:https://leetcode.com/problems/palindrome-number -public class Code01_IsPalindrome { - - // n<0 不是回文数 - public static boolean isPalindrome(int n) { - if (n < 0) { - return false; - } - int help = 1; - while (n / help >= 10) { - help *= 10; - } - while (n != 0) { - if (n / help != n % 10) { - return false; - } - n = (n % help) / 10; - help /= 100; - } - return true; - } - -} diff --git a/公开课/class030/Code02_MySqrt.java b/公开课/class030/Code02_MySqrt.java deleted file mode 100644 index ca6275c..0000000 --- a/公开课/class030/Code02_MySqrt.java +++ /dev/null @@ -1,30 +0,0 @@ -package class030; - -// 测试链接:https://leetcode.com/problems/sqrtx -public class Code02_MySqrt { - - public static int mySqrt(int x) { - if (x == 0) { - return 0; - } - if (x < 3) { - return 1; - } - long ans = 1; - long L = 1; - long R = x; - long M = 0; - // L...R 1....x - while (L <= R) { - M = (L + R) / 2; - if (M * M <= x) { - ans = M; - L = M + 1; - } else { - R = M - 1; - } - } - return (int) ans; - } - -} diff --git a/公开课/class030/Code03_UglyNumber.java b/公开课/class030/Code03_UglyNumber.java deleted file mode 100644 index a307344..0000000 --- a/公开课/class030/Code03_UglyNumber.java +++ /dev/null @@ -1,51 +0,0 @@ -package class030; - -// 测试链接:https://leetcode.com/problems/ugly-number-ii -public class Code03_UglyNumber { - - public static boolean isUgly(int num) { - while (num % 2 == 0) { - num /= 2; - } - while (num % 3 == 0) { - num /= 3; - } - while (num % 5 == 0) { - num /= 5; - } - return num == 1; - } - - public static int nthUglyNumber1(int n) { - int find = 0; - int num = 1; - for (; find < n; num++) { - if (isUgly(num)) { - find++; - } - } - return num - 1; - } - - public static int nthUglyNumber2(int n) { - int[] ugly = new int[n + 1]; - ugly[1] = 1; - int i2 = 1; - int i3 = 1; - int i5 = 1; - for (int i = 2; i <= n; i++) { - ugly[i] = Math.min(Math.min(ugly[i2] * 2, ugly[i3] * 3), ugly[i5] * 5); - if (ugly[i] == ugly[i2] * 2) { - i2++; - } - if (ugly[i] == ugly[i3] * 3) { - i3++; - } - if (ugly[i] == ugly[i5] * 5) { - i5++; - } - } - return ugly[n]; - } - -} diff --git a/公开课/class030/Code04_EnterLoopNode.java b/公开课/class030/Code04_EnterLoopNode.java deleted file mode 100644 index 082b3f3..0000000 --- a/公开课/class030/Code04_EnterLoopNode.java +++ /dev/null @@ -1,34 +0,0 @@ -package class030; - -// 测试链接:https://leetcode.com/problems/linked-list-cycle-ii -public class Code04_EnterLoopNode { - - // 这个类不用提交 - public static class ListNode { - public int val; - public ListNode next; - } - - // 只提交以下的代码 - public static ListNode detectCycle(ListNode head) { - if (head == null || head.next == null || head.next.next == null) { - return null; - } - ListNode slow = head.next; - ListNode fast = head.next.next; - while (slow != fast) { - if (fast.next == null || fast.next.next == null) { - return null; - } - fast = fast.next.next; - slow = slow.next; - } - fast = head; - while (slow != fast) { - slow = slow.next; - fast = fast.next; - } - return slow; - } - -} diff --git a/公开课/class031/Code01_SwapWithoutTmp.java b/公开课/class031/Code01_SwapWithoutTmp.java deleted file mode 100644 index 805908b..0000000 --- a/公开课/class031/Code01_SwapWithoutTmp.java +++ /dev/null @@ -1,24 +0,0 @@ -package class031; - -public class Code01_SwapWithoutTmp { - - public static void main(String[] args) { - - int test1 = 23; - int test2 = 15; - System.out.println(test1 ^ test2); - - - - int a = -111; - int b = 343242111; - System.out.println(a); - System.out.println(b); - a = a ^ b; - b = a ^ b; - a = a ^ b; - System.out.println(a); - System.out.println(b); - } - -} diff --git a/公开课/class031/Code02_AddMinus.java b/公开课/class031/Code02_AddMinus.java deleted file mode 100644 index 9ed4638..0000000 --- a/公开课/class031/Code02_AddMinus.java +++ /dev/null @@ -1,29 +0,0 @@ -package class031; - -public class Code02_AddMinus { - - public static int add(int a, int b) { - int t = 0; - while (b != 0) { - t = a; - a = a ^ b; // a -> a' 无进位相加信息 - b = ((t & b) << 1); // b -> b' 进位信息 - } - return a; - } - - public static int minus(int a, int b) { - return add(a, add(~b, 1)); - } - - public static void main(String[] args) { - int a = 8739284; - int b = 7348472; - System.out.println(a + b); - System.out.println(add(a, b)); - - System.out.println(a - b); - System.out.println(minus(a, b)); - } - -} diff --git a/公开课/class031/Code03_GetMax.java b/公开课/class031/Code03_GetMax.java deleted file mode 100644 index c3f54a5..0000000 --- a/公开课/class031/Code03_GetMax.java +++ /dev/null @@ -1,49 +0,0 @@ -package class031; - -public class Code03_GetMax { - - // n 0或1 - // 0 -> 1 1 -> 0 - public static int flip(int n) { - return n ^ 1; - } - - // n 任意整数 - // n非负的,返回1 - // n负的,返回0 - public static int sign(int n) { - // (n >> 31) & 1 n非负的 0 n负的 1 - return flip((n >> 31) & 1); - } - - public static int getMax1(int a, int b) { - int c = a - b; - int scA = sign(c); // a - b >= 0 scA = 1; a - b <0 scA = 0 - int scB = flip(scA); // a - b >= 0 scB = 0; a - b <0 scB = 1 - return a * scA + b * scB; - } - - public static int getMax2(int a, int b) { - int c = a - b; - int sa = sign(a); // a的符号,非负 1 负 0 - int sb = sign(b); // b的符号,非负 1 负 0 - int sc = sign(c); // a-b的符号,非负 1 负 0 - int difSab = sa ^ sb; // 如果不一样,1;如果一样,0 - int sameSab = flip(difSab);// 如果一样,1;如果不一样,0 - int returnA = difSab * sa + sameSab * sc; - int returnB = flip(returnA); - return a * returnA + b * returnB; - } - - public static void main(String[] args) { - int a = -16; - int b = -19; - System.out.println(getMax1(a, b)); - System.out.println(getMax2(a, b)); - a = 2147483647; - b = -2147480000; - System.out.println(getMax1(a, b)); // wrong answer because of overflow - System.out.println(getMax2(a, b)); - } - -} diff --git a/公开课/class031/Code04_MissingNumber.java b/公开课/class031/Code04_MissingNumber.java deleted file mode 100644 index c750981..0000000 --- a/公开课/class031/Code04_MissingNumber.java +++ /dev/null @@ -1,27 +0,0 @@ -package class031; - -// 测试链接:https://leetcode.com/problems/first-missing-positive/ -public class Code04_MissingNumber { - - public static int firstMissingPositive(int[] arr) { - int l = 0; - int r = arr.length; - while (l != r) { - if (arr[l] == l + 1) { - l++; - } else if (arr[l] <= l + 1 || arr[l] > r || arr[arr[l] - 1] == arr[l]) { - swap(arr, l, --r); - } else { - swap(arr, l, arr[l] - 1); - } - } - return l + 1; - } - - public static void swap(int[] arr, int i, int j) { - int tmp = arr[i]; - arr[i] = arr[j]; - arr[j] = tmp; - } - -} diff --git a/公开课/class032/Code01_BinaryTreeLevelOrderTraversal.java b/公开课/class032/Code01_BinaryTreeLevelOrderTraversal.java deleted file mode 100644 index 3b913ca..0000000 --- a/公开课/class032/Code01_BinaryTreeLevelOrderTraversal.java +++ /dev/null @@ -1,46 +0,0 @@ -package class032; - -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.Queue; - -// 测试链接:https://leetcode.com/problems/binary-tree-level-order-traversal -public class Code01_BinaryTreeLevelOrderTraversal { - - public static class TreeNode { - public int val; - public TreeNode left; - public TreeNode right; - - TreeNode(int val) { - this.val = val; - } - } - - public List> levelOrder(TreeNode root) { - List> ans = new ArrayList<>(); - if (root == null) { - return ans; - } - Queue queue = new LinkedList<>(); - queue.add(root); - while (!queue.isEmpty()) { - int size = queue.size(); - List curAns = new ArrayList<>(); - for (int i = 0; i < size; i++) { - TreeNode curNode = queue.poll(); - curAns.add(curNode.val); - if (curNode.left != null) { - queue.add(curNode.left); - } - if (curNode.right != null) { - queue.add(curNode.right); - } - } - ans.add(curAns); - } - return ans; - } - -} diff --git a/公开课/class032/Code01_BinaryTreeLevelOrderTraversalII.java b/公开课/class032/Code01_BinaryTreeLevelOrderTraversalII.java deleted file mode 100644 index a5217e0..0000000 --- a/公开课/class032/Code01_BinaryTreeLevelOrderTraversalII.java +++ /dev/null @@ -1,45 +0,0 @@ -package class032; - -import java.util.LinkedList; -import java.util.List; -import java.util.Queue; - -// 测试链接:https://leetcode.com/problems/binary-tree-level-order-traversal-ii -public class Code01_BinaryTreeLevelOrderTraversalII { - - public static class TreeNode { - public int val; - public TreeNode left; - public TreeNode right; - - TreeNode(int val) { - this.val = val; - } - } - - public List> levelOrderBottom(TreeNode root) { - List> ans = new LinkedList<>(); - if (root == null) { - return ans; - } - Queue queue = new LinkedList<>(); - queue.add(root); - while (!queue.isEmpty()) { - int size = queue.size(); - List curAns = new LinkedList<>(); - for (int i = 0; i < size; i++) { - TreeNode curNode = queue.poll(); - curAns.add(curNode.val); - if (curNode.left != null) { - queue.add(curNode.left); - } - if (curNode.right != null) { - queue.add(curNode.right); - } - } - ans.add(0, curAns); - } - return ans; - } - -} diff --git a/公开课/class032/Code02_ConstructBinaryTreeFromPreorderAndInorderTraversal.java b/公开课/class032/Code02_ConstructBinaryTreeFromPreorderAndInorderTraversal.java deleted file mode 100644 index 15cde6b..0000000 --- a/公开课/class032/Code02_ConstructBinaryTreeFromPreorderAndInorderTraversal.java +++ /dev/null @@ -1,74 +0,0 @@ -package class032; - -import java.util.HashMap; - -// 测试链接:https://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal -public class Code02_ConstructBinaryTreeFromPreorderAndInorderTraversal { - - public static class TreeNode { - int val; - TreeNode left; - TreeNode right; - - TreeNode(int val) { - this.val = val; - } - } - - public static TreeNode buildTree1(int[] pre, int[] in) { - if (pre == null || in == null || pre.length != in.length) { - return null; - } - return process1(pre, 0, pre.length - 1, in, 0, in.length - 1); - } - - // 只使用pre[L1...R1]这一段,作为这棵树先序遍历的结果 - // 只使用in [L2...R2]这一段,作为这棵树中序遍历的结果 - // 建立好这棵树,然后把头节点返回 - public static TreeNode process1(int[] pre, int L1, int R1, int[] in, int L2, int R2) { - if (L1 > R1) { - return null; - } - if (L1 == R1) { - return new TreeNode(pre[L1]); - } - TreeNode head = new TreeNode(pre[L1]); - int find = L2; - while (in[find] != pre[L1]) { - find++; - } - head.left = process1(pre, L1 + 1, L1 + find - L2, in, L2, find - 1); - head.right = process1(pre, L1 + find - L2 + 1, R1, in, find + 1, R2); - return head; - } - - public static TreeNode buildTree2(int[] pre, int[] in) { - if (pre == null || in == null || pre.length != in.length) { - return null; - } - HashMap valueIndexMap = new HashMap<>(); - for (int i = 0; i < in.length; i++) { - valueIndexMap.put(in[i], i); - } - return process2(pre, 0, pre.length - 1, in, 0, in.length - 1, valueIndexMap); - } - - // 只使用pre[L1...R1]这一段,作为这棵树先序遍历的结果 - // 只使用in [L2...R2]这一段,作为这棵树中序遍历的结果 - // 建立好这棵树,然后把头节点返回 - public static TreeNode process2(int[] pre, int L1, int R1, int[] in, int L2, int R2, - HashMap valueIndexMap) { - if (L1 > R1) { - return null; - } - if (L1 == R1) { - return new TreeNode(pre[L1]); - } - TreeNode head = new TreeNode(pre[L1]); - int find = valueIndexMap.get(pre[L1]); - head.left = process2(pre, L1 + 1, L1 + find - L2, in, L2, find - 1, valueIndexMap); - head.right = process2(pre, L1 + find - L2 + 1, R1, in, find + 1, R2, valueIndexMap); - return head; - } - -} diff --git a/公开课/class032/Code03_PaperFolding.java b/公开课/class032/Code03_PaperFolding.java deleted file mode 100644 index 88a229b..0000000 --- a/公开课/class032/Code03_PaperFolding.java +++ /dev/null @@ -1,26 +0,0 @@ -package class032; - -public class Code03_PaperFolding { - - public static void printAllFolds(int N) { - process(1, N, true); - System.out.println(); - } - - // 假想中的当前节点,在i层,一共N层, - // 假想中的当前节点凹还是凸?down决定!down = true 凹 down = false 凸 - // 打印以假想节点为头的整棵树,中序打印 - public static void process(int i, int N, boolean down) { - if (i > N) { - return; - } - process(i + 1, N, true); - System.out.print(down ? "凹 " : "凸 "); - process(i + 1, N, false); - } - - public static void main(String[] args) { - int N = 4; - printAllFolds(N); - } -} diff --git a/公开课/class032/Code04_DiameterOfBinaryTree.java b/公开课/class032/Code04_DiameterOfBinaryTree.java deleted file mode 100644 index fc18efa..0000000 --- a/公开课/class032/Code04_DiameterOfBinaryTree.java +++ /dev/null @@ -1,38 +0,0 @@ -package class032; - -// 测试链接:https://leetcode.com/problems/diameter-of-binary-tree -public class Code04_DiameterOfBinaryTree { - - public static class TreeNode { - public int val; - public TreeNode left; - public TreeNode right; - } - - public static int diameterOfBinaryTree(TreeNode root) { - return process(root).maxDistance; - } - - public static class Info { - public int maxDistance; - public int height; - - public Info(int m, int h) { - maxDistance = m; - height = h; - } - } - - public static Info process(TreeNode x) { - if (x == null) { - return new Info(0, 0); - } - Info leftInfo = process(x.left); - Info rightInfo = process(x.right); - int maxDistance = Math.max(Math.max(leftInfo.maxDistance, rightInfo.maxDistance), - leftInfo.height + rightInfo.height); - int height = Math.max(leftInfo.height, rightInfo.height) + 1; - return new Info(maxDistance, height); - } - -} diff --git a/公开课/class033/Code01_FindHalfMajority.java b/公开课/class033/Code01_FindHalfMajority.java deleted file mode 100644 index 4bd4acc..0000000 --- a/公开课/class033/Code01_FindHalfMajority.java +++ /dev/null @@ -1,76 +0,0 @@ -package class033; - -import java.util.HashMap; -import java.util.Map.Entry; - -public class Code01_FindHalfMajority { - - public static int halfMajor(int[] arr) { - int target = 0; - int HP = 0; - for (int i = 0; i != arr.length; i++) { - if (HP == 0) { - target = arr[i]; - HP = 1; - } else if (arr[i] == target) { - HP++; - } else { - HP--; - } - } - if (HP == 0) { - return -1; - } - HP = 0; - for (int i = 0; i != arr.length; i++) { - if (arr[i] == target) { - HP++; - } - } - return HP > arr.length / 2 ? target : -1; - } - - // for test - public static int right(int[] arr) { - HashMap map = new HashMap<>(); - for (int cur : arr) { - if (!map.containsKey(cur)) { - map.put(cur, 0); - } - map.put(cur, map.get(cur) + 1); - } - for (Entry entry : map.entrySet()) { - if (entry.getValue() > arr.length / 2) { - return entry.getKey(); - } - } - return -1; - } - - // for test - public static int[] genareteRandomArray(int len, int max) { - int[] ans = new int[(int) (Math.random() * len) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * max) + 1; - } - return ans; - } - - public static void main(String[] args) { - int len = 100; - int max = 10; - int testTime = 100000; - System.out.println("test begin"); - for (int i = 0; i < testTime; i++) { - int[] arr = genareteRandomArray(len, max); - int ans1 = halfMajor(arr); - int ans2 = right(arr); - if (ans1 != ans2) { - System.out.println("Oops!"); - break; - } - } - System.out.println("test end"); - } - -} diff --git a/公开课/class033/Code02_RotateImage.java b/公开课/class033/Code02_RotateImage.java deleted file mode 100644 index e3d48f2..0000000 --- a/公开课/class033/Code02_RotateImage.java +++ /dev/null @@ -1,52 +0,0 @@ -package class033; - -public class Code02_RotateImage { - - public static void rotate(int[][] matrix) { - int a = 0; - int b = 0; - int c = matrix.length - 1; - int d = matrix[0].length - 1; - while (a < c) { - rotateEdge(matrix, a++, b++, c--, d--); - } - } - - // 在二维数组m中,左上角点(a,b), 右下角点(c,d) - // 只在规定好的框上,顺时针转好 - public static void rotateEdge(int[][] m, int a, int b, int c, int d) { - int tmp = 0; - for (int i = 0; i < d - b; i++) { - tmp = m[a][b + i]; - m[a][b + i] = m[c - i][b]; - m[c - i][b] = m[c][d - i]; - m[c][d - i] = m[a + i][d]; - m[a + i][d] = tmp; - } - } - - public static void printMatrix(int[][] m) { - int N = m.length; - for (int i = 0; i < N; i++) { - for (int j = 0; j < N; j++) { - System.out.print(m[i][j] + " "); - } - System.out.println(); - } - } - - public static void main(String[] args) { - int[][] matrix = { - { 1, 2, 3 }, - { 4, 5, 6 }, - { 7, 8, 9 } }; - printMatrix(matrix); - System.out.println("========"); - - rotate(matrix); - printMatrix(matrix); - System.out.println("========"); - - } - -} diff --git a/公开课/class033/Code03_ZigZagPrintMatrix.java b/公开课/class033/Code03_ZigZagPrintMatrix.java deleted file mode 100644 index b062447..0000000 --- a/公开课/class033/Code03_ZigZagPrintMatrix.java +++ /dev/null @@ -1,48 +0,0 @@ -package class033; - -public class Code03_ZigZagPrintMatrix { - - public static void printMatrixZigZag(int[][] m) { - // (a,b) A 先往右,再往下 - int a = 0; - int b = 0; - // (c,d) B 先往下,在往右 - int c = 0; - int d = 0; - int er = m.length - 1; - int ec = m[0].length - 1; - boolean fromUp = false; - while (a != er + 1) { - printLevel(m, a, b, c, d, fromUp); - // A 先往右,再往下 - a = b == ec ? a + 1 : a; - b = b == ec ? b : b + 1; - // B 先往下,在往右 - d = c == er ? d + 1 : d; - c = c == er ? c : c + 1; - fromUp = !fromUp; - } - } - - public static void printLevel(int[][] m, int a, int b, int c, int d, boolean f) { - if (f) { - while (a != c + 1) { - System.out.print(m[a++][b--] + " "); - } - } else { - while (c != a - 1) { - System.out.print(m[c--][d++] + " "); - } - } - } - - public static void main(String[] args) { - int[][] matrix = { - { 1, 2, 3, 4 }, - { 5, 6, 7, 8 }, - { 9, 10, 11, 12 } }; - printMatrixZigZag(matrix); - - } - -} diff --git a/公开课/class033/Code04_PrintStar.java b/公开课/class033/Code04_PrintStar.java deleted file mode 100644 index bf51f37..0000000 --- a/公开课/class033/Code04_PrintStar.java +++ /dev/null @@ -1,46 +0,0 @@ -package class033; - -public class Code04_PrintStar { - - public static void printStar(int N) { - int leftUp = 0; - int rightDown = N - 1; - char[][] m = new char[N][N]; - for (int i = 0; i < N; i++) { - for (int j = 0; j < N; j++) { - m[i][j] = ' '; - } - } - while (leftUp <= rightDown) { - set(m, leftUp, rightDown); - leftUp += 2; - rightDown -= 2; - } - for (int i = 0; i < N; i++) { - for (int j = 0; j < N; j++) { - System.out.print(m[i][j] + " "); - } - System.out.println(); - } - } - - public static void set(char[][] m, int leftUp, int rightDown) { - for (int col = leftUp; col <= rightDown; col++) { - m[leftUp][col] = '*'; - } - for (int row = leftUp + 1; row <= rightDown; row++) { - m[row][rightDown] = '*'; - } - for (int col = rightDown - 1; col > leftUp; col--) { - m[rightDown][col] = '*'; - } - for (int row = rightDown - 1; row > leftUp + 1; row--) { - m[row][leftUp + 1] = '*'; - } - } - - public static void main(String[] args) { - printStar(8); - } - -} diff --git a/公开课/class034/Code01_Water.java b/公开课/class034/Code01_Water.java deleted file mode 100644 index cea25b0..0000000 --- a/公开课/class034/Code01_Water.java +++ /dev/null @@ -1,118 +0,0 @@ -package class034; - -public class Code01_Water { - - // 本题测试链接:https://leetcode.com/problems/trapping-rain-water/ - // 给定一个正整数数组arr,把arr想象成一个直方图。返回这个直方图如果装水,能装下几格水? - public static int water1(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int water = 0; - for (int i = 1; i < N - 1; i++) { - int leftMax = Integer.MIN_VALUE; - for (int j = 0; j < i; j++) { - leftMax = Math.max(leftMax, arr[j]); - } - int rightMax = Integer.MIN_VALUE; - for (int j = i + 1; j < N; j++) { - rightMax = Math.max(rightMax, arr[j]); - } - water += Math.max(Math.min(leftMax, rightMax) - arr[i], 0); - } - return water; - } - - public static int water2(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int[] leftMaxs = new int[N]; - leftMaxs[0] = arr[0]; - for (int i = 1; i < N; i++) { - leftMaxs[i] = Math.max(leftMaxs[i - 1], arr[i]); - } - - int[] rightMaxs = new int[N]; - rightMaxs[N - 1] = arr[N - 1]; - for (int i = N - 2; i >= 0; i--) { - rightMaxs[i] = Math.max(rightMaxs[i + 1], arr[i]); - } - int water = 0; - for (int i = 1; i < N - 1; i++) { - water += Math.max(Math.min(leftMaxs[i - 1], rightMaxs[i + 1]) - arr[i], 0); - } - return water; - } - - public static int water3(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int[] rightMaxs = new int[N]; - rightMaxs[N - 1] = arr[N - 1]; - for (int i = N - 2; i >= 0; i--) { - rightMaxs[i] = Math.max(rightMaxs[i + 1], arr[i]); - } - int water = 0; - int leftMax = arr[0]; - for (int i = 1; i < N - 1; i++) { - water += Math.max(Math.min(leftMax, rightMaxs[i + 1]) - arr[i], 0); - leftMax = Math.max(leftMax, arr[i]); - } - return water; - } - - public static int water4(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int L = 1; - int leftMax = arr[0]; - int R = N - 2; - int rightMax = arr[N - 1]; - int water = 0; - while (L <= R) { - if (leftMax <= rightMax) { - water += Math.max(0, leftMax - arr[L]); - leftMax = Math.max(leftMax, arr[L++]); - } else { - water += Math.max(0, rightMax - arr[R]); - rightMax = Math.max(rightMax, arr[R--]); - } - } - return water; - } - - // for test - public static int[] generateRandomArray(int len, int value) { - int[] ans = new int[(int) (Math.random() * len) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * value) + 1; - } - return ans; - } - - public static void main(String[] args) { - int len = 100; - int value = 200; - int testTimes = 100000; - System.out.println("test begin"); - for (int i = 0; i < testTimes; i++) { - int[] arr = generateRandomArray(len, value); - int ans1 = water1(arr); - int ans2 = water2(arr); - int ans3 = water3(arr); - int ans4 = water4(arr); - if (ans1 != ans2 || ans3 != ans4 || ans1 != ans3) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - } - -} diff --git a/公开课/class034/Code02_RandToRand.java b/公开课/class034/Code02_RandToRand.java deleted file mode 100644 index a81c764..0000000 --- a/公开课/class034/Code02_RandToRand.java +++ /dev/null @@ -1,134 +0,0 @@ -package class034; - -public class Code02_RandToRand { - - // 此函数只能用,不能修改 - // 等概率返回1~5 - public static int f() { - return (int) (Math.random() * 5) + 1; - } - - // 等概率得到0和1 - public static int a() { - int ans = 0; - do { - ans = f(); - } while (ans == 3); - return ans < 3 ? 0 : 1; - } - - // 等概率返回0~6 - public static int b() { - int ans = 0; - do { - ans = (a() << 2) + (a() << 1) + a(); - } while (ans == 7); - return ans; - } - - // 等概率返回1~7 - public static int c() { - return b() + 1; - } - - // 这个结构是唯一的随机机制 - // 你只能初始化并使用,不可修改 - public static class RandomBox { - private final int min; - private final int max; - - // 初始化时请一定不要让mi==ma - public RandomBox(int mi, int ma) { - min = mi; - max = ma; - } - - // 13 ~ 17 - // 13 + [0,4] - public int random() { - return min + (int) (Math.random() * (max - min + 1)); - } - - public int min() { - return min; - } - - public int max() { - return max; - } - } - - // 利用条件RandomBox,如何等概率返回0和1 - public static int rand01(RandomBox randomBox) { - int min = randomBox.min(); - int max = randomBox.max(); - // min ~ max - int size = max - min + 1; - // size是不是奇数,odd 奇数 - boolean odd = (size & 1) != 0; - int mid = size / 2; - int ans = 0; - do { - ans = randomBox.random() - min; - } while (odd && ans == mid); - return ans < mid ? 0 : 1; - } - - // 给你一个RandomBox,这是唯一能借助的随机机制 - // 等概率返回from~to范围上任何一个数 - // 要求from<=to - public static int random(RandomBox randomBox, int from, int to) { - if (from == to) { - return from; - } - // 3 ~ 9 - // 0 ~ 6 - // 0 ~ range - int range = to - from; - int num = 1; - // 求0~range需要几个2进制位 - while ((1 << num) - 1 < range) { - num++; - } - - // 我们一共需要num位 - // 最终的累加和,首先+0位上是1还是0,1位上是1还是0,2位上是1还是0... - int ans = 0; - do { - ans = 0; - for (int i = 0; i < num; i++) { - ans |= (rand01(randomBox) << i); - } - } while (ans > range); - return ans + from; - } - - public static void main(String[] args) { - - int[] count = new int[8]; // 0 1 2 .. 7 - int testTime = 10000000; - for (int i = 0; i < testTime; i++) { - int ans = c(); - count[ans]++; - } - - for (int i = 0; i < 8; i++) { - System.out.println(i + " : " + count[i]); - } - -// RandomBox randomBox = new RandomBox(3, 9); -// int from = 17; -// int to = 29; -// int[] ans = new int[to + 1]; -// int testTime1 = 1000000; -// for (int i = 0; i < testTime1; i++) { -// ans[random(randomBox, from, to)]++; -// } -// for (int i = 0; i < ans.length; i++) { -// System.out.println(ans[i]); -// } -// System.out.println("=========="); - - } - -} diff --git a/公开课/class034/Code03_EqualProbabilityRandom.java b/公开课/class034/Code03_EqualProbabilityRandom.java deleted file mode 100644 index 8254281..0000000 --- a/公开课/class034/Code03_EqualProbabilityRandom.java +++ /dev/null @@ -1,67 +0,0 @@ -package class034; - -public class Code03_EqualProbabilityRandom { - - // 内部内容不可见 - public static int f() { - return Math.random() < 0.8 ? 0 : 1; - } - - // 等概率返回0和1 - public static int g() { - int first = 0; - do { - first = f(); // 0 1 - } while (first == f()); - return first; - } - - // 这个结构是唯一的随机机制 - // 你只能初始化并使用,不可修改 - public static class RandomBox { - private final double p; - - // 初始化时请一定满足:0 < zeroP < 1 - public RandomBox(double zeroP) { - p = zeroP; - } - - public int random() { - return Math.random() < p ? 0 : 1; - } - - } - - // 底层依赖一个以p概率返回0,以1-p概率返回1的随机函数rand01p - // 如何加工出等概率返回0和1的函数 - public static int rand01(RandomBox randomBox) { - int num; - do { - num = randomBox.random(); - } while (num == randomBox.random()); - return num; - } - - public static void main(String[] args) { - int[] count = new int[2];// 0 1 - for (int i = 0; i < 1000000; i++) { - int ans = g(); - count[ans]++; - } - System.out.println(count[0] + " , " + count[1]); - -// double zeroP = 0.88; -// RandomBox randomBox = new RandomBox(zeroP); -// -// int testTime = 10000000; -// int count = 0; -// for (int i = 0; i < testTime; i++) { -// if (rand01(randomBox) == 0) { -// count++; -// } -// } -// System.out.println((double) count / (double) testTime); - - } - -} diff --git a/公开课/class034/Code04_EvenTimesOddTimes.java b/公开课/class034/Code04_EvenTimesOddTimes.java deleted file mode 100644 index 7851b57..0000000 --- a/公开课/class034/Code04_EvenTimesOddTimes.java +++ /dev/null @@ -1,52 +0,0 @@ -package class034; - -public class Code04_EvenTimesOddTimes { - - public static void printOddTimesNum1(int[] arr) { - int eor = 0; - for (int i = 0; i < arr.length; i++) { - eor ^= arr[i]; - } - System.out.println(eor); - } - - public static void printOddTimesNum2(int[] arr) { - // arr中,a和b出现了奇数次,其他数都是偶数次 - int eor = 0; - for (int i = 0; i < arr.length; i++) { - eor ^= arr[i]; - } - // eor = a ^ b - // eor != 0 - // eor : 001100100 - // rightOne : 000000100 - int rightOne = eor & (~eor + 1); - int onlyOne = 0; // eor' - for (int i = 0; i < arr.length; i++) { - if ((arr[i] & rightOne) != 0) { - onlyOne ^= arr[i]; - } - } - // eor' = a or b - System.out.println(onlyOne + " " + (eor ^ onlyOne)); - } - - public static int bit1counts(int N) { - int count = 0; - while (N != 0) { - int rightOne = N & ((~N) + 1); - count++; - N -= rightOne; - } - return count; - } - - public static void main(String[] args) { - int[] arr1 = { 3, 3, 2, 3, 1, 1, 1, 3, 1, 1, 1 }; - printOddTimesNum1(arr1); - - int[] arr2 = { 4, 3, 4, 2, 2, 2, 4, 1, 1, 1, 3, 3, 1, 1, 1, 4, 2, 2 }; - printOddTimesNum2(arr2); - } - -} diff --git a/公开课/class034/Code05_MakeNo.java b/公开课/class034/Code05_MakeNo.java deleted file mode 100644 index f5bd4ea..0000000 --- a/公开课/class034/Code05_MakeNo.java +++ /dev/null @@ -1,50 +0,0 @@ -package class034; - -public class Code05_MakeNo { - - public static int[] makeNo(int size) { - if (size == 1) { - return new int[] { 1 }; - } - int halfSize = (size + 1) / 2; - int[] base = makeNo(halfSize); - int[] ans = new int[size]; - int index = 0; - for (; index < halfSize; index++) { - ans[index] = base[index] * 2 + 1; - } - for (int i = 0; index < size; index++, i++) { - ans[index] = base[i] * 2; - } - return ans; - } - - // 检验函数 - public static boolean isValid(int[] arr) { - int N = arr.length; - for (int i = 0; i < N; i++) { - for (int k = i + 1; k < N; k++) { - for (int j = k + 1; j < N; j++) { - if (arr[i] + arr[j] == 2 * arr[k]) { - return false; - } - } - } - } - return true; - } - - public static void main(String[] args) { - System.out.println("test begin"); - for (int N = 1; N < 1000; N++) { - int[] arr = makeNo(N); - if (!isValid(arr)) { - System.out.println("Oops!"); - } - } - System.out.println("test end"); - System.out.println(isValid(makeNo(1042))); - System.out.println(isValid(makeNo(2981))); - } - -} diff --git a/公开课/class035/Code01_UglyNumber.java b/公开课/class035/Code01_UglyNumber.java deleted file mode 100644 index 23dcb10..0000000 --- a/公开课/class035/Code01_UglyNumber.java +++ /dev/null @@ -1,62 +0,0 @@ -package class035; - -// 测试链接:https://leetcode.com/problems/ugly-number-ii -public class Code01_UglyNumber { - - public static boolean isUgly(int num) { - while (num % 2 == 0) { - num /= 2; - } - while (num % 3 == 0) { - num /= 3; - } - while (num % 5 == 0) { - num /= 5; - } - return num == 1; - } - - public static int nthUglyNumber1(int n) { - int find = 0; - int num = 1; - for (; find < n; num++) { - if (isUgly(num)) { - find++; - } - } - return num - 1; - } - - - - - - - - - public static int nthUglyNumber2(int n) { - int[] ugly = new int[n + 1]; - ugly[1] = 1; - int i2 = 1; - int i3 = 1; - int i5 = 1; - for (int i = 2; i <= n; i++) { - ugly[i] = Math.min(Math.min(ugly[i2] * 2, ugly[i3] * 3), ugly[i5] * 5); - if (ugly[i] == ugly[i2] * 2) { - i2++; - } - if (ugly[i] == ugly[i3] * 3) { - i3++; - } - if (ugly[i] == ugly[i5] * 5) { - i5++; - } - } - return ugly[n]; - } - - public static void main(String[] args) { - System.out.println(nthUglyNumber2(10000)); - } - -} diff --git a/公开课/class035/Code02_MakeNo.java b/公开课/class035/Code02_MakeNo.java deleted file mode 100644 index 25027ed..0000000 --- a/公开课/class035/Code02_MakeNo.java +++ /dev/null @@ -1,50 +0,0 @@ -package class035; - -public class Code02_MakeNo { - - public static int[] makeNo(int size) { - if (size == 1) { - return new int[] { 1 }; - } - int halfSize = (size + 1) / 2; - int[] base = makeNo(halfSize); - int[] ans = new int[size]; - int index = 0; - for (; index < halfSize; index++) { - ans[index] = base[index] * 2 + 1; - } - for (int i = 0; index < size; index++, i++) { - ans[index] = base[i] * 2; - } - return ans; - } - - // 检验函数 - public static boolean isValid(int[] arr) { - int N = arr.length; - for (int i = 0; i < N; i++) { - for (int k = i + 1; k < N; k++) { - for (int j = k + 1; j < N; j++) { - if (arr[i] + arr[j] == 2 * arr[k]) { - return false; - } - } - } - } - return true; - } - - public static void main(String[] args) { - System.out.println("test begin"); - for (int N = 1; N < 1000; N++) { - int[] arr = makeNo(N); - if (!isValid(arr)) { - System.out.println("Oops!"); - } - } - System.out.println("test end"); - System.out.println(isValid(makeNo(1042))); - System.out.println(isValid(makeNo(2981))); - } - -} diff --git a/公开课/class035/Code03_CoverMax.java b/公开课/class035/Code03_CoverMax.java deleted file mode 100644 index fa7a3cb..0000000 --- a/公开课/class035/Code03_CoverMax.java +++ /dev/null @@ -1,131 +0,0 @@ -package class035; - -import java.util.Arrays; -import java.util.Comparator; -import java.util.PriorityQueue; - -public class Code03_CoverMax { - - public static int maxCover1(int[][] lines) { - int min = Integer.MAX_VALUE; - int max = Integer.MIN_VALUE; - for (int i = 0; i < lines.length; i++) { - min = Math.min(min, lines[i][0]); - max = Math.max(max, lines[i][1]); - } - int cover = 0; - for (double p = min + 0.5; p < max; p += 1) { - int cur = 0; - for (int i = 0; i < lines.length; i++) { - if (lines[i][0] < p && lines[i][1] > p) { - cur++; - } - } - cover = Math.max(cover, cur); - } - return cover; - } - - public static int maxCover2(int[][] m) { - Line[] lines = new Line[m.length]; - for (int i = 0; i < m.length; i++) { - lines[i] = new Line(m[i][0], m[i][1]); - } - Arrays.sort(lines, new StartComparator()); - PriorityQueue heap = new PriorityQueue<>(); - int max = 0; - for (int i = 0; i < lines.length; i++) { - // lines[i] -> cur 在黑盒中,把<=cur.start 东西都弹出 - while (!heap.isEmpty() && heap.peek() <= lines[i].start) { - heap.poll(); - } - heap.add(lines[i].end); - max = Math.max(max, heap.size()); - } - return max; - } - - public static class Line { - public int start; - public int end; - - public Line(int s, int e) { - start = s; - end = e; - } - } - - public static class EndComparator implements Comparator { - - @Override - public int compare(Line o1, Line o2) { - return o1.end - o2.end; - } - - } - - // for test - public static int[][] generateLines(int N, int L, int R) { - int size = (int) (Math.random() * N) + 1; - int[][] ans = new int[size][2]; - for (int i = 0; i < size; i++) { - int a = L + (int) (Math.random() * (R - L + 1)); - int b = L + (int) (Math.random() * (R - L + 1)); - if (a == b) { - b = a + 1; - } - ans[i][0] = Math.min(a, b); - ans[i][1] = Math.max(a, b); - } - return ans; - } - - public static class StartComparator implements Comparator { - - @Override - public int compare(Line o1, Line o2) { - return o1.start - o2.start; - } - - } - - public static void main(String[] args) { - - Line l1 = new Line(4, 9); - Line l2 = new Line(1, 4); - Line l3 = new Line(7, 15); - Line l4 = new Line(2, 4); - Line l5 = new Line(4, 6); - Line l6 = new Line(3, 7); - - // 底层堆结构,heap - PriorityQueue heap = new PriorityQueue<>(new StartComparator()); - heap.add(l1); - heap.add(l2); - heap.add(l3); - heap.add(l4); - heap.add(l5); - heap.add(l6); - - while (!heap.isEmpty()) { - Line cur = heap.poll(); - System.out.println(cur.start + "," + cur.end); - } - - System.out.println("test begin"); - int N = 100; - int L = 0; - int R = 200; - int testTimes = 200000; - for (int i = 0; i < testTimes; i++) { - int[][] lines = generateLines(N, L, R); - int ans1 = maxCover1(lines); - int ans2 = maxCover2(lines); - if (ans1 != ans2) { - System.out.println("Oops!"); - } - } - System.out.println("test end"); - } - -} diff --git a/公开课/class036/Code01_LongestNoRepeatSubstring.java b/公开课/class036/Code01_LongestNoRepeatSubstring.java deleted file mode 100644 index b61e15b..0000000 --- a/公开课/class036/Code01_LongestNoRepeatSubstring.java +++ /dev/null @@ -1,76 +0,0 @@ -package class036; - -public class Code01_LongestNoRepeatSubstring { - /* - * 给定一个只由小写字母(a~z)组成的字符串str, 返回其中最长无重复字符的子串长度 - * - */ - - public static int lnrs1(String s) { - if (s == null || s.length() == 0) { - return 0; - } - char[] str = s.toCharArray(); - int N = str.length; - int max = 0; - for (int i = 0; i < N; i++) { - boolean[] set = new boolean[26]; - for (int j = i; j < N; j++) { - if (set[str[j] - 'a']) { - break; - } - set[str[j] - 'a'] = true; - max = Math.max(max, j - i + 1); - } - } - return max; - } - - public static int lnrs2(String s) { - if (s == null || s.length() == 0) { - return 0; - } - char[] str = s.toCharArray(); - int N = str.length; - int[] last = new int[26]; - for (int i = 0; i < 26; i++) { - last[i] = -1; - } - last[str[0] - 'a'] = 0; - int max = 1; - int preMaxLen = 1; - for (int i = 1; i < N; i++) { - preMaxLen = Math.min(i - last[str[i] - 'a'], preMaxLen + 1); - max = Math.max(max, preMaxLen); - last[str[i] - 'a'] = i; - } - return max; - } - - // for test - public static String getRandomString(int possibilities, int maxSize) { - char[] ans = new char[(int) (Math.random() * maxSize) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (char) ((int) (Math.random() * possibilities) + 'a'); - } - return String.valueOf(ans); - } - - public static void main(String[] args) { - int possibilities = 26; - int strMaxSize = 100; - int testTimes = 1000000; - System.out.println("test begin, test time : " + testTimes); - for (int i = 0; i < testTimes; i++) { - String str = getRandomString(possibilities, strMaxSize); - int ans1 = lnrs1(str); - int ans2 = lnrs2(str); - if (ans1 != ans2) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - - } - -} diff --git a/公开课/class036/Code02_CordCoverMaxPoint.java b/公开课/class036/Code02_CordCoverMaxPoint.java deleted file mode 100644 index 634826f..0000000 --- a/公开课/class036/Code02_CordCoverMaxPoint.java +++ /dev/null @@ -1,88 +0,0 @@ -package class036; - -import java.util.Arrays; - -public class Code02_CordCoverMaxPoint { - - public static int maxPoint1(int[] arr, int L) { - int res = 1; - for (int i = 0; i < arr.length; i++) { - int nearest = nearestIndex(arr, i, arr[i] - L); - res = Math.max(res, i - nearest + 1); - } - return res; - } - - public static int nearestIndex(int[] arr, int R, int value) { - int L = 0; - int index = R; - while (L <= R) { - int mid = L + ((R - L) >> 1); - if (arr[mid] >= value) { - index = mid; - R = mid - 1; - } else { - L = mid + 1; - } - } - return index; - } - - public static int maxPoint2(int[] arr, int L) { - int left = 0; - int right = 0; - int N = arr.length; - int max = 0; - while (left < N) { - while (right < N && arr[right] - arr[left] <= L) { - right++; - } - max = Math.max(max, right - (left++)); - } - return max; - } - - // for test - public static int test(int[] arr, int L) { - int max = 0; - for (int i = 0; i < arr.length; i++) { - int pre = i - 1; - while (pre >= 0 && arr[i] - arr[pre] <= L) { - pre--; - } - max = Math.max(max, i - pre); - } - return max; - } - - // for test - public static int[] generateArray(int len, int max) { - int[] ans = new int[(int) (Math.random() * len) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * max); - } - Arrays.sort(ans); - return ans; - } - - public static void main(String[] args) { - int len = 100; - int max = 1000; - int testTime = 100000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int L = (int) (Math.random() * max); - int[] arr = generateArray(len, max); - int ans1 = maxPoint1(arr, L); - int ans2 = maxPoint2(arr, L); - int ans3 = test(arr, L); - if (ans1 != ans2 || ans2 != ans3) { - System.out.println("oops!"); - break; - } - } - System.out.println("测试结束"); - - } - -} diff --git a/公开课/class036/Code03_ColorLeftRight.java b/公开课/class036/Code03_ColorLeftRight.java deleted file mode 100644 index c11c3d9..0000000 --- a/公开课/class036/Code03_ColorLeftRight.java +++ /dev/null @@ -1,72 +0,0 @@ -package class036; - -public class Code03_ColorLeftRight { - - // RGRGR -> RRRGG - public static int minPaint(String s) { - if (s == null || s.length() < 2) { - return 0; - } - char[] str = s.toCharArray(); - int N = str.length; - int rAll = 0; - for (int i = 0; i < N; i++) { - rAll += str[i] == 'R' ? 1 : 0; - } - int ans = rAll; // 如果数组所有的范围,都是右侧范围,都变成G - int left = 0; - for (int i = 0; i < N - 1; i++) { // 0..i 左侧 n-1..N-1 - left += str[i] == 'G' ? 1 : 0; - rAll -= str[i] == 'R' ? 1 : 0; - ans = Math.min(ans, left + rAll); - } - // 0...N-1 左全部 右无 - ans = Math.min(ans, left + (str[N - 1] == 'G' ? 1 : 0)); - return ans; - } - - // RGRGR -> RRRGG - public static int test(String s) { - if (s == null || s.length() < 2) { - return 0; - } - char[] str = s.toCharArray(); - int ans = Integer.MAX_VALUE; - for (int leftEnd = -1; leftEnd < str.length; leftEnd++) { - int left = 0; - for (int i = 0; i <= leftEnd; i++) { - left += str[i] == 'G' ? 1 : 0; - } - int right = 0; - for (int i = leftEnd + 1; i < str.length; i++) { - right += str[i] == 'R' ? 1 : 0; - } - ans = Math.min(ans, left + right); - } - return ans; - } - - public static String generateString(int len) { - char[] str = new char[(int) (Math.random() * len) + 1]; - for (int i = 0; i < str.length; i++) { - str[i] = Math.random() < 0.5 ? 'R' : 'G'; - } - return String.valueOf(str); - } - - public static void main(String[] args) { - int len = 100; - int testTime = 100000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - String str = generateString(len); - int ans1 = minPaint(str); - int ans2 = test(str); - if (ans1 != ans2) { - System.out.println("Oops!"); - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class037/Code01_MaxABSBetweenLeftAndRight.java b/公开课/class037/Code01_MaxABSBetweenLeftAndRight.java deleted file mode 100644 index 8c21244..0000000 --- a/公开课/class037/Code01_MaxABSBetweenLeftAndRight.java +++ /dev/null @@ -1,72 +0,0 @@ -package class037; - -public class Code01_MaxABSBetweenLeftAndRight { - - public static int maxABS1(int[] arr) { - int res = Integer.MIN_VALUE; - int maxLeft = 0; - int maxRight = 0; - for (int i = 0; i != arr.length - 1; i++) { - maxLeft = Integer.MIN_VALUE; - for (int j = 0; j != i + 1; j++) { - maxLeft = Math.max(arr[j], maxLeft); - } - maxRight = Integer.MIN_VALUE; - for (int j = i + 1; j != arr.length; j++) { - maxRight = Math.max(arr[j], maxRight); - } - res = Math.max(Math.abs(maxLeft - maxRight), res); - } - return res; - } - - public static int maxABS2(int[] arr) { - int[] lArr = new int[arr.length]; - int[] rArr = new int[arr.length]; - lArr[0] = arr[0]; - rArr[arr.length - 1] = arr[arr.length - 1]; - for (int i = 1; i < arr.length; i++) { - lArr[i] = Math.max(lArr[i - 1], arr[i]); - } - for (int i = arr.length - 2; i > -1; i--) { - rArr[i] = Math.max(rArr[i + 1], arr[i]); - } - int max = 0; - for (int i = 0; i < arr.length - 1; i++) { - max = Math.max(max, Math.abs(lArr[i] - rArr[i + 1])); - } - return max; - } - - public static int maxABS3(int[] arr) { - int max = Integer.MIN_VALUE; - for (int i = 0; i < arr.length; i++) { - max = Math.max(arr[i], max); - } - return max - Math.min(arr[0], arr[arr.length - 1]); - } - - public static int[] generateRandomArray(int length) { - int[] arr = new int[length]; - for (int i = 0; i != arr.length; i++) { - arr[i] = (int) (Math.random() * 1000) - 499; - } - return arr; - } - - public static void main(String[] args) { - int len = 100; - int testTime = 100000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int[] arr = generateRandomArray(len); - int ans1 = maxABS1(arr); - int ans2 = maxABS2(arr); - int ans3 = maxABS3(arr); - if (ans1 != ans2 || ans1 != ans3) { - System.out.println("Oops!"); - } - } - System.out.println("测试结束"); - } -} diff --git a/公开课/class037/Code02_JumpGameII.java b/公开课/class037/Code02_JumpGameII.java deleted file mode 100644 index 6fc6134..0000000 --- a/公开课/class037/Code02_JumpGameII.java +++ /dev/null @@ -1,23 +0,0 @@ -package class037; - -// 测试页面:https://leetcode.com/problems/jump-game-ii/ -public class Code02_JumpGameII { - - public static int jump(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int step = 0; - int cur = 0; - int next = 0; - for (int i = 0; i < arr.length; i++) { - if (cur < i) { - step++; - cur = next; - } - next = Math.max(next, i + arr[i]); - } - return step; - } - -} diff --git a/公开课/class037/Code03_FindHalfMajority.java b/公开课/class037/Code03_FindHalfMajority.java deleted file mode 100644 index 0cb2953..0000000 --- a/公开课/class037/Code03_FindHalfMajority.java +++ /dev/null @@ -1,76 +0,0 @@ -package class037; - -import java.util.HashMap; -import java.util.Map.Entry; - -public class Code03_FindHalfMajority { - - public static int halfMajor(int[] arr) { - int target = 0; - int HP = 0; - for (int i = 0; i != arr.length; i++) { - if (HP == 0) { - target = arr[i]; - HP = 1; - } else if (arr[i] == target) { - HP++; - } else { - HP--; - } - } - if (HP == 0) { - return -1; - } - HP = 0; - for (int i = 0; i != arr.length; i++) { - if (arr[i] == target) { - HP++; - } - } - return HP > arr.length / 2 ? target : -1; - } - - // for test - public static int right(int[] arr) { - HashMap map = new HashMap<>(); - for (int cur : arr) { - if (!map.containsKey(cur)) { - map.put(cur, 0); - } - map.put(cur, map.get(cur) + 1); - } - for (Entry entry : map.entrySet()) { - if (entry.getValue() > arr.length / 2) { - return entry.getKey(); - } - } - return -1; - } - - // for test - public static int[] genareteRandomArray(int len, int max) { - int[] ans = new int[(int) (Math.random() * len) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * max) + 1; - } - return ans; - } - - public static void main(String[] args) { - int len = 100; - int max = 10; - int testTime = 100000; - System.out.println("test begin"); - for (int i = 0; i < testTime; i++) { - int[] arr = genareteRandomArray(len, max); - int ans1 = halfMajor(arr); - int ans2 = right(arr); - if (ans1 != ans2) { - System.out.println("Oops!"); - break; - } - } - System.out.println("test end"); - } - -} diff --git a/公开课/class038/Code01_SubArrayMaxSum.java b/公开课/class038/Code01_SubArrayMaxSum.java deleted file mode 100644 index e80f0e3..0000000 --- a/公开课/class038/Code01_SubArrayMaxSum.java +++ /dev/null @@ -1,195 +0,0 @@ -package class038; - -import java.util.ArrayList; -import java.util.List; - -public class Code01_SubArrayMaxSum { - - public static int test(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int N = arr.length; - int max = Integer.MIN_VALUE; - for (int L = 0; L < N; L++) { - for (int R = L; R < N; R++) { - // arr[L...R] - int sum = 0; - for (int i = L; i <= R; i++) { - sum += arr[i]; - } - max = Math.max(max, sum); - } - } - return max; - } - - public static int max1(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int N = arr.length; - int[] ans = new int[N]; - ans[0] = arr[0]; - int max = ans[0]; - for (int end = 1; end < N; end++) { - int p1 = arr[end]; - int p2 = ans[end - 1] + arr[end]; - ans[end] = Math.max(p1, p2); - max = Math.max(max, ans[end]); - } - return max; - } - - - public static int max2(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int N = arr.length; - int pre = arr[0]; - int max = pre; - for (int end = 1; end < N; end++) { - int p1 = arr[end]; - int p2 = pre + arr[end]; - max = Math.max(max, Math.max(p1, p2)); - pre = Math.max(p1, p2); - } - return max; - } - - public static int dp1(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int[] dp = new int[arr.length]; - // dp[i] 子数组必须以i位置结尾的情况下,能得到的最大累加和 - dp[0] = arr[0]; - for (int i = 1; i < arr.length; i++) { - int p1 = arr[i]; - int p2 = dp[i - 1] + arr[i]; - dp[i] = Math.max(p1, p2); - } - int max = Integer.MIN_VALUE; - for (int i = 0; i < dp.length; i++) { - max = Math.max(max, dp[i]); - } - return max; - } - - public static int dp2(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int preDp = arr[0]; - int max = preDp; - for (int i = 1; i < arr.length; i++) { - int p1 = arr[i]; - int p2 = preDp + arr[i]; - int dp = Math.max(p1, p2); - max = Math.max(max, dp); - preDp = dp; - } - return max; - } - - public static int maxSum(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int cur = 0; - int max = Integer.MIN_VALUE; - for (int i = 0; i < arr.length; i++) { - cur += arr[i]; - max = Math.max(max, cur); - cur = cur < 0 ? 0 : cur; - } - return max; - } - - public static int maxSum1(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - // 0结尾时候的答案 - int pre = arr[0]; - int max = arr[0]; - for (int i = 1; i < arr.length; i++) { - // i结尾时候的答案 - pre = arr[i] + (pre > 0 ? pre : 0); - max = Math.max(max, pre); - } - return max; - } - - public static List> maxSum2(int[] arr) { - List> ans = new ArrayList<>(); - if (arr == null || arr.length == 0) { - return ans; - } - int L = 0; - int maxLen = 0; - int maxSum = Integer.MIN_VALUE; - int cur = 0; - for (int i = 0; i < arr.length; i++) { - // L...i sum - cur += arr[i]; - if (cur == maxSum && (i - L + 1) == maxLen) { - List curAns = new ArrayList<>(); - curAns.add(L); - curAns.add(i); - ans.add(curAns); - } - if (cur > maxSum || (cur == maxSum && (i - L + 1) > maxLen)) { - ans.clear(); - List curAns = new ArrayList<>(); - curAns.add(L); - curAns.add(i); - ans.add(curAns); - maxLen = i - L + 1; - } - maxSum = Math.max(maxSum, cur); - if (cur < 0) { - cur = 0; - L = i + 1; - } - } - return ans; - } - - public static int[] generateArray(int N, int V) { - int n = (int) (Math.random() * N) + 1; - int[] arr = new int[n]; - for (int i = 0; i < n; i++) { - arr[i] = (int) (Math.random() * V) - (int) (Math.random() * V); - } - return arr; - } - - public static void main(String[] args) { - int N = 100; - int V = 100; - int testTime = 10000; - System.out.println("test begin"); - for (int i = 0; i < testTime; i++) { - int[] arr = generateArray(N, V); - int ans1 = test(arr); - int ans2 = dp1(arr); - int ans3 = dp2(arr); - if (ans1 != ans2 || ans1 != ans3) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - - int[] test = { 2, 2, 1, -9, 2, 3, -9, 6, -9, 2, 2, 2, -9, 2, 2, 2, -9, 1, 4, 1 }; - - List> ans = maxSum2(test); - - for (List cur : ans) { - System.out.println("start : " + cur.get(0) + ", end : " + cur.get(1)); - } - - } - -} diff --git a/公开课/class038/Code02_MaxSumFollowUp.java b/公开课/class038/Code02_MaxSumFollowUp.java deleted file mode 100644 index 93e52e3..0000000 --- a/公开课/class038/Code02_MaxSumFollowUp.java +++ /dev/null @@ -1,83 +0,0 @@ -package class038; - -public class Code02_MaxSumFollowUp { - - public static int maxSum1(int[][] matrix) { - int n = matrix.length; - int m = matrix[0].length; - int max = Integer.MIN_VALUE; - for (int ai = 0; ai < n; ai++) { - for (int aj = 0; aj < m; aj++) { - for (int bi = ai; bi < n; bi++) { - for (int bj = aj; bj < m; bj++) { - max = Math.max(max, sum(matrix, ai, aj, bi, bj)); - } - } - } - } - return max; - } - - public static int sum(int[][] matrix, int ai, int aj, int bi, int bj) { - int sum = 0; - for (int i = ai; i <= bi; i++) { - for (int j = aj; j <= bj; j++) { - sum += matrix[i][j]; - } - } - return sum; - } - - public static int maxSum2(int[][] matrix) { - if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { - return 0; - } - int max = Integer.MIN_VALUE; - int cur = 0; - int[] s = null; - for (int i = 0; i != matrix.length; i++) { - s = new int[matrix[0].length]; - for (int j = i; j != matrix.length; j++) { - cur = 0; - for (int k = 0; k != s.length; k++) { - s[k] += matrix[j][k]; - cur += s[k]; - max = Math.max(max, cur); - cur = cur < 0 ? 0 : cur; - } - } - } - return max; - } - - public static int[][] generateMatrix(int N, int M, int V) { - int n = (int) (Math.random() * N) + 1; - int m = (int) (Math.random() * M) + 1; - int[][] matrix = new int[n][m]; - for (int i = 0; i < n; i++) { - for (int j = 0; j < m; j++) { - matrix[i][j] = (int) (Math.random() * V) - (int) (Math.random() * V); - } - } - return matrix; - } - - public static void main(String[] args) { - int N = 20; - int M = 20; - int V = 100; - int testTime = 50000; - System.out.println("test begin"); - for (int i = 0; i < testTime; i++) { - int[][] matrix = generateMatrix(N, M, V); - int ans1 = maxSum1(matrix); - int ans2 = maxSum2(matrix); - if (ans1 != ans2) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - - } - -} diff --git a/公开课/class038/Code03_MaxSumNoAdjoin.java b/公开课/class038/Code03_MaxSumNoAdjoin.java deleted file mode 100644 index fe8c17a..0000000 --- a/公开课/class038/Code03_MaxSumNoAdjoin.java +++ /dev/null @@ -1,58 +0,0 @@ -package class038; - -public class Code03_MaxSumNoAdjoin { - - public static int subSqeMaxSumNoNext(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - if (arr.length == 1) { - return arr[0]; - } - int[] dp = new int[arr.length]; - // dp[i] : arr[0..i]挑选,满足不相邻设定的情况下,随意挑选,最大的累加和 - dp[0] = arr[0]; - dp[1] = Math.max(arr[0], arr[1]); - for (int i = 2; i < arr.length; i++) { - int p1 = dp[i - 1]; - int p2 = arr[i] + Math.max(dp[i - 2], 0); - dp[i] = Math.max(p1, p2); - } - return dp[arr.length - 1]; - } - - // 给定一个数组arr,在不能取相邻数的情况下,返回所有组合中的最大累加和 - // 思路: - // 定义dp[i] : 表示arr[0...i]范围上,在不能取相邻数的情况下,返回所有组合中的最大累加和 - // 在arr[0...i]范围上,在不能取相邻数的情况下,得到的最大累加和,可能性分类: - // 可能性 1) 选出的组合,不包含arr[i]。那么dp[i] = dp[i-1] - // 比如,arr[0...i] = {3,4,-4},最大累加和是不包含i位置数的时候 - // - // 可能性 2) 选出的组合,只包含arr[i]。那么dp[i] = arr[i] - // 比如,arr[0...i] = {-3,-4,4},最大累加和是只包含i位置数的时候 - // - // 可能性 3) 选出的组合,包含arr[i], 且包含arr[0...i-2]范围上的累加和。那么dp[i] = arr[i] + dp[i-2] - // 比如,arr[0...i] = {3,1,4},最大累加和是3和4组成的7,因为相邻不能选,所以i-1位置的数要跳过 - // - // 综上所述:dp[i] = Max { dp[i-1], arr[i] , arr[i] + dp[i-2] } - public static int maxSum(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int N = arr.length; - if (N == 1) { - return arr[0]; - } - if (N == 2) { - return Math.max(arr[0], arr[1]); - } - int[] dp = new int[N]; - dp[0] = arr[0]; - dp[1] = Math.max(arr[0], arr[1]); - for (int i = 2; i < N; i++) { - dp[i] = Math.max(Math.max(dp[i - 1], arr[i]), arr[i] + dp[i - 2]); - } - return dp[N - 1]; - } - -} diff --git a/公开课/class038/Code04_MissingNumber.java b/公开课/class038/Code04_MissingNumber.java deleted file mode 100644 index a96221e..0000000 --- a/公开课/class038/Code04_MissingNumber.java +++ /dev/null @@ -1,27 +0,0 @@ -package class038; - -// 测试链接:https://leetcode.com/problems/first-missing-positive/ -public class Code04_MissingNumber { - - public static int firstMissingPositive(int[] arr) { - int l = 0; - int r = arr.length; - while (l != r) { - if (arr[l] == l + 1) { - l++; - } else if (arr[l] <= l || arr[l] > r || arr[arr[l] - 1] == arr[l]) { - swap(arr, l, --r); - } else { - swap(arr, l, arr[l] - 1); - } - } - return l + 1; - } - - public static void swap(int[] arr, int i, int j) { - int tmp = arr[i]; - arr[i] = arr[j]; - arr[j] = tmp; - } - -} diff --git a/公开课/class039/Code01_Water.java b/公开课/class039/Code01_Water.java deleted file mode 100644 index 2a28dc1..0000000 --- a/公开课/class039/Code01_Water.java +++ /dev/null @@ -1,120 +0,0 @@ -package class039; - -public class Code01_Water { - - // 本题测试链接:https://leetcode.com/problems/trapping-rain-water/ - // 给定一个正整数数组arr,把arr想象成一个直方图。返回这个直方图如果装水,能装下几格水? - public static int water1(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - // O位置无水量 - // 0~N-1,N-1无水量 - int N = arr.length; - int water = 0; - for (int i = 1; i < N - 1; i++) { - int leftMax = Integer.MIN_VALUE; - for (int j = 0; j < i; j++) { - leftMax = Math.max(leftMax, arr[j]); - } - int rightMax = Integer.MIN_VALUE; - for (int j = i + 1; j < N; j++) { - rightMax = Math.max(rightMax, arr[j]); - } - water += Math.max(Math.min(leftMax, rightMax) - arr[i], 0); - } - return water; - } - - public static int water2(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int[] leftMaxs = new int[N]; - leftMaxs[0] = arr[0]; - for (int i = 1; i < N; i++) { - leftMaxs[i] = Math.max(leftMaxs[i - 1], arr[i]); - } - - int[] rightMaxs = new int[N]; - rightMaxs[N - 1] = arr[N - 1]; - for (int i = N - 2; i >= 0; i--) { - rightMaxs[i] = Math.max(rightMaxs[i + 1], arr[i]); - } - int water = 0; - for (int i = 1; i < N - 1; i++) { - water += Math.max(Math.min(leftMaxs[i - 1], rightMaxs[i + 1]) - arr[i], 0); - } - return water; - } - - public static int water3(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int[] rightMaxs = new int[N]; - rightMaxs[N - 1] = arr[N - 1]; - for (int i = N - 2; i >= 0; i--) { - rightMaxs[i] = Math.max(rightMaxs[i + 1], arr[i]); - } - int water = 0; - int leftMax = arr[0]; - for (int i = 1; i < N - 1; i++) { - water += Math.max(Math.min(leftMax, rightMaxs[i + 1]) - arr[i], 0); - leftMax = Math.max(leftMax, arr[i]); - } - return water; - } - - public static int water4(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int L = 1; - int leftMax = arr[0]; - int R = N - 2; - int rightMax = arr[N - 1]; - int water = 0; - while (L <= R) { - if (leftMax <= rightMax) { - water += Math.max(0, leftMax - arr[L]); - leftMax = Math.max(leftMax, arr[L++]); - } else { - water += Math.max(0, rightMax - arr[R]); - rightMax = Math.max(rightMax, arr[R--]); - } - } - return water; - } - - // for test - public static int[] generateRandomArray(int len, int value) { - int[] ans = new int[(int) (Math.random() * len) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * value) + 1; - } - return ans; - } - - public static void main(String[] args) { - int len = 100; - int value = 200; - int testTimes = 100000; - System.out.println("test begin"); - for (int i = 0; i < testTimes; i++) { - int[] arr = generateRandomArray(len, value); - int ans1 = water1(arr); - int ans2 = water2(arr); - int ans3 = water3(arr); - int ans4 = water4(arr); - if (ans1 != ans2 || ans3 != ans4 || ans1 != ans3) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - } - -} diff --git a/公开课/class039/Code02_RandToRand.java b/公开课/class039/Code02_RandToRand.java deleted file mode 100644 index c55c7d5..0000000 --- a/公开课/class039/Code02_RandToRand.java +++ /dev/null @@ -1,134 +0,0 @@ -package class039; - -public class Code02_RandToRand { - - // 此函数只能用,不能修改 - // 等概率返回1~5 - public static int f() { - return (int) (Math.random() * 5) + 1; - } - - // 等概率得到0和1 - public static int a() { - int ans = 0; - do { - ans = f(); - } while (ans == 3); - return ans < 3 ? 0 : 1; - } - - // 等概率返回0~6 - public static int b() { - int ans = 0; - do { - ans = (a() << 2) + (a() << 1) + a(); - } while (ans == 7); - return ans; - } - - // 等概率返回1~7 - public static int c() { - return b() + 1; - } - - // 这个结构是唯一的随机机制 - // 你只能初始化并使用,不可修改 - public static class RandomBox { - private final int min; - private final int max; - - // 初始化时请一定不要让mi==ma - public RandomBox(int mi, int ma) { - min = mi; - max = ma; - } - - // 13 ~ 17 - // 13 + [0,4] - public int random() { - return min + (int) (Math.random() * (max - min + 1)); - } - - public int min() { - return min; - } - - public int max() { - return max; - } - } - - // 利用条件RandomBox,如何等概率返回0和1 - public static int rand01(RandomBox randomBox) { - int min = randomBox.min(); - int max = randomBox.max(); - // min ~ max - int size = max - min + 1; - // size是不是奇数,odd 奇数 - boolean odd = (size & 1) != 0; - int mid = size / 2; - int ans = 0; - do { - ans = randomBox.random() - min; - } while (odd && ans == mid); - return ans < mid ? 0 : 1; - } - - // 给你一个RandomBox,这是唯一能借助的随机机制 - // 等概率返回from~to范围上任何一个数 - // 要求from<=to - public static int random(RandomBox randomBox, int from, int to) { - if (from == to) { - return from; - } - // 3 ~ 9 - // 0 ~ 6 - // 0 ~ range - int range = to - from; - int num = 1; - // 求0~range需要几个2进制位 - while ((1 << num) - 1 < range) { - num++; - } - - // 我们一共需要num位 - // 最终的累加和,首先+0位上是1还是0,1位上是1还是0,2位上是1还是0... - int ans = 0; - do { - ans = 0; - for (int i = 0; i < num; i++) { - ans |= (rand01(randomBox) << i); - } - } while (ans > range); - return ans + from; - } - - public static void main(String[] args) { - - int[] count = new int[8]; // 0 1 2 .. 7 - int testTime = 10000000; - for (int i = 0; i < testTime; i++) { - int ans = c(); - count[ans]++; - } - - for (int i = 0; i < 8; i++) { - System.out.println(i + " : " + count[i]); - } - -// RandomBox randomBox = new RandomBox(3, 9); -// int from = 17; -// int to = 29; -// int[] ans = new int[to + 1]; -// int testTime1 = 1000000; -// for (int i = 0; i < testTime1; i++) { -// ans[random(randomBox, from, to)]++; -// } -// for (int i = 0; i < ans.length; i++) { -// System.out.println(ans[i]); -// } -// System.out.println("=========="); - - } - -} diff --git a/公开课/class039/Code03_EqualProbabilityRandom.java b/公开课/class039/Code03_EqualProbabilityRandom.java deleted file mode 100644 index bee7c63..0000000 --- a/公开课/class039/Code03_EqualProbabilityRandom.java +++ /dev/null @@ -1,67 +0,0 @@ -package class039; - -public class Code03_EqualProbabilityRandom { - - // 内部内容不可见 - public static int f() { - return Math.random() < 0.8 ? 0 : 1; - } - - // 等概率返回0和1 - public static int g() { - int first = 0; - do { - first = f(); // 0 1 - } while (first == f()); - return first; - } - - // 这个结构是唯一的随机机制 - // 你只能初始化并使用,不可修改 - public static class RandomBox { - private final double p; - - // 初始化时请一定满足:0 < zeroP < 1 - public RandomBox(double zeroP) { - p = zeroP; - } - - public int random() { - return Math.random() < p ? 0 : 1; - } - - } - - // 底层依赖一个以p概率返回0,以1-p概率返回1的随机函数rand01p - // 如何加工出等概率返回0和1的函数 - public static int rand01(RandomBox randomBox) { - int num; - do { - num = randomBox.random(); - } while (num == randomBox.random()); - return num; - } - - public static void main(String[] args) { - int[] count = new int[2];// 0 1 - for (int i = 0; i < 1000000; i++) { - int ans = g(); - count[ans]++; - } - System.out.println(count[0] + " , " + count[1]); - -// double zeroP = 0.88; -// RandomBox randomBox = new RandomBox(zeroP); -// -// int testTime = 10000000; -// int count = 0; -// for (int i = 0; i < testTime; i++) { -// if (rand01(randomBox) == 0) { -// count++; -// } -// } -// System.out.println((double) count / (double) testTime); - - } - -} diff --git a/公开课/class039/Code04_EvenTimesOddTimes.java b/公开课/class039/Code04_EvenTimesOddTimes.java deleted file mode 100644 index cc80817..0000000 --- a/公开课/class039/Code04_EvenTimesOddTimes.java +++ /dev/null @@ -1,52 +0,0 @@ -package class039; - -public class Code04_EvenTimesOddTimes { - - public static void printOddTimesNum1(int[] arr) { - int eor = 0; - for (int i = 0; i < arr.length; i++) { - eor ^= arr[i]; - } - System.out.println(eor); - } - - public static void printOddTimesNum2(int[] arr) { - // arr中,a和b出现了奇数次,其他数都是偶数次 - int eor = 0; - for (int i = 0; i < arr.length; i++) { - eor ^= arr[i]; - } - // eor = a ^ b - // eor != 0 - // eor : 001100100 - // rightOne : 000000100 - int rightOne = eor & (~eor + 1); - int onlyOne = 0; // eor' - for (int i = 0; i < arr.length; i++) { - if ((arr[i] & rightOne) != 0) { - onlyOne ^= arr[i]; - } - } - // eor' = a or b - System.out.println(onlyOne + " " + (eor ^ onlyOne)); - } - - public static int bit1counts(int N) { - int count = 0; - while (N != 0) { - int rightOne = N & ((~N) + 1); - count++; - N -= rightOne; - } - return count; - } - - public static void main(String[] args) { - int[] arr1 = { 3, 3, 2, 3, 1, 1, 1, 3, 1, 1, 1 }; - printOddTimesNum1(arr1); - - int[] arr2 = { 4, 3, 4, 2, 2, 2, 4, 1, 1, 1, 3, 3, 1, 1, 1, 4, 2, 2 }; - printOddTimesNum2(arr2); - } - -} diff --git a/公开课/class039/Code05_KM.java b/公开课/class039/Code05_KM.java deleted file mode 100644 index 6b52eb7..0000000 --- a/公开课/class039/Code05_KM.java +++ /dev/null @@ -1,144 +0,0 @@ -package class039; - -import java.util.HashMap; -import java.util.HashSet; - -public class Code05_KM { - - public static int test(int[] arr, int k, int m) { - HashMap map = new HashMap<>(); - for (int num : arr) { - if (map.containsKey(num)) { - map.put(num, map.get(num) + 1); - } else { - map.put(num, 1); - } - } - for (int num : map.keySet()) { - if (map.get(num) == k) { - return num; - } - } - return -1; - } - - public static HashMap map = new HashMap<>(); - - // 请保证arr中,只有一种数出现了K次,其他数都出现了M次 - public static int onlyKTimes(int[] arr, int k, int m) { - if (map.size() == 0) { - mapCreater(map); - } - int[] t = new int[32]; - // t[0] 0位置的1出现了几个 - // t[i] i位置的1出现了几个 - for (int num : arr) { - while (num != 0) { - int rightOne = num & (-num); - t[map.get(rightOne)]++; - num ^= rightOne; - } - } - int ans = 0; - for (int i = 0; i < 32; i++) { - if (t[i] % m != 0) { - if (t[i] % m == k) { - ans |= (1 << i); - } else { - return -1; - } - } - } - if (ans == 0) { - int count = 0; - for (int num : arr) { - if (num == 0) { - count++; - } - } - if (count != k) { - return -1; - } - } - return ans; - } - - public static void mapCreater(HashMap map) { - int value = 1; - for (int i = 0; i < 32; i++) { - map.put(value, i); - value <<= 1; - } - } - - public static int[] randomArray(int maxKinds, int range, int k, int m) { - int ktimeNum = randomNumber(range); - // 真命天子出现的次数 - int times = Math.random() < 0.5 ? k : ((int) (Math.random() * (m - 1)) + 1); - // 2 - int numKinds = (int) (Math.random() * maxKinds) + 2; - // k * 1 + (numKinds - 1) * m - int[] arr = new int[times + (numKinds - 1) * m]; - int index = 0; - for (; index < times; index++) { - arr[index] = ktimeNum; - } - numKinds--; - HashSet set = new HashSet<>(); - set.add(ktimeNum); - while (numKinds != 0) { - int curNum = 0; - do { - curNum = randomNumber(range); - } while (set.contains(curNum)); - set.add(curNum); - numKinds--; - for (int i = 0; i < m; i++) { - arr[index++] = curNum; - } - } - // arr 填好了 - for (int i = 0; i < arr.length; i++) { - // i 位置的数,我想随机和j位置的数做交换 - int j = (int) (Math.random() * arr.length);// 0 ~ N-1 - int tmp = arr[i]; - arr[i] = arr[j]; - arr[j] = tmp; - } - return arr; - } - - // [-range, +range] - public static int randomNumber(int range) { - return ((int) (Math.random() * range) + 1) - ((int) (Math.random() * range) + 1); - } - - public static void main(String[] args) { - int kinds = 5; - int range = 30; - int testTime = 100000; - int max = 9; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int a = (int) (Math.random() * max) + 1; // a 1 ~ 9 - int b = (int) (Math.random() * max) + 1; // b 1 ~ 9 - int k = Math.min(a, b); - int m = Math.max(a, b); - // k < m - if (k == m) { - m++; - } - int[] arr = randomArray(kinds, range, k, m); - int ans1 = test(arr, k, m); - int ans2 = onlyKTimes(arr, k, m); - if (ans1 != ans2) { - System.out.println(ans1); - System.out.println(ans2); - System.out.println("出错了!"); - } - } - System.out.println("测试结束"); - - } - -} diff --git a/公开课/class040/Code01_PalindromeNumber.java b/公开课/class040/Code01_PalindromeNumber.java deleted file mode 100644 index 86e81db..0000000 --- a/公开课/class040/Code01_PalindromeNumber.java +++ /dev/null @@ -1,23 +0,0 @@ -package class040; - -public class Code01_PalindromeNumber { - - public static boolean isPalindrome(int n) { - if (n < 0) { - return false; - } - int help = 1; - while (n / help >= 10) { - help *= 10; - } - while (n != 0) { - if (n / help != n % 10) { - return false; - } - n = (n % help) / 10; - help /= 100; - } - return true; - } - -} diff --git a/公开课/class040/Code02_MaximumProductSubarray.java b/公开课/class040/Code02_MaximumProductSubarray.java deleted file mode 100644 index 6e33994..0000000 --- a/公开课/class040/Code02_MaximumProductSubarray.java +++ /dev/null @@ -1,24 +0,0 @@ -package class040; - -// 本次测试链接 : https://leetcode.com/problems/maximum-product-subarray/ -public class Code02_MaximumProductSubarray { - - public static int maxProduct(int[] nums) { - // 答案,最终要返回的! - int ans = nums[0]; - // min : 必须以0结尾时,最小累乘积 - int min = nums[0]; - // min : 必须以0结尾时,最大累乘积 - int max = nums[0]; - for (int i = 1; i < nums.length; i++) { - // curmin : 必须以i结尾时,最小累乘积 - int curmin = Math.min(nums[i], Math.min(min * nums[i], max * nums[i])); - int curmax = Math.max(nums[i], Math.max(min * nums[i], max * nums[i])); - min = curmin; - max = curmax; - ans = Math.max(ans, max); - } - return ans; - } - -} diff --git a/公开课/class040/Code03_CoverMax.java b/公开课/class040/Code03_CoverMax.java deleted file mode 100644 index 6480260..0000000 --- a/公开课/class040/Code03_CoverMax.java +++ /dev/null @@ -1,135 +0,0 @@ -package class040; - -import java.util.Arrays; -import java.util.Comparator; -import java.util.PriorityQueue; - -public class Code03_CoverMax { - - public static int maxCover1(int[][] lines) { - int min = Integer.MAX_VALUE; - int max = Integer.MIN_VALUE; - for (int i = 0; i < lines.length; i++) { - min = Math.min(min, lines[i][0]); - max = Math.max(max, lines[i][1]); - } - int cover = 0; - for (double p = min + 0.5; p < max; p += 1) { - int cur = 0; - for (int i = 0; i < lines.length; i++) { - if (lines[i][0] < p && lines[i][1] > p) { - cur++; - } - } - cover = Math.max(cover, cur); - } - return cover; - } - - // [10,30] - // [1,5] - // [3,9] - public static int maxCover2(int[][] m) { - Line[] lines = new Line[m.length]; - for (int i = 0; i < m.length; i++) { - lines[i] = new Line(m[i][0], m[i][1]); - } - Arrays.sort(lines, new StartComparator()); - // 小根堆 - PriorityQueue heap = new PriorityQueue<>(); - int max = 0; - for (int i = 0; i < lines.length; i++) { - // lines[i] -> cur 在黑盒中,把<=cur.start 东西都弹出 - while (!heap.isEmpty() && heap.peek() <= lines[i].start) { - heap.poll(); - } - heap.add(lines[i].end); - max = Math.max(max, heap.size()); - } - return max; - } - - public static class Line { - public int start; - public int end; - - public Line(int s, int e) { - start = s; - end = e; - } - } - - public static class EndComparator implements Comparator { - - @Override - public int compare(Line o1, Line o2) { - return o1.end - o2.end; - } - - } - - // for test - public static int[][] generateLines(int N, int L, int R) { - int size = (int) (Math.random() * N) + 1; - int[][] ans = new int[size][2]; - for (int i = 0; i < size; i++) { - int a = L + (int) (Math.random() * (R - L + 1)); - int b = L + (int) (Math.random() * (R - L + 1)); - if (a == b) { - b = a + 1; - } - ans[i][0] = Math.min(a, b); - ans[i][1] = Math.max(a, b); - } - return ans; - } - - public static class StartComparator implements Comparator { - - @Override - public int compare(Line o1, Line o2) { - return o1.start - o2.start; - } - - } - - public static void main(String[] args) { - - Line l1 = new Line(4, 9); - Line l2 = new Line(1, 4); - Line l3 = new Line(7, 15); - Line l4 = new Line(2, 4); - Line l5 = new Line(4, 6); - Line l6 = new Line(3, 7); - - // 底层堆结构,heap - PriorityQueue heap = new PriorityQueue<>(new StartComparator()); - heap.add(l1); - heap.add(l2); - heap.add(l3); - heap.add(l4); - heap.add(l5); - heap.add(l6); - - while (!heap.isEmpty()) { - Line cur = heap.poll(); - System.out.println(cur.start + "," + cur.end); - } - - System.out.println("test begin"); - int N = 100; - int L = 0; - int R = 200; - int testTimes = 200000; - for (int i = 0; i < testTimes; i++) { - int[][] lines = generateLines(N, L, R); - int ans1 = maxCover1(lines); - int ans2 = maxCover2(lines); - if (ans1 != ans2) { - System.out.println("Oops!"); - } - } - System.out.println("test end"); - } - -} diff --git a/公开课/class040/Code04_KM.java b/公开课/class040/Code04_KM.java deleted file mode 100644 index 0cd9175..0000000 --- a/公开课/class040/Code04_KM.java +++ /dev/null @@ -1,144 +0,0 @@ -package class040; - -import java.util.HashMap; -import java.util.HashSet; - -public class Code04_KM { - - public static int test(int[] arr, int k, int m) { - HashMap map = new HashMap<>(); - for (int num : arr) { - if (map.containsKey(num)) { - map.put(num, map.get(num) + 1); - } else { - map.put(num, 1); - } - } - for (int num : map.keySet()) { - if (map.get(num) == k) { - return num; - } - } - return -1; - } - - public static HashMap map = new HashMap<>(); - - // 请保证arr中,只有一种数出现了K次,其他数都出现了M次 - public static int onlyKTimes(int[] arr, int k, int m) { - if (map.size() == 0) { - mapCreater(map); - } - int[] t = new int[32]; - // t[0] 0位置的1出现了几个 - // t[i] i位置的1出现了几个 - for (int num : arr) { - while (num != 0) { - int rightOne = num & (-num); - t[map.get(rightOne)]++; - num ^= rightOne; - } - } - int ans = 0; - for (int i = 0; i < 32; i++) { - if (t[i] % m != 0) { - if (t[i] % m == k) { - ans |= (1 << i); - } else { - return -1; - } - } - } - if (ans == 0) { - int count = 0; - for (int num : arr) { - if (num == 0) { - count++; - } - } - if (count != k) { - return -1; - } - } - return ans; - } - - public static void mapCreater(HashMap map) { - int value = 1; - for (int i = 0; i < 32; i++) { - map.put(value, i); - value <<= 1; - } - } - - public static int[] randomArray(int maxKinds, int range, int k, int m) { - int ktimeNum = randomNumber(range); - // 真命天子出现的次数 - int times = Math.random() < 0.5 ? k : ((int) (Math.random() * (m - 1)) + 1); - // 2 - int numKinds = (int) (Math.random() * maxKinds) + 2; - // k * 1 + (numKinds - 1) * m - int[] arr = new int[times + (numKinds - 1) * m]; - int index = 0; - for (; index < times; index++) { - arr[index] = ktimeNum; - } - numKinds--; - HashSet set = new HashSet<>(); - set.add(ktimeNum); - while (numKinds != 0) { - int curNum = 0; - do { - curNum = randomNumber(range); - } while (set.contains(curNum)); - set.add(curNum); - numKinds--; - for (int i = 0; i < m; i++) { - arr[index++] = curNum; - } - } - // arr 填好了 - for (int i = 0; i < arr.length; i++) { - // i 位置的数,我想随机和j位置的数做交换 - int j = (int) (Math.random() * arr.length);// 0 ~ N-1 - int tmp = arr[i]; - arr[i] = arr[j]; - arr[j] = tmp; - } - return arr; - } - - // [-range, +range] - public static int randomNumber(int range) { - return ((int) (Math.random() * range) + 1) - ((int) (Math.random() * range) + 1); - } - - public static void main(String[] args) { - int kinds = 5; - int range = 30; - int testTime = 100000; - int max = 9; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int a = (int) (Math.random() * max) + 1; // a 1 ~ 9 - int b = (int) (Math.random() * max) + 1; // b 1 ~ 9 - int k = Math.min(a, b); - int m = Math.max(a, b); - // k < m - if (k == m) { - m++; - } - int[] arr = randomArray(kinds, range, k, m); - int ans1 = test(arr, k, m); - int ans2 = onlyKTimes(arr, k, m); - if (ans1 != ans2) { - System.out.println(ans1); - System.out.println(ans2); - System.out.println("出错了!"); - } - } - System.out.println("测试结束"); - - } - -} diff --git a/公开课/class041/Code01_LongestNoRepeatSubstring.java b/公开课/class041/Code01_LongestNoRepeatSubstring.java deleted file mode 100644 index e9fe9b7..0000000 --- a/公开课/class041/Code01_LongestNoRepeatSubstring.java +++ /dev/null @@ -1,76 +0,0 @@ -package class041; - -public class Code01_LongestNoRepeatSubstring { - /* - * 给定一个只由小写字母(a~z)组成的字符串str, 返回其中最长无重复字符的子串长度 - * - */ - - public static int lnrs1(String s) { - if (s == null || s.length() == 0) { - return 0; - } - char[] str = s.toCharArray(); - int N = str.length; - int max = 0; - for (int i = 0; i < N; i++) { - boolean[] set = new boolean[26]; - for (int j = i; j < N; j++) { - if (set[str[j] - 'a']) { - break; - } - set[str[j] - 'a'] = true; - max = Math.max(max, j - i + 1); - } - } - return max; - } - - public static int lnrs2(String s) { - if (s == null || s.length() == 0) { - return 0; - } - char[] str = s.toCharArray(); - int N = str.length; - int[] last = new int[26]; - for (int i = 0; i < 26; i++) { - last[i] = -1; - } - last[str[0] - 'a'] = 0; - int max = 1; - int preMaxLen = 1; - for (int i = 1; i < N; i++) { - preMaxLen = Math.min(i - last[str[i] - 'a'], preMaxLen + 1); - max = Math.max(max, preMaxLen); - last[str[i] - 'a'] = i; - } - return max; - } - - // for test - public static String getRandomString(int possibilities, int maxSize) { - char[] ans = new char[(int) (Math.random() * maxSize) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (char) ((int) (Math.random() * possibilities) + 'a'); - } - return String.valueOf(ans); - } - - public static void main(String[] args) { - int possibilities = 26; - int strMaxSize = 100; - int testTimes = 1000000; - System.out.println("test begin, test time : " + testTimes); - for (int i = 0; i < testTimes; i++) { - String str = getRandomString(possibilities, strMaxSize); - int ans1 = lnrs1(str); - int ans2 = lnrs2(str); - if (ans1 != ans2) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - - } - -} diff --git a/公开课/class041/Code02_CordCoverMaxPoint.java b/公开课/class041/Code02_CordCoverMaxPoint.java deleted file mode 100644 index 97297c0..0000000 --- a/公开课/class041/Code02_CordCoverMaxPoint.java +++ /dev/null @@ -1,88 +0,0 @@ -package class041; - -import java.util.Arrays; - -public class Code02_CordCoverMaxPoint { - - public static int maxPoint1(int[] arr, int L) { - int res = 1; - for (int i = 0; i < arr.length; i++) { - int nearest = nearestIndex(arr, i, arr[i] - L); - res = Math.max(res, i - nearest + 1); - } - return res; - } - - public static int nearestIndex(int[] arr, int R, int value) { - int L = 0; - int index = R; - while (L <= R) { - int mid = L + ((R - L) >> 1); - if (arr[mid] >= value) { - index = mid; - R = mid - 1; - } else { - L = mid + 1; - } - } - return index; - } - - public static int maxPoint2(int[] arr, int L) { - int left = 0; - int right = 0; - int N = arr.length; - int max = 0; - while (left < N) { - while (right < N && arr[right] - arr[left] <= L) { - right++; - } - max = Math.max(max, right - (left++)); - } - return max; - } - - // for test - public static int test(int[] arr, int L) { - int max = 0; - for (int i = 0; i < arr.length; i++) { - int pre = i - 1; - while (pre >= 0 && arr[i] - arr[pre] <= L) { - pre--; - } - max = Math.max(max, i - pre); - } - return max; - } - - // for test - public static int[] generateArray(int len, int max) { - int[] ans = new int[(int) (Math.random() * len) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * max); - } - Arrays.sort(ans); - return ans; - } - - public static void main(String[] args) { - int len = 100; - int max = 1000; - int testTime = 100000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int L = (int) (Math.random() * max); - int[] arr = generateArray(len, max); - int ans1 = maxPoint1(arr, L); - int ans2 = maxPoint2(arr, L); - int ans3 = test(arr, L); - if (ans1 != ans2 || ans2 != ans3) { - System.out.println("oops!"); - break; - } - } - System.out.println("测试结束"); - - } - -} diff --git a/公开课/class041/Code03_MaxABSBetweenLeftAndRight.java b/公开课/class041/Code03_MaxABSBetweenLeftAndRight.java deleted file mode 100644 index 418dff6..0000000 --- a/公开课/class041/Code03_MaxABSBetweenLeftAndRight.java +++ /dev/null @@ -1,72 +0,0 @@ -package class041; - -public class Code03_MaxABSBetweenLeftAndRight { - - public static int maxABS1(int[] arr) { - int res = Integer.MIN_VALUE; - int maxLeft = 0; - int maxRight = 0; - for (int i = 0; i != arr.length - 1; i++) { - maxLeft = Integer.MIN_VALUE; - for (int j = 0; j != i + 1; j++) { - maxLeft = Math.max(arr[j], maxLeft); - } - maxRight = Integer.MIN_VALUE; - for (int j = i + 1; j != arr.length; j++) { - maxRight = Math.max(arr[j], maxRight); - } - res = Math.max(Math.abs(maxLeft - maxRight), res); - } - return res; - } - - public static int maxABS2(int[] arr) { - int[] lArr = new int[arr.length]; - int[] rArr = new int[arr.length]; - lArr[0] = arr[0]; - rArr[arr.length - 1] = arr[arr.length - 1]; - for (int i = 1; i < arr.length; i++) { - lArr[i] = Math.max(lArr[i - 1], arr[i]); - } - for (int i = arr.length - 2; i > -1; i--) { - rArr[i] = Math.max(rArr[i + 1], arr[i]); - } - int max = 0; - for (int i = 0; i < arr.length - 1; i++) { - max = Math.max(max, Math.abs(lArr[i] - rArr[i + 1])); - } - return max; - } - - public static int maxABS3(int[] arr) { - int max = Integer.MIN_VALUE; - for (int i = 0; i < arr.length; i++) { - max = Math.max(arr[i], max); - } - return max - Math.min(arr[0], arr[arr.length - 1]); - } - - public static int[] generateRandomArray(int length) { - int[] arr = new int[length]; - for (int i = 0; i != arr.length; i++) { - arr[i] = (int) (Math.random() * 1000) - 499; - } - return arr; - } - - public static void main(String[] args) { - int len = 100; - int testTime = 100000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int[] arr = generateRandomArray(len); - int ans1 = maxABS1(arr); - int ans2 = maxABS2(arr); - int ans3 = maxABS3(arr); - if (ans1 != ans2 || ans1 != ans3) { - System.out.println("Oops!"); - } - } - System.out.println("测试结束"); - } -} diff --git a/公开课/class041/Code04_KM.java b/公开课/class041/Code04_KM.java deleted file mode 100644 index a4e6c07..0000000 --- a/公开课/class041/Code04_KM.java +++ /dev/null @@ -1,143 +0,0 @@ -package class041; - -import java.util.HashMap; -import java.util.HashSet; - -public class Code04_KM { - - public static int test(int[] arr, int k, int m) { - HashMap map = new HashMap<>(); - for (int num : arr) { - if (map.containsKey(num)) { - map.put(num, map.get(num) + 1); - } else { - map.put(num, 1); - } - } - for (int num : map.keySet()) { - if (map.get(num) == k) { - return num; - } - } - return -1; - } - - public static HashMap map = new HashMap<>(); - // 请保证arr中,只有一种数出现了K次,其他数都出现了M次 - public static int onlyKTimes(int[] arr, int k, int m) { - if (map.size() == 0) { - mapCreater(map); - } - int[] t = new int[32]; - // t[0] 0位置的1出现了几个 - // t[i] i位置的1出现了几个 - for (int num : arr) { - while (num != 0) { - int rightOne = num & (-num); - t[map.get(rightOne)]++; - num ^= rightOne; - } - } - int ans = 0; - for (int i = 0; i < 32; i++) { - if (t[i] % m != 0) { - if (t[i] % m == k) { - ans |= (1 << i); - } else { - return -1; - } - } - } - if (ans == 0) { - int count = 0; - for (int num : arr) { - if (num == 0) { - count++; - } - } - if (count != k) { - return -1; - } - } - return ans; - } - - public static void mapCreater(HashMap map) { - int value = 1; - for (int i = 0; i < 32; i++) { - map.put(value, i); - value <<= 1; - } - } - - public static int[] randomArray(int maxKinds, int range, int k, int m) { - int ktimeNum = randomNumber(range); - // 真命天子出现的次数 - int times = Math.random() < 0.5 ? k : ((int) (Math.random() * (m - 1)) + 1); - // 2 - int numKinds = (int) (Math.random() * maxKinds) + 2; - // k * 1 + (numKinds - 1) * m - int[] arr = new int[times + (numKinds - 1) * m]; - int index = 0; - for (; index < times; index++) { - arr[index] = ktimeNum; - } - numKinds--; - HashSet set = new HashSet<>(); - set.add(ktimeNum); - while (numKinds != 0) { - int curNum = 0; - do { - curNum = randomNumber(range); - } while (set.contains(curNum)); - set.add(curNum); - numKinds--; - for (int i = 0; i < m; i++) { - arr[index++] = curNum; - } - } - // arr 填好了 - for (int i = 0; i < arr.length; i++) { - // i 位置的数,我想随机和j位置的数做交换 - int j = (int) (Math.random() * arr.length);// 0 ~ N-1 - int tmp = arr[i]; - arr[i] = arr[j]; - arr[j] = tmp; - } - return arr; - } - - // [-range, +range] - public static int randomNumber(int range) { - return ((int) (Math.random() * range) + 1) - ((int) (Math.random() * range) + 1); - } - - public static void main(String[] args) { - int kinds = 5; - int range = 30; - int testTime = 100000; - int max = 9; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int a = (int) (Math.random() * max) + 1; // a 1 ~ 9 - int b = (int) (Math.random() * max) + 1; // b 1 ~ 9 - int k = Math.min(a, b); - int m = Math.max(a, b); - // k < m - if (k == m) { - m++; - } - int[] arr = randomArray(kinds, range, k, m); - int ans1 = test(arr, k, m); - int ans2 = onlyKTimes(arr, k, m); - if (ans1 != ans2) { - System.out.println(ans1); - System.out.println(ans2); - System.out.println("出错了!"); - } - } - System.out.println("测试结束"); - - } - -} diff --git a/公开课/class042/Code02_ContainAllCharExactly.java b/公开课/class042/Code02_ContainAllCharExactly.java deleted file mode 100644 index 265acfe..0000000 --- a/公开课/class042/Code02_ContainAllCharExactly.java +++ /dev/null @@ -1,114 +0,0 @@ -package class042; - -import java.util.Arrays; - -public class Code02_ContainAllCharExactly { - - public static int containExactly1(String s, String a) { - if (s == null || a == null || s.length() < a.length()) { - return -1; - } - char[] aim = a.toCharArray(); - Arrays.sort(aim); - String aimSort = String.valueOf(aim); - for (int L = 0; L < s.length(); L++) { - for (int R = L; R < s.length(); R++) { - char[] cur = s.substring(L, R + 1).toCharArray(); - Arrays.sort(cur); - String curSort = String.valueOf(cur); - if (curSort.equals(aimSort)) { - return L; - } - } - } - return -1; - } - - public static int containExactly2(String s, String a) { - if (s == null || a == null || s.length() < a.length()) { - return -1; - } - char[] str = s.toCharArray(); - char[] aim = a.toCharArray(); - for (int L = 0; L <= str.length - aim.length; L++) { - if (isCountEqual(str, L, aim)) { - return L; - } - } - return -1; - } - - public static boolean isCountEqual(char[] str, int L, char[] aim) { - int[] count = new int[256]; - for (int i = 0; i < aim.length; i++) { - count[aim[i]]++; - } - for (int i = 0; i < aim.length; i++) { - if (count[str[L + i]]-- == 0) { - return false; - } - } - return true; - } - - public static int containExactly3(String s, String a) { - if (s == null || a == null || s.length() < a.length()) { - return -1; - } - char[] aim = a.toCharArray(); - int[] count = new int[256]; - for (int i = 0; i < aim.length; i++) { - count[aim[i]]++; - } - int M = aim.length; - char[] str = s.toCharArray(); - int inValidTimes = 0; - int R = 0; - for (; R < M; R++) { - if (count[str[R]]-- <= 0) { - inValidTimes++; - } - } - for (; R < str.length; R++) { - if (inValidTimes == 0) { - return R - M; - } - if (count[str[R]]-- <= 0) { - inValidTimes++; - } - if (count[str[R - M]]++ < 0) { - inValidTimes--; - } - } - return inValidTimes == 0 ? R - M : -1; - } - - // for test - public static String getRandomString(int possibilities, int maxSize) { - char[] ans = new char[(int) (Math.random() * maxSize) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (char) ((int) (Math.random() * possibilities) + 'a'); - } - return String.valueOf(ans); - } - - public static void main(String[] args) { - int possibilities = 5; - int strMaxSize = 20; - int aimMaxSize = 5; - int testTimes = 500000; - System.out.println("test begin, test time : " + testTimes); - for (int i = 0; i < testTimes; i++) { - String str = getRandomString(possibilities, strMaxSize); - String aim = getRandomString(possibilities, aimMaxSize); - int ans1 = containExactly1(str, aim); - int ans2 = containExactly2(str, aim); - int ans3 = containExactly3(str, aim); - if (ans1 != ans2 || ans2 != ans3) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - } - -} diff --git a/公开课/class042/Code03_FindHalfMajority.java b/公开课/class042/Code03_FindHalfMajority.java deleted file mode 100644 index 4ca6ea6..0000000 --- a/公开课/class042/Code03_FindHalfMajority.java +++ /dev/null @@ -1,137 +0,0 @@ -package class042; - -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map.Entry; - -public class Code03_FindHalfMajority { - - public static int superWater(int[] arr) { - int candidate = 0; - int hp = 0; - for (int num : arr) { - if (hp == 0) { - candidate = num; - hp = 1; - } else if (num == candidate) { - hp++; - } else { - hp--; - } - } - if (hp == 0) { - return -1; - } - hp = 0; - for (int i = 0; i < arr.length; i++) { - if (arr[i] == candidate) { - hp++; - } - } - return hp > arr.length / 2 ? candidate : -1; - } - - // for test - public static int right(int[] arr) { - HashMap map = new HashMap<>(); - for (int cur : arr) { - if (!map.containsKey(cur)) { - map.put(cur, 0); - } - map.put(cur, map.get(cur) + 1); - } - for (Entry entry : map.entrySet()) { - if (entry.getValue() > arr.length / 2) { - return entry.getKey(); - } - } - return -1; - } - - // for test - public static int[] genareteRandomArray(int len, int max) { - int[] ans = new int[(int) (Math.random() * len) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * max) + 1; - } - return ans; - } - - public static void main(String[] args) { - int len = 100; - int max = 10; - int testTime = 100000; - System.out.println("test begin"); - for (int i = 0; i < testTime; i++) { - int[] arr = genareteRandomArray(len, max); - int ans1 = superWater(arr); - int ans2 = right(arr); - if (ans1 != ans2) { - System.out.println("Oops!"); - break; - } - } - System.out.println("test end"); - } - - public static void printKMajor(int[] arr, int K) { - if (K < 2) { - System.out.println("the value of K is invalid."); - return; - } - HashMap cands = new HashMap(); - for (int i = 0; i != arr.length; i++) { - if (cands.containsKey(arr[i])) { - cands.put(arr[i], cands.get(arr[i]) + 1); - } else { - if (cands.size() == K - 1) { - allCandsMinusOne(cands); - } else { - cands.put(arr[i], 1); - } - } - } - HashMap reals = getReals(arr, cands); - boolean hasPrint = false; - for (Entry set : cands.entrySet()) { - Integer key = set.getKey(); - if (reals.get(key) > arr.length / K) { - hasPrint = true; - System.out.print(key + " "); - } - } - System.out.println(hasPrint ? "" : "no such number."); - } - - public static void allCandsMinusOne(HashMap map) { - List removeList = new LinkedList(); - for (Entry set : map.entrySet()) { - Integer key = set.getKey(); - Integer value = set.getValue(); - if (value == 1) { - removeList.add(key); - } - map.put(key, value - 1); - } - for (Integer removeKey : removeList) { - map.remove(removeKey); - } - } - - public static HashMap getReals(int[] arr, HashMap cands) { - HashMap reals = new HashMap(); - for (int i = 0; i != arr.length; i++) { - int curNum = arr[i]; - if (cands.containsKey(curNum)) { - if (reals.containsKey(curNum)) { - reals.put(curNum, reals.get(curNum) + 1); - } else { - reals.put(curNum, 1); - } - } - } - return reals; - } - -} diff --git a/公开课/class043/Code01_AppleMinBags.java b/公开课/class043/Code01_AppleMinBags.java deleted file mode 100644 index d437f78..0000000 --- a/公开课/class043/Code01_AppleMinBags.java +++ /dev/null @@ -1,69 +0,0 @@ -package class043; - -public class Code01_AppleMinBags { - - public static int minBag1(int apple) { - if (apple < 0) { - return -1; - } - if (apple == 0) { - return 0; - } - // 最多的8号袋开始试,apple / 8 - for (int max = (apple / 8); max >= 0; max--) { - int rest = apple - (max * 8); - if (rest % 6 == 0) { - return max + rest / 6; - } - } - return -1; - } - - public static int minBag2(int apple) { - if (apple < 18) { - if (apple < 0) { - return -1; - } - if (apple == 0) { - return 0; - } - if (apple == 6 || apple == 8) { - return 1; - } - if (apple == 12 || apple == 14 || apple == 16) { - return 2; - } - return -1; - } - int team = (apple - 18) / 8; - return (apple & 1) == 0 ? (team + 3) : -1; - } - - public static int minBagAwesome(int apple) { - if (apple < 0 || (apple & 1) != 0) { - return -1; - } - if (apple == 0) { - return 0; - } - if (apple < 18) { - if (apple == 6 || apple == 8) { - return 1; - } else if (apple == 12 || apple == 14 || apple == 16) { - return 2; - } else { - return -1; - } - } else { // apple >= 18 且 是偶数 - return (apple - 18) / 8 + 3; - } - } - - public static void main(String[] args) { - for (int apple = 0; apple <= 100; apple++) { - System.out.println(apple + " : " + minBag1(apple)); - } - - } - -} diff --git a/公开课/class043/Code02_SplitNumber.java b/公开课/class043/Code02_SplitNumber.java deleted file mode 100644 index fe1b176..0000000 --- a/公开课/class043/Code02_SplitNumber.java +++ /dev/null @@ -1,49 +0,0 @@ -package class043; - -public class Code02_SplitNumber { - - public static boolean isSplit1(int num) { - if (num <= 2) { - return false; - } - // num > 2 - for (int start = 1; start < num; start++) { - int ans = start; - for (int next = start + 1; next < num; next++) { - if (ans + next > num) { - break; - } - if (ans + next == num) { - return true; - } - ans += next; - } - } - return false; - } - - public static boolean isSplit2(int num) { - // num > 0 - return num > 0 && (num & (num - 1)) != 0; - } - - public static void printNumberBinary(int num) { - for (int i = 31; i >= 0; i--) { - int status = (num & (1 << i)) != 0 ? 1 : 0; - System.out.print(status); - } - System.out.println(); - } - - public static void main(String[] args) { - int num = 128; // 0...0111 - printNumberBinary(num); - - printNumberBinary(num - 1); - -// for (int i = 0; i < 100; i++) { -// System.out.println(i + " : " + isSplit2(i)); -// } - } - -} diff --git a/公开课/class043/Code03_EatGrass.java b/公开课/class043/Code03_EatGrass.java deleted file mode 100644 index 176f2c8..0000000 --- a/公开课/class043/Code03_EatGrass.java +++ /dev/null @@ -1,44 +0,0 @@ -package class043; - -public class Code03_EatGrass { - - public static String whoWin(int grass) { - return process(grass, "先手"); - } - - // 只有两个选手,分别是字符串 "先手" "后手" - // 当前,轮到cur这个选手 - // 还剩rest份草 - // 返回谁赢,"先手"先手赢 "后手"后手赢 - public static String process(int rest, String cur) { - String against = cur.equals("先手") ? "后手" : "先手"; - if (rest == 0) { - return against; - } - // 还剩下不止0份草 1 4 16 64 rest - int choose = 1; - while (choose <= rest) { - int nextRest = rest - choose; - if (process(nextRest, against).equals(cur)) { - return cur; - } - choose *= 4; - } - return against; - } - - public static String winner2(int n) { - if (n % 5 == 0 || n % 5 == 2) { - return "后手"; - } else { - return "先手"; - } - } - - public static void main(String[] args) { - for (int i = 0; i <= 50; i++) { - System.out.println(i + " : " + whoWin(i)); - } - } - -} diff --git a/公开课/class043/Code04_FindOddTimesNumber.java b/公开课/class043/Code04_FindOddTimesNumber.java deleted file mode 100644 index abf064f..0000000 --- a/公开课/class043/Code04_FindOddTimesNumber.java +++ /dev/null @@ -1,18 +0,0 @@ -package class043; - -public class Code04_FindOddTimesNumber { - - public static int oddTimesNumber(int[] arr) { - int xor = 0; - for (int num : arr) { - xor ^= num; - } - return xor; - } - - public static void main(String[] args) { - int[] arr = { 3, 4, 3, 4, 2, 1, 4, 3, 3, 2, 4, 2, 3, 6, 2, 3, 6, 1, 6 }; - System.out.println(oddTimesNumber(arr)); - } - -} diff --git a/公开课/class044/Code01_SubArrayMaxSum.java b/公开课/class044/Code01_SubArrayMaxSum.java deleted file mode 100644 index ed1234f..0000000 --- a/公开课/class044/Code01_SubArrayMaxSum.java +++ /dev/null @@ -1,95 +0,0 @@ -package class044; - -// 本题测试链接 : https://leetcode.com/problems/maximum-subarray/ -public class Code01_SubArrayMaxSum { - - public static int maxSubArray(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int N = arr.length; - int[] dp = new int[N]; - // 0 arr[0..0] - dp[0] = arr[0]; - int max = dp[0]; - for (int end = 1; end < N; end++) { - int p1 = arr[end]; - int p2 = dp[end - 1] + arr[end]; - dp[end] = Math.max(p1, p2); - max = Math.max(max, dp[end]); - } - return max; - } - - - public static int maxSubArray5(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int N = arr.length; - int pre = arr[0];// 上一步的dp值 pre dp[0] - int max = pre; - for (int end = 1; end < N; end++) { - pre = Math.max(arr[end], pre + arr[end]); - max = Math.max(max, pre); - } - return max; - } - - - - - - - - - public static int maxSubArray1(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int N = arr.length; - int max = Integer.MIN_VALUE; - for (int L = 0; L < N; L++) { - for (int R = L; R < N; R++) { - int sum = 0; - for (int i = L; i <= R; i++) { - sum += arr[i]; - } - max = Math.max(max, sum); - } - } - return max; - } - - public static int maxSubArray2(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int[] dp = new int[arr.length]; - dp[0] = arr[0]; - for (int i = 1; i < arr.length; i++) { - int p1 = arr[i]; - int p2 = dp[i - 1] + arr[i]; - dp[i] = Math.max(p1, p2); - } - int max = Integer.MIN_VALUE; - for (int i = 0; i < dp.length; i++) { - max = Math.max(max, dp[i]); - } - return max; - } - - public static int maxSubArray3(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int pre = arr[0]; - int max = pre; - for (int i = 1; i < arr.length; i++) { - pre = Math.max(arr[i], pre + arr[i]); - max = Math.max(max, pre); - } - return max; - } - -} diff --git a/公开课/class044/Code02_MaxSumFollowUp.java b/公开课/class044/Code02_MaxSumFollowUp.java deleted file mode 100644 index c64d71b..0000000 --- a/公开课/class044/Code02_MaxSumFollowUp.java +++ /dev/null @@ -1,119 +0,0 @@ -package class044; - -public class Code02_MaxSumFollowUp { - - public static int maxSumSubMatrix(int[][] matrix) { - if (matrix == null || matrix.length == 0 || matrix[0] == null || matrix[0].length == 0) { - return 0; - } - int N = matrix.length; - int M = matrix[0].length; - // 0..0 0..1 0..2 0..N-1 - // 1..1 - int max = Integer.MIN_VALUE; - for (int s = 0; s < N; s++) { - int[] arr = new int[M]; - for (int e = s; e < N; e++) { - for (int i = 0; i < M; i++) { - arr[i] += matrix[e][i]; - } - // arr 被加工好了 - max = Math.max(max, maxSumSubArray(arr)); - } - } - return max; - } - - public static int maxSumSubArray(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int N = arr.length; - int pre = arr[0];// 上一步的dp值 pre dp[0] - int max = pre; - for (int end = 1; end < N; end++) { - pre = Math.max(arr[end], pre + arr[end]); - max = Math.max(max, pre); - } - return max; - } - - public static int maxSum1(int[][] matrix) { - int n = matrix.length; - int m = matrix[0].length; - int max = Integer.MIN_VALUE; - for (int ai = 0; ai < n; ai++) { - for (int aj = 0; aj < m; aj++) { - for (int bi = ai; bi < n; bi++) { - for (int bj = aj; bj < m; bj++) { - max = Math.max(max, sum(matrix, ai, aj, bi, bj)); - } - } - } - } - return max; - } - - public static int sum(int[][] matrix, int ai, int aj, int bi, int bj) { - int sum = 0; - for (int i = ai; i <= bi; i++) { - for (int j = aj; j <= bj; j++) { - sum += matrix[i][j]; - } - } - return sum; - } - - public static int maxSum2(int[][] matrix) { - if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { - return 0; - } - int max = Integer.MIN_VALUE; - int cur = 0; - int[] s = null; - for (int i = 0; i != matrix.length; i++) { - s = new int[matrix[0].length]; - for (int j = i; j != matrix.length; j++) { - cur = 0; - for (int k = 0; k != s.length; k++) { - s[k] += matrix[j][k]; - cur += s[k]; - max = Math.max(max, cur); - cur = cur < 0 ? 0 : cur; - } - } - } - return max; - } - - public static int[][] generateMatrix(int N, int M, int V) { - int n = (int) (Math.random() * N) + 1; - int m = (int) (Math.random() * M) + 1; - int[][] matrix = new int[n][m]; - for (int i = 0; i < n; i++) { - for (int j = 0; j < m; j++) { - matrix[i][j] = (int) (Math.random() * V) - (int) (Math.random() * V); - } - } - return matrix; - } - - public static void main(String[] args) { - int N = 20; - int M = 20; - int V = 100; - int testTime = 50000; - System.out.println("test begin"); - for (int i = 0; i < testTime; i++) { - int[][] matrix = generateMatrix(N, M, V); - int ans1 = maxSum1(matrix); - int ans2 = maxSum2(matrix); - if (ans1 != ans2) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - - } - -} diff --git a/公开课/class044/Code03_MaxSumNoAdjoin.java b/公开课/class044/Code03_MaxSumNoAdjoin.java deleted file mode 100644 index 63834d8..0000000 --- a/公开课/class044/Code03_MaxSumNoAdjoin.java +++ /dev/null @@ -1,97 +0,0 @@ -package class044; - -public class Code03_MaxSumNoAdjoin { - - public static int maxSumSubseqNoAdjoin(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - if (arr.length == 1) { - return arr[0]; - } - if (arr.length == 2) { - return Math.max(arr[0], arr[1]); - } - // arr不止两个数 - int N = arr.length; - int[] dp = new int[N]; - // dp[i] 0...i 不能选相邻数的情况下,子序列的最大累加和 - // dp[N-1] 0..N-1 - dp[0] = arr[0]; - dp[1] = Math.max(arr[0], arr[1]); - for (int i = 2; i < N; i++) { - int p1 = dp[i - 1]; - int p2 = arr[i]; - int p3 = arr[i] + dp[i - 2]; - dp[i] = Math.max(Math.max(p1, p2), p3); - } - return dp[N - 1]; - } - - public static int subSqeMaxSumNoNext(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - if (arr.length == 1) { - return arr[0]; - } - int[] dp = new int[arr.length]; - // dp[i] : arr[0..i]挑选,满足不相邻设定的情况下,随意挑选,最大的累加和 - dp[0] = arr[0]; - dp[1] = Math.max(arr[0], arr[1]); - for (int i = 2; i < arr.length; i++) { - int p1 = dp[i - 1]; - int p2 = arr[i] + Math.max(dp[i - 2], 0); - dp[i] = Math.max(p1, p2); - } - return dp[arr.length - 1]; - } - - // 给定一个数组arr,在不能取相邻数的情况下,返回所有组合中的最大累加和 - // 思路: - // 定义dp[i] : 表示arr[0...i]范围上,在不能取相邻数的情况下,返回所有组合中的最大累加和 - // 在arr[0...i]范围上,在不能取相邻数的情况下,得到的最大累加和,可能性分类: - // 可能性 1) 选出的组合,不包含arr[i]。那么dp[i] = dp[i-1] - // 比如,arr[0...i] = {3,4,-4},最大累加和是不包含i位置数的时候 - // - // 可能性 2) 选出的组合,只包含arr[i]。那么dp[i] = arr[i] - // 比如,arr[0...i] = {-3,-4,4},最大累加和是只包含i位置数的时候 - // - // 可能性 3) 选出的组合,包含arr[i], 且包含arr[0...i-2]范围上的累加和。那么dp[i] = arr[i] + dp[i-2] - // 比如,arr[0...i] = {3,1,4},最大累加和是3和4组成的7,因为相邻不能选,所以i-1位置的数要跳过 - // - // 综上所述:dp[i] = Max { dp[i-1], arr[i] , arr[i] + dp[i-2] } - public static int maxSum(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int N = arr.length; - if (N == 1) { - return arr[0]; - } - if (N == 2) { - return Math.max(arr[0], arr[1]); - } - int[] dp = new int[N]; - dp[0] = arr[0]; - dp[1] = Math.max(arr[0], arr[1]); - for (int i = 2; i < N; i++) { - dp[i] = Math.max(Math.max(dp[i - 1], arr[i]), arr[i] + dp[i - 2]); - } - return dp[N - 1]; - } - - public static int[] randomArray(int N, int V) { - int[] ans = new int[N]; - - for (int i = 0; i < N; i++) { - ans[i] = (int) (Math.random() * V) - (V >> 1); - } - return ans; - } - - public static void main(String[] args) { - - } - -} diff --git a/公开课/class045/Code01_MaxLeftMaxRight.java b/公开课/class045/Code01_MaxLeftMaxRight.java deleted file mode 100644 index 66384b2..0000000 --- a/公开课/class045/Code01_MaxLeftMaxRight.java +++ /dev/null @@ -1,80 +0,0 @@ -package class045; - -public class Code01_MaxLeftMaxRight { - - // 笨办法,但是好想 - public static int solution1(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int ans = Integer.MIN_VALUE; - for (int leftEnd = 0; leftEnd < N - 1; leftEnd++) { - int leftMax = arr[0]; - for (int i = 1; i <= leftEnd; i++) { - leftMax = Math.max(leftMax, arr[i]); - } - int rightMax = arr[leftEnd + 1]; - for (int i = leftEnd + 2; i < N; i++) { - rightMax = Math.max(rightMax, arr[i]); - } - ans = Math.max(ans, Math.abs(leftMax - rightMax)); - } - return ans; - } - - // 好办法,是我们真正想测试的 - public static int solution2(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int max = arr[0]; - for (int i = 1; i < N; i++) { - max = Math.max(max, arr[i]); - } - return max - Math.min(arr[0], arr[N - 1]); - } - - public static int[] randomArray(int maxLen, int maxValue) { - int len = (int) (Math.random() * (maxLen + 1)); - int[] arr = new int[len]; - for (int i = 0; i < arr.length; i++) { - arr[i] = (int) (Math.random() * (maxValue + 1)) - (int) (Math.random() * (maxValue + 1)); - } - return arr; - } - - public static void main(String[] args) { - // 随机数组的最大长度 - int maxLen = 6; - // 随机数组值的范围 - int maxValue = 30; - // 测试次数 - int testTime = 3000000; - System.out.println("如果没有错误信息打印,说明所有测试通过"); - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - // 随机得到一个数组,长度也随机,每个值也随机 - int[] arr = randomArray(maxLen, maxValue); - // 用方法1跑出答案1 - int ans1 = solution1(arr); - // 用方法2跑出答案2 - int ans2 = solution2(arr); - // 如果答案1和答案2不一样,提示出错了 - if (ans1 != ans2) { - System.out.println("出错了!"); - System.out.println(ans1 + " , " + ans2); - - for (int k = 0; k < arr.length; k++) { - System.out.print(arr[k] + " "); - } - System.out.println(); - - break; - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class045/Code02_RotateImage.java b/公开课/class045/Code02_RotateImage.java deleted file mode 100644 index bf6cd01..0000000 --- a/公开课/class045/Code02_RotateImage.java +++ /dev/null @@ -1,52 +0,0 @@ -package class045; - -public class Code02_RotateImage { - - public static void rotate(int[][] matrix) { - int a = 0; - int b = 0; - int c = matrix.length - 1; - int d = matrix[0].length - 1; - while (a < c) { // a>=c - rotateEdge(matrix, a++, b++, c--, d--); - } - } - - // 在二维数组m中,左上角点(a,b), 右下角点(c,d) - // 只在规定好的框上,顺时针转好 - public static void rotateEdge(int[][] m, int a, int b, int c, int d) { - int tmp = 0; - for (int i = 0; i < d - b; i++) { - tmp = m[a][b + i]; - m[a][b + i] = m[c - i][b]; - m[c - i][b] = m[c][d - i]; - m[c][d - i] = m[a + i][d]; - m[a + i][d] = tmp; - } - } - - public static void printMatrix(int[][] m) { - int N = m.length; - for (int i = 0; i < N; i++) { - for (int j = 0; j < N; j++) { - System.out.print(m[i][j] + " "); - } - System.out.println(); - } - } - - public static void main(String[] args) { - int[][] matrix = { - { 1, 2, 3 }, - { 4, 5, 6 }, - { 7, 8, 9 } }; - printMatrix(matrix); - System.out.println("========"); - - rotate(matrix); - printMatrix(matrix); - System.out.println("========"); - - } - -} diff --git a/公开课/class045/Code03_ZigZagPrintMatrix.java b/公开课/class045/Code03_ZigZagPrintMatrix.java deleted file mode 100644 index 47c4f2c..0000000 --- a/公开课/class045/Code03_ZigZagPrintMatrix.java +++ /dev/null @@ -1,48 +0,0 @@ -package class045; - -public class Code03_ZigZagPrintMatrix { - - public static void printMatrixZigZag(int[][] m) { - // (a,b) A 先往右,再往下 - int a = 0; - int b = 0; - // (c,d) B 先往下,在往右 - int c = 0; - int d = 0; - int er = m.length - 1; - int ec = m[0].length - 1; - boolean fromUp = false; - while (a != er + 1) { - printLevel(m, a, b, c, d, fromUp); - // A 先往右,再往下 - a = b == ec ? a + 1 : a; - b = b == ec ? b : b + 1; - // B 先往下,在往右 - d = c == er ? d + 1 : d; - c = c == er ? c : c + 1; - fromUp = !fromUp; - } - } - - public static void printLevel(int[][] m, int a, int b, int c, int d, boolean f) { - if (f) { - while (a != c + 1) { - System.out.print(m[a++][b--] + " "); - } - } else { - while (c != a - 1) { - System.out.print(m[c--][d++] + " "); - } - } - } - - public static void main(String[] args) { - int[][] matrix = { - { 1, 2, 3, 4 }, - { 5, 6, 7, 8 }, - { 9, 10, 11, 12 } }; - printMatrixZigZag(matrix); - - } - -} diff --git a/公开课/class045/Code04_MissingNumber.java b/公开课/class045/Code04_MissingNumber.java deleted file mode 100644 index b5f5cab..0000000 --- a/公开课/class045/Code04_MissingNumber.java +++ /dev/null @@ -1,29 +0,0 @@ -package class045; - -// 测试链接:https://leetcode.com/problems/first-missing-positive/ -public class Code04_MissingNumber { - - public static int firstMissingPositive(int[] arr) { - // l是盯着的位置 - // 0~l-1 - int l = 0; - int r = arr.length; - while (l != r) { - if (arr[l] == l + 1) { - l++; - } else if (arr[l] <= l || arr[l] > r || arr[arr[l] - 1] == arr[l]) { - swap(arr, l, --r); - } else { - swap(arr, l, arr[l] - 1); - } - } - return l + 1; - } - - public static void swap(int[] arr, int i, int j) { - int tmp = arr[i]; - arr[i] = arr[j]; - arr[j] = tmp; - } - -} diff --git a/公开课/class046/Code01_MergeKSortedLists.java b/公开课/class046/Code01_MergeKSortedLists.java deleted file mode 100644 index 736b494..0000000 --- a/公开课/class046/Code01_MergeKSortedLists.java +++ /dev/null @@ -1,52 +0,0 @@ -package class046; - -import java.util.Comparator; -import java.util.PriorityQueue; - -// 本题测试链接 : https://leetcode.com/problems/merge-k-sorted-lists/ -public class Code01_MergeKSortedLists { - - public static class ListNode { - public int val; - public ListNode next; - } - - public static class ListNodeComparator implements Comparator { - - @Override - public int compare(ListNode o1, ListNode o2) { - return o1.val - o2.val; - } - - } - - public static ListNode mergeKLists(ListNode[] lists) { - if (lists == null) { - return null; - } - PriorityQueue heap = new PriorityQueue<>(new ListNodeComparator()); - for (int i = 0; i < lists.length; i++) { - if (lists[i] != null) { - heap.add(lists[i]); - } - } - if (heap.isEmpty()) { - return null; - } - ListNode head = heap.poll(); - ListNode pre = head; - if (pre.next != null) { - heap.add(pre.next); - } - while (!heap.isEmpty()) { - ListNode cur = heap.poll(); - pre.next = cur; - pre = cur; - if (cur.next != null) { - heap.add(cur.next); - } - } - return head; - } - -} diff --git a/公开课/class046/Code02_LongestNoRepeatSubstring.java b/公开课/class046/Code02_LongestNoRepeatSubstring.java deleted file mode 100644 index f0fe821..0000000 --- a/公开课/class046/Code02_LongestNoRepeatSubstring.java +++ /dev/null @@ -1,97 +0,0 @@ -package class046; - -public class Code02_LongestNoRepeatSubstring { - /* - * 给定一个只由小写字母(a~z)组成的字符串str, 返回其中最长无重复字符的子串长度 - * - */ - - public static int max(String s) { - if (s == null || s.length() == 0) { - return 0; - } - char[] str = s.toCharArray(); - int N = str.length; - int[] map = new int[256]; - for (int i = 0; i < 255; i++) { - map[i] = -1; - } - map[str[0]] = 0; - int pre = 1; - int max = 1; - for (int i = 1; i < N; i++) { - pre = Math.min(i - map[str[i]], pre + 1); - max = Math.max(max, pre); - map[str[i]] = i; - } - return max; - } - - public static int lnrs1(String s) { - if (s == null || s.length() == 0) { - return 0; - } - char[] str = s.toCharArray(); - int N = str.length; - int max = 0; - for (int i = 0; i < N; i++) { - boolean[] set = new boolean[26]; - for (int j = i; j < N; j++) { - if (set[str[j] - 'a']) { - break; - } - set[str[j] - 'a'] = true; - max = Math.max(max, j - i + 1); - } - } - return max; - } - - public static int lnrs2(String s) { - if (s == null || s.length() == 0) { - return 0; - } - char[] str = s.toCharArray(); - int N = str.length; - int[] last = new int[26]; - for (int i = 0; i < 26; i++) { - last[i] = -1; - } - last[str[0] - 'a'] = 0; - int max = 1; - int preMaxLen = 1; - for (int i = 1; i < N; i++) { - preMaxLen = Math.min(i - last[str[i] - 'a'], preMaxLen + 1); - max = Math.max(max, preMaxLen); - last[str[i] - 'a'] = i; - } - return max; - } - - // for test - public static String getRandomString(int possibilities, int maxSize) { - char[] ans = new char[(int) (Math.random() * maxSize) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (char) ((int) (Math.random() * possibilities) + 'a'); - } - return String.valueOf(ans); - } - - public static void main(String[] args) { - int possibilities = 26; - int strMaxSize = 100; - int testTimes = 1000000; - System.out.println("test begin, test time : " + testTimes); - for (int i = 0; i < testTimes; i++) { - String str = getRandomString(possibilities, strMaxSize); - int ans1 = lnrs1(str); - int ans2 = lnrs2(str); - if (ans1 != ans2) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - - } - -} diff --git a/公开课/class046/Code03_CordCoverMaxPoint.java b/公开课/class046/Code03_CordCoverMaxPoint.java deleted file mode 100644 index 66e3040..0000000 --- a/公开课/class046/Code03_CordCoverMaxPoint.java +++ /dev/null @@ -1,88 +0,0 @@ -package class046; - -import java.util.Arrays; - -public class Code03_CordCoverMaxPoint { - - public static int maxPoint1(int[] arr, int L) { - int res = 1; - for (int i = 0; i < arr.length; i++) { - int nearest = nearestIndex(arr, i, arr[i] - L); - res = Math.max(res, i - nearest + 1); - } - return res; - } - - public static int nearestIndex(int[] arr, int R, int value) { - int L = 0; - int index = R; - while (L <= R) { - int mid = L + ((R - L) >> 1); - if (arr[mid] >= value) { - index = mid; - R = mid - 1; - } else { - L = mid + 1; - } - } - return index; - } - - public static int maxPoint2(int[] arr, int L) { - int left = 0; - int right = 0; - int N = arr.length; - int max = 0; - while (left < N) { - while (right < N && arr[right] - arr[left] <= L) { - right++; - } - max = Math.max(max, right - (left++)); - } - return max; - } - - // for test - public static int test(int[] arr, int L) { - int max = 0; - for (int i = 0; i < arr.length; i++) { - int pre = i - 1; - while (pre >= 0 && arr[i] - arr[pre] <= L) { - pre--; - } - max = Math.max(max, i - pre); - } - return max; - } - - // for test - public static int[] generateArray(int len, int max) { - int[] ans = new int[(int) (Math.random() * len) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * max); - } - Arrays.sort(ans); - return ans; - } - - public static void main(String[] args) { - int len = 100; - int max = 1000; - int testTime = 100000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int L = (int) (Math.random() * max); - int[] arr = generateArray(len, max); - int ans1 = maxPoint1(arr, L); - int ans2 = maxPoint2(arr, L); - int ans3 = test(arr, L); - if (ans1 != ans2 || ans2 != ans3) { - System.out.println("oops!"); - break; - } - } - System.out.println("测试结束"); - - } - -} diff --git a/公开课/class047/Code01_Water.java b/公开课/class047/Code01_Water.java deleted file mode 100644 index db6b1a8..0000000 --- a/公开课/class047/Code01_Water.java +++ /dev/null @@ -1,120 +0,0 @@ -package class047; - -public class Code01_Water { - - // 本题测试链接:https://leetcode.com/problems/trapping-rain-water/ - // 给定一个正整数数组arr,把arr想象成一个直方图。返回这个直方图如果装水,能装下几格水? - public static int water1(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - // O位置无水量 - // 0~N-1,N-1无水量 - int N = arr.length; - int water = 0; - for (int i = 1; i < N - 1; i++) { - int leftMax = Integer.MIN_VALUE; - for (int j = 0; j < i; j++) { - leftMax = Math.max(leftMax, arr[j]); - } - int rightMax = Integer.MIN_VALUE; - for (int j = i + 1; j < N; j++) { - rightMax = Math.max(rightMax, arr[j]); - } - water += Math.max(Math.min(leftMax, rightMax) - arr[i], 0); - } - return water; - } - - public static int water2(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int[] leftMaxs = new int[N]; - leftMaxs[0] = arr[0]; - for (int i = 1; i < N; i++) { - leftMaxs[i] = Math.max(leftMaxs[i - 1], arr[i]); - } - - int[] rightMaxs = new int[N]; - rightMaxs[N - 1] = arr[N - 1]; - for (int i = N - 2; i >= 0; i--) { - rightMaxs[i] = Math.max(rightMaxs[i + 1], arr[i]); - } - int water = 0; - for (int i = 1; i < N - 1; i++) { - water += Math.max(Math.min(leftMaxs[i - 1], rightMaxs[i + 1]) - arr[i], 0); - } - return water; - } - - public static int water3(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int[] rightMaxs = new int[N]; - rightMaxs[N - 1] = arr[N - 1]; - for (int i = N - 2; i >= 0; i--) { - rightMaxs[i] = Math.max(rightMaxs[i + 1], arr[i]); - } - int water = 0; - int leftMax = arr[0]; - for (int i = 1; i < N - 1; i++) { - water += Math.max(Math.min(leftMax, rightMaxs[i + 1]) - arr[i], 0); - leftMax = Math.max(leftMax, arr[i]); - } - return water; - } - - public static int water4(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int L = 1; - int leftMax = arr[0]; - int R = N - 2; - int rightMax = arr[N - 1]; - int water = 0; - while (L <= R) { - if (leftMax <= rightMax) { - water += Math.max(0, leftMax - arr[L]); - leftMax = Math.max(leftMax, arr[L++]); - } else { - water += Math.max(0, rightMax - arr[R]); - rightMax = Math.max(rightMax, arr[R--]); - } - } - return water; - } - - // for test - public static int[] generateRandomArray(int len, int value) { - int[] ans = new int[(int) (Math.random() * len) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * value) + 1; - } - return ans; - } - - public static void main(String[] args) { - int len = 100; - int value = 200; - int testTimes = 100000; - System.out.println("test begin"); - for (int i = 0; i < testTimes; i++) { - int[] arr = generateRandomArray(len, value); - int ans1 = water1(arr); - int ans2 = water2(arr); - int ans3 = water3(arr); - int ans4 = water4(arr); - if (ans1 != ans2 || ans3 != ans4 || ans1 != ans3) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - } - -} diff --git a/公开课/class047/Code02_RandToRand.java b/公开课/class047/Code02_RandToRand.java deleted file mode 100644 index c3487e0..0000000 --- a/公开课/class047/Code02_RandToRand.java +++ /dev/null @@ -1,137 +0,0 @@ -package class047; - -public class Code02_RandToRand { - - // 此函数只能用,不能修改 - // 等概率返回1~5 黑盒! - public static int f() { - return (int) (Math.random() * 5) + 1; - } - - // 等概率得到0和1 - public static int a() { - int ans = 0; - do { - ans = f(); - } while (ans == 3); - // 1 2 4 5 - return ans < 3 ? 0 : 1; - } - - // 等概率返回0~6 - public static int b() { - int ans = 0; - do { - // 0/1 << 2 0/1 << 1 0/1 - ans = (a() << 2) + (a() << 1) + a(); - } while (ans == 7); - // 0 1 2 3 4 5 6 - return ans; - } - - // 等概率返回1~7 - public static int c() { - return b() + 1; - } - - // 这个结构是唯一的随机机制 - // 你只能初始化并使用,不可修改 - public static class RandomBox { - private final int min; - private final int max; - - // 初始化时请一定不要让mi==ma - public RandomBox(int mi, int ma) { - min = mi; - max = ma; - } - - // 13 ~ 17 - // 13 + [0,4] - public int random() { - return min + (int) (Math.random() * (max - min + 1)); - } - - public int min() { - return min; - } - - public int max() { - return max; - } - } - - // 利用条件RandomBox,如何等概率返回0和1 - public static int rand01(RandomBox randomBox) { - int min = randomBox.min(); - int max = randomBox.max(); - // min ~ max - int size = max - min + 1; - // size是不是奇数,odd 奇数 - boolean odd = (size & 1) != 0; - int mid = size / 2; - int ans = 0; - do { - ans = randomBox.random() - min; - } while (odd && ans == mid); - return ans < mid ? 0 : 1; - } - - // 给你一个RandomBox,这是唯一能借助的随机机制 - // 等概率返回from~to范围上任何一个数 - // 要求from<=to - public static int random(RandomBox randomBox, int from, int to) { - if (from == to) { - return from; - } - // 3 ~ 9 - // 0 ~ 6 - // 0 ~ range - int range = to - from; - int num = 1; - // 求0~range需要几个2进制位 - while ((1 << num) - 1 < range) { - num++; - } - - // 我们一共需要num位 - // 最终的累加和,首先+0位上是1还是0,1位上是1还是0,2位上是1还是0... - int ans = 0; - do { - ans = 0; - for (int i = 0; i < num; i++) { - ans |= (rand01(randomBox) << i); - } - } while (ans > range); - return ans + from; - } - - public static void main(String[] args) { - - int[] count = new int[8]; // 0 1 2 .. 7 - int testTime = 10000000; - for (int i = 0; i < testTime; i++) { - int ans = c(); - count[ans]++; - } - - for (int i = 0; i < 8; i++) { - System.out.println(i + " : " + count[i]); - } - -// RandomBox randomBox = new RandomBox(3, 9); -// int from = 17; -// int to = 29; -// int[] ans = new int[to + 1]; -// int testTime1 = 1000000; -// for (int i = 0; i < testTime1; i++) { -// ans[random(randomBox, from, to)]++; -// } -// for (int i = 0; i < ans.length; i++) { -// System.out.println(ans[i]); -// } -// System.out.println("=========="); - - } - -} diff --git a/公开课/class047/Code03_EqualProbabilityRandom.java b/公开课/class047/Code03_EqualProbabilityRandom.java deleted file mode 100644 index f99826b..0000000 --- a/公开课/class047/Code03_EqualProbabilityRandom.java +++ /dev/null @@ -1,67 +0,0 @@ -package class047; - -public class Code03_EqualProbabilityRandom { - - // 内部内容不可见 - public static int f() { - return Math.random() < 0.8 ? 0 : 1; - } - - // 等概率返回0和1 - public static int g() { - int first = 0; - do { - first = f(); // 0 1 - } while (first == f()); - return first; - } - - // 这个结构是唯一的随机机制 - // 你只能初始化并使用,不可修改 - public static class RandomBox { - private final double p; - - // 初始化时请一定满足:0 < zeroP < 1 - public RandomBox(double zeroP) { - p = zeroP; - } - - public int random() { - return Math.random() < p ? 0 : 1; - } - - } - - // 底层依赖一个以p概率返回0,以1-p概率返回1的随机函数rand01p - // 如何加工出等概率返回0和1的函数 - public static int rand01(RandomBox randomBox) { - int num; - do { - num = randomBox.random(); - } while (num == randomBox.random()); - return num; - } - - public static void main(String[] args) { - int[] count = new int[2];// 0 1 - for (int i = 0; i < 1000000; i++) { - int ans = g(); - count[ans]++; - } - System.out.println(count[0] + " , " + count[1]); - -// double zeroP = 0.88; -// RandomBox randomBox = new RandomBox(zeroP); -// -// int testTime = 10000000; -// int count = 0; -// for (int i = 0; i < testTime; i++) { -// if (rand01(randomBox) == 0) { -// count++; -// } -// } -// System.out.println((double) count / (double) testTime); - - } - -} diff --git a/公开课/class047/Code04_EvenTimesOddTimes.java b/公开课/class047/Code04_EvenTimesOddTimes.java deleted file mode 100644 index a185fda..0000000 --- a/公开课/class047/Code04_EvenTimesOddTimes.java +++ /dev/null @@ -1,52 +0,0 @@ -package class047; - -public class Code04_EvenTimesOddTimes { - - public static void printOddTimesNum1(int[] arr) { - int eor = 0; - for (int i = 0; i < arr.length; i++) { - eor ^= arr[i]; - } - System.out.println(eor); - } - - public static void printOddTimesNum2(int[] arr) { - // arr中,a和b出现了奇数次,其他数都是偶数次 - int eor = 0; - for (int i = 0; i < arr.length; i++) { - eor ^= arr[i]; - } - // eor = a ^ b - // eor != 0 - // eor : 001100100 - // rightOne : 000000100 - int rightOne = eor & (~eor + 1); - int onlyOne = 0; // eor' - for (int i = 0; i < arr.length; i++) { - if ((arr[i] & rightOne) != 0) { - onlyOne ^= arr[i]; - } - } - // eor' = a or b - System.out.println(onlyOne + " " + (eor ^ onlyOne)); - } - - public static int bit1counts(int N) { - int count = 0; - while (N != 0) { - int rightOne = N & ((~N) + 1); - count++; - N -= rightOne; - } - return count; - } - - public static void main(String[] args) { - int[] arr1 = { 3, 3, 2, 3, 1, 1, 1, 3, 1, 1, 1 }; - printOddTimesNum1(arr1); - - int[] arr2 = { 4, 3, 4, 2, 2, 2, 4, 1, 1, 1, 3, 3, 1, 1, 1, 4, 2, 2 }; - printOddTimesNum2(arr2); - } - -} diff --git a/公开课/class048/Code01_SubArrayMaxSum.java b/公开课/class048/Code01_SubArrayMaxSum.java deleted file mode 100644 index 1771b0d..0000000 --- a/公开课/class048/Code01_SubArrayMaxSum.java +++ /dev/null @@ -1,137 +0,0 @@ -package class048; - -// 本题测试链接 : https://leetcode.com/problems/maximum-subarray/ -public class Code01_SubArrayMaxSum { - - public static int maxSubarraySum1(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int ans = 0; - for (int L = 0; L < arr.length; L++) { // 枚举所有子数组的开头 - for (int R = L; R < arr.length; R++) { - // arr[L...R] 求这个子数组的累加和 - int sum = 0; - for (int i = L; i <= R; i++) { - sum += arr[i]; - } - // sum -> arr[L..R] - ans = Math.max(ans, sum); - } - } - return ans; - } - - public static int maxSubarraySum2(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int N = arr.length; - int[] dp = new int[N]; // dp[i] : 子数组必须以i位置的数结尾的情况下,获得的最大累加和 - dp[0] = arr[0];// arr[...0] - int ans = dp[0]; - for (int i = 1; i < N; i++) { - int p1 = arr[i]; - int p2 = dp[i - 1] + arr[i]; - dp[i] = Math.max(p1, p2); - ans = Math.max(ans, dp[i]); - } - return ans; - } - - public static int maxSubarraySum3(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int N = arr.length; - int pre = arr[0];// pre -> dp[0] - int ans = arr[0]; - for (int i = 1; i < N; i++) { - pre = Math.max(arr[i], pre + arr[i]); - ans = Math.max(ans, pre); - } - return ans; - } - - public static int maxSubArray(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int N = arr.length; - int[] dp = new int[N]; - // 0 arr[0..0] - dp[0] = arr[0]; - int max = dp[0]; - for (int end = 1; end < N; end++) { - int p1 = arr[end]; - int p2 = dp[end - 1] + arr[end]; - dp[end] = Math.max(p1, p2); - max = Math.max(max, dp[end]); - } - return max; - } - - public static int maxSubArray5(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int N = arr.length; - int pre = arr[0];// 上一步的dp值 pre dp[0] - int max = pre; - for (int end = 1; end < N; end++) { - pre = Math.max(arr[end], pre + arr[end]); - max = Math.max(max, pre); - } - return max; - } - - public static int maxSubArray1(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int N = arr.length; - int max = Integer.MIN_VALUE; - for (int L = 0; L < N; L++) { - for (int R = L; R < N; R++) { - int sum = 0; - for (int i = L; i <= R; i++) { - sum += arr[i]; - } - max = Math.max(max, sum); - } - } - return max; - } - - public static int maxSubArray2(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int[] dp = new int[arr.length]; - dp[0] = arr[0]; - for (int i = 1; i < arr.length; i++) { - int p1 = arr[i]; - int p2 = dp[i - 1] + arr[i]; - dp[i] = Math.max(p1, p2); - } - int max = Integer.MIN_VALUE; - for (int i = 0; i < dp.length; i++) { - max = Math.max(max, dp[i]); - } - return max; - } - - public static int maxSubArray3(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int pre = arr[0]; - int max = pre; - for (int i = 1; i < arr.length; i++) { - pre = Math.max(arr[i], pre + arr[i]); - max = Math.max(max, pre); - } - return max; - } - -} diff --git a/公开课/class048/Code02_MaxSumFollowUp.java b/公开课/class048/Code02_MaxSumFollowUp.java deleted file mode 100644 index ac6dc16..0000000 --- a/公开课/class048/Code02_MaxSumFollowUp.java +++ /dev/null @@ -1,119 +0,0 @@ -package class048; - -public class Code02_MaxSumFollowUp { - - public static int maxSumSubMatrix(int[][] matrix) { - if (matrix == null || matrix.length == 0 || matrix[0] == null || matrix[0].length == 0) { - return 0; - } - int N = matrix.length; - int M = matrix[0].length; - // 0..0 0..1 0..2 0..N-1 - // 1..1 - int max = Integer.MIN_VALUE; - for (int s = 0; s < N; s++) { - int[] arr = new int[M]; - for (int e = s; e < N; e++) { - for (int i = 0; i < M; i++) { - arr[i] += matrix[e][i]; - } - // arr 被加工好了 - max = Math.max(max, maxSumSubArray(arr)); - } - } - return max; - } - - public static int maxSumSubArray(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int N = arr.length; - int pre = arr[0];// 上一步的dp值 pre dp[0] - int max = pre; - for (int end = 1; end < N; end++) { - pre = Math.max(arr[end], pre + arr[end]); - max = Math.max(max, pre); - } - return max; - } - - public static int maxSum1(int[][] matrix) { - int n = matrix.length; - int m = matrix[0].length; - int max = Integer.MIN_VALUE; - for (int ai = 0; ai < n; ai++) { - for (int aj = 0; aj < m; aj++) { - for (int bi = ai; bi < n; bi++) { - for (int bj = aj; bj < m; bj++) { - max = Math.max(max, sum(matrix, ai, aj, bi, bj)); - } - } - } - } - return max; - } - - public static int sum(int[][] matrix, int ai, int aj, int bi, int bj) { - int sum = 0; - for (int i = ai; i <= bi; i++) { - for (int j = aj; j <= bj; j++) { - sum += matrix[i][j]; - } - } - return sum; - } - - public static int maxSum2(int[][] matrix) { - if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { - return 0; - } - int max = Integer.MIN_VALUE; - int cur = 0; - int[] s = null; - for (int i = 0; i != matrix.length; i++) { - s = new int[matrix[0].length]; - for (int j = i; j != matrix.length; j++) { - cur = 0; - for (int k = 0; k != s.length; k++) { - s[k] += matrix[j][k]; - cur += s[k]; - max = Math.max(max, cur); - cur = cur < 0 ? 0 : cur; - } - } - } - return max; - } - - public static int[][] generateMatrix(int N, int M, int V) { - int n = (int) (Math.random() * N) + 1; - int m = (int) (Math.random() * M) + 1; - int[][] matrix = new int[n][m]; - for (int i = 0; i < n; i++) { - for (int j = 0; j < m; j++) { - matrix[i][j] = (int) (Math.random() * V) - (int) (Math.random() * V); - } - } - return matrix; - } - - public static void main(String[] args) { - int N = 20; - int M = 20; - int V = 100; - int testTime = 50000; - System.out.println("test begin"); - for (int i = 0; i < testTime; i++) { - int[][] matrix = generateMatrix(N, M, V); - int ans1 = maxSum1(matrix); - int ans2 = maxSum2(matrix); - if (ans1 != ans2) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - - } - -} diff --git a/公开课/class048/Code03_MaxSumNoAdjoin.java b/公开课/class048/Code03_MaxSumNoAdjoin.java deleted file mode 100644 index a1aed7b..0000000 --- a/公开课/class048/Code03_MaxSumNoAdjoin.java +++ /dev/null @@ -1,118 +0,0 @@ -package class048; - -public class Code03_MaxSumNoAdjoin { - - public static int max1(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - if (arr.length == 1) { - return arr[0]; - } - int N = arr.length; - int[] dp = new int[N]; - dp[0] = arr[0]; - dp[1] = Math.max(arr[0], arr[1]);// arr[0..1] - for (int i = 2; i < N; i++) { - // dp[i] - int p1 = arr[i]; - int p2 = dp[i - 1]; - int p3 = dp[i - 2] + arr[i]; - dp[i] = Math.max(Math.max(p1, p2), p3); - } - return dp[N - 1]; - } - - public static int maxSumSubseqNoAdjoin(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - if (arr.length == 1) { - return arr[0]; - } - if (arr.length == 2) { - return Math.max(arr[0], arr[1]); - } - // arr不止两个数 - int N = arr.length; - int[] dp = new int[N]; - // dp[i] 0...i 不能选相邻数的情况下,子序列的最大累加和 - // dp[N-1] 0..N-1 - dp[0] = arr[0]; - dp[1] = Math.max(arr[0], arr[1]); - for (int i = 2; i < N; i++) { - int p1 = dp[i - 1]; - int p2 = arr[i]; - int p3 = arr[i] + dp[i - 2]; - dp[i] = Math.max(Math.max(p1, p2), p3); - } - return dp[N - 1]; - } - - public static int subSqeMaxSumNoNext(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - if (arr.length == 1) { - return arr[0]; - } - int[] dp = new int[arr.length]; - // dp[i] : arr[0..i]挑选,满足不相邻设定的情况下,随意挑选,最大的累加和 - dp[0] = arr[0]; - dp[1] = Math.max(arr[0], arr[1]); - for (int i = 2; i < arr.length; i++) { - int p1 = dp[i - 1]; - int p2 = arr[i] + Math.max(dp[i - 2], 0); - dp[i] = Math.max(p1, p2); - } - return dp[arr.length - 1]; - } - - // 给定一个数组arr,在不能取相邻数的情况下,返回所有组合中的最大累加和 - // 思路: - // 定义dp[i] : 表示arr[0...i]范围上,在不能取相邻数的情况下,返回所有组合中的最大累加和 - // 在arr[0...i]范围上,在不能取相邻数的情况下,得到的最大累加和,可能性分类: - // 可能性 1) 选出的组合,不包含arr[i]。那么dp[i] = dp[i-1] - // 比如,arr[0...i] = {3,4,-4},最大累加和是不包含i位置数的时候 - // - // 可能性 2) 选出的组合,只包含arr[i]。那么dp[i] = arr[i] - // 比如,arr[0...i] = {-3,-4,4},最大累加和是只包含i位置数的时候 - // - // 可能性 3) 选出的组合,包含arr[i], 且包含arr[0...i-2]范围上的累加和。那么dp[i] = arr[i] + dp[i-2] - // 比如,arr[0...i] = {3,1,4},最大累加和是3和4组成的7,因为相邻不能选,所以i-1位置的数要跳过 - // - // 综上所述:dp[i] = Max { dp[i-1], arr[i] , arr[i] + dp[i-2] } - public static int maxSum(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int N = arr.length; - if (N == 1) { - return arr[0]; - } - if (N == 2) { - return Math.max(arr[0], arr[1]); - } - int[] dp = new int[N]; - dp[0] = arr[0]; - dp[1] = Math.max(arr[0], arr[1]); - for (int i = 2; i < N; i++) { - dp[i] = Math.max(Math.max(dp[i - 1], arr[i]), arr[i] + dp[i - 2]); - } - return dp[N - 1]; - } - - public static int[] randomArray(int N, int V) { - int[] ans = new int[N]; - - for (int i = 0; i < N; i++) { - ans[i] = (int) (Math.random() * V) - (V >> 1); - } - return ans; - } - - public static void main(String[] args) { - - } - -} diff --git a/公开课/class049/Code01_AppleMinBags.java b/公开课/class049/Code01_AppleMinBags.java deleted file mode 100644 index 11632cb..0000000 --- a/公开课/class049/Code01_AppleMinBags.java +++ /dev/null @@ -1,114 +0,0 @@ -package class049; - -public class Code01_AppleMinBags { - - public static int minBags1(int apple) { - if (apple < 0) { - return -1; - } - // apple 奇数 -1 - if ((apple & 1) != 0) { - return -1; - } - for (int bag8 = apple / 8; bag8 >= 0; bag8--) { - int already = (bag8 << 3); - int rest = apple - already; - if (rest % 6 == 0) { - return bag8 + rest / 6; - } - } - return -1; - } - - public static int minBags2(int apple) { - if (apple < 0) { - return -1; - } - // apple 奇数 -1 - if ((apple & 1) != 0) { - return -1; - } - if (apple == 0) { - return 0; - } - // apple必为偶数 - if (apple < 18) { - if (apple == 6 || apple == 8) { - return 1; - } - if (apple == 12 || apple == 14 || apple == 16) { - return 2; - } - return -1; - } - // apple >= 18; - int rest = apple - 18; - int i = rest / 8; - return i + 3; - } - - public static int minBag1(int apple) { - if (apple < 0) { - return -1; - } - if (apple == 0) { - return 0; - } - // 最多的8号袋开始试,apple / 8 - for (int max = (apple / 8); max >= 0; max--) { - int rest = apple - (max * 8); - if (rest % 6 == 0) { - return max + rest / 6; - } - } - return -1; - } - - public static int minBag2(int apple) { - if (apple < 18) { - if (apple < 0) { - return -1; - } - if (apple == 0) { - return 0; - } - if (apple == 6 || apple == 8) { - return 1; - } - if (apple == 12 || apple == 14 || apple == 16) { - return 2; - } - return -1; - } - int team = (apple - 18) / 8; - return (apple & 1) == 0 ? (team + 3) : -1; - } - - public static int minBagAwesome(int apple) { - if (apple < 0 || (apple & 1) != 0) { - return -1; - } - if (apple == 0) { - return 0; - } - if (apple < 18) { - if (apple == 6 || apple == 8) { - return 1; - } else if (apple == 12 || apple == 14 || apple == 16) { - return 2; - } else { - return -1; - } - } else { // apple >= 18 且 是偶数 - return (apple - 18) / 8 + 3; - } - } - - public static void main(String[] args) { - for (int apple = 0; apple <= 100; apple++) { - System.out.println(apple + " : " + minBags1(apple)); - } - - } - -} diff --git a/公开课/class049/Code02_SplitNumber.java b/公开课/class049/Code02_SplitNumber.java deleted file mode 100644 index 0d46fb3..0000000 --- a/公开课/class049/Code02_SplitNumber.java +++ /dev/null @@ -1,48 +0,0 @@ -package class049; - -public class Code02_SplitNumber { - - public static boolean isSplit1(int num) { - if (num <= 2) { - return false; - } - for (int start = 1; start < num; start++) { // 开始的最小数字 - int ans = start; - for (int next = start + 1; next < num; next++) { - if (ans + next > num) { - break; - } - if (ans + next == num) { - return true; - } - ans += next; - } - } - return false; - } - - public static boolean isSplit2(int num) { - // num > 0 - return num > 0 && (num & (num - 1)) != 0; - } - - public static void printNumberBinary(int num) { - for (int i = 31; i >= 0; i--) { - int status = (num & (1 << i)) != 0 ? 1 : 0; - System.out.print(status); - } - System.out.println(); - } - - public static void main(String[] args) { -// int num = 128; // 0...0111 -// printNumberBinary(num); -// -// printNumberBinary(num - 1); - - for (int i = 0; i < 100; i++) { - System.out.println(i + " : " + isSplit1(i)); - } - } - -} diff --git a/公开课/class049/Code03_EatGrass.java b/公开课/class049/Code03_EatGrass.java deleted file mode 100644 index faf11de..0000000 --- a/公开课/class049/Code03_EatGrass.java +++ /dev/null @@ -1,41 +0,0 @@ -package class049; - -public class Code03_EatGrass { - - public static String whoWin(int N) { - return who(N, "先手"); - } - - // int rest : 剩下多少草 - // String cur : "先手"、"后手" 表示,当前轮到谁 - // 返回:"先手"、"后手",最终谁会赢 - public static String who(int rest, String cur) { - if (rest == 0) { - return cur.equals("先手") ? "后手" : "先手"; - } - // 接下来,rest > 0, cur 将穷尽一切努力! - int pick = 1; - while (pick <= rest) { - if (cur.equals(who(rest - pick, cur.equals("先手") ? "后手" : "先手"))) { - return cur; - } - pick *= 4; - } - return cur.equals("先手") ? "后手" : "先手"; - } - - public static String winner2(int n) { - if (n % 5 == 0 || n % 5 == 2) { - return "后手"; - } else { - return "先手"; - } - } - - public static void main(String[] args) { - for (int i = 0; i <= 50; i++) { - System.out.println(i + " : " + whoWin(i)); - } - } - -} diff --git a/公开课/class050/Code01_HowManyTypes.java b/公开课/class050/Code01_HowManyTypes.java deleted file mode 100644 index 37fac50..0000000 --- a/公开课/class050/Code01_HowManyTypes.java +++ /dev/null @@ -1,83 +0,0 @@ -package class050; - -import java.util.HashSet; - -public class Code01_HowManyTypes { - - /* - * 只由小写字母(a~z)组成的一批字符串,都放在字符类型的数组String[] arr中, - * 如果其中某两个字符串,所含有的字符种类完全一样,就将两个字符串算作一类 比如:baacba和bac就算作一类 - * 虽然长度不一样,但是所含字符的种类完全一样(a、b、c) 返回arr中有多少类? - * - */ - - public static int types1(String[] arr) { - HashSet types = new HashSet<>(); - for (String str : arr) { - char[] chs = str.toCharArray(); - boolean[] map = new boolean[26]; - for (int i = 0; i < chs.length; i++) { - map[chs[i] - 'a'] = true; - } - String key = ""; - for (int i = 0; i < 26; i++) { - if (map[i]) { - key += String.valueOf((char) (i + 'a')); - } - } - types.add(key); - } - return types.size(); - } - - public static int types2(String[] arr) { - // 放整型的set - HashSet types = new HashSet<>(); - for (String str : arr) { - char[] chs = str.toCharArray(); - int key = 0; - for (int i = 0; i < chs.length; i++) { - key |= (1 << (chs[i] - 'a')); - } - types.add(key); - } - return types.size(); - } - - // for test - public static String[] getRandomStringArray(int possibilities, int strMaxSize, int arrMaxSize) { - String[] ans = new String[(int) (Math.random() * arrMaxSize) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = getRandomString(possibilities, strMaxSize); - } - return ans; - } - - // for test - public static String getRandomString(int possibilities, int strMaxSize) { - char[] ans = new char[(int) (Math.random() * strMaxSize) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (char) ((int) (Math.random() * possibilities) + 'a'); - } - return String.valueOf(ans); - } - - public static void main(String[] args) { -// int possibilities = 5; -// int strMaxSize = 10; -// int arrMaxSize = 100; -// int testTimes = 500000; -// System.out.println("test begin, test time : " + testTimes); -// for (int i = 0; i < testTimes; i++) { -// String[] arr = getRandomStringArray(possibilities, strMaxSize, arrMaxSize); -// int ans1 = types1(arr); -// int ans2 = types2(arr); -// if (ans1 != ans2) { -// System.out.println("Oops!"); -// } -// } -// System.out.println("test finish"); - - } - -} diff --git a/公开课/class050/Code02_CordCoverMaxPoint.java b/公开课/class050/Code02_CordCoverMaxPoint.java deleted file mode 100644 index 9b63b87..0000000 --- a/公开课/class050/Code02_CordCoverMaxPoint.java +++ /dev/null @@ -1,88 +0,0 @@ -package class050; - -import java.util.Arrays; - -public class Code02_CordCoverMaxPoint { - - public static int maxPoint1(int[] arr, int L) { - int res = 1; - for (int i = 0; i < arr.length; i++) { - int nearest = nearestIndex(arr, i, arr[i] - L); - res = Math.max(res, i - nearest + 1); - } - return res; - } - - public static int nearestIndex(int[] arr, int R, int value) { - int L = 0; - int index = R; - while (L <= R) { - int mid = L + ((R - L) >> 1); - if (arr[mid] >= value) { - index = mid; - R = mid - 1; - } else { - L = mid + 1; - } - } - return index; - } - - public static int maxPoint2(int[] arr, int L) { - int left = 0; - int right = 0; - int N = arr.length; - int max = 0; - while (left < N) { - while (right < N && arr[right] - arr[left] <= L) { - right++; - } - max = Math.max(max, right - (left++)); - } - return max; - } - - // for test - public static int test(int[] arr, int L) { - int max = 0; - for (int i = 0; i < arr.length; i++) { - int pre = i - 1; - while (pre >= 0 && arr[i] - arr[pre] <= L) { - pre--; - } - max = Math.max(max, i - pre); - } - return max; - } - - // for test - public static int[] generateArray(int len, int max) { - int[] ans = new int[(int) (Math.random() * len) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * max); - } - Arrays.sort(ans); - return ans; - } - - public static void main(String[] args) { - int len = 100; - int max = 1000; - int testTime = 100000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int L = (int) (Math.random() * max); - int[] arr = generateArray(len, max); - int ans1 = maxPoint1(arr, L); - int ans2 = maxPoint2(arr, L); - int ans3 = test(arr, L); - if (ans1 != ans2 || ans2 != ans3) { - System.out.println("oops!"); - break; - } - } - System.out.println("测试结束"); - - } - -} diff --git a/公开课/class050/Code03_FindHalfMajority.java b/公开课/class050/Code03_FindHalfMajority.java deleted file mode 100644 index 59ce2ac..0000000 --- a/公开课/class050/Code03_FindHalfMajority.java +++ /dev/null @@ -1,138 +0,0 @@ -package class050; - -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map.Entry; - -public class Code03_FindHalfMajority { - - public static int superWater(int[] arr) { - int candidate = 0; - int hp = 0; - for (int num : arr) { - if (hp == 0) { - candidate = num; - hp = 1; - } else if (num == candidate) { - hp++; - } else { - hp--; - } - } - if (hp == 0) { - return -1; - } - // hp!=0 , candidate - hp = 0; - for (int i = 0; i < arr.length; i++) { - if (arr[i] == candidate) { - hp++; - } - } - return hp > arr.length / 2 ? candidate : -1; - } - - // for test - public static int right(int[] arr) { - HashMap map = new HashMap<>(); - for (int cur : arr) { - if (!map.containsKey(cur)) { - map.put(cur, 0); - } - map.put(cur, map.get(cur) + 1); - } - for (Entry entry : map.entrySet()) { - if (entry.getValue() > arr.length / 2) { - return entry.getKey(); - } - } - return -1; - } - - // for test - public static int[] genareteRandomArray(int len, int max) { - int[] ans = new int[(int) (Math.random() * len) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * max) + 1; - } - return ans; - } - - public static void main(String[] args) { - int len = 100; - int max = 10; - int testTime = 100000; - System.out.println("test begin"); - for (int i = 0; i < testTime; i++) { - int[] arr = genareteRandomArray(len, max); - int ans1 = superWater(arr); - int ans2 = right(arr); - if (ans1 != ans2) { - System.out.println("Oops!"); - break; - } - } - System.out.println("test end"); - } - - public static void printKMajor(int[] arr, int K) { - if (K < 2) { - System.out.println("the value of K is invalid."); - return; - } - HashMap cands = new HashMap(); - for (int i = 0; i != arr.length; i++) { - if (cands.containsKey(arr[i])) { - cands.put(arr[i], cands.get(arr[i]) + 1); - } else { - if (cands.size() == K - 1) { - allCandsMinusOne(cands); - } else { - cands.put(arr[i], 1); - } - } - } - HashMap reals = getReals(arr, cands); - boolean hasPrint = false; - for (Entry set : cands.entrySet()) { - Integer key = set.getKey(); - if (reals.get(key) > arr.length / K) { - hasPrint = true; - System.out.print(key + " "); - } - } - System.out.println(hasPrint ? "" : "no such number."); - } - - public static void allCandsMinusOne(HashMap map) { - List removeList = new LinkedList(); - for (Entry set : map.entrySet()) { - Integer key = set.getKey(); - Integer value = set.getValue(); - if (value == 1) { - removeList.add(key); - } - map.put(key, value - 1); - } - for (Integer removeKey : removeList) { - map.remove(removeKey); - } - } - - public static HashMap getReals(int[] arr, HashMap cands) { - HashMap reals = new HashMap(); - for (int i = 0; i != arr.length; i++) { - int curNum = arr[i]; - if (cands.containsKey(curNum)) { - if (reals.containsKey(curNum)) { - reals.put(curNum, reals.get(curNum) + 1); - } else { - reals.put(curNum, 1); - } - } - } - return reals; - } - -} diff --git a/公开课/class050/Code04_ZigZagPrintMatrix.java b/公开课/class050/Code04_ZigZagPrintMatrix.java deleted file mode 100644 index ff40d95..0000000 --- a/公开课/class050/Code04_ZigZagPrintMatrix.java +++ /dev/null @@ -1,55 +0,0 @@ -package class050; - -public class Code04_ZigZagPrintMatrix { - - public static void printZigZag(int[][] m) { - int N = m.length; - int M = m[0].length; - int Ar = 0; - int Ac = 0; - int Br = 0; - int Bc = 0; - boolean up = true; - while (Ar != N) { - // B 左下角的点 A右上角的点 - print(m, Br, Bc, Ar, Ac, up); - up = !up; - Ar = Ac == M - 1 ? (Ar + 1) : Ar; - Ac = Ac == M - 1 ? Ac : (Ac + 1); - Bc = Br == N - 1 ? (Bc + 1) : Bc; - Br = (Br == N - 1) ? Br : (Br + 1); - } - } - - // (a,b)这个位置,一定在左下方 - // (c,d)这个位置,一定在右上方 - // (a,b) -> (c,d)是一条笔直的斜线! - // up == true, 请你从(a,b)打印到(c,d),斜线 - // up == false, 请你从(c,d)打印到(a,b),斜线 - public static void print(int[][] m, int a, int b, int c, int d, boolean up) { - if (up) { - for (;; a--, b++) { - System.out.print(m[a][b] + " "); - if (a == c && b == d) { - return; - } - } - } else { - for (;; c++, d--) { - System.out.print(m[c][d] + " "); - if (a == c && b == d) { - return; - } - } - } - } - - public static void main(String[] args) { - int[][] matrix = { - { 1, 2, 3, 4 }, - { 5, 6, 7, 8 }, - { 9, 10, 11, 12 } }; - printZigZag(matrix); - } - -} diff --git a/公开课/class050/Code05_RotateImage.java b/公开课/class050/Code05_RotateImage.java deleted file mode 100644 index ebfccf2..0000000 --- a/公开课/class050/Code05_RotateImage.java +++ /dev/null @@ -1,52 +0,0 @@ -package class050; - -public class Code05_RotateImage { - - public static void rotate(int[][] matrix) { - int a = 0; - int b = 0; - int c = matrix.length - 1; - int d = matrix[0].length - 1; - while (a < c) { // a>=c - rotateEdge(matrix, a++, b++, c--, d--); - } - } - - // 在二维数组m中,左上角点(a,b), 右下角点(c,d) - // 只在规定好的框上,顺时针转好 - public static void rotateEdge(int[][] m, int a, int b, int c, int d) { - int tmp = 0; - for (int i = 0; i < d - b; i++) { - tmp = m[a][b + i]; - m[a][b + i] = m[c - i][b]; - m[c - i][b] = m[c][d - i]; - m[c][d - i] = m[a + i][d]; - m[a + i][d] = tmp; - } - } - - public static void printMatrix(int[][] m) { - int N = m.length; - for (int i = 0; i < N; i++) { - for (int j = 0; j < N; j++) { - System.out.print(m[i][j] + " "); - } - System.out.println(); - } - } - - public static void main(String[] args) { - int[][] matrix = { - { 1, 2, 3 }, - { 4, 5, 6 }, - { 7, 8, 9 } }; - printMatrix(matrix); - System.out.println("========"); - - rotate(matrix); - printMatrix(matrix); - System.out.println("========"); - - } - -} diff --git a/公开课/class051/Code01_LongestNoRepeatSubstring.java b/公开课/class051/Code01_LongestNoRepeatSubstring.java deleted file mode 100644 index cdf9f32..0000000 --- a/公开课/class051/Code01_LongestNoRepeatSubstring.java +++ /dev/null @@ -1,124 +0,0 @@ -package class051; - -public class Code01_LongestNoRepeatSubstring { - - // 返回str的最长无重复字符子串长度 - public static int maxLen1(String str) { - if (str == null || str.length() == 0) { - return 0; - } - char[] s = str.toCharArray(); - int N = s.length; - int[] dp = new int[N]; // 0 dp[0] 1 dp[1] ... dp max - int[] map = new int[256];// a 上次出现的位置 b 0 ~ 255 - for (int i = 0; i < 256; i++) { - // i 字符的asc码 map[i] == -1 - map[i] = -1; - } - int ans = 1; - dp[0] = 1; - map[s[0]] = 0; - for (int i = 1; i < N; i++) { - // i [i]上次出现的位置,i距离 - int p1 = i - map[s[i]]; - int p2 = dp[i - 1] + 1; - dp[i] = Math.min(p1, p2); - map[s[i]] = i; - ans = Math.max(ans, dp[i]); - } - return ans; - } - - public static int maxLen2(String str) { - if (str == null || str.length() == 0) { - return 0; - } - char[] s = str.toCharArray(); - int N = s.length; - int[] map = new int[256]; - for (int i = 0; i < 256; i++) { - map[i] = -1; - } - int ans = 1; - int pre = 1; - map[s[0]] = 0; - for (int i = 1; i < N; i++) { - pre = Math.min(i - map[s[i]], pre + 1); - map[s[i]] = i; - ans = Math.max(ans, pre); - } - return ans; - } - - /* - * 给定一个只由小写字母(a~z)组成的字符串str, 返回其中最长无重复字符的子串长度 - * - */ - public static int lnrs1(String s) { - if (s == null || s.length() == 0) { - return 0; - } - char[] str = s.toCharArray(); - int N = str.length; - int max = 0; - for (int i = 0; i < N; i++) { - boolean[] set = new boolean[26]; - for (int j = i; j < N; j++) { - if (set[str[j] - 'a']) { - break; - } - set[str[j] - 'a'] = true; - max = Math.max(max, j - i + 1); - } - } - return max; - } - - public static int lnrs2(String s) { - if (s == null || s.length() == 0) { - return 0; - } - char[] str = s.toCharArray(); - int N = str.length; - int[] last = new int[26]; - for (int i = 0; i < 26; i++) { - last[i] = -1; - } - last[str[0] - 'a'] = 0; - int max = 1; - int preMaxLen = 1; - for (int i = 1; i < N; i++) { - preMaxLen = Math.min(i - last[str[i] - 'a'], preMaxLen + 1); - max = Math.max(max, preMaxLen); - last[str[i] - 'a'] = i; - } - return max; - } - - // for test - public static String getRandomString(int possibilities, int maxSize) { - char[] ans = new char[(int) (Math.random() * maxSize) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (char) ((int) (Math.random() * possibilities) + 'a'); - } - return String.valueOf(ans); - } - - public static void main(String[] args) { - int possibilities = 26; - int strMaxSize = 100; - int testTimes = 1000000; - System.out.println("test begin, test time : " + testTimes); - for (int i = 0; i < testTimes; i++) { - String str = getRandomString(possibilities, strMaxSize); - int ans1 = lnrs1(str); - int ans2 = maxLen2(str); - if (ans1 != ans2) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - - } - -} diff --git a/公开课/class051/Code02_CoverMax.java b/公开课/class051/Code02_CoverMax.java deleted file mode 100644 index 935ec3c..0000000 --- a/公开课/class051/Code02_CoverMax.java +++ /dev/null @@ -1,204 +0,0 @@ -package class051; - -import java.util.Arrays; -import java.util.Comparator; -import java.util.PriorityQueue; - -public class Code02_CoverMax { - - public static int maxCover1(int[][] lines) { - int min = Integer.MAX_VALUE; - int max = Integer.MIN_VALUE; - for (int i = 0; i < lines.length; i++) { - min = Math.min(min, lines[i][0]); - max = Math.max(max, lines[i][1]); - } - int cover = 0; - for (double p = min + 0.5; p < max; p += 1) { - int cur = 0; - for (int i = 0; i < lines.length; i++) { - if (lines[i][0] < p && lines[i][1] > p) { - cur++; - } - } - cover = Math.max(cover, cur); - } - return cover; - } - - public static int maxCover2(int[][] m) { - Line[] lines = new Line[m.length]; - for (int i = 0; i < m.length; i++) { - lines[i] = new Line(m[i][0], m[i][1]); - } - Arrays.sort(lines, new StartComparator()); - PriorityQueue heap = new PriorityQueue<>(); - int max = 0; - for (int i = 0; i < lines.length; i++) { - // lines[i] -> cur 在黑盒中,把<=cur.start 东西都弹出 - while (!heap.isEmpty() && heap.peek() <= lines[i].start) { - heap.poll(); - } - heap.add(lines[i].end); - max = Math.max(max, heap.size()); - } - return max; - } - - public static class Line { - public int start; - public int end; - - public Line(int s, int e) { - start = s; - end = e; - } - } - - public static class EndComparator implements Comparator { - - @Override - public int compare(Line o1, Line o2) { - return o1.end - o2.end; - } - - } - - public static class LineStartComparator implements Comparator { - - @Override - public int compare(Line o1, Line o2) { - return o1.start - o2.start; - } - - } - - public static int maxOver(int[][] ls) { - if (ls == null || ls.length == 0) { - return 0; - } - int N = ls.length; - Line[] lines = new Line[N]; - for (int i = 0; i < N; i++) { - lines[i] = new Line(ls[i][0], ls[i][1]); - } - // 把所有线段,根据开头位置排序 - Arrays.sort(lines, new LineStartComparator()); - PriorityQueue heap = new PriorityQueue<>(); - int ans = 0; - for (Line line : lines) { - int start = line.start; - int end = line.end; - while (!heap.isEmpty() && heap.peek() <= start) { - heap.poll(); - } - heap.add(end); - ans = Math.max(ans, heap.size()); - } - return ans; - } - - // for test - public static int[][] generateLines(int N, int L, int R) { - int size = (int) (Math.random() * N) + 1; - int[][] ans = new int[size][2]; - for (int i = 0; i < size; i++) { - int a = L + (int) (Math.random() * (R - L + 1)); - int b = L + (int) (Math.random() * (R - L + 1)); - if (a == b) { - b = a + 1; - } - ans[i][0] = Math.min(a, b); - ans[i][1] = Math.max(a, b); - } - return ans; - } - - public static class StartComparator implements Comparator { - - @Override - public int compare(Line o1, Line o2) { - return o1.start - o2.start; - } - - } - - public static void main(String[] args) { - -// Line l1 = new Line(4, 9); -// Line l2 = new Line(1, 4); -// Line l3 = new Line(7, 15); -// Line l4 = new Line(2, 4); -// Line l5 = new Line(4, 6); -// Line l6 = new Line(3, 7); -// -// Line[] lines = { l1, l2, l3, l4, l5, l6 }; -// Arrays.sort(lines, new StartComparator()); -// -// for (Line l : lines) { -// System.out.println(l.start + "," + l.end); -// } - -// // add peek poll O(logN) -// PriorityQueue heap = new PriorityQueue<>(); -// -// heap.add(6); -// -// // 6 -// System.out.println(heap.peek()); -// -// heap.add(3); -// // 3 6 -// System.out.println(heap.peek()); -// -// heap.add(9); -// // 3 6 9 -// System.out.println(heap.peek()); -// -// heap.add(3); -// // 3 3 6 9 -// heap.add(6); -// System.out.println("======"); -// // 3 3 6 6 9; -// while(!heap.isEmpty()) { -// System.out.println(heap.poll()); -// } - -// Line l1 = new Line(4, 9); -// Line l2 = new Line(1, 4); -// Line l3 = new Line(7, 15); -// Line l4 = new Line(2, 4); -// Line l5 = new Line(4, 6); -// Line l6 = new Line(3, 7); -// -// // 底层堆结构,heap -// PriorityQueue heap = new PriorityQueue<>(new StartComparator()); -// heap.add(l1); -// heap.add(l2); -// heap.add(l3); -// heap.add(l4); -// heap.add(l5); -// heap.add(l6); -// -// while (!heap.isEmpty()) { -// Line cur = heap.poll(); -// System.out.println(cur.start + "," + cur.end); -// } - - System.out.println("test begin"); - int N = 100; - int L = 0; - int R = 200; - int testTimes = 200000; - for (int i = 0; i < testTimes; i++) { - int[][] lines = generateLines(N, L, R); - int ans1 = maxCover1(lines); - int ans2 = maxOver(lines); - if (ans1 != ans2) { - System.out.println("Oops!"); - } - } - System.out.println("test end"); - } - -} diff --git a/公开课/class052/Code01_EvenTimesOddTimes.java b/公开课/class052/Code01_EvenTimesOddTimes.java deleted file mode 100644 index 265c71d..0000000 --- a/公开课/class052/Code01_EvenTimesOddTimes.java +++ /dev/null @@ -1,75 +0,0 @@ -package class052; - -public class Code01_EvenTimesOddTimes { - - public static void printOddTimesNum1(int[] arr) { - int eor = 0; - for (int i = 0; i < arr.length; i++) { - eor ^= arr[i]; - } - System.out.println(eor); - } - - public static void printOddTimesHas2Nums(int[] arr) { - int eor = 0; - for (int num : arr) { - eor ^= num; - } - // a和b,出现了奇数次 eor -> a ^ b - // eor : 0..000101011000 - // 最右的1: 0..000000001000 - // ~num + 1 -> -num - int mostRightOne = eor & (-eor); - int eor2 = 0; - for (int num : arr) { - // 第3位上有1的数字,异或进 eor2里 - if ((num & mostRightOne) != 0) { - eor2 ^= num; - } - } - System.out.println("找到的第一个是 : " + eor2); - System.out.println("找到的第二个是 : " + (eor ^ eor2)); - } - - public static void printOddTimesNum2(int[] arr) { - // arr中,a和b出现了奇数次,其他数都是偶数次 - int eor = 0; - for (int i = 0; i < arr.length; i++) { - eor ^= arr[i]; - } - // eor = a ^ b - // eor != 0 - // eor : 001100100 - // rightOne : 000000100 - int rightOne = eor & (~eor + 1); - int onlyOne = 0; // eor' - for (int i = 0; i < arr.length; i++) { - if ((arr[i] & rightOne) != 0) { - onlyOne ^= arr[i]; - } - } - // eor' = a or b - System.out.println(onlyOne + " " + (eor ^ onlyOne)); - } - - public static int bit1counts(int N) { - int count = 0; - while (N != 0) { - int rightOne = N & ((~N) + 1); - count++; - N -= rightOne; - } - return count; - } - - public static void main(String[] args) { - int[] arr1 = { 1500, 3, 1, 1500, 1, 1, 1500, 3, 1500 }; - // 3 3 1500 1500 1 1 1 - printOddTimesNum1(arr1); - - int[] arr = { 4, 3, 3, 4, 3, 3, 2, 5, 5, 5, 5, 2, 2, 1, 1, 5, 1, 2, 2, 2 }; - - printOddTimesHas2Nums(arr); - } - -} diff --git a/公开课/class052/Code02_KM.java b/公开课/class052/Code02_KM.java deleted file mode 100644 index 47089c3..0000000 --- a/公开课/class052/Code02_KM.java +++ /dev/null @@ -1,176 +0,0 @@ -package class052; - -import java.util.HashMap; -import java.util.HashSet; - -public class Code02_KM { - - public static int test(int[] arr, int k, int m) { - HashMap map = new HashMap<>(); - for (int num : arr) { - if (map.containsKey(num)) { - map.put(num, map.get(num) + 1); - } else { - map.put(num, 1); - } - } - for (int num : map.keySet()) { - if (map.get(num) == k) { - return num; - } - } - return -1; - } - - // 其他所有的数字都出现了M次,只有一种数,出现了K次 - // 请打印出现了K次的数,K < M - public static void find(int[] arr, int K, int M) { - // 1) 先遍历一遍数组,看看0,是不是出现了K次的数 - // 如果是,直接打印0 - - int[] tmp = new int[32]; - for (int num : arr) { - // 我要提取出,num的每一位 - for (int i = 31; i >= 0; i--) { - // 第i位如果是1,curbit = 1;第i位如果是0,curbit = 0; - int curbit = (num & (1 << i)) != 0 ? 1 : 0; - tmp[i] += curbit; - tmp[i] %= M; - } - } - // tmp 得到了! - int ans = 0; - for(int i = 31; i >=0 ;i--) { - // tmp[i]有没有数字剩下来! - // i位上,有数剩下来,has = 1 - // i位上,没有数剩下来,has = 0 - ans |= ((tmp[i] != 0 ? 1 : 0) << i); - } - System.out.println(ans); - // 打印ans - - - - - } - - public static HashMap map = new HashMap<>(); - - // 请保证arr中,只有一种数出现了K次,其他数都出现了M次 - public static int onlyKTimes(int[] arr, int k, int m) { - if (map.size() == 0) { - mapCreater(map); - } - int[] t = new int[32]; - // t[0] 0位置的1出现了几个 - // t[i] i位置的1出现了几个 - for (int num : arr) { - while (num != 0) { - int rightOne = num & (-num); - t[map.get(rightOne)]++; - num ^= rightOne; - } - } - int ans = 0; - for (int i = 0; i < 32; i++) { - if (t[i] % m != 0) { - if (t[i] % m == k) { - ans |= (1 << i); - } else { - return -1; - } - } - } - if (ans == 0) { - int count = 0; - for (int num : arr) { - if (num == 0) { - count++; - } - } - if (count != k) { - return -1; - } - } - return ans; - } - - public static void mapCreater(HashMap map) { - int value = 1; - for (int i = 0; i < 32; i++) { - map.put(value, i); - value <<= 1; - } - } - - public static int[] randomArray(int maxKinds, int range, int k, int m) { - int ktimeNum = randomNumber(range); - // 真命天子出现的次数 - int times = Math.random() < 0.5 ? k : ((int) (Math.random() * (m - 1)) + 1); - // 2 - int numKinds = (int) (Math.random() * maxKinds) + 2; - // k * 1 + (numKinds - 1) * m - int[] arr = new int[times + (numKinds - 1) * m]; - int index = 0; - for (; index < times; index++) { - arr[index] = ktimeNum; - } - numKinds--; - HashSet set = new HashSet<>(); - set.add(ktimeNum); - while (numKinds != 0) { - int curNum = 0; - do { - curNum = randomNumber(range); - } while (set.contains(curNum)); - set.add(curNum); - numKinds--; - for (int i = 0; i < m; i++) { - arr[index++] = curNum; - } - } - // arr 填好了 - for (int i = 0; i < arr.length; i++) { - // i 位置的数,我想随机和j位置的数做交换 - int j = (int) (Math.random() * arr.length);// 0 ~ N-1 - int tmp = arr[i]; - arr[i] = arr[j]; - arr[j] = tmp; - } - return arr; - } - - // [-range, +range] - public static int randomNumber(int range) { - return ((int) (Math.random() * range) + 1) - ((int) (Math.random() * range) + 1); - } - - public static void main(String[] args) { - int kinds = 5; - int range = 30; - int testTime = 100000; - int max = 9; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int a = (int) (Math.random() * max) + 1; // a 1 ~ 9 - int b = (int) (Math.random() * max) + 1; // b 1 ~ 9 - int k = Math.min(a, b); - int m = Math.max(a, b); - // k < m - if (k == m) { - m++; - } - int[] arr = randomArray(kinds, range, k, m); - int ans1 = test(arr, k, m); - int ans2 = onlyKTimes(arr, k, m); - if (ans1 != ans2) { - System.out.println(ans1); - System.out.println(ans2); - System.out.println("出错了!"); - } - } - System.out.println("测试结束"); - - } - -} diff --git a/公开课/class052/Code03_UglyNumber.java b/公开课/class052/Code03_UglyNumber.java deleted file mode 100644 index a3284ba..0000000 --- a/公开课/class052/Code03_UglyNumber.java +++ /dev/null @@ -1,63 +0,0 @@ -package class052; - -// 测试链接:https://leetcode.com/problems/ugly-number-ii -public class Code03_UglyNumber { - - public static boolean isUgly(int num) { - while (num % 2 == 0) { - num /= 2; - } - while (num % 3 == 0) { - num /= 3; - } - while (num % 5 == 0) { - num /= 5; - } - return num == 1; - } - - public static int nthUglyNumber1(int n) { - int find = 0; - int num = 1; - for (; find < n; num++) { - if (isUgly(num)) { - find++; - } - } - return num - 1; - } - - - - - - - - - public static int nthUglyNumber2(int n) { - int[] ugly = new int[n + 1]; - // ugly[0] 不用了,废掉 - ugly[1] = 1; - int i2 = 1; - int i3 = 1; - int i5 = 1; - for (int i = 2; i <= n; i++) { - ugly[i] = Math.min(Math.min(ugly[i2] * 2, ugly[i3] * 3), ugly[i5] * 5); - if (ugly[i] == ugly[i2] * 2) { - i2++; - } - if (ugly[i] == ugly[i3] * 3) { - i3++; - } - if (ugly[i] == ugly[i5] * 5) { - i5++; - } - } - return ugly[n]; - } - - public static void main(String[] args) { - System.out.println(nthUglyNumber2(10000)); - } - -} diff --git a/公开课/class052/Code04_MakeNo.java b/公开课/class052/Code04_MakeNo.java deleted file mode 100644 index b687a5f..0000000 --- a/公开课/class052/Code04_MakeNo.java +++ /dev/null @@ -1,52 +0,0 @@ -package class052; - -public class Code04_MakeNo { - - public static int[] makeNo(int N) { - if (N == 1) { - return new int[] { 1 }; - } - // N -> 一半 - // N = 7 -> 4 - int halfSize = (N + 1) / 2; - int[] base = makeNo(halfSize); - int[] ans = new int[N]; - int index = 0; - for (; index < halfSize; index++) { - ans[index] = base[index] * 2 + 1; - } - for (int i = 0; index < N; index++, i++) { - ans[index] = base[i] * 2; - } - return ans; - } - - // 检验函数 - public static boolean isValid(int[] arr) { - int N = arr.length; - for (int i = 0; i < N; i++) { - for (int k = i + 1; k < N; k++) { - for (int j = k + 1; j < N; j++) { - if (arr[i] + arr[j] == 2 * arr[k]) { - return false; - } - } - } - } - return true; - } - - public static void main(String[] args) { - System.out.println("test begin"); - for (int N = 1; N < 1000; N++) { - int[] arr = makeNo(N); - if (!isValid(arr)) { - System.out.println("Oops!"); - } - } - System.out.println("test end"); - System.out.println(isValid(makeNo(1042))); - System.out.println(isValid(makeNo(2981))); - } - -} diff --git a/公开课/class053/Code01_BestTimeToBuyAndSellStock.java b/公开课/class053/Code01_BestTimeToBuyAndSellStock.java deleted file mode 100644 index 22e1c38..0000000 --- a/公开课/class053/Code01_BestTimeToBuyAndSellStock.java +++ /dev/null @@ -1,18 +0,0 @@ -package class053; - -public class Code01_BestTimeToBuyAndSellStock { - - public static int maxProfit(int[] prices) { - if (prices == null || prices.length == 0) { - return 0; - } - int ans = 0; - int min = prices[0]; - for (int i = 1; i < prices.length; i++) { - min = Math.min(min, prices[i]); - ans = Math.max(ans, prices[i] - min); - } - return ans; - } - -} diff --git a/公开课/class053/Code02_BestTimeToBuyAndSellStockII.java b/公开课/class053/Code02_BestTimeToBuyAndSellStockII.java deleted file mode 100644 index bc5d22a..0000000 --- a/公开课/class053/Code02_BestTimeToBuyAndSellStockII.java +++ /dev/null @@ -1,17 +0,0 @@ -package class053; - -//leetcode 122 -public class Code02_BestTimeToBuyAndSellStockII { - - public static int maxProfit(int[] prices) { - if (prices == null || prices.length == 0) { - return 0; - } - int ans = 0; - for (int i = 1; i < prices.length; i++) { - ans += Math.max(prices[i] - prices[i-1], 0); - } - return ans; - } - -} diff --git a/公开课/class053/Code03_BestTimeToBuyAndSellStockIII.java b/公开课/class053/Code03_BestTimeToBuyAndSellStockIII.java deleted file mode 100644 index 1e3c7d7..0000000 --- a/公开课/class053/Code03_BestTimeToBuyAndSellStockIII.java +++ /dev/null @@ -1,23 +0,0 @@ -package class053; - -//leetcode 123 -public class Code03_BestTimeToBuyAndSellStockIII { - - public static int maxProfit(int[] prices) { - if (prices == null || prices.length < 2) { - return 0; - } - int ans = 0; - int doneOnceMinusBuyMax = -prices[0]; - int doneOnceMax = 0; - int min = prices[0]; - for (int i = 1; i < prices.length; i++) { - min = Math.min(min, prices[i]); - ans = Math.max(ans, doneOnceMinusBuyMax + prices[i]); - doneOnceMax = Math.max(doneOnceMax, prices[i] - min); - doneOnceMinusBuyMax = Math.max(doneOnceMinusBuyMax, doneOnceMax - prices[i]); - } - return ans; - } - -} diff --git a/公开课/class053/Code04_RabbitsInForest.java b/公开课/class053/Code04_RabbitsInForest.java deleted file mode 100644 index 025cb5c..0000000 --- a/公开课/class053/Code04_RabbitsInForest.java +++ /dev/null @@ -1,28 +0,0 @@ -package class053; - -import java.util.Arrays; - -public class Code04_RabbitsInForest { - - public static int numRabbits(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - Arrays.sort(arr); - int x = arr[0]; - int c = 1; - int ans = 0; - for (int i = 1; i < arr.length; i++) { - if (x != arr[i]) { - ans += ((c + x) / (x + 1)) * (x + 1); - x = arr[i]; - c = 1; - } else { - c++; - } - } - return ans + ((c + x) / (x + 1)) * (x + 1); - } - - -} diff --git a/公开课/class053/Code05_LIS.java b/公开课/class053/Code05_LIS.java deleted file mode 100644 index b8b91f2..0000000 --- a/公开课/class053/Code05_LIS.java +++ /dev/null @@ -1,58 +0,0 @@ -package class053; - -// 本题测试链接 : https://leetcode.com/problems/longest-increasing-subsequence -public class Code05_LIS { - - // 时间复杂度O(N^2) - public static int maxLen(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int N = arr.length; - int[] dp = new int[N]; - dp[0] = 1; - int max = 1; - for (int i = 1; i < N; i++) { - dp[i] = 1; - int preMax = 0; - for (int j = 0; j < i; j++) { - if (arr[j] < arr[i]) { - preMax = Math.max(preMax, dp[j]); - } - } - dp[i] = Math.max(dp[i], preMax + 1); - max = Math.max(max, dp[i]); - } - return max; - } - - public static int lengthOfLIS(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int[] ends = new int[arr.length]; - ends[0] = arr[0]; - int right = 0; - int l = 0; - int r = 0; - int m = 0; - int max = 1; - for (int i = 1; i < arr.length; i++) { - l = 0; - r = right; - while (l <= r) { - m = (l + r) / 2; - if (arr[i] > ends[m]) { - l = m + 1; - } else { - r = m - 1; - } - } - right = Math.max(right, l); - ends[l] = arr[i]; - max = Math.max(max, l + 1); - } - return max; - } - -} \ No newline at end of file diff --git a/公开课/class053/Code06_EnvelopesProblem.java b/公开课/class053/Code06_EnvelopesProblem.java deleted file mode 100644 index 0a0719a..0000000 --- a/公开课/class053/Code06_EnvelopesProblem.java +++ /dev/null @@ -1,60 +0,0 @@ -package class053; - -import java.util.Arrays; -import java.util.Comparator; - -// 本题测试链接 : https://leetcode.com/problems/russian-doll-envelopes/ -public class Code06_EnvelopesProblem { - - public static int maxEnvelopes(int[][] matrix) { - Envelope[] arr = sort(matrix); - int[] ends = new int[matrix.length]; - ends[0] = arr[0].h; - int right = 0; - int l = 0; - int r = 0; - int m = 0; - for (int i = 1; i < arr.length; i++) { - l = 0; - r = right; - while (l <= r) { - m = (l + r) / 2; - if (arr[i].h > ends[m]) { - l = m + 1; - } else { - r = m - 1; - } - } - right = Math.max(right, l); - ends[l] = arr[i].h; - } - return right + 1; - } - - public static class Envelope { - public int l; - public int h; - - public Envelope(int weight, int hight) { - l = weight; - h = hight; - } - } - - public static class EnvelopeComparator implements Comparator { - @Override - public int compare(Envelope o1, Envelope o2) { - return o1.l != o2.l ? o1.l - o2.l : o2.h - o1.h; - } - } - - public static Envelope[] sort(int[][] matrix) { - Envelope[] res = new Envelope[matrix.length]; - for (int i = 0; i < matrix.length; i++) { - res[i] = new Envelope(matrix[i][0], matrix[i][1]); - } - Arrays.sort(res, new EnvelopeComparator()); - return res; - } - -} diff --git a/公开课/class054/Code01_FindHalfMajority.java b/公开课/class054/Code01_FindHalfMajority.java deleted file mode 100644 index 6763c84..0000000 --- a/公开课/class054/Code01_FindHalfMajority.java +++ /dev/null @@ -1,104 +0,0 @@ -package class054; - -import java.util.HashMap; -import java.util.Map.Entry; - -public class Code01_FindHalfMajority { - - // 时间复杂度O(N),额外空间复杂度O(1) - // [1,5,2,5,3,5] - public static int find(int[] arr) { - int target = 0; - int hp = 0; - for (int num : arr) { - if (hp == 0) { - target = num; - hp = 1; - } else if (num != target) { - hp--; - } else { - hp++; - } - } - if (hp == 0) { - return -1; - } - // hp > 0, target - hp = 0; - for (int num : arr) { - if (num == target) { - hp++; - } - } - return hp > arr.length / 2 ? target : -1; - } - - public static int halfMajor(int[] arr) { - int target = 0; - int HP = 0; - for (int i = 0; i != arr.length; i++) { - if (HP == 0) { - target = arr[i]; - HP = 1; - } else if (arr[i] == target) { - HP++; - } else { - HP--; - } - } - if (HP == 0) { - return -1; - } - HP = 0; - for (int i = 0; i != arr.length; i++) { - if (arr[i] == target) { - HP++; - } - } - return HP > arr.length / 2 ? target : -1; - } - - // for test - public static int right(int[] arr) { - HashMap map = new HashMap<>(); - for (int cur : arr) { - if (!map.containsKey(cur)) { - map.put(cur, 0); - } - map.put(cur, map.get(cur) + 1); - } - for (Entry entry : map.entrySet()) { - if (entry.getValue() > arr.length / 2) { - return entry.getKey(); - } - } - return -1; - } - - // for test - public static int[] genareteRandomArray(int len, int max) { - int[] ans = new int[(int) (Math.random() * len) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * max) + 1; - } - return ans; - } - - public static void main(String[] args) { - int len = 100; - int max = 10; - int testTime = 100000; - System.out.println("test begin"); - for (int i = 0; i < testTime; i++) { - int[] arr = genareteRandomArray(len, max); - int ans1 = halfMajor(arr); - int ans2 = right(arr); - if (ans1 != ans2) { - System.out.println("Oops!"); - break; - } - } - System.out.println("test end"); - } - -} diff --git a/公开课/class054/Code02_PalindromeNumber.java b/公开课/class054/Code02_PalindromeNumber.java deleted file mode 100644 index d1765c8..0000000 --- a/公开课/class054/Code02_PalindromeNumber.java +++ /dev/null @@ -1,30 +0,0 @@ -package class054; - -public class Code02_PalindromeNumber { - - public static boolean isPalindrome(int n) { - if (n < 0) { - return false; - } - int tmp = 1; - // num = 7654567 - // tmp = 1000000 - while (n / tmp >= 10) { - tmp *= 10; - } - while (n != 0) { - if (n / tmp != n % 10) { - return false; - } - // num = 7654567 - // tmp = 1000000 - // n%t = 654567 - // /10 = 65456 - // = 10000 - n = (n % tmp) / 10; - tmp /= 100; - } - return true; - } - -} diff --git a/公开课/class054/Code03_Water.java b/公开课/class054/Code03_Water.java deleted file mode 100644 index 863ec5a..0000000 --- a/公开课/class054/Code03_Water.java +++ /dev/null @@ -1,120 +0,0 @@ -package class054; - -public class Code03_Water { - - // 本题测试链接:https://leetcode.com/problems/trapping-rain-water/ - // 给定一个正整数数组arr,把arr想象成一个直方图。返回这个直方图如果装水,能装下几格水? - public static int water1(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - // O位置无水量 - // 0~N-1,N-1无水量 - int N = arr.length; - int water = 0; - for (int i = 1; i < N - 1; i++) { - int leftMax = Integer.MIN_VALUE; - for (int j = 0; j < i; j++) { - leftMax = Math.max(leftMax, arr[j]); - } - int rightMax = Integer.MIN_VALUE; - for (int j = i + 1; j < N; j++) { - rightMax = Math.max(rightMax, arr[j]); - } - water += Math.max(Math.min(leftMax, rightMax) - arr[i], 0); - } - return water; - } - - public static int water2(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int[] leftMaxs = new int[N]; - leftMaxs[0] = arr[0]; - for (int i = 1; i < N; i++) { - leftMaxs[i] = Math.max(leftMaxs[i - 1], arr[i]); - } - - int[] rightMaxs = new int[N]; - rightMaxs[N - 1] = arr[N - 1]; - for (int i = N - 2; i >= 0; i--) { - rightMaxs[i] = Math.max(rightMaxs[i + 1], arr[i]); - } - int water = 0; - for (int i = 1; i < N - 1; i++) { - water += Math.max(Math.min(leftMaxs[i - 1], rightMaxs[i + 1]) - arr[i], 0); - } - return water; - } - - public static int water3(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int[] rightMaxs = new int[N]; - rightMaxs[N - 1] = arr[N - 1]; - for (int i = N - 2; i >= 0; i--) { - rightMaxs[i] = Math.max(rightMaxs[i + 1], arr[i]); - } - int water = 0; - int leftMax = arr[0]; - for (int i = 1; i < N - 1; i++) { - water += Math.max(Math.min(leftMax, rightMaxs[i + 1]) - arr[i], 0); - leftMax = Math.max(leftMax, arr[i]); - } - return water; - } - - public static int water4(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int L = 1; - int leftMax = arr[0]; - int R = N - 2; - int rightMax = arr[N - 1]; - int water = 0; - while (L <= R) { - if (leftMax <= rightMax) { - water += Math.max(0, leftMax - arr[L]); - leftMax = Math.max(leftMax, arr[L++]); - } else { - water += Math.max(0, rightMax - arr[R]); - rightMax = Math.max(rightMax, arr[R--]); - } - } - return water; - } - - // for test - public static int[] generateRandomArray(int len, int value) { - int[] ans = new int[(int) (Math.random() * len) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * value) + 1; - } - return ans; - } - - public static void main(String[] args) { - int len = 100; - int value = 200; - int testTimes = 100000; - System.out.println("test begin"); - for (int i = 0; i < testTimes; i++) { - int[] arr = generateRandomArray(len, value); - int ans1 = water1(arr); - int ans2 = water2(arr); - int ans3 = water3(arr); - int ans4 = water4(arr); - if (ans1 != ans2 || ans3 != ans4 || ans1 != ans3) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - } - -} diff --git a/公开课/class054/Code04_JumpGameII.java b/公开课/class054/Code04_JumpGameII.java deleted file mode 100644 index b1ed486..0000000 --- a/公开课/class054/Code04_JumpGameII.java +++ /dev/null @@ -1,24 +0,0 @@ -package class054; - -// 测试页面:https://leetcode.com/problems/jump-game-ii/ -public class Code04_JumpGameII { - - public static int jump(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - // 一开始,人在0位置,一步都没有跳过 - int jump = 0; - int cur = 0; - int next = arr[0]; - for (int i = 1; i < arr.length; i++) { - if(cur < i) { - jump++; - cur = next; - } - next = Math.max(next, i + arr[i]); - } - return jump; - } - -} diff --git a/公开课/class055/Code01_LongestNoRepeatSubstring.java b/公开课/class055/Code01_LongestNoRepeatSubstring.java deleted file mode 100644 index 4350268..0000000 --- a/公开课/class055/Code01_LongestNoRepeatSubstring.java +++ /dev/null @@ -1,26 +0,0 @@ -package class055; - -// 链接 : https://leetcode.com/problems/longest-substring-without-repeating-characters/ -public class Code01_LongestNoRepeatSubstring { - - public static int lengthOfLongestSubstring(String s) { - if (s == null || s.length() == 0) { - return 0; - } - char[] str = s.toCharArray(); - int[] map = new int[256]; - for (int i = 0; i < 256; i++) { - map[i] = -1; - } - map[str[0]] = 0; - int pre = 1; - int ans = 1; - for (int i = 1; i < str.length; i++) { - pre = Math.min(i - map[str[i]], pre + 1); - ans = Math.max(ans, pre); - map[str[i]] = i; - } - return ans; - } - -} diff --git a/公开课/class055/Code02_SubArrayMaxSum.java b/公开课/class055/Code02_SubArrayMaxSum.java deleted file mode 100644 index 0903c4a..0000000 --- a/公开课/class055/Code02_SubArrayMaxSum.java +++ /dev/null @@ -1,22 +0,0 @@ -package class055; - -// 本题测试链接 : https://leetcode.com/problems/maximum-subarray/ -public class Code02_SubArrayMaxSum { - - public static int maxSubArray(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int N = arr.length; - int pre = arr[0]; // 上一步的答案 - int ans = pre; - for (int i = 1; i < N; i++) { - // 子数组必须以i位置的数结尾的情况下,最大累加和是多少 - // arr[i] pre + arr[i] - pre = Math.max(arr[i], pre + arr[i]); - ans = Math.max(ans, pre); - } - return ans; - } - -} diff --git a/公开课/class055/Code03_MaximumProductSubarray.java b/公开课/class055/Code03_MaximumProductSubarray.java deleted file mode 100644 index c037c50..0000000 --- a/公开课/class055/Code03_MaximumProductSubarray.java +++ /dev/null @@ -1,40 +0,0 @@ -package class055; - -// 本次测试链接 : https://leetcode.com/problems/maximum-product-subarray/ -public class Code03_MaximumProductSubarray { - - public static double max(double[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - double premax = arr[0]; - double premin = arr[0]; - double ans = arr[0]; - for (int i = 1; i < arr.length; i++) { - double p1 = arr[i]; - double p2 = arr[i] * premax; - double p3 = arr[i] * premin; - double curmax = Math.max(Math.max(p1, p2), p3); - double curmin = Math.min(Math.min(p1, p2), p3); - ans = Math.max(ans, curmax); - premax = curmax; - premin = curmin; - } - return ans; - } - - public static int maxProduct(int[] nums) { - int ans = nums[0]; - int min = nums[0]; - int max = nums[0]; - for (int i = 1; i < nums.length; i++) { - int curmin = Math.min(nums[i], Math.min(min * nums[i], max * nums[i])); - int curmax = Math.max(nums[i], Math.max(min * nums[i], max * nums[i])); - min = curmin; - max = curmax; - ans = Math.max(ans, max); - } - return ans; - } - -} diff --git a/公开课/class055/Code04_PaperFolding.java b/公开课/class055/Code04_PaperFolding.java deleted file mode 100644 index 77fd039..0000000 --- a/公开课/class055/Code04_PaperFolding.java +++ /dev/null @@ -1,26 +0,0 @@ -package class055; - -public class Code04_PaperFolding { - - public static void printAllFolds(int N) { - process(1, N, true); - System.out.println(); - } - - // 想象中的节点,在第i层 - // N,最多有多少层,固定参数 - // 想象中的节点,是凸还是凹,down = true 凹 down = false 凸 - public static void process(int i, int N, boolean down) { - if (i > N) { - return; - } - process(i + 1, N, true); - System.out.print(down ? "凹 " : "凸 "); - process(i + 1, N, false); - } - - public static void main(String[] args) { - int N = 3; - printAllFolds(N); - } -} diff --git a/公开课/class056/Code01_MissingNumber.java b/公开课/class056/Code01_MissingNumber.java deleted file mode 100644 index 4c87618..0000000 --- a/公开课/class056/Code01_MissingNumber.java +++ /dev/null @@ -1,34 +0,0 @@ -package class056; - -// 测试链接:https://leetcode.com/problems/first-missing-positive/ -public class Code01_MissingNumber { - - public static int firstMissingPositive(int[] arr) { - int l = 0; // l的左边,每一个位置i,上面都放着i+1这个数 - // 最好预期:1~r每个数字收集全,且只收集一次 - // 垃圾区:r.... - int r = arr.length; - while (l != r) { - if (arr[l] == l + 1) { - l++; - } else if (arr[l] <= l || arr[l] > r || arr[arr[l] - 1] == arr[l]) { - // [l] = 83 - // 83应该放在82位置 - // arr [ arr[l] - 1 ] = arr[l] - // arr[82] = 83 - // 此时的arr[l]是垃圾 - swap(arr, l, --r); - } else { // l上面的数不是l+1 l上面的数也不是垃圾 - swap(arr, l, arr[l] - 1); - } - } - return l + 1; - } - - public static void swap(int[] arr, int i, int j) { - int tmp = arr[i]; - arr[i] = arr[j]; - arr[j] = tmp; - } - -} diff --git a/公开课/class056/Code02_RabbitsInForest.java b/公开课/class056/Code02_RabbitsInForest.java deleted file mode 100644 index 9a96dd8..0000000 --- a/公开课/class056/Code02_RabbitsInForest.java +++ /dev/null @@ -1,30 +0,0 @@ -package class056; - -import java.util.Arrays; - -public class Code02_RabbitsInForest { - - public static int numRabbits(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - Arrays.sort(arr); - int x = arr[0]; - int k = 1; - int ans = 0; - for (int i = 1; i < arr.length; i++) { - if (x != arr[i]) { - // (k / (x + 1)) 上 * (x+1) - // (k + x + 1 - 1) / (x + 1) - // (k + x) / (x + 1) (x + 1) - ans += ((k + x) / (x + 1)) * (x + 1); - x = arr[i]; - k = 1; - } else { - k++; - } - } - return ans + ((k + x) / (x + 1)) * (x + 1); - } - -} diff --git a/公开课/class056/Code03_LIS.java b/公开课/class056/Code03_LIS.java deleted file mode 100644 index 5eac4eb..0000000 --- a/公开课/class056/Code03_LIS.java +++ /dev/null @@ -1,58 +0,0 @@ -package class056; - -// 本题测试链接 : https://leetcode.com/problems/longest-increasing-subsequence -public class Code03_LIS { - - // 时间复杂度O(N^2) - public static int maxLen(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int N = arr.length; - int[] dp = new int[N]; - dp[0] = 1; - int max = 1; - for (int i = 1; i < N; i++) { - dp[i] = 1; - int preMax = 0; - for (int j = 0; j < i; j++) { - if (arr[j] < arr[i]) { - preMax = Math.max(preMax, dp[j]); - } - } - dp[i] = Math.max(dp[i], preMax + 1); - max = Math.max(max, dp[i]); - } - return max; - } - - public static int lengthOfLIS(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int[] ends = new int[arr.length]; - ends[0] = arr[0]; - int right = 0; - int l = 0; - int r = 0; - int m = 0; - int max = 1; - for (int i = 1; i < arr.length; i++) { - l = 0; - r = right; - while (l <= r) { - m = (l + r) / 2; - if (arr[i] > ends[m]) { - l = m + 1; - } else { - r = m - 1; - } - } - right = Math.max(right, l); - ends[l] = arr[i]; - max = Math.max(max, l + 1); - } - return max; - } - -} \ No newline at end of file diff --git a/公开课/class056/Code04_EnvelopesProblem.java b/公开课/class056/Code04_EnvelopesProblem.java deleted file mode 100644 index 977ad79..0000000 --- a/公开课/class056/Code04_EnvelopesProblem.java +++ /dev/null @@ -1,60 +0,0 @@ -package class056; - -import java.util.Arrays; -import java.util.Comparator; - -// 本题测试链接 : https://leetcode.com/problems/russian-doll-envelopes/ -public class Code04_EnvelopesProblem { - - public static int maxEnvelopes(int[][] matrix) { - Envelope[] arr = sort(matrix); - int[] ends = new int[matrix.length]; - ends[0] = arr[0].h; - int right = 0; - int l = 0; - int r = 0; - int m = 0; - for (int i = 1; i < arr.length; i++) { - l = 0; - r = right; - while (l <= r) { - m = (l + r) / 2; - if (arr[i].h > ends[m]) { - l = m + 1; - } else { - r = m - 1; - } - } - right = Math.max(right, l); - ends[l] = arr[i].h; - } - return right + 1; - } - - public static class Envelope { - public int l; - public int h; - - public Envelope(int weight, int hight) { - l = weight; - h = hight; - } - } - - public static class EnvelopeComparator implements Comparator { - @Override - public int compare(Envelope o1, Envelope o2) { - return o1.l != o2.l ? o1.l - o2.l : o2.h - o1.h; - } - } - - public static Envelope[] sort(int[][] matrix) { - Envelope[] res = new Envelope[matrix.length]; - for (int i = 0; i < matrix.length; i++) { - res[i] = new Envelope(matrix[i][0], matrix[i][1]); - } - Arrays.sort(res, new EnvelopeComparator()); - return res; - } - -} diff --git a/公开课/class057/Code01_MagicStone.java b/公开课/class057/Code01_MagicStone.java deleted file mode 100644 index 79c20a8..0000000 --- a/公开课/class057/Code01_MagicStone.java +++ /dev/null @@ -1,49 +0,0 @@ -package class057; - -import java.util.Arrays; - -// 来自小红书 -// [0,4,7] : 0表示这里石头没有颜色,如果变红代价是4,如果变蓝代价是7 -// [1,X,X] : 1表示这里石头已经是红,而且不能改颜色,所以后两个数X无意义 -// [2,X,X] : 2表示这里石头已经是蓝,而且不能改颜色,所以后两个数X无意义 -// 颜色只可能是0、1、2,代价一定>=0 -// 给你一批这样的小数组,要求最后必须所有石头都有颜色,且红色和蓝色一样多,返回最小代价 -// 如果怎么都无法做到所有石头都有颜色、且红色和蓝色一样多,返回-1 -public class Code01_MagicStone { - - public static int minCost(int[][] stones) { - int n = stones.length; - if ((n & 1) != 0) { - return -1; - } - Arrays.sort(stones, (a, b) -> a[0] == 0 && b[0] == 0 ? (b[1] - b[2] - a[1] + a[2]) : (a[0] - b[0])); - int zero = 0; - int red = 0; - int blue = 0; - int cost = 0; - for (int i = 0; i < n; i++) { - if (stones[i][0] == 0) { - zero++; - cost += stones[i][1]; - } else if (stones[i][0] == 1) { - red++; - } else { - blue++; - } - } - if (red > (n >> 1) || blue > (n >> 1)) { - return -1; - } - blue = zero - ((n >> 1) - red); - for (int i = 0; i < blue; i++) { - cost += stones[i][2] - stones[i][1]; - } - return cost; - } - - public static void main(String[] args) { - int[][] stones = { { 1, 5, 3 }, { 2, 7, 9 }, { 0, 6, 4 }, { 0, 7, 9 }, { 0, 2, 1 }, { 0, 5, 9 } }; - System.out.println(minCost(stones)); - } - -} diff --git a/公开课/class057/Code02_CircleCandy.java b/公开课/class057/Code02_CircleCandy.java deleted file mode 100644 index f6242af..0000000 --- a/公开课/class057/Code02_CircleCandy.java +++ /dev/null @@ -1,58 +0,0 @@ -package class057; - -// 来自网易 -// 给定一个正数数组arr,表示每个小朋友的得分 -// 任何两个相邻的小朋友,如果得分一样,怎么分糖果无所谓,但如果得分不一样,分数大的一定要比分数少的多拿一些糖果 -// 假设所有的小朋友坐成一个环形,返回在不破坏上一条规则的情况下,需要的最少糖果数 -public class Code02_CircleCandy { - - public static int minCandy(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - if (arr.length == 1) { - return 1; - } - int n = arr.length; - int minIndex = 0; - for (int i = 0; i < n; i++) { - if (arr[i] <= arr[lastIndex(i, n)] && arr[i] <= arr[nextIndex(i, n)]) { - minIndex = i; - break; - } - } - int[] nums = new int[n + 1]; - for (int i = 0; i <= n; i++, minIndex = nextIndex(minIndex, n)) { - nums[i] = arr[minIndex]; - } - int[] left = new int[n + 1]; - left[0] = 1; - for (int i = 1; i <= n; i++) { - left[i] = nums[i] > nums[i - 1] ? (left[i - 1] + 1) : 1; - } - int[] right = new int[n + 1]; - right[n] = 1; - for (int i = n - 1; i >= 0; i--) { - right[i] = nums[i] > nums[i + 1] ? (right[i + 1] + 1) : 1; - } - int ans = 0; - for (int i = 0; i < n; i++) { - ans += Math.max(left[i], right[i]); - } - return ans; - } - - public static int nextIndex(int i, int n) { - return i == n - 1 ? 0 : (i + 1); - } - - public static int lastIndex(int i, int n) { - return i == 0 ? (n - 1) : (i - 1); - } - - public static void main(String[] args) { - int[] arr = { 3, 4, 2, 3, 2 }; - System.out.println(minCandy(arr)); - } - -} diff --git a/公开课/class057/Code03_ComputeExpressionValue.java b/公开课/class057/Code03_ComputeExpressionValue.java deleted file mode 100644 index 98d24da..0000000 --- a/公开课/class057/Code03_ComputeExpressionValue.java +++ /dev/null @@ -1,58 +0,0 @@ -package class057; - -// 来自美团 -// () 分值为2 -// (()) 分值为3 -// ((())) 分值为4 -// 也就是说,每包裹一层,分数就是里面的分值+1 -// ()() 分值为2 * 2 -// (())() 分值为3 * 2 -// 也就是说,每连接一段,分数就是各部分相乘,以下是一个结合起来的例子 -// (()())()(()) -> (2 * 2 + 1) * 2 * 3 -> 30 -// 给定一个括号字符串str,已知str一定是正确的括号结合,不会有违规嵌套 -// 返回分数 -public class Code03_ComputeExpressionValue { - - public static int sores(String s) { - return compute(s.toCharArray(), 0)[0]; - } - - // s[i.....]一旦遇到 ) 或者 字符串终止位置,停! - // 返回值: - // 0) 负责这一段的结果(得分)是多少? - // 1) 计算到了什么位置也返回 - public static int[] compute(char[] s, int i) { - if (s[i] == ')') { - return new int[] { 1, i }; - } - int ans = 1; - while (i < s.length && s[i] != ')') { - int[] info = compute(s, i + 1); - ans *= info[0] + 1; - i = info[1] + 1; - } - return new int[] { ans, i }; - } - - public static void main(String[] args) { - - String str1 = "(()())()(())"; - System.out.println(sores(str1)); - - // (()()) + (((()))) + ((())()) - // (()()) -> 2 * 2 + 1 -> 5 - // (((()))) -> 5 - // ((())()) -> ((2 + 1) * 2) + 1 -> 7 - // 所以下面的结果应该是175 - String str2 = "(()())(((())))((())())"; - System.out.println(sores(str2)); - - // (()()()) + (()(())) - // (()()()) -> 2 * 2 * 2 + 1 -> 9 - // (()(())) -> 2 * 3 + 1 -> 7 - // 所以下面的结果应该是63 - String str3 = "(()()())(()(()))"; - System.out.println(sores(str3)); - } - -} diff --git a/公开课/class057/Code04_Ratio01Split.java b/公开课/class057/Code04_Ratio01Split.java deleted file mode 100644 index 4f9e63b..0000000 --- a/公开课/class057/Code04_Ratio01Split.java +++ /dev/null @@ -1,67 +0,0 @@ -package class057; - -import java.util.HashMap; - -// 来自网易 -// 把一个01字符串切成多个部分,要求每一部分的0和1比例一样,同时要求尽可能多的划分 -// 比如 : 01010101 -// 01 01 01 01 这是一种切法,0和1比例为 1 : 1 -// 0101 0101 也是一种切法,0和1比例为 1 : 1 -// 两种切法都符合要求,但是那么尽可能多的划分为第一种切法,部分数为4 -// 比如 : 00001111 -// 只有一种切法就是00001111整体作为一块,那么尽可能多的划分,部分数为1 -// 给定一个01字符串str,假设长度为N,要求返回一个长度为N的数组ans -// 其中ans[i] = str[0...i]这个前缀串,要求每一部分的0和1比例一样, -// 同时要求尽可能多的划分下,部分数是多少 -// 输入: str = "010100001" -// 输出: ans = [1, 1, 1, 2, 1, 2, 1, 1, 3] -public class Code04_Ratio01Split { - - public static int[] split(int[] arr) { - - // key -> int -> 分子 - // value -> key这个分子下的,分母表 -> 次数 - HashMap> pre = new HashMap<>(); - int n = arr.length; - int[] ans = new int[n]; - int zero = 0; - int one = 0; - for (int i = 0; i < n; i++) { - if (arr[i] == 0) { - zero++; - } else { - one++; - } - if (zero == 0 || one == 0) { - ans[i] = i + 1; - } else { // 0和1都有数量 -> 0和1的比例的最简形式 - int gcd = gcd(zero, one); - int a = zero / gcd; - int b = one / gcd; - if (!pre.containsKey(a)) { - pre.put(a, new HashMap<>()); - } - if (!pre.get(a).containsKey(b)) { - pre.get(a).put(b, 1); - } else { - pre.get(a).put(b, pre.get(a).get(b) + 1); - } - ans[i] = pre.get(a).get(b); - } - } - return ans; - } - - public static int gcd(int m, int n) { - return n == 0 ? m : gcd(n, m % n); - } - - public static void main(String[] args) { - int[] arr = { 0, 1, 0, 1, 0, 1, 1, 0 }; - int[] ans = split(arr); - for (int i = 0; i < ans.length; i++) { - System.out.print(ans[i] + " "); - } - } - -} diff --git a/公开课/class058/Code01_MinBoatEvenNumbers.java b/公开课/class058/Code01_MinBoatEvenNumbers.java deleted file mode 100644 index d0d6311..0000000 --- a/公开课/class058/Code01_MinBoatEvenNumbers.java +++ /dev/null @@ -1,78 +0,0 @@ -package class058; - -import java.util.Arrays; - -// 来自腾讯 -// 给定一个正数数组arr,代表每个人的体重。给定一个正数limit代表船的载重,所有船都是同样的载重量 -// 每个人的体重都一定不大于船的载重 -// 要求: -// 1, 可以1个人单独一搜船 -// 2, 一艘船如果坐2人,两个人的体重相加需要是偶数,且总体重不能超过船的载重 -// 3, 一艘船最多坐2人 -// 返回如果想所有人同时坐船,船的最小数量 -public class Code01_MinBoatEvenNumbers { - - public static int minBoat(int[] arr, int limit) { - Arrays.sort(arr); - int odd = 0; - int even = 0; - for (int num : arr) { - if ((num & 1) == 0) { - even++; - } else { - odd++; - } - } - int[] odds = new int[odd]; - int[] evens = new int[even]; - for (int i = arr.length - 1; i >= 0; i--) { - if ((arr[i] & 1) == 0) { - evens[--even] = arr[i]; - } else { - odds[--odd] = arr[i]; - } - } - return min(odds, limit) + min(evens, limit); - } - - public static int min(int[] arr, int limit) { - if (arr == null || arr.length == 0) { - return 0; - } - int N = arr.length; - if (arr[N - 1] > limit) { - return -1; - } - int lessR = -1; - for (int i = N - 1; i >= 0; i--) { - if (arr[i] <= (limit / 2)) { - lessR = i; - break; - } - } - if (lessR == -1) { - return N; - } - int L = lessR; - int R = lessR + 1; - int noUsed = 0; - while (L >= 0) { - int solved = 0; - while (R < N && arr[L] + arr[R] <= limit) { - R++; - solved++; - } - if (solved == 0) { - noUsed++; - L--; - } else { - L = Math.max(-1, L - solved); - } - } - int all = lessR + 1; - int used = all - noUsed; - int moreUnsolved = (N - all) - used; - return used + ((noUsed + 1) >> 1) + moreUnsolved; - } - -} diff --git a/公开课/class058/Code02_MaxKLenSequence.java b/公开课/class058/Code02_MaxKLenSequence.java deleted file mode 100644 index 0473f6d..0000000 --- a/公开课/class058/Code02_MaxKLenSequence.java +++ /dev/null @@ -1,87 +0,0 @@ -package class058; - -import java.util.TreeSet; - -// 来自腾讯 -// 给定一个字符串str,和一个正数k -// 返回长度为k的所有子序列中,字典序最大的子序列 -public class Code02_MaxKLenSequence { - - public static String maxString(String s, int k) { - if (k <= 0 || s.length() < k) { - return ""; - } - char[] str = s.toCharArray(); - int n = str.length; - char[] stack = new char[n]; - int size = 0; - for (int i = 0; i < n; i++) { - while (size > 0 && stack[size - 1] < str[i] && size + n - i > k) { - size--; - } - if (size + n - i == k) { - return String.valueOf(stack, 0, size) + s.substring(i); - } - stack[size++] = str[i]; - } - return String.valueOf(stack, 0, k); - } - - // 为了测试 - public static String test(String str, int k) { - if (k <= 0 || str.length() < k) { - return ""; - } - TreeSet ans = new TreeSet<>(); - process(0, 0, str.toCharArray(), new char[k], ans); - return ans.last(); - } - - // 为了测试 - public static void process(int si, int pi, char[] str, char[] path, TreeSet ans) { - if (si == str.length) { - if (pi == path.length) { - ans.add(String.valueOf(path)); - } - } else { - process(si + 1, pi, str, path, ans); - if (pi < path.length) { - path[pi] = str[si]; - process(si + 1, pi + 1, str, path, ans); - } - } - } - - // 为了测试 - public static String randomString(int len, int range) { - char[] str = new char[len]; - for (int i = 0; i < len; i++) { - str[i] = (char) ((int) (Math.random() * range) + 'a'); - } - return String.valueOf(str); - } - - public static void main(String[] args) { - int n = 12; - int r = 5; - int testTime = 10000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int len = (int) (Math.random() * (n + 1)); - String str = randomString(len, r); - int k = (int) (Math.random() * (str.length() + 1)); - String ans1 = maxString(str, k); - String ans2 = test(str, k); - if (!ans1.equals(ans2)) { - System.out.println("出错了!"); - System.out.println(str); - System.out.println(k); - System.out.println(ans1); - System.out.println(ans2); - break; - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class058/Code03_StoneGameIV.java b/公开课/class058/Code03_StoneGameIV.java deleted file mode 100644 index 3871748..0000000 --- a/公开课/class058/Code03_StoneGameIV.java +++ /dev/null @@ -1,99 +0,0 @@ -package class058; - -// 来自哈喽单车 -// 本题是leetcode原题 : https://leetcode.com/problems/stone-game-iv/ -public class Code03_StoneGameIV { - - // 当前的!拿分数的人,如果面对x这个分数,最终 当前的!拿分数的人 会不会赢 - public static boolean win(int x) { - if (x == 0) { - return false; - } - for (int p = 1; p * p <= x; p++) { - // 某一个决定 - int pick = p * p; - // 下一轮的对手,面对的分值 - int rest = x - pick; - if (!win(rest)) { - return true; - } - } - return false; - } - - public static boolean win2(int n) { - // f[x] -> win(x) - boolean[] f = new boolean[n + 1]; - // f[0] -> win(0) -> false - for (int i = 1; i <= n; i++) { - // f[1] : f[0...0] - // f[2] : f[0...1] - // f[3] : f[0...2] - // f[i] : f[0...i-1] - for (int p = 1; p * p <= i; p++) { - if (!f[i - p * p]) { - f[i] = true; - break; - } - } - } - return f[n]; - } - - // 当前的!先手,会不会赢 - // 打表,不能发现规律 - public static boolean winnerSquareGame1(int n) { - if (n == 0) { - return false; - } - // 当前的先手,会尝试所有的情况,1,4,9,16,25,36.... - for (int i = 1; i * i <= n; i++) { - // 当前的先手,决定拿走 i * i 这个平方数 - // 它的对手会不会赢? winnerSquareGame1(n - i * i) - if (!winnerSquareGame1(n - i * i)) { - return true; - } - } - return false; - } - - public static boolean winnerSquareGame2(int n) { - int[] dp = new int[n + 1]; - dp[0] = -1; - return process2(n, dp); - } - - public static boolean process2(int n, int[] dp) { - if (dp[n] != 0) { - return dp[n] == 1 ? true : false; - } - boolean ans = false; - for (int i = 1; i * i <= n; i++) { - if (!process2(n - i * i, dp)) { - ans = true; - break; - } - } - dp[n] = ans ? 1 : -1; - return ans; - } - - public static boolean winnerSquareGame3(int n) { - boolean[] dp = new boolean[n + 1]; - for (int i = 1; i <= n; i++) { - for (int j = 1; j * j <= i; j++) { - if (!dp[i - j * j]) { - dp[i] = true; - break; - } - } - } - return dp[n]; - } - - public static void main(String[] args) { - int n = 10000000; - System.out.println(winnerSquareGame3(n)); - } - -} diff --git a/公开课/class059/Code01_MagicStone.java b/公开课/class059/Code01_MagicStone.java deleted file mode 100644 index 8b73087..0000000 --- a/公开课/class059/Code01_MagicStone.java +++ /dev/null @@ -1,49 +0,0 @@ -package class059; - -import java.util.Arrays; - -// 来自小红书 -// [0,4,7] : 0表示这里石头没有颜色,如果变红代价是4,如果变蓝代价是7 -// [1,X,X] : 1表示这里石头已经是红,而且不能改颜色,所以后两个数X无意义 -// [2,X,X] : 2表示这里石头已经是蓝,而且不能改颜色,所以后两个数X无意义 -// 颜色只可能是0、1、2,代价一定>=0 -// 给你一批这样的小数组,要求最后必须所有石头都有颜色,且红色和蓝色一样多,返回最小代价 -// 如果怎么都无法做到所有石头都有颜色、且红色和蓝色一样多,返回-1 -public class Code01_MagicStone { - - public static int minCost(int[][] stones) { - int n = stones.length; - if ((n & 1) != 0) { - return -1; - } - Arrays.sort(stones, (a, b) -> a[0] == 0 && b[0] == 0 ? (b[1] - b[2] - a[1] + a[2]) : (a[0] - b[0])); - int zero = 0; - int red = 0; - int blue = 0; - int cost = 0; - for (int i = 0; i < n; i++) { - if (stones[i][0] == 0) { - zero++; - cost += stones[i][1]; - } else if (stones[i][0] == 1) { - red++; - } else { - blue++; - } - } - if (red > (n >> 1) || blue > (n >> 1)) { - return -1; - } - blue = zero - ((n >> 1) - red); - for (int i = 0; i < blue; i++) { - cost += stones[i][2] - stones[i][1]; - } - return cost; - } - - public static void main(String[] args) { - int[][] stones = { { 1, 5, 3 }, { 2, 7, 9 }, { 0, 6, 4 }, { 0, 7, 9 }, { 0, 2, 1 }, { 0, 5, 9 } }; - System.out.println(minCost(stones)); - } - -} diff --git a/公开课/class059/Code02_CircleCandy.java b/公开课/class059/Code02_CircleCandy.java deleted file mode 100644 index d31afc8..0000000 --- a/公开课/class059/Code02_CircleCandy.java +++ /dev/null @@ -1,58 +0,0 @@ -package class059; - -// 来自网易 -// 给定一个正数数组arr,表示每个小朋友的得分 -// 任何两个相邻的小朋友,如果得分一样,怎么分糖果无所谓,但如果得分不一样,分数大的一定要比分数少的多拿一些糖果 -// 假设所有的小朋友坐成一个环形,返回在不破坏上一条规则的情况下,需要的最少糖果数 -public class Code02_CircleCandy { - - public static int minCandy(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - if (arr.length == 1) { - return 1; - } - int n = arr.length; - int minIndex = 0; - for (int i = 0; i < n; i++) { - if (arr[i] <= arr[lastIndex(i, n)] && arr[i] <= arr[nextIndex(i, n)]) { - minIndex = i; - break; - } - } - int[] nums = new int[n + 1]; - for (int i = 0; i <= n; i++, minIndex = nextIndex(minIndex, n)) { - nums[i] = arr[minIndex]; - } - int[] left = new int[n + 1]; - left[0] = 1; - for (int i = 1; i <= n; i++) { - left[i] = nums[i] > nums[i - 1] ? (left[i - 1] + 1) : 1; - } - int[] right = new int[n + 1]; - right[n] = 1; - for (int i = n - 1; i >= 0; i--) { - right[i] = nums[i] > nums[i + 1] ? (right[i + 1] + 1) : 1; - } - int ans = 0; - for (int i = 0; i < n; i++) { - ans += Math.max(left[i], right[i]); - } - return ans; - } - - public static int nextIndex(int i, int n) { - return i == n - 1 ? 0 : (i + 1); - } - - public static int lastIndex(int i, int n) { - return i == 0 ? (n - 1) : (i - 1); - } - - public static void main(String[] args) { - int[] arr = { 3, 4, 2, 3, 2 }; - System.out.println(minCandy(arr)); - } - -} diff --git a/公开课/class059/Code03_MinBoatEvenNumbers.java b/公开课/class059/Code03_MinBoatEvenNumbers.java deleted file mode 100644 index 111e7c6..0000000 --- a/公开课/class059/Code03_MinBoatEvenNumbers.java +++ /dev/null @@ -1,78 +0,0 @@ -package class059; - -import java.util.Arrays; - -// 来自腾讯 -// 给定一个正数数组arr,代表每个人的体重。给定一个正数limit代表船的载重,所有船都是同样的载重量 -// 每个人的体重都一定不大于船的载重 -// 要求: -// 1, 可以1个人单独一搜船 -// 2, 一艘船如果坐2人,两个人的体重相加需要是偶数,且总体重不能超过船的载重 -// 3, 一艘船最多坐2人 -// 返回如果想所有人同时坐船,船的最小数量 -public class Code03_MinBoatEvenNumbers { - - public static int minBoat(int[] arr, int limit) { - Arrays.sort(arr); - int odd = 0; - int even = 0; - for (int num : arr) { - if ((num & 1) == 0) { - even++; - } else { - odd++; - } - } - int[] odds = new int[odd]; - int[] evens = new int[even]; - for (int i = arr.length - 1; i >= 0; i--) { - if ((arr[i] & 1) == 0) { - evens[--even] = arr[i]; - } else { - odds[--odd] = arr[i]; - } - } - return min(odds, limit) + min(evens, limit); - } - - public static int min(int[] arr, int limit) { - if (arr == null || arr.length == 0) { - return 0; - } - int N = arr.length; - if (arr[N - 1] > limit) { - return -1; - } - int lessR = -1; - for (int i = N - 1; i >= 0; i--) { - if (arr[i] <= (limit / 2)) { - lessR = i; - break; - } - } - if (lessR == -1) { - return N; - } - int L = lessR; - int R = lessR + 1; - int noUsed = 0; - while (L >= 0) { - int solved = 0; - while (R < N && arr[L] + arr[R] <= limit) { - R++; - solved++; - } - if (solved == 0) { - noUsed++; - L--; - } else { - L = Math.max(-1, L - solved); - } - } - int all = lessR + 1; - int used = all - noUsed; - int moreUnsolved = (N - all) - used; - return used + ((noUsed + 1) >> 1) + moreUnsolved; - } - -} diff --git a/公开课/class059/Code04_StringKth.java b/公开课/class059/Code04_StringKth.java deleted file mode 100644 index d89104e..0000000 --- a/公开课/class059/Code04_StringKth.java +++ /dev/null @@ -1,97 +0,0 @@ -package class059; - -import java.util.ArrayList; -import java.util.List; - -// 来自阿里 -// 给定一个长度len,表示一共有几位 -// 所有字符都是小写(a~z),可以生成长度为1,长度为2, -// 长度为3...长度为len的所有字符串 -// 如果把所有字符串根据字典序排序,每个字符串都有所在的位置。 -// 给定一个字符串str,给定len,请返回str是总序列中的第几个 -// 比如len = 4,字典序的前几个字符串为: -// a aa aaa aaaa aaab ... aaaz ... azzz b ba baa baaa ... bzzz c ... -// a是这个序列中的第1个,bzzz是这个序列中的第36558个 -public class Code04_StringKth { - // 思路: - // cdb,总共长度为7,请问cdb是第几个? - // 第一位c : - // 以a开头,剩下长度为(0~6)的所有可能性有几个 - // + - // 以b开头,剩下长度为(0~6)的所有可能性有几个 - // + - // 以c开头,剩下长度为(0)的所有可能性有几个 - // 第二位d : - // + - // 以ca开头的情况下,剩下长度为(0~5)的所有可能性有几个 - // + - // 以cb开头的情况下,剩下长度为(0~5)的所有可能性有几个 - // + - // 以cc开头的情况下,剩下长度为(0~5)的所有可能性有几个 - // + - // 以cd开头的情况下,剩下长度为(0)的所有可能性有几个 - // 第三位b - // + - // 以cda开头的情况下,剩下长度为(0~4)的所有可能性有几个 - // + - // 以cdb开头的情况下,剩下长度为(0)的所有可能性有几个 - public static int kth(String s, int len) { - if (s == null || s.length() == 0 || s.length() > len) { - return -1; - } - char[] num = s.toCharArray(); - int ans = 0; - for (int i = 0, rest = len - 1; i < num.length; i++, rest--) { - ans += (num[i] - 'a') * f(rest) + 1; - } - return ans; - } - - // 不管以什么开头,剩下长度为(0~len)的所有可能性有几个 - public static int f(int len) { - int ans = 1; - for (int i = 1, base = 26; i <= len; i++, base *= 26) { - ans += base; - } - return ans; - } - - // 为了测试 - public static List all(int len) { - List ans = new ArrayList<>(); - for (int i = 1; i <= len; i++) { - char[] path = new char[i]; - process(path, 0, ans); - } - return ans; - } - - // 为了测试 - public static void process(char[] path, int index, List ans) { - if (index == path.length) { - ans.add(String.valueOf(path)); - } else { - for (char c = 'a'; c <= 'z'; c++) { - path[index] = c; - process(path, index + 1, ans); - } - } - } - - public static void main(String[] args) { - int len = 4; - // 暴力方法得到所有字符串 - List ans = all(len); - // 根据字典序排序,所有字符串都在其中 - ans.sort((a, b) -> a.compareTo(b)); - - String test = "bzzz"; - // 根据我们的方法算出test是第几个? - // 注意我们算出的第几个,是从1开始的 - // 而下标是从0开始的,所以变成index,还需要-1 - int index = kth(test, len) - 1; - // 验证 - System.out.println(ans.get(index)); - } - -} diff --git a/公开课/class059/Code05_SubarraySumEqualsK.java b/公开课/class059/Code05_SubarraySumEqualsK.java deleted file mode 100644 index 7376f87..0000000 --- a/公开课/class059/Code05_SubarraySumEqualsK.java +++ /dev/null @@ -1,34 +0,0 @@ -package class059; - -import java.util.HashMap; - -public class Code05_SubarraySumEqualsK { - - public static int subarraySum(int[] nums, int sum) { - if (nums == null || nums.length == 0) { - return 0; - } - // key : 某一个前缀和! - // value : 这个前缀和,出现了几次! - HashMap preSumTimesMap = new HashMap<>(); - preSumTimesMap.put(0, 1); - // 每一步的整体和, 当你遍历到i位置,0~i整体的累加和! - int all = 0; - int ans = 0; - for (int i = 0; i < nums.length; i++) { - // 0...i的整体累加和了!1000 200 1000 - 200 = 800 - all += nums[i]; - if (preSumTimesMap.containsKey(all - sum)) { - ans += preSumTimesMap.get(all - sum); - } - // 0....i 这个前缀和,一定要去!更新map! - if (!preSumTimesMap.containsKey(all)) { - preSumTimesMap.put(all, 1); - } else { - preSumTimesMap.put(all, preSumTimesMap.get(all) + 1); - } - } - return ans; - } - -} diff --git a/公开课/class059/Code06_Ratio01Split.java b/公开课/class059/Code06_Ratio01Split.java deleted file mode 100644 index a38022c..0000000 --- a/公开课/class059/Code06_Ratio01Split.java +++ /dev/null @@ -1,68 +0,0 @@ -package class059; - -import java.util.HashMap; - -// 来自京东 -// 把一个01字符串切成多个部分,要求每一部分的0和1比例一样,同时要求尽可能多的划分 -// 比如 : 01010101 -// 01 01 01 01 这是一种切法,0和1比例为 1 : 1 -// 0101 0101 也是一种切法,0和1比例为 1 : 1 -// 两种切法都符合要求,但是那么尽可能多的划分为第一种切法,部分数为4 -// 比如 : 00001111 -// 只有一种切法就是00001111整体作为一块,那么尽可能多的划分,部分数为1 -// 给定一个01字符串str,假设长度为N,要求返回一个长度为N的数组ans -// 其中ans[i] = str[0...i]这个前缀串,要求每一部分的0和1比例一样,同时要求尽可能多的划分下,部分数是多少 -// 输入: str = "010100001" -// 输出: ans = [1, 1, 1, 2, 1, 2, 1, 1, 3] -public class Code06_Ratio01Split { - - // 001010010100... - public static int[] split(int[] arr) { - - // key : 分子 - // value : 属于key的分母表, 每一个分母,及其 分子/分母 这个比例,多少个前缀拥有 - HashMap> pre = new HashMap<>(); - int n = arr.length; - int[] ans = new int[n]; - int zero = 0; // 0出现的次数 - int one = 0; // 1出现的次数 - for (int i = 0; i < n; i++) { - if (arr[i] == 0) { - zero++; - } else { - one++; - } - if (zero == 0 || one == 0) { - ans[i] = i + 1; - } else { // 0和1,都有数量 -> 最简分数 - int gcd = gcd(zero, one); - int a = zero / gcd; - int b = one / gcd; - // a / b 比例,之前有多少前缀拥有? 3+1 4 5+1 6 - if (!pre.containsKey(a)) { - pre.put(a, new HashMap<>()); - } - if (!pre.get(a).containsKey(b)) { - pre.get(a).put(b, 1); - } else { - pre.get(a).put(b, pre.get(a).get(b) + 1); - } - ans[i] = pre.get(a).get(b); - } - } - return ans; - } - - public static int gcd(int m, int n) { - return n == 0 ? m : gcd(n, m % n); - } - - public static void main(String[] args) { - int[] arr = { 0, 1, 0, 1, 0, 1, 1, 0 }; - int[] ans = split(arr); - for (int i = 0; i < ans.length; i++) { - System.out.print(ans[i] + " "); - } - } - -} diff --git a/公开课/class060/Code01_MinSwapTimes.java b/公开课/class060/Code01_MinSwapTimes.java deleted file mode 100644 index d20d191..0000000 --- a/公开课/class060/Code01_MinSwapTimes.java +++ /dev/null @@ -1,88 +0,0 @@ -package class060; - -// 来自小红书 -// 一个无序数组长度为n,所有数字都不一样,并且值都在[0...n-1]范围上 -// 返回让这个无序数组变成有序数组的最少交换次数 -public class Code01_MinSwapTimes { - - // 纯暴力,arr长度大一点都会超时 - // 但是绝对正确 - public static int minSwap1(int[] arr) { - return process1(arr, 0); - } - - // 让arr变有序,最少的交换次数是多少!返回 - // times, 之前已经做了多少次交换 - public static int process1(int[] arr, int times) { - boolean sorted = true; - for (int i = 1; i < arr.length; i++) { - if (arr[i - 1] > arr[i]) { - sorted = false; - break; - } - } - if (sorted) { - return times; - } - // 数组现在是无序的状态! - if (times >= arr.length - 1) { - return Integer.MAX_VALUE; - } - int ans = Integer.MAX_VALUE; - for (int i = 0; i < arr.length; i++) { - for (int j = i + 1; j < arr.length; j++) { - swap(arr, i, j); - ans = Math.min(ans, process1(arr, times + 1)); - swap(arr, i, j); - } - } - return ans; - } - - public static void swap(int[] arr, int i, int j) { - int tmp = arr[i]; - arr[i] = arr[j]; - arr[j] = tmp; - } - - // 已知arr中,只有0~n-1这些值,并且都出现1次 - public static int minSwap2(int[] arr) { - int ans = 0; - for (int i = 0; i < arr.length; i++) { // i -> i - while (i != arr[i]) { - swap(arr, i, arr[i]); - ans++; - } - } - return ans; - } - - // 为了测试 - public static int[] randomArray(int len) { - int[] arr = new int[len]; - for (int i = 0; i < len; i++) { - arr[i] = i; - } - for (int i = 0; i < len; i++) { - swap(arr, i, (int) (Math.random() * len)); - } - return arr; - } - - public static void main(String[] args) { - int n = 6; - int testTime = 2000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int len = (int) (Math.random() * n) + 1; - int[] arr = randomArray(len); - int ans1 = minSwap1(arr); - int ans2 = minSwap2(arr); - if (ans1 != ans2) { - System.out.println("出错了!"); - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class060/Code02_MaxMeetingScore.java b/公开课/class060/Code02_MaxMeetingScore.java deleted file mode 100644 index 8a0f764..0000000 --- a/公开课/class060/Code02_MaxMeetingScore.java +++ /dev/null @@ -1,114 +0,0 @@ -package class060; - -import java.util.Arrays; -import java.util.PriorityQueue; - -// 来自阿里 -// 给定int[][] meetings,比如 -// { -// {66, 70} 0号会议截止时间66,获得收益70 -// {25, 90} 1号会议截止时间25,获得收益90 -// {50, 30} 2号会议截止时间50,获得收益30 -// } -// 一开始的时间是0,任何会议都持续10的时间,但是一个会议一定要在该会议截止时间之前开始 -// 只有一个会议室,任何会议不能共用会议室,一旦一个会议被正确安排,将获得这个会议的收益 -// 请返回最大的收益 -public class Code02_MaxMeetingScore { - - public static int maxScore1(int[][] meetings) { - Arrays.sort(meetings, (a, b) -> a[0] - b[0]); - int[][] path = new int[meetings.length][]; - int size = 0; - return process1(meetings, 0, path, size); - } - - public static int process1(int[][] meetings, int index, int[][] path, int size) { - if (index == meetings.length) { - int time = 0; - int ans = 0; - for (int i = 0; i < size; i++) { - if (time + 10 <= path[i][0]) { - ans += path[i][1]; - time += 10; - } else { - return 0; - } - } - return ans; - } - int p1 = process1(meetings, index + 1, path, size); - path[size] = meetings[index]; - int p2 = process1(meetings, index + 1, path, size + 1); - // path[size] = null; - return Math.max(p1, p2); - } - - // 所有会议,先根据截止时间排序 - // [10,40] 、 [5,32] -> [5,32] [10,40] - // 比较器!java c++ 重载比较运算符 - public static int maxScore2(int[][] meetings) { - Arrays.sort(meetings, (a, b) -> a[0] - b[0]); - // 小根堆,里面放收益,收益小的在顶,收益大的在底 - PriorityQueue heap = new PriorityQueue<>(); - int time = 0; - // 已经把所有会议,按照截止时间,从小到大,排序了! - // 截止时间一样的,谁排前谁排后,无所谓 - for (int i = 0; i < meetings.length; i++) { - if (time + 10 <= meetings[i][0]) { - heap.add(meetings[i][1]); - time += 10; - } else { // 不能通过增加会议数量,来安排;只能看,能不能挤掉之前的、最不行的会议 - if (!heap.isEmpty() && heap.peek() < meetings[i][1]) { - heap.poll(); - heap.add(meetings[i][1]); - } - } - } - int ans = 0; - while (!heap.isEmpty()) { - ans += heap.poll(); - } - return ans; - } - - public static int[][] randomMeetings(int n, int t, int s) { - int[][] ans = new int[n][2]; - for (int i = 0; i < n; i++) { - ans[i][0] = (int) (Math.random() * t) + 1; - ans[i][1] = (int) (Math.random() * s) + 1; - } - return ans; - } - - public static int[][] copyMeetings(int[][] meetings) { - int n = meetings.length; - int[][] ans = new int[n][2]; - for (int i = 0; i < n; i++) { - ans[i][0] = meetings[i][0]; - ans[i][1] = meetings[i][1]; - } - return ans; - } - - public static void main(String[] args) { - int n = 12; - int t = 100; - int s = 500; - int testTime = 10000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int size = (int) (Math.random() * n) + 1; - int[][] meetings1 = randomMeetings(size, t, s); - int[][] meetings2 = copyMeetings(meetings1); - int ans1 = maxScore1(meetings1); - int ans2 = maxScore2(meetings2); - if (ans1 != ans2) { - System.out.println("出错了!"); - System.out.println(ans1); - System.out.println(ans2); - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class060/Code03_NextPermutation.java b/公开课/class060/Code03_NextPermutation.java deleted file mode 100644 index 21dc1b1..0000000 --- a/公开课/class060/Code03_NextPermutation.java +++ /dev/null @@ -1,46 +0,0 @@ -package class060; - -// 来自Amazon -// leetcode原题 : https://leetcode.com/problems/next-permutation/ -public class Code03_NextPermutation { - - public static void nextPermutation(int[] nums) { - int N = nums.length; - // 从右往左第一次降序的位置 - int firstLess = -1; - for (int i = N - 2; i >= 0; i--) { - if (nums[i] < nums[i + 1]) { - firstLess = i; - break; - } - } - if (firstLess < 0) { - reverse(nums, 0, N - 1); - } else { - int rightClosestMore = -1; - // 找最靠右的、同时比nums[firstLess]大的数,位置在哪 - // 这里其实也可以用二分优化,但是这种优化无关紧要了 - for (int i = N - 1; i > firstLess; i--) { - if (nums[i] > nums[firstLess]) { - rightClosestMore = i; - break; - } - } - swap(nums, firstLess, rightClosestMore); - reverse(nums, firstLess + 1, N - 1); - } - } - - public static void reverse(int[] nums, int L, int R) { - while (L < R) { - swap(nums, L++, R--); - } - } - - public static void swap(int[] nums, int i, int j) { - int tmp = nums[i]; - nums[i] = nums[j]; - nums[j] = tmp; - } - -} diff --git a/公开课/class060/Code04_SequenceKDifferentKinds.java b/公开课/class060/Code04_SequenceKDifferentKinds.java deleted file mode 100644 index c208eaf..0000000 --- a/公开课/class060/Code04_SequenceKDifferentKinds.java +++ /dev/null @@ -1,111 +0,0 @@ -package class060; - -// 来自百度 -// 给定一个字符串str,和一个正数k -// str子序列的字符种数必须是k种,返回有多少子序列满足这个条件 -// 已知str中都是小写字母 -public class Code04_SequenceKDifferentKinds { - -// public static int waysAll(String str, int k) { -// -// int[] arr = 通过str生成; -// // arr[0....]自由选择,一定要选出k中字符来!不同的子序列有多少个 -// return ways(arr, 0, k); -// -// } - - // "aababddfeeef" - // a 3个 - // b 2个 - // c 0个 - // d 2个 - // e 3个 - // f 2个 - // g 0个 - // ... - // z 0个 - // int[] arr = { 3 2 0 2 3 } - // 0 1 2 3 4... - // 原始的字符串,变成了arr的形式来表达! - // restKinds : 还剩下几种字符,需要去选! - // "....." K = 3 - // "....." -> int[] arr - // return ways(arr, 3); - // arr[i....]桶,自由选择,一定要选出restKinds种来 - public static int zuo(int[] arr, int i, int restKinds) { - if (i == arr.length) { // 结束了 - return restKinds == 0 ? 1 : 0; - } else { // 没结束,还有字符,可供选择 - - // 就是不考虑i位置的字符 - int p1 = zuo(arr, i + 1, restKinds); - - // 一定要选择,i位置的字符 - int p2 = 0; - if (arr[i] != 0) { - -// 选i字符的方法 = C n 1 + C n 2 + C n 3 + ..... + C n n -// -// -// p2 = 选i字符的方法 * ways(arr, i+1, restKinds-1); -// -// p2 = (2的arr[i]次方 - 1) * ways(arr, i+1, restKinds-1); - - p2 = ((1 << arr[i]) - 1) * zuo(arr, i + 1, restKinds - 1); - } - return p1 + p2; - } - } - - // bu -> {6,7,0,0,6,3} - // 0 1 2 3 4 5 - // a b c d e f - // 在桶数组bu[index....] 一定要凑出rest种来!请问几种方法! - public static int f(int[] bu, int index, int rest) { - if (index == bu.length) { - return rest == 0 ? 1 : 0; - } - // 最后形成的子序列,一个index代表的字符也没有! - int p1 = f(bu, index + 1, rest); - // 最后形成的子序列,一定要包含index代表的字符,几个呢?(所有可能性都要算上!) - int p2 = 0; - if (rest > 0) { // 剩余的种数,没耗尽,可以包含当前桶的字符 - p2 = (1 << bu[index] - 1) * f(bu, index + 1, rest - 1); - } - return p1 + p2; - } - - public static int nums(String s, int k) { - char[] str = s.toCharArray(); - int[] counts = new int[26]; - for (char c : str) { - counts[c - 97]++; - } - return ways(counts, 0, k); - } - - public static int ways(int[] c, int i, int r) { - if (r == 0) { - return 1; - } - if (i == c.length) { - return 0; - } - // math(n) -> 2 ^ n -1 - return math(c[i]) * ways(c, i + 1, r - 1) + ways(c, i + 1, r); - } - - // n个不同的球 - // 挑出1个的方法数 + 挑出2个的方法数 + ... + 挑出n个的方法数为: - // C(n,1) + C(n,2) + ... + C(n,n) == (2 ^ n) -1 - public static int math(int n) { - return (1 << n) - 1; - } - - public static void main(String[] args) { - String str = "acbbca"; - int k = 3; - System.out.println(nums(str, k)); - } - -} diff --git a/公开课/class061/Code01_HashFunction.java b/公开课/class061/Code01_HashFunction.java deleted file mode 100644 index 28091b3..0000000 --- a/公开课/class061/Code01_HashFunction.java +++ /dev/null @@ -1,51 +0,0 @@ -package class061; - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.Security; - -import javax.xml.bind.DatatypeConverter; - -public class Code01_HashFunction { - - public static class Hash { - - private MessageDigest hash; - - public Hash(String algorithm) { - try { - hash = MessageDigest.getInstance(algorithm); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } - } - - public String hashCode(String input) { - return DatatypeConverter.printHexBinary(hash.digest(input.getBytes())).toUpperCase(); - } - } - - public static void main(String[] args) { - System.out.println("支持的算法 : "); - for (String str : Security.getAlgorithms("MessageDigest")) { - System.out.println(str); - } - System.out.println("======="); - - String algorithm = "MD5"; - Hash hash = new Hash(algorithm); - - String input1 = "zuofdjkafjksadfjasdkljfalsjflaskfjklasdfjklsdjflkdsfjadksfjlkdfjasdlkfjadlskjfkldjflkadsfjlkasdjflkdfjlkdjf"; - String input2 = "zuochengyunzuochengyun2"; - String input3 = "zuochengyunzuochengyun3"; - String input4 = "zuochengyunzuochengyun4"; - String input5 = "zuochengyunzuochengyun5"; - System.out.println(hash.hashCode(input1)); - System.out.println(hash.hashCode(input2)); - System.out.println(hash.hashCode(input3)); - System.out.println(hash.hashCode(input4)); - System.out.println(hash.hashCode(input5)); - - } - -} diff --git a/公开课/class061/Code02_FillGapMinStep.java b/公开课/class061/Code02_FillGapMinStep.java deleted file mode 100644 index 9aaa3fc..0000000 --- a/公开课/class061/Code02_FillGapMinStep.java +++ /dev/null @@ -1,103 +0,0 @@ -package class061; - -// 来自字节 -// 给定两个数a和b -// 第1轮,把1选择给a或者b -// 第2轮,把2选择给a或者b -// ... -// 第i轮,把i选择给a或者b -// 想让a和b的值一样大,请问至少需要多少轮? -public class Code02_FillGapMinStep { - - // 暴力方法 - // 不要让a、b过大! - public static int minStep0(int a, int b) { - if (a == b) { - return 0; - } - int limit = 15; - return process(a, b, 1, limit); - } - - public static int process(int a, int b, int i, int n) { - if (i > n) { - return Integer.MAX_VALUE; - } - if (a + i == b || a == b + i) { - return i; - } - return Math.min(process(a + i, b, i + 1, n), process(a, b + i, i + 1, n)); - } - - public static int minStep1(int a, int b) { - if (a == b) { - return 0; - } - int s = Math.abs(a - b); - int num = 1; - int sum = 0; - for (; !(sum >= s && (sum - s) % 2 == 0); num++) { - sum += num; - } - return num - 1; - } - - public static int minStep2(int a, int b) { - if (a == b) { - return 0; - } - int s = Math.abs(a - b); - // 找到sum >= s, 最小的i - int begin = best(s << 1); - for (; (begin * (begin + 1) / 2 - s) % 2 != 0;) { - begin++; - } - return begin; - } - - public static int best(int s2) { - int L = 0; - int R = 1; - for (; R * (R + 1) < s2;) { - L = R; - R *= 2; - } - int ans = 0; - while (L <= R) { - int M = (L + R) / 2; - if (M * (M + 1) >= s2) { - ans = M; - R = M - 1; - } else { - L = M + 1; - } - } - return ans; - } - - public static void main(String[] args) { - System.out.println("功能测试开始"); - for (int a = 1; a < 100; a++) { - for (int b = 1; b < 100; b++) { - int ans1 = minStep0(a, b); - int ans2 = minStep1(a, b); - int ans3 = minStep2(a, b); - if (ans1 != ans2 || ans1 != ans3) { - System.out.println("出错了!"); - System.out.println(a + " , " + b); - break; - } - } - } - System.out.println("功能测试结束"); - - int a = 19019; - int b = 8439284; - int ans2 = minStep1(a, b); - int ans3 = minStep2(a, b); - System.out.println(ans2); - System.out.println(ans3); - - } - -} diff --git a/公开课/class061/Code03_Mod3Max.java b/公开课/class061/Code03_Mod3Max.java deleted file mode 100644 index 236db82..0000000 --- a/公开课/class061/Code03_Mod3Max.java +++ /dev/null @@ -1,160 +0,0 @@ -package class061; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.TreeSet; - -// 来自去哪儿网 -// 给定一个arr,里面的数字都是0~9 -// 你可以随意使用arr中的数字,哪怕打乱顺序也行 -// 请拼出一个能被3整除的,最大的数字,用str形式返回 -public class Code03_Mod3Max { - - public static String max1(int[] arr) { - Arrays.sort(arr); - for (int l = 0, r = arr.length - 1; l < r; l++, r--) { - int tmp = arr[l]; - arr[l] = arr[r]; - arr[r] = tmp; - } - StringBuilder builder = new StringBuilder(); - TreeSet set = new TreeSet<>((a, b) -> Integer.valueOf(b).compareTo(Integer.valueOf(a))); - process1(arr, 0, builder, set); - return set.isEmpty() ? "" : set.first(); - } - - public static void process1(int[] arr, int index, StringBuilder builder, TreeSet set) { - if (index == arr.length) { - if (builder.length() != 0 && Integer.valueOf(builder.toString()) % 3 == 0) { - set.add(builder.toString()); - } - } else { - process1(arr, index + 1, builder, set); - builder.append(arr[index]); - process1(arr, index + 1, builder, set); - builder.deleteCharAt(builder.length() - 1); - } - } - - // 贪心的思路解法 : - // 先得到数组的累加和,记为sum - // 1) 如果sum%3==0,说明所有数从大到小拼起来就可以了 - // 2) 如果sum%3==1,说明多了一个余数1, - // 只需要删掉一个最小的数(该数是%3==1的数); - // 如果没有,只需要删掉两个最小的数(这两个数都是%3==2的数); - // 3) 如果sum%3==2,说明多了一个余数2, - // 只需要删掉一个最小的数(该数是%3==2的数); - // 如果没有,只需要删掉两个最小的数(这两个数都是%3==1的数); - // 如果上面都做不到,说明拼不成 - public static String max2(int[] A) { - if (A == null || A.length == 0) { - return ""; - } - int mod = 0; - ArrayList arr = new ArrayList<>(); - for (int num : A) { - arr.add(num); - mod += num; - mod %= 3; - } - if ((mod == 1 || mod == 2) && !remove(arr, mod, 3 - mod)) { - return ""; - } - if (arr.isEmpty()) { - return ""; - } - arr.sort((a, b) -> b - a); - if (arr.get(0) == 0) { - return "0"; - } - StringBuilder builder = new StringBuilder(); - for (int num : arr) { - builder.append(num); - } - return builder.toString(); - } - - // 在arr中,要么删掉最小的一个、且%3之后余数是first的数 - // 如果做不到,删掉最小的两个、且%3之后余数是second的数 - // 如果能做到返回true,不能做到返回false - public static boolean remove(ArrayList arr, int first, int second) { - if (arr.size() == 0) { - return false; - } - arr.sort((a, b) -> compare(a, b, first, second)); - int size = arr.size(); - if (arr.get(size - 1) % 3 == first) { - arr.remove(size - 1); - return true; - } else if (size > 1 && arr.get(size - 1) % 3 == second && arr.get(size - 2) % 3 == second) { - arr.remove(size - 1); - arr.remove(size - 2); - return true; - } else { - return false; - } - } - - // a和b比较: - // 如果余数一样,谁大谁放前面 - // 如果余数不一样,余数是0的放最前面、余数是s的放中间、余数是f的放最后 - public static int compare(int a, int b, int f, int s) { - int ma = a % 3; - int mb = b % 3; - if (ma == mb) { - return b - a; - } else { - if (ma == 0 || mb == 0) { - return ma == 0 ? -1 : 1; - } else { - return ma == s ? -1 : 1; - } - } - } - - // 为了测试 - public static int[] randomArray(int len) { - int[] arr = new int[len]; - for (int i = 0; i < len; i++) { - arr[i] = (int) (Math.random() * 10); - } - return arr; - } - - // 为了测试 - public static int[] copyArray(int[] arr) { - int[] ans = new int[arr.length]; - for (int i = 0; i < arr.length; i++) { - ans[i] = arr[i]; - } - return ans; - } - - // 为了测试 - public static void main(String[] args) { - int N = 10; - int testTimes = 10000; - System.out.println("测试开始"); - for (int i = 0; i < testTimes; i++) { - int len = (int) (Math.random() * N); - int[] arr1 = randomArray(len); - int[] arr2 = copyArray(arr1); - int[] arr3 = copyArray(arr1); - String ans1 = max1(arr1); - String ans2 = max2(arr2); - if (!ans1.equals(ans2) ) { - System.out.println("出错了!"); - for (int num : arr3) { - System.out.print(num + " "); - } - System.out.println(); - System.out.println(ans1); - System.out.println(ans2); - break; - } - } - System.out.println("测试结束"); - - } - -} diff --git a/公开课/class062/Code01_MonotonousStack.java b/公开课/class062/Code01_MonotonousStack.java deleted file mode 100644 index f7d2ae2..0000000 --- a/公开课/class062/Code01_MonotonousStack.java +++ /dev/null @@ -1,172 +0,0 @@ -package class062; - -import java.util.List; -import java.util.ArrayList; -import java.util.Stack; - -public class Code01_MonotonousStack { - - // arr = [ 3, 1, 2, 3] - // 0 1 2 3 - // [ - // 0 : [-1, 1] - // 1 : [-1, -1] - // 2 : [ 1, -1] - // 3 : [ 2, -1] - // ] - public static int[][] getNearLessNoRepeat(int[] arr) { - int[][] res = new int[arr.length][2]; - // 只存位置! - Stack stack = new Stack<>(); - for (int i = 0; i < arr.length; i++) { // 当遍历到i位置的数,arr[i] - while (!stack.isEmpty() && arr[stack.peek()] > arr[i]) { - int j = stack.pop(); - int leftLessIndex = stack.isEmpty() ? -1 : stack.peek(); - res[j][0] = leftLessIndex; - res[j][1] = i; - } - stack.push(i); - } - while (!stack.isEmpty()) { - int j = stack.pop(); - int leftLessIndex = stack.isEmpty() ? -1 : stack.peek(); - res[j][0] = leftLessIndex; - res[j][1] = -1; - } - return res; - } - - - // arr [ 3 , 4, 3, 2, 3, 4, 1 ] - // 0 1 2 3 4 5 6 - - - // 0 -> 3 [-1, 3] - // 1 -> 4 [0 , 2] - public static int[][] getNearLess(int[] arr) { - int[][] res = new int[arr.length][2]; - Stack> stack = new Stack<>(); - for (int i = 0; i < arr.length; i++) { // i -> arr[i] 进栈 - while (!stack.isEmpty() && arr[stack.peek().get(0)] > arr[i]) { - List popIs = stack.pop(); - int leftLessIndex = stack.isEmpty() ? -1 : stack.peek().get(stack.peek().size() - 1); - for (Integer popi : popIs) { - res[popi][0] = leftLessIndex; - res[popi][1] = i; - } - } - if (!stack.isEmpty() && arr[stack.peek().get(0)] == arr[i]) { - stack.peek().add(Integer.valueOf(i)); - } else { - ArrayList list = new ArrayList<>(); - list.add(i); - stack.push(list); - } - } - while (!stack.isEmpty()) { - List popIs = stack.pop(); - int leftLessIndex = stack.isEmpty() ? -1 : stack.peek().get(stack.peek().size() - 1); - for (Integer popi : popIs) { - res[popi][0] = leftLessIndex; - res[popi][1] = -1; - } - } - return res; - } - - // for test - public static int[] getRandomArrayNoRepeat(int size) { - int[] arr = new int[(int) (Math.random() * size) + 1]; - for (int i = 0; i < arr.length; i++) { - arr[i] = i; - } - for (int i = 0; i < arr.length; i++) { - int swapIndex = (int) (Math.random() * arr.length); - int tmp = arr[swapIndex]; - arr[swapIndex] = arr[i]; - arr[i] = tmp; - } - return arr; - } - - // for test - public static int[] getRandomArray(int size, int max) { - int[] arr = new int[(int) (Math.random() * size) + 1]; - for (int i = 0; i < arr.length; i++) { - arr[i] = (int) (Math.random() * max) - (int) (Math.random() * max); - } - return arr; - } - - // for test - public static int[][] rightWay(int[] arr) { - int[][] res = new int[arr.length][2]; - for (int i = 0; i < arr.length; i++) { - int leftLessIndex = -1; - int rightLessIndex = -1; - int cur = i - 1; - while (cur >= 0) { - if (arr[cur] < arr[i]) { - leftLessIndex = cur; - break; - } - cur--; - } - cur = i + 1; - while (cur < arr.length) { - if (arr[cur] < arr[i]) { - rightLessIndex = cur; - break; - } - cur++; - } - res[i][0] = leftLessIndex; - res[i][1] = rightLessIndex; - } - return res; - } - - // for test - public static boolean isEqual(int[][] res1, int[][] res2) { - if (res1.length != res2.length) { - return false; - } - for (int i = 0; i < res1.length; i++) { - if (res1[i][0] != res2[i][0] || res1[i][1] != res2[i][1]) { - return false; - } - } - - return true; - } - - // for test - public static void printArray(int[] arr) { - for (int i = 0; i < arr.length; i++) { - System.out.print(arr[i] + " "); - } - System.out.println(); - } - - public static void main(String[] args) { - int size = 10; - int max = 20; - int testTimes = 2000000; - System.out.println("测试开始"); - for (int i = 0; i < testTimes; i++) { - int[] arr1 = getRandomArrayNoRepeat(size); - int[] arr2 = getRandomArray(size, max); - if (!isEqual(getNearLessNoRepeat(arr1), rightWay(arr1))) { - System.out.println("Oops!"); - printArray(arr1); - break; - } - if (!isEqual(getNearLess(arr2), rightWay(arr2))) { - System.out.println("Oops!"); - printArray(arr2); - break; - } - } - System.out.println("测试结束"); - } -} diff --git a/公开课/class062/Code02_LargestRectangleInHistogram.java b/公开课/class062/Code02_LargestRectangleInHistogram.java deleted file mode 100644 index fb57699..0000000 --- a/公开课/class062/Code02_LargestRectangleInHistogram.java +++ /dev/null @@ -1,58 +0,0 @@ -package class062; - -import java.util.Stack; - -// 测试链接:https://leetcode.com/problems/largest-rectangle-in-histogram -public class Code02_LargestRectangleInHistogram { - - public static int largestRectangleArea1(int[] height) { - if (height == null || height.length == 0) { - return 0; - } - int maxArea = 0; - Stack stack = new Stack(); - for (int i = 0; i < height.length; i++) { - while (!stack.isEmpty() && height[i] <= height[stack.peek()]) { - int j = stack.pop(); - int k = stack.isEmpty() ? -1 : stack.peek(); - int curArea = (i - k - 1) * height[j]; - maxArea = Math.max(maxArea, curArea); - } - stack.push(i); - } - while (!stack.isEmpty()) { - int j = stack.pop(); - int k = stack.isEmpty() ? -1 : stack.peek(); - int curArea = (height.length - k - 1) * height[j]; - maxArea = Math.max(maxArea, curArea); - } - return maxArea; - } - - public static int largestRectangleArea2(int[] height) { - if (height == null || height.length == 0) { - return 0; - } - int N = height.length; - int[] stack = new int[N]; - int si = -1; - int maxArea = 0; - for (int i = 0; i < height.length; i++) { - while (si != -1 && height[i] <= height[stack[si]]) { - int j = stack[si--]; - int k = si == -1 ? -1 : stack[si]; - int curArea = (i - k - 1) * height[j]; - maxArea = Math.max(maxArea, curArea); - } - stack[++si] = i; - } - while (si != -1) { - int j = stack[si--]; - int k = si == -1 ? -1 : stack[si]; - int curArea = (height.length - k - 1) * height[j]; - maxArea = Math.max(maxArea, curArea); - } - return maxArea; - } - -} diff --git a/公开课/class062/Code03_ValidSequence.java b/公开课/class062/Code03_ValidSequence.java deleted file mode 100644 index 79a0480..0000000 --- a/公开课/class062/Code03_ValidSequence.java +++ /dev/null @@ -1,113 +0,0 @@ -package class062; - -// 来自腾讯 -// 给定一个长度为n的数组arr,求有多少个子数组满足 : -// 子数组两端的值,是这个子数组的最小值和次小值,最小值和次小值谁在最左和最右无所谓 -// n<=100000(10^5) n*logn O(N) -public class Code03_ValidSequence { - - - public static int nums(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int n = arr.length; - int[] values = new int[n]; - int[] times = new int[n]; - int size = 0; - int ans = 0; - for (int i = 0; i < arr.length; i++) { - while (size != 0 && values[size - 1] > arr[i]) { - size--; - ans += times[size] + cn2(times[size]); - } - if (size != 0 && values[size - 1] == arr[i]) { - times[size - 1]++; - } else { - values[size] = arr[i]; - times[size++] = 1; - } - } - while (size != 0) { - ans += cn2(times[--size]); - } - for (int i = arr.length - 1; i >= 0; i--) { - while (size != 0 && values[size - 1] > arr[i]) { - ans += times[--size]; - } - if (size != 0 && values[size - 1] == arr[i]) { - times[size - 1]++; - } else { - values[size] = arr[i]; - times[size++] = 1; - } - } - return ans; - } - - public static int cn2(int n) { - return (n * (n - 1)) >> 1; - } - - // 为了测试 - // 暴力方法 - public static int test(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int ans = 0; - for (int s = 0; s < arr.length; s++) { - for (int e = s + 1; e < arr.length; e++) { - int max = Math.max(arr[s], arr[e]); - boolean valid = true; - for (int i = s + 1; i < e; i++) { - if (arr[i] < max) { - valid = false; - break; - } - } - ans += valid ? 1 : 0; - } - } - return ans; - } - - // 为了测试 - public static int[] randomArray(int n, int v) { - int[] arr = new int[n]; - for (int i = 0; i < n; i++) { - arr[i] = (int) (Math.random() * v); - } - return arr; - } - - // 为了测试 - public static void printArray(int[] arr) { - for (int num : arr) { - System.out.print(num + " "); - } - System.out.println(); - } - - // 为了测试 - public static void main(String[] args) { - int n = 30; - int v = 30; - int testTime = 100000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int m = (int) (Math.random() * n); - int[] arr = randomArray(m, v); - int ans1 = nums(arr); - int ans2 = test(arr); - if (ans1 != ans2) { - System.out.println("出错了!"); - printArray(arr); - System.out.println(ans1); - System.out.println(ans2); - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class062/Code04_MaxKLenSequence.java b/公开课/class062/Code04_MaxKLenSequence.java deleted file mode 100644 index 111c86b..0000000 --- a/公开课/class062/Code04_MaxKLenSequence.java +++ /dev/null @@ -1,92 +0,0 @@ -package class062; - -import java.util.TreeSet; - -// 来自腾讯 -// 给定一个字符串str,和一个正数k -// 返回长度为k的所有子序列中,字典序最大的子序列 -public class Code04_MaxKLenSequence { - - public static String maxString(String s, int k) { - if (k <= 0 || s.length() < k) { - return ""; - } - char[] str = s.toCharArray(); - int n = str.length; - // 栈,栈大小 size 栈顶stack[size-1] - char[] stack = new char[n]; - int size = 0; - for (int i = 0; i < n; i++) { - // 当前字符 str[i] - while (size > 0 && stack[size - 1] < str[i] && size + n - i > k) { - size--; - } - if (size + n - i == k) { - return String.valueOf(stack, 0, size) + s.substring(i); - } - stack[size++] = str[i]; - } - return String.valueOf(stack, 0, k); - } - - // 为了测试 - // 纯暴力,我把str,所有的、长度为k的,子序列全生成了!找出一个最大的! - public static String test(String str, int k) { - if (k <= 0 || str.length() < k) { - return ""; - } - TreeSet ans = new TreeSet<>(); - process(0, 0, str.toCharArray(), new char[k], ans); - return ans.last(); - } - - // 为了测试 - public static void process(int si, int pi, char[] str, char[] path, TreeSet ans) { - if (si == str.length) { - if (pi == path.length) { - ans.add(String.valueOf(path)); - } - } else { - process(si + 1, pi, str, path, ans); - if (pi < path.length) { - path[pi] = str[si]; - process(si + 1, pi + 1, str, path, ans); - } - } - } - - // 为了测试 - public static String randomString(int len, int range) { - char[] str = new char[len]; - for (int i = 0; i < len; i++) { - str[i] = (char) ((int) (Math.random() * range) + 'a'); - } - return String.valueOf(str); - } - - public static void main(String[] args) { - System.out.println(maxString("ccfaa", 3)); - - int n = 12; - int r = 5; - int testTime = 10000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int len = (int) (Math.random() * (n + 1)); - String str = randomString(len, r); - int k = (int) (Math.random() * (str.length() + 1)); - String ans1 = maxString(str, k); - String ans2 = test(str, k); - if (!ans1.equals(ans2)) { - System.out.println("出错了!"); - System.out.println(str); - System.out.println(k); - System.out.println(ans1); - System.out.println(ans2); - break; - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class063/Code01_SumNoPositiveMinCost.java b/公开课/class063/Code01_SumNoPositiveMinCost.java deleted file mode 100644 index f893321..0000000 --- a/公开课/class063/Code01_SumNoPositiveMinCost.java +++ /dev/null @@ -1,138 +0,0 @@ -package class063; - -import java.util.Arrays; - -// 来自微软面试 -// 给定一个正数数组arr长度为n、正数x、正数y -// 你的目标是让arr整体的累加和<=0 -// 你可以对数组中的数num执行以下三种操作中的一种,且每个数最多能执行一次操作 : -// 1)不变 -// 2)可以选择让num变成0,承担x的代价 -// 3)可以选择让num变成-num,承担y的代价 -// 返回你达到目标的最小代价 -// 数据规模 : 面试时面试官没有说数据规模 -public class Code01_SumNoPositiveMinCost { - - // 暴力尝试 - public static int minOpStep1(int[] arr, int x, int y) { - int sum = 0; - for (int num : arr) { - sum += num; - } - return process1(arr, x, y, 0, sum); - } - - // arr[i...]自由选择,每个位置的数可以执行三种操作中的一种! - // 执行变0的操作,x操作,代价 -> x - // 执行变相反数的操作,y操作,代价 -> y - // 还剩下sum这么多累加和,需要去搞定! - // 返回搞定了sum,最低代价是多少? - public static int process1(int[] arr, int x, int y, int i, int sum) { - if (sum <= 0) { - return 0; - } - // sum > 0 没搞定 - if (i == arr.length) { - return Integer.MAX_VALUE; - } - // 第一选择,什么也不干! - int p1 = process1(arr, x, y, i + 1, sum); - // 第二选择,执行x的操作,变0 x + 后续 - int p2 = Integer.MAX_VALUE; - int next2 = process1(arr, x, y, i + 1, sum - arr[i]); - if (next2 != Integer.MAX_VALUE) { - p2 = x + next2; - } - // 第三选择,执行y的操作,变相反数 x + 后续 7 -7 -14 - int p3 = Integer.MAX_VALUE; - int next3 = process1(arr, x, y, i + 1, sum - (arr[i] << 1)); - if (next3 != Integer.MAX_VALUE) { - p3 = y + next3; - } - return Math.min(p1, Math.min(p2, p3)); - } - - // 最优解(贪心) - public static int minOpStep2(int[] arr, int x, int y) { - // 系统排序,小 -> 大 - Arrays.sort(arr); - int n = arr.length; - // 如何变成 大 -> 小 - for (int l = 0, r = n - 1; l <= r; l++, r--) { - int tmp = arr[l]; - arr[l] = arr[r]; - arr[r] = tmp; - } - if (x >= y) { - int sum = 0; - for (int num : arr) { - sum += num; - } - int cost = 0; - for (int i = 0; i < n && sum > 0; i++) { - sum -= arr[i] << 1; - cost += y; - } - return cost; - } else { - // 0个数执行Y - int benefit = 0; - // 全部的数都需要执行x,才能让累加和<=0 - int cost = arr.length * x; - int holdSum = 0; - for (int yRight = 0, holdLeft = n; yRight < holdLeft - 1; yRight++) { - benefit += arr[yRight]; - while (holdLeft - 1 > yRight && holdSum + arr[holdLeft - 1] <= benefit) { - holdSum += arr[holdLeft - 1]; - holdLeft--; - } - // 0...yRight x holdLeft.... - int curCost = (yRight + 1) * y + (holdLeft - yRight - 1) * x; - cost = Math.min(cost, curCost); - } - return cost; - } - } - - // 为了测试 - public static int[] randomArray(int len, int v) { - int[] arr = new int[len]; - for (int i = 0; i < len; i++) { - arr[i] = (int) (Math.random() * v) + 1; - } - return arr; - } - - // 为了测试 - public static int[] copyArray(int[] arr) { - int[] ans = new int[arr.length]; - for (int i = 0; i < arr.length; i++) { - ans[i] = arr[i]; - } - return ans; - } - - // 为了测试 - public static void main(String[] args) { - int n = 14; - int v = 20; - int c = 6; - int testTime = 2000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int len = (int) (Math.random() * n); - int[] arr = randomArray(len, v); - int[] arr1 = copyArray(arr); - int[] arr2 = copyArray(arr); - int x = (int) (Math.random() * c); - int y = (int) (Math.random() * c); - int ans1 = minOpStep1(arr1, x, y); - int ans2 = minOpStep2(arr2, x, y); - if (ans1 != ans2) { - System.out.println("出错了!"); - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class063/Code02_SplitBuildingBlock.java b/公开课/class063/Code02_SplitBuildingBlock.java deleted file mode 100644 index d70a1e9..0000000 --- a/公开课/class063/Code02_SplitBuildingBlock.java +++ /dev/null @@ -1,61 +0,0 @@ -package class063; - -import java.util.Arrays; - -// 来自京东笔试 -// 小明手中有n块积木,并且小明知道每块积木的重量。现在小明希望将这些积木堆起来 -// 要求是任意一块积木如果想堆在另一块积木上面,那么要求: -// 1) 上面的积木重量不能小于下面的积木重量 -// 2) 上面积木的重量减去下面积木的重量不能超过x -// 3) 每堆中最下面的积木没有重量要求 -// 现在小明有一个机会,除了这n块积木,还可以获得k块任意重量的积木。 -// 小明希望将积木堆在一起,同时希望积木堆的数量越少越好,你能帮他找到最好的方案么? -// 输入描述: -// 第一行三个整数n,k,x,1<=n<=200000,0<=x,k<=1000000000 -// 第二行n个整数,表示积木的重量,任意整数范围都在[1,1000000000] -// 样例输出: -// 13 1 38 -// 20 20 80 70 70 70 420 5 1 5 1 60 90 -// 1 1 5 5 20 20 60 70 70 70 80 90 420 -> 只有1块魔法积木,x = 38 -// 输出:2 -// 解释: -// 两堆分别是 -// 1 1 5 5 20 20 (50) 60 70 70 70 80 90 -// 420 -// 其中x是一个任意重量的积木,夹在20和60之间可以让积木继续往上搭 -public class Code02_SplitBuildingBlock { - - // arr里装着所有积木的重量 - // k是魔法积木的数量,每一块魔法积木都能变成任何重量 - // x差值,后 - 前 <= x - public static int minSplit(int[] arr, int k, int x) { - // 从小到大排序! - Arrays.sort(arr); - int n = arr.length; - int[] needs = new int[n]; - int size = 0; - int splits = 1; - for (int i = 1; i < n; i++) { - if (arr[i] - arr[i - 1] > x) { - needs[size++] = arr[i] - arr[i - 1]; - splits++; - } - } - if (splits == 1 || x == 0 || k == 0) { - return splits; - } - // 试图去利用魔法积木,弥合堆! - Arrays.sort(needs, 0, size); - for (int i = 0; i < size; i++) { - int need = (needs[i] - 1) / x; - if (k >= need) { - splits--; - k -= need; - } else { - break; - } - } - return splits; - } - -} diff --git a/公开课/class064/Code01_LIS.java b/公开课/class064/Code01_LIS.java deleted file mode 100644 index 481e54b..0000000 --- a/公开课/class064/Code01_LIS.java +++ /dev/null @@ -1,58 +0,0 @@ -package class064; - -// 本题测试链接 : https://leetcode.com/problems/longest-increasing-subsequence -public class Code01_LIS { - - // 时间复杂度O(N^2) - public static int maxLen(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int N = arr.length; - int[] dp = new int[N]; - dp[0] = 1; - int max = 1; - for (int i = 1; i < N; i++) { - dp[i] = 1; - int preMax = 0; - for (int j = 0; j < i; j++) { - if (arr[j] < arr[i]) { - preMax = Math.max(preMax, dp[j]); - } - } - dp[i] = Math.max(dp[i], preMax + 1); - max = Math.max(max, dp[i]); - } - return max; - } - - public static int lengthOfLIS(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int[] ends = new int[arr.length]; - ends[0] = arr[0]; - int right = 0; - int l = 0; - int r = 0; - int m = 0; - int max = 1; - for (int i = 1; i < arr.length; i++) { - l = 0; - r = right; - while (l <= r) { - m = (l + r) / 2; - if (arr[i] > ends[m]) { - l = m + 1; - } else { - r = m - 1; - } - } - right = Math.max(right, l); - ends[l] = arr[i]; - max = Math.max(max, l + 1); - } - return max; - } - -} \ No newline at end of file diff --git a/公开课/class064/Code02_EnvelopesProblem.java b/公开课/class064/Code02_EnvelopesProblem.java deleted file mode 100644 index 76387d9..0000000 --- a/公开课/class064/Code02_EnvelopesProblem.java +++ /dev/null @@ -1,60 +0,0 @@ -package class064; - -import java.util.Arrays; -import java.util.Comparator; - -// 本题测试链接 : https://leetcode.com/problems/russian-doll-envelopes/ -public class Code02_EnvelopesProblem { - - public static int maxEnvelopes(int[][] matrix) { - Envelope[] arr = sort(matrix); - int[] ends = new int[matrix.length]; - ends[0] = arr[0].h; - int right = 0; - int l = 0; - int r = 0; - int m = 0; - for (int i = 1; i < arr.length; i++) { - l = 0; - r = right; - while (l <= r) { - m = (l + r) / 2; - if (arr[i].h > ends[m]) { - l = m + 1; - } else { - r = m - 1; - } - } - right = Math.max(right, l); - ends[l] = arr[i].h; - } - return right + 1; - } - - public static class Envelope { - public int l; - public int h; - - public Envelope(int weight, int hight) { - l = weight; - h = hight; - } - } - - public static class EnvelopeComparator implements Comparator { - @Override - public int compare(Envelope o1, Envelope o2) { - return o1.l != o2.l ? o1.l - o2.l : o2.h - o1.h; - } - } - - public static Envelope[] sort(int[][] matrix) { - Envelope[] res = new Envelope[matrix.length]; - for (int i = 0; i < matrix.length; i++) { - res[i] = new Envelope(matrix[i][0], matrix[i][1]); - } - Arrays.sort(res, new EnvelopeComparator()); - return res; - } - -} diff --git a/公开课/class064/Code03_MinSwapTimes.java b/公开课/class064/Code03_MinSwapTimes.java deleted file mode 100644 index 93ab4ec..0000000 --- a/公开课/class064/Code03_MinSwapTimes.java +++ /dev/null @@ -1,95 +0,0 @@ -package class064; - -// 来自小红书 -// 一个无序数组长度为n,所有数字都不一样,并且值都在[0...n-1]范围上 -// 返回让这个无序数组变成有序数组的最小交换次数 -public class Code03_MinSwapTimes { - - // 纯暴力,arr长度大一点都会超时 - // 但是绝对正确 - public static int minSwap1(int[] arr) { - return process1(arr, 0); - } - - // 让arr变有序,最少的交换次数是多少!返回 - // times, 之前已经做了多少次交换 - public static int process1(int[] arr, int times) { - boolean sorted = true; - for (int i = 1; i < arr.length; i++) { - if (arr[i - 1] > arr[i]) { - sorted = false; - break; - } - } - if (sorted) { - return times; - } - // 数组现在是无序的状态! - if (times >= arr.length - 1) { - return Integer.MAX_VALUE; - } - int ans = Integer.MAX_VALUE; - for (int i = 0; i < arr.length; i++) { - for (int j = i + 1; j < arr.length; j++) { - swap(arr, i, j); - ans = Math.min(ans, process1(arr, times + 1)); - swap(arr, i, j); - } - } - return ans; - } - - public static void swap(int[] arr, int i, int j) { - int tmp = arr[i]; - arr[i] = arr[j]; - arr[j] = tmp; - } - - // 已知arr中,只有0~n-1这些值,并且都出现1次 - public static int minSwap2(int[] arr) { - int ans = 0; - for (int i = 0; i < arr.length; i++) { - // 来到0、1、2、3、。。。。i - // 0 -> 0 跳过 - // 7 -> 7 跳过 - // 6 -> 13 不能跳过! - // 6 != 13 6位置,13位置的数,交换 - // [6] = 13 -> 正确归为 - // [13] = ? -> 来到6位置 - while (i != arr[i]) { - swap(arr, i, arr[i]); - ans++; - } - } - return ans; - } - - // 为了测试 - public static int[] randomArray(int len) { - int[] arr = new int[len]; - for (int i = 0; i < len; i++) { - arr[i] = i; - } - for (int i = 0; i < len; i++) { - swap(arr, i, (int) (Math.random() * len)); - } - return arr; - } - - public static void main(String[] args) { - int n = 6; - int testTime = 2000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int len = (int) (Math.random() * n) + 1; - int[] arr = randomArray(len); - int ans1 = minSwap1(arr); - int ans2 = minSwap2(arr); - if (ans1 != ans2) { - System.out.println("出错了!"); - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class064/Code04_PoemProblem.java b/公开课/class064/Code04_PoemProblem.java deleted file mode 100644 index f271199..0000000 --- a/公开课/class064/Code04_PoemProblem.java +++ /dev/null @@ -1,149 +0,0 @@ -package class064; - -import java.util.Arrays; -import java.util.HashMap; - -// 来自小红书 -// 有四种诗的韵律分别为: AABB、ABAB、ABBA、AAAA -// 比如 : 1 1 3 3就属于AABB型的韵律、6 6 6 6就属于AAAA型的韵律等等 -// 一个数组arr,当然可以生成很多的子序列,如果某个子序列一直以韵律的方式连接起来,我们称这样的子序列是有效的 -// 比如, arr = { 1, 1, 15, 1, 34, 1, 2, 67, 3, 3, 2, 4, 15, 3, 17, 4, 3, 7, 52, 7, 81, 9, 9 } -// arr的一个子序列为{1, 1, 1, 1, 2, 3, 3, 2, 4, 3, 4, 3, 7, 7, 9, 9} -// 其中1, 1, 1, 1是AAAA、2, 3, 3, 2是ABBA、4, 3, 4, 3是ABAB、7, 7, 9, 9是AABB -// 可以看到,整个子序列一直以韵律的方式连接起来,所以这个子序列是有效的 -// 给定一个数组arr, 返回最长的有效子序列长度 -// 题目限制 : arr长度 <= 4000, arr中的值<= 10^9 -// 离散化之后,arr长度 <= 4000, arr中的值<= 4000 -public class Code04_PoemProblem { - - public static int maxLen1(int[] arr) { - if (arr == null || arr.length < 4) { - return 0; - } - int[] path = new int[arr.length]; - return process1(arr, 0, path, 0); - } - - public static int process1(int[] arr, int index, int[] path, int size) { - if (index == arr.length) { - if (size % 4 != 0) { - return 0; - } else { - for (int i = 0; i < size; i += 4) { - if (!valid(path, i)) { - return 0; - } - } - return size; - } - } else { - int p1 = process1(arr, index + 1, path, size); - path[size] = arr[index]; - int p2 = process1(arr, index + 1, path, size + 1); - return Math.max(p1, p2); - } - } - - public static boolean valid(int[] p, int i) { - // AABB - // ABAB - // ABBA - // AAAA - return (p[i] == p[i + 1] && p[i + 2] == p[i + 3]) - || (p[i] == p[i + 2] && p[i + 1] == p[i + 3] && p[i] != p[i + 1]) - || (p[i] == p[i + 3] && p[i + 1] == p[i + 2] && p[i] != p[i + 1]); - } - - // AABB - // ABAB - // ABBA - // AAAA - // 先看前三个规则:AABB、ABAB、ABBA - // 首先A、A、B、B的全排列为: - // AABB -> AABB - // ABAB -> ABAB - // ABBA -> ABBA - // BBAA -> 等同于AABB,因为A和B谁在前、谁在后都算是 : AABB的范式 - // BABA -> 等同于ABAB,因为A和B谁在前、谁在后都算是 : ABAB的范式 - // BAAB -> 等同于ABBA,因为A和B谁在前、谁在后都算是 : ABBA的范式 - // 也就是说,AABB、ABAB、ABBA这三个规则,可以这么用: - // 只要有两个不同的数,都出现2次,那么这一共4个数就一定符合韵律规则。 - // 所以: - // 1) 当来到arr中的一个数字num的时候, - // 如果num已经出现了2次了, 只要之前还有一个和num不同的数, - // 也出现了两次,则一定符合了某个规则, 长度直接+4,然后清空所有的统计 - // 2) 当来到arr中的一个数字num的时候, - // 如果num已经出现了4次了(规则四), 长度直接+4,然后清空所有的统计 - public static int maxLen2(int[] arr) { - // 统计某个数(key),出现的次数(value) - HashMap map = new HashMap<>(); - // tow代表目前有多少数出现了2次 - int two = 0; - // ans代表目前符合韵律链接的子序列增长到了多长 - int ans = 0; - // 当前的num出现了几次 - int numTimes = 0; - for (int num : arr) { - // 对当前的num,做次数统计 - map.put(num, map.getOrDefault(num, 0) + 1); - // 把num出现的次数拿出来 - numTimes = map.get(num); - // 如果num刚刚出现了2次, 那么目前出现了2次的数,的数量,需要增加1个 - two += numTimes == 2 ? 1 : 0; - // 下面的if代表 : - // 如果目前有2个数出现2次了,可以连接了 - // 如果目前有1个数出现4次了,可以连接了 - if (two == 2 || numTimes == 4) { - ans += 4; - map.clear(); - two = 0; - } - } - return ans; - } - - // 为了测试 - public static int[] randomArray(int len, int value) { - int[] arr = new int[len]; - for (int i = 0; i < len; i++) { - arr[i] = (int) (Math.random() * value); - } - return arr; - } - - // 为了测试 - public static void main(String[] args) { - // 1111 2332 4343 7799 - int[] test = { 1, 1, 15, 1, 34, 1, 2, 67, 3, 3, 2, 4, 15, 3, 17, 4, 3, 7, 52, 7, 81, 9, 9 }; - System.out.println(maxLen1(test)); - System.out.println(maxLen2(test)); - System.out.println("==========="); - System.out.println("随机测试开始"); - int len = 20; - int value = 6; - int testTime = 1000; - for (int i = 0; i < testTime; i++) { - int n = (int) (Math.random() * len) + 1; - int[] arr = randomArray(n, value); - int[] arr1 = Arrays.copyOf(arr, arr.length); - int[] arr2 = Arrays.copyOf(arr, arr.length); - int ans1 = maxLen1(arr1); - int ans2 = maxLen2(arr2); - if (ans1 != ans2) { - System.out.println("出错了!"); - } - } - System.out.println("随机测试结束"); - System.out.println("==========="); - - long start; - long end; - int[] longArr = randomArray(5000000, 20); - start = System.currentTimeMillis(); - maxLen2(longArr); - end = System.currentTimeMillis(); - System.out.println("大样本量运行时间(毫秒) : " + (end - start)); - System.out.println("==========="); - } - -} diff --git a/公开课/class065/Code01_CoverMax.java b/公开课/class065/Code01_CoverMax.java deleted file mode 100644 index a64a9c6..0000000 --- a/公开课/class065/Code01_CoverMax.java +++ /dev/null @@ -1,157 +0,0 @@ -package class065; - -import java.util.Arrays; -import java.util.Comparator; -import java.util.PriorityQueue; - -public class Code01_CoverMax { - - public static int maxCover1(int[][] lines) { - int min = Integer.MAX_VALUE; - int max = Integer.MIN_VALUE; - for (int i = 0; i < lines.length; i++) { - min = Math.min(min, lines[i][0]); - max = Math.max(max, lines[i][1]); - } - int cover = 0; - for (double p = min + 0.5; p < max; p += 1) { - int cur = 0; - for (int i = 0; i < lines.length; i++) { - if (lines[i][0] < p && lines[i][1] > p) { - cur++; - } - } - cover = Math.max(cover, cur); - } - return cover; - } - - public static int maxCover2(int[][] m) { - Line[] lines = new Line[m.length]; - for (int i = 0; i < m.length; i++) { - lines[i] = new Line(m[i][0], m[i][1]); - } - Arrays.sort(lines, new StartComparator()); - // lines - // - PriorityQueue heap = new PriorityQueue<>(); - int max = 0; - for (int i = 0; i < lines.length; i++) { - // lines[i] -> cur 在黑盒中,把<=cur.start 东西都弹出 - while (!heap.isEmpty() && heap.peek() <= lines[i].start) { - heap.poll(); - } - heap.add(lines[i].end); - max = Math.max(max, heap.size()); - } - return max; - } - - public static class Line { - public int start; - public int end; - - public Line(int s, int e) { - start = s; - end = e; - } - } - - public static class EndComparator implements Comparator { - - @Override - public int compare(Line o1, Line o2) { - return o1.end - o2.end; - } - - } - - // for test - public static int[][] generateLines(int N, int L, int R) { - int size = (int) (Math.random() * N) + 1; - int[][] ans = new int[size][2]; - for (int i = 0; i < size; i++) { - int a = L + (int) (Math.random() * (R - L + 1)); - int b = L + (int) (Math.random() * (R - L + 1)); - if (a == b) { - b = a + 1; - } - ans[i][0] = Math.min(a, b); - ans[i][1] = Math.max(a, b); - } - return ans; - } - - public static class StartComparator implements Comparator { - - @Override - public int compare(Line o1, Line o2) { - return o1.start - o2.start; - } - - } - - public static void main(String[] args) { - - - PriorityQueue t = new PriorityQueue<>(); - - // add poll 极快,O(logN) - t.add(5); - t.add(3); - t.add(2); - t.add(4); - t.add(2); - t.add(3); - - while(!t.isEmpty()) { - System.out.println(t.poll()); - } - - - - - - - - - - -// Line l1 = new Line(4, 9); -// Line l2 = new Line(1, 4); -// Line l3 = new Line(7, 15); -// Line l4 = new Line(2, 4); -// Line l5 = new Line(4, 6); -// Line l6 = new Line(3, 7); -// -// // 底层堆结构,heap -// PriorityQueue heap = new PriorityQueue<>(new StartComparator()); -// heap.add(l1); -// heap.add(l2); -// heap.add(l3); -// heap.add(l4); -// heap.add(l5); -// heap.add(l6); -// -// while (!heap.isEmpty()) { -// Line cur = heap.poll(); -// System.out.println(cur.start + "," + cur.end); -// } -// -// System.out.println("test begin"); -// int N = 100; -// int L = 0; -// int R = 200; -// int testTimes = 200000; -// for (int i = 0; i < testTimes; i++) { -// int[][] lines = generateLines(N, L, R); -// int ans1 = maxCover1(lines); -// int ans2 = maxCover2(lines); -// if (ans1 != ans2) { -// System.out.println("Oops!"); -// } -// } -// System.out.println("test end"); - } - -} diff --git a/公开课/class065/Code02_Heaters.java b/公开课/class065/Code02_Heaters.java deleted file mode 100644 index 3d1fc0e..0000000 --- a/公开课/class065/Code02_Heaters.java +++ /dev/null @@ -1,114 +0,0 @@ -package class065; - -import java.util.Arrays; - -// leetcode 475题 -public class Code02_Heaters { - - // 比如地点是7, 9, 14 - // 供暖点的位置: 1 3 4 5 13 15 17 - // 先看地点7 - // 由1供暖,半径是6 - // 由3供暖,半径是4 - // 由4供暖,半径是3 - // 由5供暖,半径是2 - // 由13供暖,半径是6 - // 由此可知,地点7应该由供暖点5来供暖,半径是2 - // 再看地点9 - // 供暖点不回退 - // 由5供暖,半径是4 - // 由13供暖,半径是4 - // 由15供暖,半径是6 - // 由此可知,地点9应该由供暖点13来供暖,半径是4 - // 为什么是13而不是5?因为接下来的地点都会更靠右,所以半径一样的时候,就应该选更右的供暖点 - // 再看地点14 - // 供暖点不回退 - // 由13供暖,半径是1 - // 由15供暖,半径是1 - // 由17供暖,半径是3 - // 由此可知,地点14应该由供暖点15来供暖,半径是1 - // 以此类推 - public static int findRadius(int[] houses, int[] heaters) { - Arrays.sort(houses); - Arrays.sort(heaters); - int ans = 0; - // 时间复杂度O(N) - // i是地点,j是供暖点 - for (int i = 0, j = 0; i < houses.length; i++) { - while (!best(houses, heaters, i, j)) { - j++; - } - ans = Math.max(ans, Math.abs(heaters[j] - houses[i])); - } - return ans; - } - - // 这个函数含义: - // 当前的地点houses[i]由heaters[j]来供暖是最优的吗? - // 当前的地点houses[i]由heaters[j]来供暖,产生的半径是a - // 当前的地点houses[i]由heaters[j + 1]来供暖,产生的半径是b - // 如果a < b, 说明是最优,供暖不应该跳下一个位置 - // 如果a >= b, 说明不是最优,应该跳下一个位置 - public static boolean best(int[] houses, int[] heaters, int i, int j) { - return j == heaters.length - 1 - || Math.abs(heaters[j] - houses[i]) < Math.abs(heaters[j + 1] - houses[i]); - } - - // 下面这个方法不对,你能找出原因嘛?^_^ - public static int findRadius2(int[] houses, int[] heaters) { - Arrays.sort(houses); - Arrays.sort(heaters); - int ans = 0; - // 时间复杂度O(N) - // i是地点,j是供暖点 - for (int i = 0, j = 0; i < houses.length; i++) { - while (!best2(houses, heaters, i, j)) { - j++; - } - ans = Math.max(ans, Math.abs(heaters[j] - houses[i])); - } - return ans; - } - - public static boolean best2(int[] houses, int[] heaters, int i, int j) { - return j == heaters.length - 1 || Math.abs(heaters[j] - houses[i]) <= Math.abs(heaters[j + 1] - houses[i]); - } - - // 为了测试 - public static int[] randomArray(int len, int v) { - int[] arr = new int[len]; - for (int i = 0; i < len; i++) { - arr[i] = (int) (Math.random() * v) + 1; - } - return arr; - } - - // 为了测试 - public static void main(String[] args) { - int len = 5; - int v = 10; - int testTime = 10000; - for (int i = 0; i < testTime; i++) { - int[] a = randomArray(len, v); - int[] b = randomArray(len, v); - int ans1 = findRadius(a, b); - int ans2 = findRadius2(a, b); - if (ans1 != ans2) { - System.out.println("A : "); - for (int num : a) { - System.out.print(num + " "); - } - System.out.println(); - System.out.println("B : "); - for (int num : b) { - System.out.print(num + " "); - } - System.out.println(); - System.out.println(ans1); - System.out.println(ans2); - break; - } - } - } - -} diff --git a/公开课/class065/Code03_TrappingRainWater.java b/公开课/class065/Code03_TrappingRainWater.java deleted file mode 100644 index 9428906..0000000 --- a/公开课/class065/Code03_TrappingRainWater.java +++ /dev/null @@ -1,121 +0,0 @@ -package class065; - -public class Code03_TrappingRainWater { - - /* - * 给定一个正整数数组arr,把arr想象成一个直方图。返回这个直方图如果装水,能装下几格水? - * - */ - - public static int water1(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int water = 0; - for (int i = 1; i < N - 1; i++) { - int leftMax = Integer.MIN_VALUE; - for (int j = 0; j < i; j++) { - leftMax = Math.max(leftMax, arr[j]); - } - int rightMax = Integer.MIN_VALUE; - for (int j = i + 1; j < N; j++) { - rightMax = Math.max(rightMax, arr[j]); - } - water += Math.max(Math.min(leftMax, rightMax) - arr[i], 0); - } - return water; - } - - public static int water2(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int[] leftMaxs = new int[N]; - leftMaxs[0] = arr[0]; - for (int i = 1; i < N; i++) { - leftMaxs[i] = Math.max(leftMaxs[i - 1], arr[i]); - } - - int[] rightMaxs = new int[N]; - rightMaxs[N - 1] = arr[N - 1]; - for (int i = N - 2; i >= 0; i--) { - rightMaxs[i] = Math.max(rightMaxs[i + 1], arr[i]); - } - int water = 0; - for (int i = 1; i < N - 1; i++) { - water += Math.max(Math.min(leftMaxs[i - 1], rightMaxs[i + 1]) - arr[i], 0); - } - return water; - } - - public static int water3(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int[] rightMaxs = new int[N]; - rightMaxs[N - 1] = arr[N - 1]; - for (int i = N - 2; i >= 0; i--) { - rightMaxs[i] = Math.max(rightMaxs[i + 1], arr[i]); - } - int water = 0; - int leftMax = arr[0]; - for (int i = 1; i < N - 1; i++) { - water += Math.max(Math.min(leftMax, rightMaxs[i + 1]) - arr[i], 0); - leftMax = Math.max(leftMax, arr[i]); - } - return water; - } - - public static int water4(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int L = 1; - int leftMax = arr[0]; - int R = N - 2; - int rightMax = arr[N - 1]; - int water = 0; - while (L <= R) { - if (leftMax <= rightMax) { - water += Math.max(0, leftMax - arr[L]); - leftMax = Math.max(leftMax, arr[L++]); - } else { - water += Math.max(0, rightMax - arr[R]); - rightMax = Math.max(rightMax, arr[R--]); - } - } - return water; - } - - // for test - public static int[] generateRandomArray(int len, int value) { - int[] ans = new int[(int) (Math.random() * len) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * value) + 1; - } - return ans; - } - - public static void main(String[] args) { - int len = 100; - int value = 200; - int testTimes = 100000; - System.out.println("测试开始"); - for (int i = 0; i < testTimes; i++) { - int[] arr = generateRandomArray(len, value); - int ans1 = water1(arr); - int ans2 = water2(arr); - int ans3 = water3(arr); - int ans4 = water4(arr); - if (ans1 != ans2 || ans3 != ans4 || ans1 != ans3) { - System.out.println("Oops!"); - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class065/Code04_CombinationSumIV.java b/公开课/class065/Code04_CombinationSumIV.java deleted file mode 100644 index 77b746e..0000000 --- a/公开课/class065/Code04_CombinationSumIV.java +++ /dev/null @@ -1,65 +0,0 @@ -package class065; - -import java.util.Arrays; - -// leetcode 377题 -public class Code04_CombinationSumIV { - - // 当前剩下的值是rest, - // nums中所有的值,都可能作为分解rest的,第一块!全试一试 - // nums, 无重复,都是正 - // rest, - public static int ways(int rest, int[] nums) { - if (rest < 0) { - return 0; - } - if (rest == 0) { - return 1; - } - int ways = 0; - for (int num : nums) { - ways += ways(rest - num, nums); - } - return ways; - } - - public static int[] dp = new int[1001]; - - public static int combinationSum41(int[] nums, int target) { - Arrays.fill(dp, 0, target + 1, -1); - return process1(nums, target); - } - - public static int process1(int[] nums, int rest) { - if (rest < 0) { - return 0; - } - if (dp[rest] != -1) { - return dp[rest]; - } - int ans = 0; - if (rest == 0) { - ans = 1; - } else { - for (int num : nums) { - ans += process1(nums, rest - num); - } - } - dp[rest] = ans; - return ans; - } - - // 剪枝 + 严格位置依赖的动态规划 - public static int combinationSum42(int[] nums, int target) { - Arrays.sort(nums); - int[] dp = new int[target + 1]; - dp[0] = 1; - for (int rest = 1; rest <= target; rest++) { - for (int i = 0; i < nums.length && nums[i] <= rest; i++) { - dp[rest] += dp[rest - nums[i]]; - } - } - return dp[target]; - } - -} diff --git a/公开课/class066/Code01_BestTimeToBuyAndSellStock.java b/公开课/class066/Code01_BestTimeToBuyAndSellStock.java deleted file mode 100644 index 79de03c..0000000 --- a/公开课/class066/Code01_BestTimeToBuyAndSellStock.java +++ /dev/null @@ -1,25 +0,0 @@ -package class066; - -// leetcode题目 : https://leetcode.com/problems/best-time-to-buy-and-sell-stock/ -public class Code01_BestTimeToBuyAndSellStock { - - public static int maxProfit(int[] prices) { - if (prices == null || prices.length == 0) { - return 0; - } - // 最好的一笔收入,是多少 - int ans = 0; - // 0..0 范围上的最小值 - int min = prices[0]; - // 假设每一个i,都是卖出时机! - for (int i = 1; i < prices.length; i++) { - // 更新min,min 0...i-1的最小值 - // min 0...i整体的最小值! - min = Math.min(min, prices[i]); - // prices[i] - min 挣得最多的钱 - ans = Math.max(ans, prices[i] - min); - } - return ans; - } - -} diff --git a/公开课/class066/Code02_BestTimeToBuyAndSellStockII.java b/公开课/class066/Code02_BestTimeToBuyAndSellStockII.java deleted file mode 100644 index 7b730dc..0000000 --- a/公开课/class066/Code02_BestTimeToBuyAndSellStockII.java +++ /dev/null @@ -1,17 +0,0 @@ -package class066; - -//leetcode题目 : https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/ -public class Code02_BestTimeToBuyAndSellStockII { - - public static int maxProfit(int[] prices) { - if (prices == null || prices.length == 0) { - return 0; - } - int ans = 0; - for (int i = 1; i < prices.length; i++) { - ans += Math.max(prices[i] - prices[i-1], 0); - } - return ans; - } - -} diff --git a/公开课/class066/Code03_BestTimeToBuyAndSellStockIII.java b/公开课/class066/Code03_BestTimeToBuyAndSellStockIII.java deleted file mode 100644 index 1dd09fc..0000000 --- a/公开课/class066/Code03_BestTimeToBuyAndSellStockIII.java +++ /dev/null @@ -1,123 +0,0 @@ -package class066; - -//leetcode题目 : https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/ -public class Code03_BestTimeToBuyAndSellStockIII { - -// public static int maxProfit1(int[] prices) { -// if (prices == null || prices.length < 2) { -// return 0; -// } -// int n = prices.length; -// int ans = 0; -// int[] doneOnceMax = new int[n]; -// // doneOnceMax 去生成! -// // doneOnceMax[i] 指的是:0~i范围上,只做一笔交易!获得的最大钱! -// for(int j = 0; j < n; j++) { -// // 第二笔交易的卖出时机 -// // j时刻 -// // 13时刻,第二笔交易的卖出时机 -// // 第二笔交易的买入时机:0 【0~0】 0 -// // 1 [0~1] 1 13 -// // 2 [0~2] 2 13 -// // i j -// // 0 13 -// // 1 13 -// // .. -// // 13..13 -// for(int i = 0; i <= j; i++) { -// int second = prices[j] - prices[i]; -// int first = doneOnceMax[i];// 0...i 只做一笔交易!获得的最大钱! -// int cur = first + second; -// ans -// -// -// } -// return ans; -// -//// } -// -// -// -// -// -// -// -// for (int i = 1; i < n; i++) { -// -// } -// return ans; -// } - -// public static int maxProfit2(int[] prices) { -// if (prices == null || prices.length < 2) { -// return 0; -// } -// int n = prices.length; -// // 指标:doneOnceMinusOneBuyMax[i] : 0 ~ i上,一定要做完一次交易,还得扣除掉一次买入, -// // 所有情况中,整体的最优! -// -// -// -// // 第一步:请把如下的含义结构生成 -// int[] doneOnceMax = new int[n]; // 该怎么生成怎么生成! -// // doneOnceMax[i] : 0..i 做完一笔交易的最好钱数 -// -// // 第二步,把指标数组生成! -// int[] doneOnceMinusOneBuyMax = new int[n]; -// -// // doneOnceMinusOneBuyMax[0] : 0 ~ 0 -// // doneOnceMinusOneBuyMax[1] : 0 ~ 1 -// // doneOnceMinusOneBuyMax[2] : 0 ~ 2 -// // ... -// -// doneOnceMinusOneBuyMax[0] = -prices[0]; -// -// -// for (int i = 1; i < n; i++) { -// // doneOnceMinusOneBuyMax[i] -// // 0 ~ i上,一定要做完一次交易,还得扣除掉一次买入 -// // 可能性1:扣除掉的这一次买入,和i无关! -// int p1 = doneOnceMinusOneBuyMax[i-1]; -// // 可能性2 :扣除掉的这一次买入,和i有关! -// int p2 = doneOnceMax[i] - prices[i]; -// doneOnceMinusOneBuyMax[i] = Math.max(p1, p2); -// } -// -// // 第三步 -// int ans = 0; -// for(int i = 0; i < n; i++) { -// ans = Math.max(ans, doneOnceMinusOneBuyMax[i] + prices[i]); -// } -// return ans; -// } - - - - public static int maxProfit(int[] prices) { - if (prices == null || prices.length < 2) { - return 0; - } - int ans = 0; - // doneOnceMinusBuyMax -> 指标0 - int doneOnceMinusBuyMax = -prices[0]; - // doneOnceMax -> 0 ~ 0 只做一次交易,获得的最好钱数 - int doneOnceMax = 0; - // 0 ~ 0 上的最小值! - int min = prices[0]; - for (int i = 1; i < prices.length; i++) { - // 0 ~ i整体的最小值! - min = Math.min(min, prices[i]); - ans = Math.max(ans, doneOnceMinusBuyMax + prices[i]); - // 0 ~ i上,只做一次交易,获得的最好钱数 - // 可能性1:只做的这一次交易,不是在i位置卖的,(0~i-1)上一步的doneOnceMax - // 可能性2:只做的这一次交易,是在i位置卖的, prices[i] - min - doneOnceMax = Math.max(doneOnceMax, prices[i] - min); - // 0 ~ i上,只做一次交易 并且 扣掉一次买入,整体获得的最好钱数 - // 可能性1:扣掉一次的这一次买入,不在i上发生,(0~i-1)上一步的doneOnceMinusBuyMax - // 可能性2:扣掉一次的这一次买入,必须在i上发生,(0~i)上的那次最好交易,- prices[i] - doneOnceMinusBuyMax = Math.max(doneOnceMinusBuyMax, doneOnceMax - prices[i]); - } - return ans; - } - -} diff --git a/公开课/class066/Code04_SplitArrayLargestSum.java b/公开课/class066/Code04_SplitArrayLargestSum.java deleted file mode 100644 index a30afe1..0000000 --- a/公开课/class066/Code04_SplitArrayLargestSum.java +++ /dev/null @@ -1,47 +0,0 @@ -package class066; - -// leetcode原题 -// 测试链接:https://leetcode.com/problems/split-array-largest-sum/ -public class Code04_SplitArrayLargestSum { - - public static int splitArray(int[] nums, int M) { - long sum = 0; - for (int i = 0; i < nums.length; i++) { - sum += nums[i]; - } - long l = 0; - long r = sum; - long ans = 0; - while (l <= r) { - long mid = (l + r) / 2; - long cur = getNeedParts(nums, mid); - if (cur <= M) { - ans = mid; - r = mid - 1; - } else { - l = mid + 1; - } - } - return (int) ans; - } - - public static int getNeedParts(int[] arr, long aim) { - for (int i = 0; i < arr.length; i++) { - if (arr[i] > aim) { - return Integer.MAX_VALUE; - } - } - int parts = 1; - int all = arr[0]; - for (int i = 1; i < arr.length; i++) { - if (all + arr[i] > aim) { - parts++; - all = arr[i]; - } else { - all += arr[i]; - } - } - return parts; - } - -} diff --git a/公开课/class066/Code05_KokoEatingBananas.java b/公开课/class066/Code05_KokoEatingBananas.java deleted file mode 100644 index 86ad9de..0000000 --- a/公开课/class066/Code05_KokoEatingBananas.java +++ /dev/null @@ -1,50 +0,0 @@ -package class066; - -// leetcode题目 : https://leetcode.com/problems/koko-eating-bananas/ -public class Code05_KokoEatingBananas { - - public static int minEatingSpeed(int[] piles, int h) { - int L = 1; - int R = 0; - for (int pile : piles) { - R = Math.max(R, pile); - } - // L --- R - // 去寻找最合适的速度! - int ans = 0; - int M = 0; - while (L <= R) { - // M = (L + R) / 2 - M = L + ((R - L) >> 1); - if (hours(piles, M) <= h) { - ans = M; - R = M - 1; - } else { - L = M + 1; - } - } - return ans; - } - - // 一堆香蕉,piles - // 给定一个速度,speed - // 同一堆,吃完就躺平, - // 请返回需要几小时? - public static int hours(int[] piles, int speed) { - int ans = 0; - for (int pile : piles) { - ans += (pile + speed - 1) / speed; - } - return ans; - } - - - public static void main(String[] args) { - int a = 8; - int b = 2; - // 8 / 2 4 4 - int ans = (a + b - 1) / b; - System.out.println(ans); - } - -} diff --git a/公开课/class067/Code01_IsStepSum.java b/公开课/class067/Code01_IsStepSum.java deleted file mode 100644 index 0ccd89d..0000000 --- a/公开课/class067/Code01_IsStepSum.java +++ /dev/null @@ -1,68 +0,0 @@ -package class067; - -import java.util.HashMap; - -public class Code01_IsStepSum { - - public static boolean isStepSum(int x) { - // L = 0 R = stepSum; - // 可能的答案,只会在L ~ R上 - int L = 0; - int R = x; - int M = 0; - int cur = 0; - // L <= R 还能继续二分 - while (L <= R) { - // 求中点 - // M = (L + R) / 2; - // M = L + (R - L) / 2 - // a / 2 -> a >> 1 - M = L + ((R - L) >> 1); - cur = stepSum(M); - if (cur == x) { - return true; - } else if (cur < x) { - L = M + 1; - } else { - R = M - 1; - } - } - return false; - } - - // 输入num, - // 输出num的step sum - // 代价 : num的十进制位的数量 - public static int stepSum(int num) { - int sum = 0; - while (num != 0) { - sum += num; - num /= 10; - } - return sum; - } - - // for test - public static HashMap generateStepSumNumberMap(int numMax) { - HashMap map = new HashMap<>(); - for (int i = 0; i <= numMax; i++) { - map.put(stepSum(i), i); - } - return map; - } - - // for test - public static void main(String[] args) { - int max = 1000000; - int maxStepSum = stepSum(max); - HashMap ans = generateStepSumNumberMap(max); - System.out.println("测试开始"); - for (int i = 0; i <= maxStepSum; i++) { - if (ans.containsKey(i) ^ isStepSum(i)) { - System.out.println("出错了!"); - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class067/Code02_KokoEatingBananas.java b/公开课/class067/Code02_KokoEatingBananas.java deleted file mode 100644 index 5a1aac4..0000000 --- a/公开课/class067/Code02_KokoEatingBananas.java +++ /dev/null @@ -1,40 +0,0 @@ -package class067; - -// 测试链接 : https://leetcode.com/problems/koko-eating-bananas/ -public class Code02_KokoEatingBananas { - - public static int minEatingSpeed(int[] piles, int h) { - int L = 1; - int R = 0; - for (int pile : piles) { - R = Math.max(R, pile); - } - // 只需要在L ~ R范围上,最小的达标速度 - // 1 ~ max - int ans = 0; - int M = 0; - while (L <= R) { - M = L + ((R - L) >> 1); - if (hours(piles, M) <= h) { - ans = M; - R = M - 1; - } else { - L = M + 1; - } - } - return ans; - } - - // 一堆香蕉都在piles数组里 - // 猩猩以speed的速度吃! - // 但是,这一小时吃完,就躺! - // 返回一共要几小时? - public static int hours(int[] piles, int speed) { - int ans = 0; - for (int pile : piles) { - ans += (pile + speed - 1) / speed; - } - return ans; - } - -} diff --git a/公开课/class067/Code03_SplitArrayLargestSum.java b/公开课/class067/Code03_SplitArrayLargestSum.java deleted file mode 100644 index c9dcdc7..0000000 --- a/公开课/class067/Code03_SplitArrayLargestSum.java +++ /dev/null @@ -1,49 +0,0 @@ -package class067; - -// 测试链接:https://leetcode.com/problems/split-array-largest-sum/ -public class Code03_SplitArrayLargestSum { - - public static int splitArray(int[] nums, int M) { - int sum = 0; - for (int i = 0; i < nums.length; i++) { - sum += nums[i]; - } - int l = 0; - int r = sum; - int ans = 0; - while (l <= r) { - int mid = (l + r) / 2; - int cur = need(nums, mid); - if (cur <= M) { - ans = mid; - r = mid - 1; - } else { - l = mid + 1; - } - } - return ans; - } - - // 每一幅画需要的时间,都在arr里 - // 如果我一定要求整体不能超过aim小时 - // 返回需要的最少画家数量 - public static int need(int[] arr, long aim) { - for (int i = 0; i < arr.length; i++) { - if (arr[i] > aim) { - return Integer.MAX_VALUE; - } - } - int parts = 1; - int all = arr[0]; - for (int i = 1; i < arr.length; i++) { - if (all + arr[i] > aim) { - parts++; - all = arr[i]; - } else { - all += arr[i]; - } - } - return parts; - } - -} diff --git a/公开课/class067/Code04_MinimumWindowSubstring.java b/公开课/class067/Code04_MinimumWindowSubstring.java deleted file mode 100644 index a2b5d0a..0000000 --- a/公开课/class067/Code04_MinimumWindowSubstring.java +++ /dev/null @@ -1,53 +0,0 @@ -package class067; - -// 测试链接 : https://leetcode.com/problems/minimum-window-substring/ -public class Code04_MinimumWindowSubstring { - - // 在s中,找到包含t的最短子串 - // 返回最短子串 - public static String minWindow(String s, String t) { - if (s.length() < t.length()) { - return ""; - } - char[] str = s.toCharArray(); - char[] target = t.toCharArray(); - int[] map = new int[256]; - for (char cha : target) { - map[cha]++; - } - int all = target.length; - int L = 0; - int R = 0; - // [L,R) - // [1,2) -> 1..1 - // [1,5) -> 1..4 - // [1,1) -> 窗口一个字符也没有了 - // 所有发现达标的窗口中,最短窗口的长度是多少minLen - // ansl...ansr 到底是哪一段的子串,记一下! - int minLen = Integer.MAX_VALUE; - int ansl = -1; - int ansr = -1; - // 窗口右边界没到底的时候 - while (R != str.length) { - map[str[R]]--; - if (map[str[R]] >= 0) { - all--; - } - if (all == 0) { - while (map[str[L]] < 0) { - map[str[L++]]++; - } - if (minLen > R - L + 1) { - minLen = R - L + 1; - ansl = L; - ansr = R; - } - all++; - map[str[L++]]++; - } - R++; - } - return minLen == Integer.MAX_VALUE ? "" : s.substring(ansl, ansr + 1); - } - -} diff --git a/公开课/class067/Code05_SubarraysWithKDifferentIntegers.java b/公开课/class067/Code05_SubarraysWithKDifferentIntegers.java deleted file mode 100644 index 318a348..0000000 --- a/公开课/class067/Code05_SubarraysWithKDifferentIntegers.java +++ /dev/null @@ -1,66 +0,0 @@ -package class067; - -// 测试链接 : https://leetcode.com/problems/subarrays-with-k-different-integers/ -public class Code05_SubarraysWithKDifferentIntegers { - - public static int subarraysWithKDistinct1(int[] arr, int k) { - return numsMostK(arr, k) - numsMostK(arr, k - 1); - } - - public static int numsMostK(int[] arr, int k) { - int n = arr.length; - int ans = 0; - int[] counts = new int[n + 1]; - for (int left = 0, right = 0, kinds = 0; right < n; right++) { - if (counts[arr[right]]++ == 0) { - kinds++; - } - while (kinds > k) { - if (counts[arr[left++]]-- == 1) { - kinds--; - } - } - ans += right - left; - } - return ans; - } - - public static int subarraysWithKDistinct2(int[] nums, int k) { - int n = nums.length; - // <= k-1种数的窗口词频统计 - int[] minusOneWindow = new int[n + 1]; - int minusOneWindowLeft = 0; - int minusOneWindowKinds = 0; - // <= k种数的窗口词频统计 - int[] kWindow = new int[n + 1]; - int kWindowLeft = 0; - int kWindowKinds = 0; - int ans = 0; - for (int r = 0; r < n; r++) { - // 当前刚来到r位置! - if (minusOneWindow[nums[r]] == 0) { - minusOneWindowKinds++; - } - if (kWindow[nums[r]] == 0) { - kWindowKinds++; - } - minusOneWindow[nums[r]]++; - kWindow[nums[r]]++; - while (minusOneWindowKinds == k) { - if (minusOneWindow[nums[minusOneWindowLeft]] == 1) { - minusOneWindowKinds--; - } - minusOneWindow[nums[minusOneWindowLeft++]]--; - } - while (kWindowKinds > k) { - if (kWindow[nums[kWindowLeft]] == 1) { - kWindowKinds--; - } - kWindow[nums[kWindowLeft++]]--; - } - ans += minusOneWindowLeft - kWindowLeft; - } - return ans; - } - -} diff --git a/公开课/class068/Code01_MagicStone.java b/公开课/class068/Code01_MagicStone.java deleted file mode 100644 index 1ef770f..0000000 --- a/公开课/class068/Code01_MagicStone.java +++ /dev/null @@ -1,100 +0,0 @@ -package class068; - -import java.util.Arrays; - -// 来自小红书 -// [0,4,7] : 0表示这里石头没有颜色,如果变红代价是4,如果变蓝代价是7 -// [1,X,X] : 1表示这里石头已经是红,而且不能改颜色,所以后两个数X无意义 -// [2,X,X] : 2表示这里石头已经是蓝,而且不能改颜色,所以后两个数X无意义 -// 颜色只可能是0、1、2,代价一定>=0 -// 给你一批这样的小数组,要求最后必须所有石头都有颜色,且红色和蓝色一样多,返回最小代价 -// 如果怎么都无法做到所有石头都有颜色、且红色和蓝色一样多,返回-1 -public class Code01_MagicStone { - - // - // [0, 5 , 10] - // [1, X , X] - // [0, 10, 6] - // .. - // N stones N * 3 - public static int minCost(int[][] stones) { - int n = stones.length; - // n : 0011100010 - // 偶数 - // n : 0011110111 - // 奇数 - // 1 : 0000000001 - if ((n & 1) != 0) { - return -1; - } - // O(N * logN) - Arrays.sort(stones, (a, b) -> a[0] == 0 && b[0] == 0 ? (b[1] - b[2] - a[1] + a[2]) : (a[0] - b[0])); - int zero = 0; - int red = 0; - int blue = 0; - int cost = 0; - for (int i = 0; i < n; i++) { - if (stones[i][0] == 0) { - zero++; - cost += stones[i][1]; - } else if (stones[i][0] == 1) { - red++; - } else { - blue++; - } - } - // 红色如果超过了一半 或者 蓝色如果超过了一半 - // 返回-1 - // red > n /2 || blue > n / 2 - // n / 2 -> n >> 1 - if (red > (n >> 1) || blue > (n >> 1)) { - return -1; - } - // 所有无色的时候,都给红色了 - // 要把适当的石头,从红色,叛逃到蓝色 - // 叛逃的数量,blue - blue = zero - ((n >> 1) - red); - // stones: 0 1 2 3 12 13块 - for (int i = 0; i < blue; i++) { - cost += stones[i][2] - stones[i][1]; - } - return cost; - } - - public static class Student { - public int age; - public int classNo; - - public Student(int a, int c) { - age = a; - classNo = c; - } - } - - public static void main(String[] args) { - Student s1 = new Student(17, 2); - Student s2 = new Student(21, 1); - Student s3 = new Student(70, 3); - Student s4 = new Student(35, 1); - Student s5 = new Student(21, 3); - Student[] arr = { s1, s2, s3, s4, s5 }; - -// for (Student s : arr) { -// System.out.println(s.age + " , " + s.classNo); -// } - - // 大 -> 小 - // 只要返回负:第一个参数放前面 - // 只要返回正:第二个参数放前面 - // 整体按照班级从小到大排序,但是班级一样的!请按照年龄从小到大排序? - Arrays.sort(arr, (a, b) -> a.classNo != b.classNo ? (a.classNo - b.classNo) : (a.age - b.age)); - - for (Student s : arr) { - System.out.println(s.age + " , " + s.classNo); - } - -// int[][] stones = { { 1, 5, 3 }, { 2, 7, 9 }, { 0, 6, 4 }, { 0, 7, 9 }, { 0, 2, 1 }, { 0, 5, 9 } }; -// System.out.println(minCost(stones)); - } - -} diff --git a/公开课/class068/Code02_CircleCandy.java b/公开课/class068/Code02_CircleCandy.java deleted file mode 100644 index 8e40eed..0000000 --- a/公开课/class068/Code02_CircleCandy.java +++ /dev/null @@ -1,58 +0,0 @@ -package class068; - -// 来自网易 -// 给定一个正数数组arr,表示每个小朋友的得分 -// 任何两个相邻的小朋友,如果得分一样,怎么分糖果无所谓,但如果得分不一样,分数大的一定要比分数少的多拿一些糖果 -// 假设所有的小朋友坐成一个环形,返回在不破坏上一条规则的情况下,需要的最少糖果数 -public class Code02_CircleCandy { - - public static int minCandy(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - if (arr.length == 1) { - return 1; - } - int n = arr.length; - int minIndex = 0; - for (int i = 0; i < n; i++) { - if (arr[i] <= arr[lastIndex(i, n)] && arr[i] <= arr[nextIndex(i, n)]) { - minIndex = i; - break; - } - } - int[] nums = new int[n + 1]; - for (int i = 0; i <= n; i++, minIndex = nextIndex(minIndex, n)) { - nums[i] = arr[minIndex]; - } - int[] left = new int[n + 1]; - left[0] = 1; - for (int i = 1; i <= n; i++) { - left[i] = nums[i] > nums[i - 1] ? (left[i - 1] + 1) : 1; - } - int[] right = new int[n + 1]; - right[n] = 1; - for (int i = n - 1; i >= 0; i--) { - right[i] = nums[i] > nums[i + 1] ? (right[i + 1] + 1) : 1; - } - int ans = 0; - for (int i = 0; i < n; i++) { - ans += Math.max(left[i], right[i]); - } - return ans; - } - - public static int nextIndex(int i, int n) { - return i == n - 1 ? 0 : (i + 1); - } - - public static int lastIndex(int i, int n) { - return i == 0 ? (n - 1) : (i - 1); - } - - public static void main(String[] args) { - int[] arr = { 3, 4, 2, 3, 2 }; - System.out.println(minCandy(arr)); - } - -} diff --git a/公开课/class068/Code03_MinBoatEvenNumbers.java b/公开课/class068/Code03_MinBoatEvenNumbers.java deleted file mode 100644 index b08133e..0000000 --- a/公开课/class068/Code03_MinBoatEvenNumbers.java +++ /dev/null @@ -1,78 +0,0 @@ -package class068; - -import java.util.Arrays; - -// 来自腾讯 -// 给定一个正数数组arr,代表每个人的体重。给定一个正数limit代表船的载重,所有船都是同样的载重量 -// 每个人的体重都一定不大于船的载重 -// 要求: -// 1, 可以1个人单独一搜船 -// 2, 一艘船如果坐2人,两个人的体重相加需要是偶数,且总体重不能超过船的载重 -// 3, 一艘船最多坐2人 -// 返回如果想所有人同时坐船,船的最小数量 -public class Code03_MinBoatEvenNumbers { - - public static int minBoat(int[] arr, int limit) { - Arrays.sort(arr); - int odd = 0; - int even = 0; - for (int num : arr) { - if ((num & 1) == 0) { - even++; - } else { - odd++; - } - } - int[] odds = new int[odd]; - int[] evens = new int[even]; - for (int i = arr.length - 1; i >= 0; i--) { - if ((arr[i] & 1) == 0) { - evens[--even] = arr[i]; - } else { - odds[--odd] = arr[i]; - } - } - return min(odds, limit) + min(evens, limit); - } - - public static int min(int[] arr, int limit) { - if (arr == null || arr.length == 0) { - return 0; - } - int N = arr.length; - if (arr[N - 1] > limit) { - return -1; - } - int lessR = -1; - for (int i = N - 1; i >= 0; i--) { - if (arr[i] <= (limit / 2)) { - lessR = i; - break; - } - } - if (lessR == -1) { - return N; - } - int L = lessR; - int R = lessR + 1; - int noUsed = 0; - while (L >= 0) { - int solved = 0; - while (R < N && arr[L] + arr[R] <= limit) { - R++; - solved++; - } - if (solved == 0) { - noUsed++; - L--; - } else { - L = Math.max(-1, L - solved); - } - } - int all = lessR + 1; - int used = all - noUsed; - int moreUnsolved = (N - all) - used; - return used + ((noUsed + 1) >> 1) + moreUnsolved; - } - -} diff --git a/公开课/class069/Code01_Hash.java b/公开课/class069/Code01_Hash.java deleted file mode 100644 index b07b79c..0000000 --- a/公开课/class069/Code01_Hash.java +++ /dev/null @@ -1,52 +0,0 @@ -package class069; - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.Security; - -// 这个类所包含的jar包需要自己找到,然后导入项目 -import javax.xml.bind.DatatypeConverter; - -public class Code01_Hash { - - public static class Hash { - - private MessageDigest hash; - - public Hash(String algorithm) { - try { - hash = MessageDigest.getInstance(algorithm); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } - } - - public String hashCode(String input) { - return DatatypeConverter.printHexBinary(hash.digest(input.getBytes())).toUpperCase(); - } - } - - public static void main(String[] args) { - System.out.println("支持的算法 : "); - for (String str : Security.getAlgorithms("MessageDigest")) { - System.out.println(str); - } - System.out.println("======="); - - String algorithm = "SHA-256"; - Hash hash = new Hash(algorithm); - - String input1 = "zuochengyunzuochengyun1"; - String input2 = "zuochengyunzuochengyun2"; - String input3 = "zuochengyunzuochengyun3"; - String input4 = "zuochengyunzuochengyun4"; - String input5 = "zuochengyunzuochengyun5"; - System.out.println(hash.hashCode(input1)); - System.out.println(hash.hashCode(input2)); - System.out.println(hash.hashCode(input3)); - System.out.println(hash.hashCode(input4)); - System.out.println(hash.hashCode(input5)); - - } - -} diff --git a/公开课/class069/Code02_BitMap.java b/公开课/class069/Code02_BitMap.java deleted file mode 100644 index 7579ed1..0000000 --- a/公开课/class069/Code02_BitMap.java +++ /dev/null @@ -1,87 +0,0 @@ -package class069; - -public class Code02_BitMap { - - // 位图 - public static class BitMap { - - private long[] bits; - - public BitMap(int max) { - bits = new long[(max + 64) >> 6]; - } - - public void add(int num) { - bits[num >> 6] |= (1L << (num & 63)); - } - - public void delete(int num) { - bits[num >> 6] &= ~(1L << (num & 63)); - } - - public boolean contains(int num) { - return (bits[num >> 6] & (1L << (num & 63))) != 0; - } - - } - - public static void main(String[] args) { - - // 表示 0~ 31 谁出现了,谁没出现 -// int a = 0; -// int num = 7; -// // 请把7位描黑! -// // 0000000000010000000 -// // 0000000000010000000 -// a |= 1 << 7; -// a |= 1 << 13; -// a |= 1 << 29; -// // 7 13 29 -// // 请告诉我,7有没有进去 -// boolean has =( a & (1 << 7)) != 0; -// -// - int[] set = new int[10]; - // set : 10个数 - // 每个数,32位 - // 0~319 - int num = 176; - // set[0] : 0~31 - // set[1] : 32~ - int team = num / 32; - set[team] |= 1 << (num % 32); - - - - - -// System.out.println("测试开始!"); -// int max = 2000000; -// BitMap bitMap = new BitMap(max); -// HashSet set = new HashSet<>(); -// int testTime = 6000000; -// for (int i = 0; i < testTime; i++) { -// int num = (int) (Math.random() * (max + 1)); -// double decide = Math.random(); -// if (decide < 0.333) { -// bitMap.add(num); -// set.add(num); -// } else if (decide < 0.666) { -// bitMap.delete(num); -// set.remove(num); -// } else { -// if (bitMap.contains(num) != set.contains(num)) { -// System.out.println("Oops!"); -// break; -// } -// } -// } -// for (int num = 0; num <= max; num++) { -// if (bitMap.contains(num) != set.contains(num)) { -// System.out.println("Oops!"); -// } -// } -// System.out.println("测试结束!"); - } - -} diff --git a/公开课/class070/Code01_FindTheCelebrity.java b/公开课/class070/Code01_FindTheCelebrity.java deleted file mode 100644 index 61f1ae2..0000000 --- a/公开课/class070/Code01_FindTheCelebrity.java +++ /dev/null @@ -1,40 +0,0 @@ -package class070; - -// 测试链接 : https://leetcode.com/problems/find-the-celebrity/ -public class Code01_FindTheCelebrity { - - // 提交时不要提交这个函数,因为默认系统会给你这个函数 - // knows方法默认自己认识自己 - public static boolean knows(int x, int i) { - return true; - } - - // 只提交下面的方法 - public int findCelebrity(int n) { - // 谁可能成为明星,谁就是cand - int cand = 0; - for (int i = 1; i < n; i++) { - if (knows(cand, i)) { - cand = i; - } - } - // cand....右边,cand都不认识! - // cand是什么?唯一可能是明星的人! - // 下一步就是验证,它到底是不是明星 - // 1) cand是不是不认识所有的人 cand...(右侧cand都不认识) - // 所以,只用验证 ....cand的左侧即可 - for (int i = 0; i < cand; i++) { - if (knows(cand, i)) { - return -1; - } - } - // 2) 是不是所有的人都认识cand - for (int i = 0; i < n; i++) { - if (!knows(i, cand)) { - return -1; - } - } - return cand; - } - -} diff --git a/公开课/class070/Code02_AvoidFloodInTheCity.java b/公开课/class070/Code02_AvoidFloodInTheCity.java deleted file mode 100644 index 0644025..0000000 --- a/公开课/class070/Code02_AvoidFloodInTheCity.java +++ /dev/null @@ -1,82 +0,0 @@ -package class070; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.PriorityQueue; - -// 测试链接 : https://leetcode.com/problems/avoid-flood-in-the-city/ -public class Code02_AvoidFloodInTheCity { - - // rains[i] = j 第i天轮到j号湖泊下雨 - // 规定,下雨日,干啥 : -1 - // 不下雨日,如果没有湖泊可抽 : 1 - public static int[] avoidFlood(int[] rains) { - int n = rains.length; - int[] ans = new int[n]; - int[] invalid = new int[0]; - // key : 某个湖 - // value : 这个湖在哪些位置降雨 - // 4 : {3,7,19,21} - // 1 : { 13 } - // 2 : {4, 56} - HashMap> map = new HashMap<>(); - for (int i = 0; i < n; i++) { - if (rains[i] != 0) { // 第i天要下雨,rains[i] - // 3天 9号 - // 9号 { 3 } - // 9号 {1, 3} - if (!map.containsKey(rains[i])) { - map.put(rains[i], new LinkedList<>()); - } - map.get(rains[i]).addLast(i); - } - } - // 没抽干的湖泊表 - // 某个湖如果满了,加入到set里 - // 某个湖被抽干了,从set中移除 - HashSet set = new HashSet<>(); - // 这个堆的堆顶表示最先处理的湖是哪个 - PriorityQueue heap = new PriorityQueue<>(); - for (int i = 0; i < n; i++) { // 0 1 2 3 ... - if (rains[i] != 0) { - if (set.contains(rains[i])) { - return invalid; - } - // 放入到没抽干的表里 - set.add(rains[i]); - map.get(rains[i]).pollFirst(); - if (!map.get(rains[i]).isEmpty()) { - heap.add(new Work(rains[i], map.get(rains[i]).peekFirst())); - } - // 题目规定 - ans[i] = -1; - } else { // 今天干活! - if (heap.isEmpty()) { - ans[i] = 1; - } else { - Work cur = heap.poll(); - set.remove(cur.lake); - ans[i] = cur.lake; - } - } - } - return ans; - } - - public static class Work implements Comparable { - public int lake; - public int nextRain; - - public Work(int l, int p) { - lake = l; - nextRain = p; - } - - @Override - public int compareTo(Work o) { - return nextRain - o.nextRain; - } - } - -} diff --git a/公开课/class070/Code03_BurstBalloons.java b/公开课/class070/Code03_BurstBalloons.java deleted file mode 100644 index 95a44f3..0000000 --- a/公开课/class070/Code03_BurstBalloons.java +++ /dev/null @@ -1,154 +0,0 @@ -package class070; - -// 本题测试链接 : https://leetcode.com/problems/burst-balloons/ -public class Code03_BurstBalloons { - - public static int max(int[] arr) { - int n = arr.length; - int[] help = new int[n + 2]; - help[0] = 1; - help[n + 1] = 1; - // 1 1 - for (int i = 0; i < arr.length; i++) { - help[i + 1] = arr[i]; - } - // arr 0 1 2 3 4 - // help 0 1 2 3 4 5 6 - return f(help, 1, n); - } - - // balls[L...R] 这个范围的气球,选择最优的打爆顺序,返回最大的得分 - // 你想调用这个函数,必须遵循一个潜台词: - // ball[L-1]气球,一定没爆! - // ball[R+1]气球,一定没爆! - // 为什么要设计这样的潜台词?是因为可能性是按照最后打爆的气球来展开的 - public static int f(int[] balls, int L, int R) { - if(L == R) { - return balls[L-1] * balls[L] * balls[R+1]; - } - // L...R 不止一个气球! - // 可能性1,L位置的气球最后打爆 - int p1 = f(balls, L+1,R) + balls[L-1] * balls[L] * balls[R+1]; - // 可能性2,R位置的气球最后打爆 - int p2 = f(balls, L, R-1) + balls[L-1] * balls[R] * balls[R+1]; - int ans = Math.max(p1, p2); - // 枚举,任何一个中间气球,最后打爆! - for(int mid = L + 1; mid < R;mid++) { - // L .... mid-1 mid mid+1.....R - int curP = f(balls, L, mid-1) + f(balls, mid+1, R) - + balls[L-1] * balls[mid] * balls[R+1]; - ans = Math.max(ans, curP); - } - return ans; - } - - - - - - - - - - public static int maxCoins0(int[] arr) { - // [3,2,1,3] - // [1,3,2,1,3,1] - int N = arr.length; - int[] help = new int[N + 2]; - for (int i = 0; i < N; i++) { - help[i + 1] = arr[i]; - } - help[0] = 1; - help[N + 1] = 1; - return func(help, 1, N); - } - - // L-1位置,和R+1位置,永远不越界,并且,[L-1] 和 [R+1] 一定没爆呢! - // 返回,arr[L...R]打爆所有气球,最大得分是什么 - public static int func(int[] arr, int L, int R) { - if (L == R) { - return arr[L - 1] * arr[L] * arr[R + 1]; - } - // 尝试每一种情况,最后打爆的气球,是什么位置 - // L...R - // L位置的气球,最后打爆 - int max = func(arr, L + 1, R) + arr[L - 1] * arr[L] * arr[R + 1]; - // R位置的气球,最后打爆 - max = Math.max(max, func(arr, L, R - 1) + arr[L - 1] * arr[R] * arr[R + 1]); - // 尝试所有L...R,中间的位置,(L,R) - for (int i = L + 1; i < R; i++) { - // i位置的气球,最后打爆 - int left = func(arr, L, i - 1); - int right = func(arr, i + 1, R); - int last = arr[L - 1] * arr[i] * arr[R + 1]; - int cur = left + right + last; - max = Math.max(max, cur); - } - return max; - } - - public static int maxCoins1(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - if (arr.length == 1) { - return arr[0]; - } - int N = arr.length; - int[] help = new int[N + 2]; - help[0] = 1; - help[N + 1] = 1; - for (int i = 0; i < N; i++) { - help[i + 1] = arr[i]; - } - return process(help, 1, N); - } - - // 打爆arr[L..R]范围上的所有气球,返回最大的分数 - // 假设arr[L-1]和arr[R+1]一定没有被打爆 - public static int process(int[] arr, int L, int R) { - if (L == R) {// 如果arr[L..R]范围上只有一个气球,直接打爆即可 - return arr[L - 1] * arr[L] * arr[R + 1]; - } - // 最后打爆arr[L]的方案,和最后打爆arr[R]的方案,先比较一下 - int max = Math.max(arr[L - 1] * arr[L] * arr[R + 1] + process(arr, L + 1, R), - arr[L - 1] * arr[R] * arr[R + 1] + process(arr, L, R - 1)); - // 尝试中间位置的气球最后被打爆的每一种方案 - for (int i = L + 1; i < R; i++) { - max = Math.max(max, arr[L - 1] * arr[i] * arr[R + 1] + process(arr, L, i - 1) + process(arr, i + 1, R)); - } - return max; - } - - public static int maxCoins2(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - if (arr.length == 1) { - return arr[0]; - } - int N = arr.length; - int[] help = new int[N + 2]; - help[0] = 1; - help[N + 1] = 1; - for (int i = 0; i < N; i++) { - help[i + 1] = arr[i]; - } - int[][] dp = new int[N + 2][N + 2]; - for (int i = 1; i <= N; i++) { - dp[i][i] = help[i - 1] * help[i] * help[i + 1]; - } - for (int L = N; L >= 1; L--) { - for (int R = L + 1; R <= N; R++) { - int ans = help[L - 1] * help[L] * help[R + 1] + dp[L + 1][R]; - ans = Math.max(ans, help[L - 1] * help[R] * help[R + 1] + dp[L][R - 1]); - for (int i = L + 1; i < R; i++) { - ans = Math.max(ans, help[L - 1] * help[i] * help[R + 1] + dp[L][i - 1] + dp[i + 1][R]); - } - dp[L][R] = ans; - } - } - return dp[1][N]; - } - -} diff --git a/公开课/class070/SuperWaterKing.java b/公开课/class070/SuperWaterKing.java deleted file mode 100644 index 7cd690e..0000000 --- a/公开课/class070/SuperWaterKing.java +++ /dev/null @@ -1,50 +0,0 @@ -package class070; - -public class SuperWaterKing { - - // int[] arr = {1 , 1, 3, 3, 1} - // 长度5,长度是N - // 水王:某个数,出现次数,大于 N / 2 (必须大于!不包括等于!) - // 1 1 3次 N = 5 N/2 = 2 - // arr = {1,1,2,2} - // n =4 n/2 2次 - // arr中的数,都不是负数!返回水王数! - // 如果没有水王数!返回-1 - // 只能使用有限几个变量,就完成寻找水王数的功能 - // 时间复杂度O(N) - public static int king(int[] arr) { - if (arr == null || arr.length == 0) { - return -1; - } - if (arr.length == 1) { - return arr[0]; - } - int cand = 0; - int hp = 0; - for (int num : arr) { - if (hp == 0) { - cand = num; - hp = 1; - } else if (num == cand) { - hp++; - } else { - hp--; - } - } - if (hp == 0) { - return -1; - } - int times = 0; - for (int num : arr) { - if (num == cand) { - times++; - } - } - if (times > arr.length / 2) { - return cand; - } else { - return -1; - } - } - -} diff --git a/公开课/class071/Code01_CoverMax.java b/公开课/class071/Code01_CoverMax.java deleted file mode 100644 index 852a1e0..0000000 --- a/公开课/class071/Code01_CoverMax.java +++ /dev/null @@ -1,90 +0,0 @@ -package class071; - -import java.util.Arrays; -import java.util.PriorityQueue; - -public class Code01_CoverMax { - - public static int maxCover1(int[][] lines) { - int min = Integer.MAX_VALUE; - int max = Integer.MIN_VALUE; - for (int i = 0; i < lines.length; i++) { - min = Math.min(min, lines[i][0]); - max = Math.max(max, lines[i][1]); - } - int cover = 0; - for (double p = min + 0.5; p < max; p += 1) { - int cur = 0; - for (int i = 0; i < lines.length; i++) { - if (lines[i][0] < p && lines[i][1] > p) { - cur++; - } - } - cover = Math.max(cover, cur); - } - return cover; - } - - // [ [4, 5], [3, 6] , [1, 3] ] - // [ [1, 3] [3, 6] [4 ,5] - public static int maxCover2(int[][] lines) { - if (lines == null || lines.length == 0) { - return 0; - } - // 排序:每个线段,根据开头位置排序,开头的位置如果一样,怎么排序无所谓! - // java Arrays sort 比较 - // java lambda 表达式 - Arrays.sort(lines, (a, b) -> a[0] - b[0]); - // 准备一个堆 - // 在这里,不去谈堆的实现,只是使用 - // 小根堆:小 到 大 组织 - PriorityQueue heap = new PriorityQueue<>(); - int max = 0; - for (int[] line : lines) { - int start = line[0]; - int end = line[1]; - // <= start的数字,都从小根堆里弹出! - while (!heap.isEmpty() && heap.peek() <= start) { - heap.poll(); - } - heap.add(end); - int cur = heap.size(); - max = Math.max(max, cur); - } - return max; - } - - // for test - public static int[][] generateLines(int N, int L, int R) { - int size = (int) (Math.random() * N) + 1; - int[][] ans = new int[size][2]; - for (int i = 0; i < size; i++) { - int a = L + (int) (Math.random() * (R - L + 1)); - int b = L + (int) (Math.random() * (R - L + 1)); - if (a == b) { - b = a + 1; - } - ans[i][0] = Math.min(a, b); - ans[i][1] = Math.max(a, b); - } - return ans; - } - - public static void main(String[] args) { - System.out.println("test begin"); - int N = 100; - int L = 0; - int R = 200; - int testTimes = 200000; - for (int i = 0; i < testTimes; i++) { - int[][] lines = generateLines(N, L, R); - int ans1 = maxCover1(lines); - int ans2 = maxCover2(lines); - if (ans1 != ans2) { - System.out.println("Oops!"); - } - } - System.out.println("test end"); - } - -} diff --git a/公开课/class071/Code02_Heaters.java b/公开课/class071/Code02_Heaters.java deleted file mode 100644 index 8120cbf..0000000 --- a/公开课/class071/Code02_Heaters.java +++ /dev/null @@ -1,114 +0,0 @@ -package class071; - -import java.util.Arrays; - -// leetcode 475题 -public class Code02_Heaters { - - // 比如地点是7, 9, 14 - // 供暖点的位置: 1 3 4 5 13 15 17 - // 先看地点7 - // 由1供暖,半径是6 - // 由3供暖,半径是4 - // 由4供暖,半径是3 - // 由5供暖,半径是2 - // 由13供暖,半径是6 - // 由此可知,地点7应该由供暖点5来供暖,半径是2 - // 再看地点9 - // 供暖点不回退 - // 由5供暖,半径是4 - // 由13供暖,半径是4 - // 由15供暖,半径是6 - // 由此可知,地点9应该由供暖点13来供暖,半径是4 - // 为什么是13而不是5?因为接下来的地点都会更靠右,所以半径一样的时候,就应该选更右的供暖点 - // 再看地点14 - // 供暖点不回退 - // 由13供暖,半径是1 - // 由15供暖,半径是1 - // 由17供暖,半径是3 - // 由此可知,地点14应该由供暖点15来供暖,半径是1 - // 以此类推 - public static int findRadius(int[] houses, int[] heaters) { - Arrays.sort(houses); - Arrays.sort(heaters); - int ans = 0; - // 时间复杂度O(N) - // i是地点,j是供暖点 - for (int i = 0, j = 0; i < houses.length; i++) { - while (!best(houses, heaters, i, j)) { - j++; - } - ans = Math.max(ans, Math.abs(heaters[j] - houses[i])); - } - return ans; - } - - // 这个函数含义: - // 当前的地点houses[i]由heaters[j]来供暖是最优的吗? - // 当前的地点houses[i]由heaters[j]来供暖,产生的半径是a - // 当前的地点houses[i]由heaters[j + 1]来供暖,产生的半径是b - // 如果a < b, 说明是最优,供暖不应该跳下一个位置 - // 如果a >= b, 说明不是最优,应该跳下一个位置 - public static boolean best(int[] houses, int[] heaters, int i, int j) { - return j == heaters.length - 1 - || Math.abs(heaters[j] - houses[i]) < Math.abs(heaters[j + 1] - houses[i]); - } - - // 下面这个方法不对,你能找出原因嘛?^_^ - public static int findRadius2(int[] houses, int[] heaters) { - Arrays.sort(houses); - Arrays.sort(heaters); - int ans = 0; - // 时间复杂度O(N) - // i是地点,j是供暖点 - for (int i = 0, j = 0; i < houses.length; i++) { - while (!best2(houses, heaters, i, j)) { - j++; - } - ans = Math.max(ans, Math.abs(heaters[j] - houses[i])); - } - return ans; - } - - public static boolean best2(int[] houses, int[] heaters, int i, int j) { - return j == heaters.length - 1 || Math.abs(heaters[j] - houses[i]) <= Math.abs(heaters[j + 1] - houses[i]); - } - - // 为了测试 - public static int[] randomArray(int len, int v) { - int[] arr = new int[len]; - for (int i = 0; i < len; i++) { - arr[i] = (int) (Math.random() * v) + 1; - } - return arr; - } - - // 为了测试 - public static void main(String[] args) { - int len = 5; - int v = 10; - int testTime = 10000; - for (int i = 0; i < testTime; i++) { - int[] a = randomArray(len, v); - int[] b = randomArray(len, v); - int ans1 = findRadius(a, b); - int ans2 = findRadius2(a, b); - if (ans1 != ans2) { - System.out.println("A : "); - for (int num : a) { - System.out.print(num + " "); - } - System.out.println(); - System.out.println("B : "); - for (int num : b) { - System.out.print(num + " "); - } - System.out.println(); - System.out.println(ans1); - System.out.println(ans2); - break; - } - } - } - -} diff --git a/公开课/class071/Code03_TrappingRainWater.java b/公开课/class071/Code03_TrappingRainWater.java deleted file mode 100644 index fb30e76..0000000 --- a/公开课/class071/Code03_TrappingRainWater.java +++ /dev/null @@ -1,121 +0,0 @@ -package class071; - -public class Code03_TrappingRainWater { - - /* - * 给定一个正整数数组arr,把arr想象成一个直方图。返回这个直方图如果装水,能装下几格水? - * - */ - - public static int water1(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int water = 0; - for (int i = 1; i < N - 1; i++) { - int leftMax = Integer.MIN_VALUE; - for (int j = 0; j < i; j++) { - leftMax = Math.max(leftMax, arr[j]); - } - int rightMax = Integer.MIN_VALUE; - for (int j = i + 1; j < N; j++) { - rightMax = Math.max(rightMax, arr[j]); - } - water += Math.max(Math.min(leftMax, rightMax) - arr[i], 0); - } - return water; - } - - public static int water2(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int[] leftMaxs = new int[N]; - leftMaxs[0] = arr[0]; - for (int i = 1; i < N; i++) { - leftMaxs[i] = Math.max(leftMaxs[i - 1], arr[i]); - } - - int[] rightMaxs = new int[N]; - rightMaxs[N - 1] = arr[N - 1]; - for (int i = N - 2; i >= 0; i--) { - rightMaxs[i] = Math.max(rightMaxs[i + 1], arr[i]); - } - int water = 0; - for (int i = 1; i < N - 1; i++) { - water += Math.max(Math.min(leftMaxs[i - 1], rightMaxs[i + 1]) - arr[i], 0); - } - return water; - } - - public static int water3(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int[] rightMaxs = new int[N]; - rightMaxs[N - 1] = arr[N - 1]; - for (int i = N - 2; i >= 0; i--) { - rightMaxs[i] = Math.max(rightMaxs[i + 1], arr[i]); - } - int water = 0; - int leftMax = arr[0]; - for (int i = 1; i < N - 1; i++) { - water += Math.max(Math.min(leftMax, rightMaxs[i + 1]) - arr[i], 0); - leftMax = Math.max(leftMax, arr[i]); - } - return water; - } - - public static int water4(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int L = 1; - int leftMax = arr[0]; - int R = N - 2; - int rightMax = arr[N - 1]; - int water = 0; - while (L <= R) { - if (leftMax <= rightMax) { - water += Math.max(0, leftMax - arr[L]); - leftMax = Math.max(leftMax, arr[L++]); - } else { - water += Math.max(0, rightMax - arr[R]); - rightMax = Math.max(rightMax, arr[R--]); - } - } - return water; - } - - // for test - public static int[] generateRandomArray(int len, int value) { - int[] ans = new int[(int) (Math.random() * len) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * value) + 1; - } - return ans; - } - - public static void main(String[] args) { - int len = 100; - int value = 200; - int testTimes = 100000; - System.out.println("测试开始"); - for (int i = 0; i < testTimes; i++) { - int[] arr = generateRandomArray(len, value); - int ans1 = water1(arr); - int ans2 = water2(arr); - int ans3 = water3(arr); - int ans4 = water4(arr); - if (ans1 != ans2 || ans3 != ans4 || ans1 != ans3) { - System.out.println("Oops!"); - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class071/Code04_ExpressionCompute.java b/公开课/class071/Code04_ExpressionCompute.java deleted file mode 100644 index cda5846..0000000 --- a/公开课/class071/Code04_ExpressionCompute.java +++ /dev/null @@ -1,57 +0,0 @@ -package class071; - -import java.util.LinkedList; - -// 本题测试链接 : https://leetcode.com/problems/basic-calculator-iii/ -public class Code04_ExpressionCompute { - - public static int calculate(String str) { - return f(str.toCharArray(), 0)[0]; - } - - // 请从str[i...]往下算,遇到字符串终止位置或者右括号,就停止 - // 返回两个值,长度为2的数组 - // 0) 负责的这一段的结果是多少 - // 1) 负责的这一段计算到了哪个位置 - public static int[] f(char[] str, int i) { - LinkedList queue = new LinkedList(); - int cur = 0; - int[] bra = null; - // 从i出发,开始撸串 - while (i < str.length && str[i] != ')') { - if (str[i] >= '0' && str[i] <= '9') { - cur = cur * 10 + str[i++] - '0'; - } else if (str[i] != '(') { // 遇到的是运算符号 - addNum(queue, cur, str[i++]); - cur = 0; - } else { // 遇到左括号了 - bra = f(str, i + 1); - cur = bra[0]; - i = bra[1] + 1; - } - } - addNum(queue, cur, '+'); - return new int[] { getAns(queue), i }; - } - - public static void addNum(LinkedList queue, int num, char op) { - if (!queue.isEmpty() && (queue.peekLast().equals("*") || queue.peekLast().equals("/"))) { - String top = queue.pollLast(); - int pre = Integer.valueOf(queue.pollLast()); - num = top.equals("*") ? (pre * num) : (pre / num); - } - queue.addLast(String.valueOf(num)); - queue.addLast(String.valueOf(op)); - } - - public static int getAns(LinkedList queue) { - int ans = Integer.valueOf(queue.pollFirst()); - while (queue.size() > 1) { - String op = queue.pollFirst(); - int num = Integer.valueOf(queue.pollFirst()); - ans += op.equals("+") ? num : -num; - } - return ans; - } - -} diff --git a/公开课/class072/Code01_SplitApples.java b/公开课/class072/Code01_SplitApples.java deleted file mode 100644 index a4cd5b7..0000000 --- a/公开课/class072/Code01_SplitApples.java +++ /dev/null @@ -1,163 +0,0 @@ -package class072; - -// 有m个同样的苹果,认为苹果之间无差别 -// 有n个同样的盘子,认为盘子之间也无差别 -// 还有,比如5个苹果如果放进3个盘子, -// 那么1、3、1和1、1、3和3、1、1的放置方法,也认为是一种方法 -// 如上的设定下,返回有多少种放置方法 -// 测试链接 : https://www.nowcoder.com/practice/bfd8234bb5e84be0b493656e390bdebf -// 提交以下的code,提交时请把类名改成"Main" -import java.util.Arrays; -import java.util.Scanner; - -public class Code01_SplitApples { - - public static int ways1(int apples, int plates) { - if (apples == 0) { // 没有苹果了!摆法有一种,“什么也不用摆” - return 1; - } - if (plates == 0) { - return 0; // 还剩下苹果,但是盘子没了!0种方法 - } - // 苹果也有,盘子也有 - if (apples < plates) { - // 多余的盘子都敲碎,因为没有,不会影响分布的种数 - return ways1(apples, apples); - } - // apples >= plates - // 1) 所有的盘子全部都要使用,方法数是a - int a = ways1(apples - plates, plates); - // 2) 不全使用!所有的盘子不都使用,方法数是b - int b = ways1(apples, plates - 1); - return a + b; - } - - // 苹果数量,初始时候,不超过100个 - // 盘子数量,初始视乎,不超过100个 - // 参数apples,0~100之间! - // 参数plates,0~100之间! - public static int[][] map = null; - // int apples, int plates -> map - - // map[7][5] -> 苹果有7个,盘子有5个,有几种摆放方法! - - // map[7][5] == 0, 苹果有7个,盘子有5个,有0种摆放方法! - - // map[7][5] == -1,苹果有7个,盘子有5个,这个过程,还没有计算过! - - public static int ways2(int apples, int plates) { - if(map == null) { - map = new int[101][101]; - for (int i = 0; i <= apples; i++) { - for (int j = 0; j <= plates; j++) { - map[i][j] = -1; - } - } - } - return process(apples, plates); - } - - // map可以用 - - public static int process(int apples, int plates) { - if(map[apples][plates] != -1) { - return map[apples][plates]; - } - int ans = 0; - if (apples == 0) { // 没有苹果了!摆法有一种,“什么也不用摆” - ans = 1; - } else if (plates == 0) { - ans = 0; // 还剩下苹果,但是盘子没了!0种方法 - } else if (apples < plates) { - ans = ways1(apples, apples); - }else { - // apples >= plates - // 1) 所有的盘子全部都要使用,方法数是a - int a = ways1(apples - plates, plates); - // 2) 不全使用!所有的盘子不都使用,方法数是b - int b = ways1(apples, plates - 1); - ans = a + b; - } - map[apples][plates] = ans; - return ans; - } - - - - - - - - public static void main(String[] args) { - Scanner sc = new Scanner(System.in); - while (sc.hasNext()) { - int m = sc.nextInt(); - int n = sc.nextInt(); - int ways = f1(m, n); - System.out.println(ways); - } - sc.close(); - } - - // 苹果有apples个,盘子有plates个 - // 返回有几种摆法 - // 如果苹果数为0,有1种摆法:什么也不摆 - // 如果苹果数不为0,但是盘子数为0,有0种摆法(做不到) - // 如果苹果数不为0,盘子数也不为0,进行如下的情况讨论: - // 假设苹果数为apples,盘子数为plates - // 可能性 1) apples < plates - // 这种情况下,一定有多余的盘子,这些盘子完全没用,所以砍掉 - // 后续是f(apples, apples) - // 可能性 2) apples >= plates - // 在可能性2)下,讨论摆法,有如下两种选择 - // 选择a) 不是所有的盘子都使用 - // 选择b) 就是所有的盘子都使用 - // 对于选择a),既然不是所有盘子都使用,那么后续就是f(apples, plates - 1) - // 意思是:既然不是所有盘子都使用,那盘子减少一个,然后继续讨论吧! - // 对于选择b),既然就是所有的盘子都使用,那么先把所有盘子都摆上1个苹果。 - // 剩余苹果数 = apples - plates - // 然后继续讨论,剩下的这些苹果,怎么摆进plates个盘子里, - // 所以后续是f(apples - plates, plates) - public static int f1(int apples, int plates) { - if (apples == 0) { - return 1; - } - if (plates == 0) { - return 0; - } - if (plates > apples) { - return f1(apples, apples); - } else { // apples >= plates; - return f1(apples, plates - 1) + f1(apples - plates, plates); - } - } - - // 下面的方法就是上面方法的记忆化搜索版本 - public static int[][] dp = new int[20][20]; - - public static int f2(int apples, int plates) { - for (int i = 0; i <= apples; i++) { - Arrays.fill(dp[i], -1); - } - return g(apples, plates, dp); - } - - public static int g(int apples, int plates, int[][] dp) { - if (dp[apples][plates] != -1) { - return dp[apples][plates]; - } - int ans = 0; - if (apples == 0) { - ans = 1; - } else if (plates == 0) { - ans = 0; - } else if (plates > apples) { - ans = g(apples, apples, dp); - } else { - ans = g(apples, plates - 1, dp) + g(apples - plates, plates, dp); - } - dp[apples][plates] = ans; - return ans; - } - -} \ No newline at end of file diff --git a/公开课/class072/Code02_SplitBuildingBlock.java b/公开课/class072/Code02_SplitBuildingBlock.java deleted file mode 100644 index 5e28eae..0000000 --- a/公开课/class072/Code02_SplitBuildingBlock.java +++ /dev/null @@ -1,61 +0,0 @@ -package class072; - -import java.util.Arrays; - -// 来自京东笔试 -// 小明手中有n块积木,并且小明知道每块积木的重量。现在小明希望将这些积木堆起来 -// 要求是任意一块积木如果想堆在另一块积木上面,那么要求: -// 1) 上面的积木重量不能小于下面的积木重量 -// 2) 上面积木的重量减去下面积木的重量不能超过x -// 3) 每堆中最下面的积木没有重量要求 -// 现在小明有一个机会,除了这n块积木,还可以获得k块任意重量的积木。 -// 小明希望将积木堆在一起,同时希望积木堆的数量越少越好,你能帮他找到最好的方案么? -// 输入描述: -// 第一行三个整数n,k,x,1<=n<=200000,0<=x,k<=1000000000 -// 第二行n个整数,表示积木的重量,任意整数范围都在[1,1000000000] -// 样例输出: -// 13 1 38 -// 20 20 80 70 70 70 420 5 1 5 1 60 90 -// 1 1 5 5 20 20 60 70 70 70 80 90 420 -> 只有1块魔法积木,x = 38 -// 输出:2 -// 解释: -// 两堆分别是 -// 1 1 5 5 20 20 (50) 60 70 70 70 80 90 -// 420 -// 其中x是一个任意重量的积木,夹在20和60之间可以让积木继续往上搭 -public class Code02_SplitBuildingBlock { - - // 这是最优解 - // arr里装着所有积木的重量 - // k是魔法积木的数量,每一块魔法积木都能变成任何重量 - // x差值,后 - 前 <= x - public static int minSplit(int[] arr, int k, int x) { - Arrays.sort(arr); - int n = arr.length; - int[] needs = new int[n]; - int size = 0; - int splits = 1; - for (int i = 1; i < n; i++) { - if (arr[i] - arr[i - 1] > x) { - needs[size++] = arr[i] - arr[i - 1]; - splits++; - } - } - if (splits == 1 || x == 0 || k == 0) { - return splits; - } - // 试图去利用魔法积木,弥合堆! - Arrays.sort(needs, 0, size); - for (int i = 0; i < size; i++) { - int need = (needs[i] - 1) / x; - if (k >= need) { - splits--; - k -= need; - } else { - break; - } - } - return splits; - } - -} diff --git a/公开课/class072/Code03_BestMeetingPoint.java b/公开课/class072/Code03_BestMeetingPoint.java deleted file mode 100644 index daa7c76..0000000 --- a/公开课/class072/Code03_BestMeetingPoint.java +++ /dev/null @@ -1,50 +0,0 @@ -package class072; - -// 测试链接 : https://leetcode.com/problems/best-meeting-point/ -// 不过这道题要开通LeetCode会员才能使用 -public class Code03_BestMeetingPoint { - - public static int minTotalDistance(int[][] grid) { - int N = grid.length; - int M = grid[0].length; - int[] iOnes = new int[N]; - int[] jOnes = new int[M]; - for (int i = 0; i < N; i++) { - for (int j = 0; j < M; j++) { - if (grid[i][j] == 1) { - iOnes[i]++; - jOnes[j]++; - } - } - } - int total = 0; - int i = 0; - int j = N - 1; - int iRest = 0; - int jRest = 0; - while (i < j) { - if (iOnes[i] + iRest <= iOnes[j] + jRest) { - total += iOnes[i] + iRest; - iRest += iOnes[i++]; - } else { - total += iOnes[j] + jRest; - jRest += iOnes[j--]; - } - } - i = 0; - j = M - 1; - iRest = 0; - jRest = 0; - while (i < j) { - if (jOnes[i] + iRest <= jOnes[j] + jRest) { - total += jOnes[i] + iRest; - iRest += jOnes[i++]; - } else { - total += jOnes[j] + jRest; - jRest += jOnes[j--]; - } - } - return total; - } - -} diff --git a/公开课/class072/Code04_CombinationSumIV.java b/公开课/class072/Code04_CombinationSumIV.java deleted file mode 100644 index fd577e8..0000000 --- a/公开课/class072/Code04_CombinationSumIV.java +++ /dev/null @@ -1,47 +0,0 @@ -package class072; - -import java.util.Arrays; - -// 测试链接 : https://leetcode.com/problems/combination-sum-iv/ -public class Code04_CombinationSumIV { - - public static int[] dp = new int[1001]; - - public static int combinationSum4(int[] nums, int target) { - Arrays.fill(dp, 0, target + 1, -1); - return process1(nums, target); - } - - public static int process1(int[] nums, int rest) { - if (rest < 0) { - return 0; - } - if (dp[rest] != -1) { - return dp[rest]; - } - int ans = 0; - if (rest == 0) { - ans = 1; - } else { - for (int num : nums) { - ans += process1(nums, rest - num); - } - } - dp[rest] = ans; - return ans; - } - -// // 剪枝 + 严格位置依赖的动态规划 -// public static int combinationSum4(int[] nums, int target) { -// Arrays.sort(nums); -// int[] dp = new int[target + 1]; -// dp[0] = 1; -// for (int rest = 1; rest <= target; rest++) { -// for (int i = 0; i < nums.length && nums[i] <= rest; i++) { -// dp[rest] += dp[rest - nums[i]]; -// } -// } -// return dp[target]; -// } - -} diff --git a/公开课/class073/Code01_CoverMax.java b/公开课/class073/Code01_CoverMax.java deleted file mode 100644 index 6e743fe..0000000 --- a/公开课/class073/Code01_CoverMax.java +++ /dev/null @@ -1,155 +0,0 @@ -package class073; - -import java.util.Arrays; -import java.util.Comparator; -import java.util.PriorityQueue; - -public class Code01_CoverMax { - - public static int maxCover1(int[][] lines) { - int min = Integer.MAX_VALUE; - int max = Integer.MIN_VALUE; - for (int i = 0; i < lines.length; i++) { - min = Math.min(min, lines[i][0]); - max = Math.max(max, lines[i][1]); - } - int cover = 0; - for (double p = min + 0.5; p < max; p += 1) { - int cur = 0; - for (int i = 0; i < lines.length; i++) { - if (lines[i][0] < p && lines[i][1] > p) { - cur++; - } - } - cover = Math.max(cover, cur); - } - return cover; - } - - public static int maxCover2(int[][] m) { - Line[] lines = new Line[m.length]; - for (int i = 0; i < m.length; i++) { - lines[i] = new Line(m[i][0], m[i][1]); - } - Arrays.sort(lines, new StartComparator()); - // 小根堆,每一条线段的结尾数值,使用默认的 - PriorityQueue heap = new PriorityQueue<>(); - int max = 0; - for (int i = 0; i < lines.length; i++) { - // lines[i] -> cur 在黑盒中,把<=cur.start 东西都弹出 - while (!heap.isEmpty() && heap.peek() <= lines[i].start) { - heap.poll(); - } - heap.add(lines[i].end); - max = Math.max(max, heap.size()); - } - return max; - } - - public static class Line { - public int start; - public int end; - - public Line(int s, int e) { - start = s; - end = e; - } - } - - public static class EndComparator implements Comparator { - - @Override - public int compare(Line o1, Line o2) { - return o1.end - o2.end; - } - - } - - // 和maxCover2过程是一样的 - // 只是代码更短 - // 不使用类定义的写法 - public static int maxCover3(int[][] m) { - // m是二维数组,可以认为m内部是一个一个的一维数组 - // 每一个一维数组就是一个对象,也就是线段 - // 如下的code,就是根据每一个线段的开始位置排序 - // 比如, m = { {5,7}, {1,4}, {2,6} } 跑完如下的code之后变成:{ {1,4}, {2,6}, {5,7} } - Arrays.sort(m, (a, b) -> (a[0] - b[0])); - // 准备好小根堆,和课堂的说法一样 - PriorityQueue heap = new PriorityQueue<>(); - int max = 0; - for (int[] line : m) { - while (!heap.isEmpty() && heap.peek() <= line[0]) { - heap.poll(); - } - heap.add(line[1]); - max = Math.max(max, heap.size()); - } - return max; - } - - // for test - public static int[][] generateLines(int N, int L, int R) { - int size = (int) (Math.random() * N) + 1; - int[][] ans = new int[size][2]; - for (int i = 0; i < size; i++) { - int a = L + (int) (Math.random() * (R - L + 1)); - int b = L + (int) (Math.random() * (R - L + 1)); - if (a == b) { - b = a + 1; - } - ans[i][0] = Math.min(a, b); - ans[i][1] = Math.max(a, b); - } - return ans; - } - - public static class StartComparator implements Comparator { - - @Override - public int compare(Line o1, Line o2) { - return o1.start - o2.start; - } - - } - - public static void main(String[] args) { - - Line l1 = new Line(4, 9); - Line l2 = new Line(1, 4); - Line l3 = new Line(7, 15); - Line l4 = new Line(2, 4); - Line l5 = new Line(4, 6); - Line l6 = new Line(3, 7); - - // 底层堆结构,heap - PriorityQueue heap = new PriorityQueue<>(new StartComparator()); - heap.add(l1); - heap.add(l2); - heap.add(l3); - heap.add(l4); - heap.add(l5); - heap.add(l6); - - while (!heap.isEmpty()) { - Line cur = heap.poll(); - System.out.println(cur.start + "," + cur.end); - } - - System.out.println("test begin"); - int N = 100; - int L = 0; - int R = 200; - int testTimes = 200000; - for (int i = 0; i < testTimes; i++) { - int[][] lines = generateLines(N, L, R); - int ans1 = maxCover1(lines); - int ans2 = maxCover2(lines); - int ans3 = maxCover3(lines); - if (ans1 != ans2 || ans1 != ans3) { - System.out.println("Oops!"); - } - } - System.out.println("test end"); - } - -} diff --git a/公开课/class073/Code02_4KeysKeyboard.java b/公开课/class073/Code02_4KeysKeyboard.java deleted file mode 100644 index f6fd74e..0000000 --- a/公开课/class073/Code02_4KeysKeyboard.java +++ /dev/null @@ -1,38 +0,0 @@ -package class073; - -// 测试链接 : https://leetcode.com/problems/4-keys-keyboard/ -public class Code02_4KeysKeyboard { - - // 可以证明: - // 来到i的时候,包括i在内最多有连续4次粘贴行为 - // 不可能更多,如果有连续5次粘贴,一定就不再是最优解 - // 假设开始时,A的数量为S,看如下的变化过程,我们称这是行为一: - // 开始 全选 复制(粘贴板S个A) 粘贴 粘贴 粘贴 粘贴 粘贴 - // S S S 2*S 3*S 4*S 5*S 6*S - // 但是,注意看如下的行为二: - // 开始 全选 复制(粘贴板S个A) 粘贴 全选 复制(粘贴板2S个A) 粘贴 粘贴 - // S S S 2*S 2*S 2*S 4*S 6*S - // 行为一,经历8步,最后是6*S个A - // 行为二,经历8步,最后是6*S个A - // 但是行为二在粘贴板上有2S个A,而行为一在粘贴板上有S个A - // 所以行为一没有行为二优 - // 以此说明:来到i的时候,包括i在内最多有连续4次粘贴行为 - // 那么就尝试:连续1次、连续2次、连续3次、连续4次粘贴行为即可 - public static int maxA(int n) { - // dp[0] 1步以内的最优解 - // dp[1] 2步以内的最优解 - // dp[2] 3步以内的最优解 - // dp[i] i+1步以内的最优解 - int[] dp = new int[n]; - for (int i = 0; i < 6 && i < n; i++) { - dp[i] = i + 1; - } - for (int i = 6; i < n; i++) { - dp[i] = Math.max( - Math.max(dp[i - 3] * 2, dp[i - 4] * 3), - Math.max(dp[i - 5] * 4, dp[i - 6] * 5)); - } - return dp[n - 1]; - } - -} diff --git a/公开课/class073/Code03_MinContinuousFragment.java b/公开课/class073/Code03_MinContinuousFragment.java deleted file mode 100644 index 2434720..0000000 --- a/公开课/class073/Code03_MinContinuousFragment.java +++ /dev/null @@ -1,162 +0,0 @@ -package class073; - -// 来自CMU入学申请考试 -// 给定一个长度为 N 的字符串 S,由字符'a'和'b'组成,空隙由 '?' 表示 -// 你的任务是用a字符或b字符替换每个间隙, -// 替换完成后想让连续出现同一种字符的最长子串尽可能短 -// 例如,S = "aa??bbb", -// 如果将"??"替换为"aa" ,即"aaaabbb",则由相等字符组成的最长子串长度为4 -// 如果将"??"替换为"ba" ,即"aababbb",则由相等字符组成的最长子串长度为3 -// 那么方案二是更好的结果,返回3 -// S的长度 <= 10^6 -public class Code03_MinContinuousFragment { - - // 暴力方法 - // 为了验证 - public static int minContinuous1(String s) { - if (s == null || s.length() == 0) { - return 0; - } - char[] str = s.toCharArray(); - return process1(str, 0); - } - - public static int process1(char[] str, int index) { - if (index == str.length) { - return maxLen(str); - } else { - if (str[index] != '?') { - return process1(str, index + 1); - } else { - str[index] = 'a'; - int p1 = process1(str, index + 1); - str[index] = 'b'; - int p2 = process1(str, index + 1); - str[index] = '?'; - return Math.min(p1, p2); - } - } - } - - // 正式方法 - // 时间复杂度O(N) - public static int minContinuous2(String s) { - if (s == null || s.length() == 0) { - return 0; - } - char[] str = s.toCharArray(); - int N = str.length; - int L = 0; - int R = -1; - for (int i = 0; i < N; i++) { - if (str[i] != '?') { - set(str, L, R); - L = i + 1; - R = i; - } else { - R++; - } - } - set(str, L, R); - // 下面的for循环,是单独处理,条件5) - for (int i = 1; i < N; i++) { - if (str[i] == '?') { - // baaaa?bbbbbbbba - for (L = i - 1; L >= 0 && str[L] == str[i - 1]; L--) - ; - for (R = i + 1; R < N && str[R] == str[i + 1]; R++) - ; - L = i - L - 1; - R = R - i - 1; - if (L <= R) { - str[i] = str[i - 1]; - } else { - str[i] = str[i + 1]; - } - } - } - return maxLen(str); - } - - // L...R 都是? - // 如果这一坨问号,满足1)2)3)4)中的一种,就填好 - // 如果满足5),就不填!a?b - public static void set(char[] str, int L, int R) { - int N = str.length; - if (L > R) { - return; - } - if (L == 0 && R == N - 1) { - for (int i = 0; i < N; i++) { - str[i] = (i & 1) == 0 ? 'a' : 'b'; - } - } else if (L == 0) { - for (int i = R; i >= 0; i--) { - str[i] = str[i + 1] == 'a' ? 'b' : 'a'; - } - } else if (R == N - 1) { - for (int i = L; i < str.length; i++) { - str[i] = str[i - 1] == 'a' ? 'b' : 'a'; - } - } else { - if (str[L - 1] == str[R + 1] || L != R) { - for (; L <= R; L++, R--) { - str[L] = str[L - 1] == 'a' ? 'b' : 'a'; - str[R] = str[R + 1] == 'a' ? 'b' : 'a'; - } - } - } - } - - public static int maxLen(char[] str) { - int ans = 1; - int cur = 1; - for (int i = 1; i < str.length; i++) { - if (str[i] != str[i - 1]) { - ans = Math.max(ans, cur); - cur = 1; - } else { - cur++; - } - } - ans = Math.max(ans, cur); - return ans; - } - - public static char[] arr = { 'a', 'b', '?' }; - - public static String randomString(int len) { - int N = (int) (Math.random() * (len + 1)); - char[] str = new char[N]; - for (int i = 0; i < N; i++) { - str[i] = arr[(int) (Math.random() * 3)]; - } - return String.valueOf(str); - } - - public static void main(String[] args) { - int len = 35; - int testTime = 10000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - String s = randomString(len); - int ans1 = minContinuous1(s); - int ans2 = minContinuous2(s); - if (ans1 != ans2) { - System.out.println(s); - System.out.println(ans1); - System.out.println(ans2); - } - } - System.out.println("测试结束"); - - len = 10000000; - String s = randomString(len); - long start = System.currentTimeMillis(); - minContinuous2(s); - long end = System.currentTimeMillis(); - System.out.println("运行时间(毫秒):" + (end - start)); - - } - -} diff --git a/公开课/class073/Code04_MaxGap.java b/公开课/class073/Code04_MaxGap.java deleted file mode 100644 index 3e92bbc..0000000 --- a/公开课/class073/Code04_MaxGap.java +++ /dev/null @@ -1,101 +0,0 @@ -package class073; - -import java.util.Arrays; - -public class Code04_MaxGap { - - public static int maxGap(int[] nums) { - if (nums == null || nums.length < 2) { - return 0; - } - int len = nums.length; - int min = Integer.MAX_VALUE; - int max = Integer.MIN_VALUE; - for (int i = 0; i < len; i++) { - min = Math.min(min, nums[i]); - max = Math.max(max, nums[i]); - } - if (min == max) { - return 0; - } - // 不止一种数,min~max一定有range, len个数据,准备len+1个桶 - boolean[] hasNum = new boolean[len + 1]; // hasNum[i] i号桶是否进来过数字 - int[] maxs = new int[len + 1]; // maxs[i] i号桶收集的所有数字的最大值 - int[] mins = new int[len + 1]; // mins[i] i号桶收集的所有数字的最小值 - int bid = 0; // 桶号 - for (int i = 0; i < len; i++) { - bid = bucket(nums[i], len, min, max); - mins[bid] = hasNum[bid] ? Math.min(mins[bid], nums[i]) : nums[i]; - maxs[bid] = hasNum[bid] ? Math.max(maxs[bid], nums[i]) : nums[i]; - hasNum[bid] = true; - } - int res = 0; - int lastMax = maxs[0]; // 上一个非空桶的最大值 - int i = 1; - for (; i <= len; i++) { - if (hasNum[i]) { - res = Math.max(res, mins[i] - lastMax); - lastMax = maxs[i]; - } - } - return res; - } - - // 如果当前的数是num,整个范围是min~max,分成了len + 1份 - // 返回num该进第几号桶 - public static int bucket(long num, long len, long min, long max) { - return (int) ((num - min) * len / (max - min)); - } - - // for test - public static int comparator(int[] nums) { - if (nums == null || nums.length < 2) { - return 0; - } - Arrays.sort(nums); - int gap = Integer.MIN_VALUE; - for (int i = 1; i < nums.length; i++) { - gap = Math.max(nums[i] - nums[i - 1], gap); - } - return gap; - } - - // for test - public static int[] generateRandomArray(int maxSize, int maxValue) { - int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; - for (int i = 0; i < arr.length; i++) { - arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random()); - } - return arr; - } - - // for test - public static int[] copyArray(int[] arr) { - if (arr == null) { - return null; - } - int[] res = new int[arr.length]; - for (int i = 0; i < arr.length; i++) { - res[i] = arr[i]; - } - return res; - } - - // for test - public static void main(String[] args) { - int testTime = 500000; - int maxSize = 100; - int maxValue = 100; - boolean succeed = true; - for (int i = 0; i < testTime; i++) { - int[] arr1 = generateRandomArray(maxSize, maxValue); - int[] arr2 = copyArray(arr1); - if (maxGap(arr1) != comparator(arr2)) { - succeed = false; - break; - } - } - System.out.println(succeed ? "Nice!" : "Fucking fucked!"); - } - -} diff --git a/公开课/class074/Code01_Mod3Max.java b/公开课/class074/Code01_Mod3Max.java deleted file mode 100644 index 3d093fd..0000000 --- a/公开课/class074/Code01_Mod3Max.java +++ /dev/null @@ -1,247 +0,0 @@ -package class074; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.TreeSet; - -// 来自去哪儿网 -// 给定一个arr,里面的数字都是0~9 -// 你可以随意使用arr中的数字,哪怕打乱顺序也行 -// 请拼出一个能被3整除的,最大的数字,用str形式返回 -public class Code01_Mod3Max { - - public static String max1(int[] arr) { - Arrays.sort(arr); - for (int l = 0, r = arr.length - 1; l < r; l++, r--) { - int tmp = arr[l]; - arr[l] = arr[r]; - arr[r] = tmp; - } - StringBuilder builder = new StringBuilder(); - TreeSet set = new TreeSet<>((a, b) -> Integer.valueOf(b).compareTo(Integer.valueOf(a))); - process1(arr, 0, builder, set); - return set.isEmpty() ? "" : set.first(); - } - - public static void process1(int[] arr, int index, StringBuilder builder, TreeSet set) { - if (index == arr.length) { - if (builder.length() != 0 && Integer.valueOf(builder.toString()) % 3 == 0) { - set.add(builder.toString()); - } - } else { - process1(arr, index + 1, builder, set); - builder.append(arr[index]); - process1(arr, index + 1, builder, set); - builder.deleteCharAt(builder.length() - 1); - } - } - - public static String max2(int[] arr) { - if (arr == null || arr.length == 0) { - return ""; - } - Arrays.sort(arr); - for (int l = 0, r = arr.length - 1; l < r; l++, r--) { - int tmp = arr[l]; - arr[l] = arr[r]; - arr[r] = tmp; - } - if (arr[0] == 0) { - return "0"; - } - String ans = process2(arr, 0, 0); - String res = ans.replaceAll("^(0+)", ""); - if (!res.equals("")) { - return res; - } - return ans.equals("") ? ans : "0"; - } - - // arr中的数字一定是0~9 - // arr是经过排序的,并且是从大到小排序,比如[9,8,7,7,7,3,1]等 - // 这个递归函数的含义 : - // 在arr[index...一直到最后]上做选择,arr[0...index-1]就当不存在 - // 每个位置的字符可以要、也可以不要,但是!选出来的数字拼完之后的结果,在%3之后,余数一定要是mod! - // 返回在上面设定的情况下,最大的数是多少? - // 如果存在这样的数,返回字符串的形式 - // 如果不存在这样的数,返回特殊字符串,比如"$",代表不可能 - // 这个递归函数可以很轻易的改出动态规划 - public static String process2(int[] arr, int index, int mod) { - if (index == arr.length) { - return mod == 0 ? "" : "$"; - } - String p1 = "$"; - int nextMod = nextMod(mod, arr[index] % 3); - String next = process2(arr, index + 1, nextMod); - if (!next.equals("$")) { - p1 = String.valueOf(arr[index]) + next; - } - String p2 = process2(arr, index + 1, mod); - if (p1.equals("$") && p2.equals("$")) { - return "$"; - } - if (!p1.equals("$") && !p2.equals("$")) { - return smaller(p1, p2) ? p2 : p1; - } - return p1.equals("$") ? p2 : p1; - } - - public static int nextMod(int require, int current) { - if (require == 0) { - if (current == 0) { - return 0; - } else if (current == 1) { - return 2; - } else { - return 1; - } - } else if (require == 1) { - if (current == 0) { - return 1; - } else if (current == 1) { - return 0; - } else { - return 2; - } - } else { // require == 2 - if (current == 0) { - return 2; - } else if (current == 1) { - return 1; - } else { - return 0; - } - } - } - - public static boolean smaller(String p1, String p2) { - if (p1.length() != p2.length()) { - return p1.length() < p2.length(); - } - return p1.compareTo(p2) < 0; - } - - // 贪心的思路解法 : - // 先得到数组的累加和,记为sum - // 1) 如果sum%3==0,说明所有数从大到小拼起来就可以了 - // 2) 如果sum%3==1,说明多了一个余数1, - // 只需要删掉一个最小的数(该数是%3==1的数); - // 如果没有,只需要删掉两个最小的数(这两个数都是%3==2的数); - // 3) 如果sum%3==2,说明多了一个余数2, - // 只需要删掉一个最小的数(该数是%3==2的数); - // 如果没有,只需要删掉两个最小的数(这两个数都是%3==1的数); - // 如果上面都做不到,说明拼不成 - public static String max3(int[] A) { - if (A == null || A.length == 0) { - return ""; - } - int mod = 0; - ArrayList arr = new ArrayList<>(); - for (int num : A) { - arr.add(num); - mod += num; - mod %= 3; - } - if ((mod == 1 || mod == 2) && !remove(arr, mod, 3 - mod)) { - return ""; - } - if (arr.isEmpty()) { - return ""; - } - arr.sort((a, b) -> b - a); - if (arr.get(0) == 0) { - return "0"; - } - StringBuilder builder = new StringBuilder(); - for (int num : arr) { - builder.append(num); - } - return builder.toString(); - } - - // 在arr中,要么删掉最小的一个、且%3之后余数是first的数 - // 如果做不到,删掉最小的两个、且%3之后余数是second的数 - // 如果能做到返回true,不能做到返回false - public static boolean remove(ArrayList arr, int first, int second) { - if (arr.size() == 0) { - return false; - } - arr.sort((a, b) -> compare(a, b, first, second)); - int size = arr.size(); - if (arr.get(size - 1) % 3 == first) { - arr.remove(size - 1); - return true; - } else if (size > 1 && arr.get(size - 1) % 3 == second && arr.get(size - 2) % 3 == second) { - arr.remove(size - 1); - arr.remove(size - 2); - return true; - } else { - return false; - } - } - - // a和b比较: - // 如果余数一样,谁大谁放前面 - // 如果余数不一样,余数是0的放最前面、余数是s的放中间、余数是f的放最后 - public static int compare(int a, int b, int f, int s) { - int ma = a % 3; - int mb = b % 3; - if (ma == mb) { - return b - a; - } else { - if (ma == 0 || mb == 0) { - return ma == 0 ? -1 : 1; - } else { - return ma == s ? -1 : 1; - } - } - } - - // 为了测试 - public static int[] randomArray(int len) { - int[] arr = new int[len]; - for (int i = 0; i < len; i++) { - arr[i] = (int) (Math.random() * 10); - } - return arr; - } - - // 为了测试 - public static int[] copyArray(int[] arr) { - int[] ans = new int[arr.length]; - for (int i = 0; i < arr.length; i++) { - ans[i] = arr[i]; - } - return ans; - } - - // 为了测试 - public static void main(String[] args) { - int N = 10; - int testTimes = 10000; - System.out.println("测试开始"); - for (int i = 0; i < testTimes; i++) { - int len = (int) (Math.random() * N); - int[] arr1 = randomArray(len); - int[] arr2 = copyArray(arr1); - int[] arr3 = copyArray(arr1); - String ans1 = max1(arr1); - String ans2 = max2(arr2); - String ans3 = max3(arr3); - if (!ans1.equals(ans2) || !ans1.equals(ans3)) { - System.out.println("出错了!"); - for (int num : arr3) { - System.out.print(num + " "); - } - System.out.println(); - System.out.println(ans1); - System.out.println(ans2); - System.out.println(ans3); - break; - } - } - System.out.println("测试结束"); - - } - -} diff --git a/公开课/class074/Code02_LetASorted.java b/公开课/class074/Code02_LetASorted.java deleted file mode 100644 index 942d4fa..0000000 --- a/公开课/class074/Code02_LetASorted.java +++ /dev/null @@ -1,97 +0,0 @@ -package class074; - -// 给定两个数组A和B,长度都是N -// A[i]不可以在A中和其他数交换,只可以选择和B[i]交换(0<=i A[index] ? false : (process(A, B, index + 1, A[index])); - // 2) 交换 - boolean p2 = pre > B[index] ? false : (process(A, B, index + 1, B[index])); - return p1 | p2; - } - - public static boolean canSorted2(int[] A, int[] B) { - if (A == null || A.length < 2) { - return true; - } - // 长度>=2 - // 0 1.. - return zuo(A, B, 1, false) || zuo(A, B, 1, true); - } - - public static boolean zuo(int[] A, int[] B, int index, boolean swap) { - if (index == A.length) { - return true; - } - int pre = swap ? B[index - 1] : A[index - 1]; - // index还没到终止位置! - // 1) 不交换 A[index] - boolean p1 = pre > A[index] ? false : (zuo(A, B, index + 1, false)); - // 2) 交换 - boolean p2 = pre > B[index] ? false : (zuo(A, B, index + 1, true)); - return p1 | p2; - - } - -// -// public static boolean letASorted(int[] A, int[] B) { -// return process(A, B, 0, Integer.MIN_VALUE); -// } -// -// // 当前推进到了i位置,对于A和B都是i位置 -// // A[i]前一个数字,lastA -// // 能否通过题意中的操作,A[i] B[i] 让A整体有序 -// public static boolean process(int[] A, int[] B, int i, int lastA) { -// if (i == A.length) { -// return true; -// } -// // 第一种选择 : A[i]不和B[i]交换 -// if (A[i] >= lastA && process(A, B, i + 1, A[i])) { -// return true; -// } -// // 第一种选择 : A[i]和B[i]交换 -// if (B[i] >= lastA && process(A, B, i + 1, B[i])) { -// return true; -// } -// return false; -// } -// -// public static boolean process2(int[] A, int[] B, int i, int lastA) { -// if (i == A.length) { -// return true; -// } -// // 第一种选择 : A[i]不和B[i]交换 -// if (A[i] <= lastA && process2(A, B, i + 1, A[i])) { -// return true; -// } -// // 第一种选择 : A[i]和B[i]交换 -// if (B[i] <= lastA && process2(A, B, i + 1, B[i])) { -// return true; -// } -// return false; -// } - - // A B 操作 : A[i] 与 B[i] 交换! - // 目的 : 让A和B都有序,能不能做到 -// public static boolean process3(int[] A, int[] B, int i, int lastA, int lastB) { -// -// } - -} diff --git a/公开课/class074/Code03_AwayFromBlackHole.java b/公开课/class074/Code03_AwayFromBlackHole.java deleted file mode 100644 index 145369c..0000000 --- a/公开课/class074/Code03_AwayFromBlackHole.java +++ /dev/null @@ -1,122 +0,0 @@ -package class074; - -// 来自美团 -// 所有黑洞的中心点记录在holes数组里 -// 比如[[3,5] [6,9]]表示,第一个黑洞在(3,5),第二个黑洞在(6,9) -// 并且所有黑洞的中心点都在左下角(0,0),右上角(x,y)的区域里 -// 飞船一旦开始进入黑洞,就会被吸进黑洞里 -// 返回: -// 如果统一所有黑洞的半径,最大半径是多少,依然能保证飞船从(0,0)能到达(x,y) -// 1000 1000*1000 10^6 * 二分 -public class Code03_AwayFromBlackHole { - - public static int maxRadius(int[][] holes, int x, int y) { - int L = 1; - int R = Math.max(x, y); - int ans = 0; - while (L <= R) { - int M = (L + R) / 2; - if (ok(holes, M, x, y)) { - ans = M; - L = M + 1; - } else { - R = M - 1; - } - } - return ans; - } - - public static boolean ok(int[][] holes, int r, int x, int y) { - int n = holes.length; - UnionFind uf = new UnionFind(holes, n, r); - for (int i = 0; i < n; i++) { - for (int j = i; j < n; j++) { - if (touch(holes[i][0], holes[i][1], holes[j][0], holes[j][1], r)) { - uf.union(i, j); - } - if (uf.block(i, x, y)) { - return false; - } - } - } - return true; - } - - public static boolean touch(int x1, int y1, int x2, int y2, int r) { - return (r << 1) >= Math.sqrt((Math.pow(Math.abs(x1 - x2), 2) + Math.pow(Math.abs(y1 - y2), 2))); - } - - public static class UnionFind { - public int[] father; - public int[] size; - public int[] xmin; - public int[] xmax; - public int[] ymin; - public int[] ymax; - public int[] help; - - public UnionFind(int[][] holes, int n, int r) { - father = new int[n]; - size = new int[n]; - xmin = new int[n]; - xmax = new int[n]; - ymin = new int[n]; - ymax = new int[n]; - help = new int[n]; - for (int i = 0; i < n; i++) { - father[i] = i; - size[i] = 1; - xmin[i] = holes[i][0] - r; - xmax[i] = holes[i][0] + r; - ymin[i] = holes[i][1] - r; - ymax[i] = holes[i][1] + r; - } - } - - private int find(int i) { - int hi = 0; - while (i != father[i]) { - help[hi++] = i; - i = father[i]; - } - for (hi--; hi >= 0; hi--) { - father[help[hi]] = i; - } - return i; - } - - public void union(int i, int j) { - int fatheri = find(i); - int fatherj = find(j); - if (fatheri != fatherj) { - int sizei = size[fatheri]; - int sizej = size[fatherj]; - int big = sizei >= sizej ? fatheri : fatherj; - int small = big == fatheri ? fatherj : fatheri; - father[small] = big; - size[big] = sizei + sizej; - xmin[big] = Math.min(xmin[big], xmin[small]); - xmax[big] = Math.max(xmax[big], xmax[small]); - ymin[big] = Math.min(ymin[big], ymin[small]); - ymax[big] = Math.max(ymax[big], ymax[small]); - } - } - - public boolean block(int i, int x, int y) { - i = find(i); - return (xmin[i] <= 0 && xmax[i] >= x) - || (ymin[i] <= 0 && ymax[i] >= y) - || (xmin[i] <= 0 && ymin[i] <= 0) - || (xmax[i] >= x && ymax[i] >= y); - } - - } - - public static void main(String[] args) { - int[][] holes = { { 1, 2 }, { 4, 4 }, { 3, 0 }, { 5, 2 } }; - int x = 4; - int y = 6; - System.out.println(maxRadius(holes, x, y)); - } - -} diff --git a/公开课/class074/Code04_AllSame.java b/公开课/class074/Code04_AllSame.java deleted file mode 100644 index 9ce0c34..0000000 --- a/公开课/class074/Code04_AllSame.java +++ /dev/null @@ -1,65 +0,0 @@ -package class074; - -// 来自腾讯 -// 比如arr = {3,1,2,4} -// 下标对应是:0 1 2 3 -// 你最开始选择一个下标进行操作,一旦最开始确定了是哪个下标,以后都只能在这个下标上进行操作 -// 比如你选定1下标,1下标上面的数字是1,你可以选择变化这个数字,比如你让这个数字变成2 -// 那么arr = {3,2,2,4} -// 下标对应是:0 1 2 3 -// 因为你最开始确定了1这个下标,所以你以后都只能对这个下标进行操作, -// 但是,和你此时下标上的数字一样的、且位置连成一片的数字,会跟着一起变 -// 比如你选择让此时下标1的数字2变成3, -// 那么arr = {3,3,3,4} 可以看到下标1和下标2的数字一起变成3,这是规则!一定会一起变 -// 下标对应是:0 1 2 3 -// 接下来,你还是只能对1下标进行操作,那么数字一样的、且位置连成一片的数字(arr[0~2]这个范围)都会一起变 -// 决定变成4 -// 那么arr = {4,4,4,4} -// 下标对应是:0 1 2 3 -// 至此,所有数都成一样的了,你在下标1上做了3个决定(第一次变成2,第二次变成3,第三次变成4), -// 因为联动规则,arr全刷成一种数字了 -// 给定一个数组arr,最开始选择哪个下标,你随意 -// 你的目的是一定要让arr都成为一种数字,注意联动效果会一直生效 -// 返回最小的变化数 -// arr长度 <= 200, arr中的值 <= 10^6 -public class Code04_AllSame { - - public static int allSame(int[] arr) { - int ans = Integer.MAX_VALUE; - for (int i = 0; i < arr.length; i++) { - ans = Math.min(ans, process(arr, i - 1, arr[i], i + 1)); - } - return ans; - } - - // 左边arr[0..left],如果left == -1,说明没有左边了 - // 右边arr[right...n-1],如果right == n,说明没有右边了 - // 中间的值是midV,中间的值代表中间一整个部分的值,中间部分有可能是一个数,也可能是一堆数,但是值都为midV - // 返回arr都刷成一样的,最小代价是多少 - // left 可能性 : N - // right 可能性 : N - // midV 可能性 : arr中的最大值! - public static int process(int[] arr, int left, int midV, int right) { - for (; left >= 0 && arr[left] == midV;) { - left--; - } - for (; right < arr.length && arr[right] == midV;) { - right++; - } - if (left == -1 && right == arr.length) { - return 0; - } - int p1 = Integer.MAX_VALUE; - if (left >= 0) { - p1 = process(arr, left - 1, arr[left], right) + 1; - } - int p2 = Integer.MAX_VALUE; - if (right < arr.length) { - p2 = process(arr, left, arr[right], right + 1) + 1; - } - return Math.min(p1, p2); - } - - // 如上的递归,请改动态规划,具体参考体系学习班,动态规划大章节! - -} diff --git a/公开课/class075/Code01_BattleshipsInABoard.java b/公开课/class075/Code01_BattleshipsInABoard.java deleted file mode 100644 index 2b010b3..0000000 --- a/公开课/class075/Code01_BattleshipsInABoard.java +++ /dev/null @@ -1,21 +0,0 @@ -package class075; - -// 来自米哈游 -// 测试链接 : https://leetcode.com/problems/battleships-in-a-board/ -public class Code01_BattleshipsInABoard { - - public static int countBattleships(char[][] m) { - int ans = 0; - for (int i = 0; i < m.length; i++) { - for (int j = 0; j < m[0].length; j++) { - if ((m[i][j] == 'X') - && (i == 0 || m[i - 1][j] != 'X') - && (j == 0 || m[i][j - 1] != 'X')) { - ans++; - } - } - } - return ans; - } - -} diff --git a/公开课/class075/Code02_ShortestSubarrayWithSumAtLeastK.java b/公开课/class075/Code02_ShortestSubarrayWithSumAtLeastK.java deleted file mode 100644 index e797f0b..0000000 --- a/公开课/class075/Code02_ShortestSubarrayWithSumAtLeastK.java +++ /dev/null @@ -1,74 +0,0 @@ -package class075; - -// 来自字节跳动 -// 给定一个数组arr,其中的值有可能正、负、0 -// 给定一个正数k -// 返回累加和>=k的所有子数组中,最短的子数组长度 -// 本题测试链接 : https://leetcode.com/problems/shortest-subarray-with-sum-at-least-k/ -public class Code02_ShortestSubarrayWithSumAtLeastK { - - public static int shortestSubarray1(int[] arr, int k) { - if (arr == null || arr.length < 1) { - return -1; - } - int n = arr.length + 1; - long[] sum = new long[n]; - for (int i = 1; i < n; i++) { - sum[i] = sum[i - 1] + arr[i - 1]; - } - int[] stack = new int[n]; - int size = 1; - int ans = Integer.MAX_VALUE; - for (int i = 1; i < n; i++) { - int mostRight = mostRight(sum, stack, size, sum[i] - k); - ans = Math.min(ans, mostRight == -1 ? Integer.MAX_VALUE : (i - mostRight)); - while (size > 0 && sum[stack[size - 1]] >= sum[i]) { - size--; - } - stack[size++] = i; - } - return ans == Integer.MAX_VALUE ? -1 : ans; - } - - public static int mostRight(long[] sum, int[] stack, int size, long aim) { - int l = 0; - int r = size - 1; - int m = 0; - int ans = -1; - while (l <= r) { - m = (l + r) / 2; - if (sum[stack[m]] <= aim) { - ans = stack[m]; - l = m + 1; - } else { - r = m - 1; - } - } - return ans; - } - - public static int shortestSubarray2(int[] arr, int K) { - int N = arr.length; - long[] sum = new long[N + 1]; - for (int i = 0; i < N; i++) { - sum[i + 1] = sum[i] + arr[i]; - } - int ans = Integer.MAX_VALUE; - int[] dq = new int[N + 1]; - int l = 0; - int r = 0; - for (int i = 0; i < N + 1; i++) { - // 头部开始,符合条件的,从头部弹出! - while (l != r && sum[i] - sum[dq[l]] >= K) { - ans = Math.min(ans, i - dq[l++]); - } - // 尾部开始,前缀和比当前的前缀和大于等于的,从尾部弹出! - while (l != r && sum[dq[r - 1]] >= sum[i]) { - r--; - } - dq[r++] = i; - } - return ans != Integer.MAX_VALUE ? ans : -1; - } - -} diff --git a/公开课/class075/Code03_BuyThingsAboutCollocation.java b/公开课/class075/Code03_BuyThingsAboutCollocation.java deleted file mode 100644 index 62110ee..0000000 --- a/公开课/class075/Code03_BuyThingsAboutCollocation.java +++ /dev/null @@ -1,103 +0,0 @@ -package class075; - -// things是一个N*3的二维数组,商品有N件,商品编号从1~N -// 比如things[3] = [300, 2, 6] -// 代表第3号商品:价格300,重要度2,它是6号商品的附属商品 -// 再比如things[6] = [500, 3, 0] -// 代表第6号商品:价格500,重要度3,它不是任何附属,它是主商品 -// 每件商品的收益是价格*重要度,花费就是价格 -// 如果一个商品是附属品,那么只有它附属的主商品购买了,它才能被购买 -// 任何一个附属商品,只会有1个主商品 -// 任何一个主商品的附属商品数量,不会超过2件 -// 主商品和附属商品的层级最多有2层 -// 给定二维数组things、钱数money,返回整体花费不超过money的情况下,最大的收益总和 -// 测试链接 : https://www.nowcoder.com/practice/f9c6f980eeec43ef85be20755ddbeaf4 -// 请把如下的代码的主类名改为"Main", 可以直接通过 -import java.util.ArrayList; -import java.util.Scanner; - -public class Code03_BuyThingsAboutCollocation { - - public static void main(String[] args) { - Scanner sc = new Scanner(System.in); - while (sc.hasNext()) { - int money = sc.nextInt(); - int size = sc.nextInt(); - ArrayList> things = new ArrayList<>(); - things.add(new ArrayList<>()); - for (int i = 0; i < size; i++) { - ArrayList cur = new ArrayList<>(); - cur.add(new int[] { sc.nextInt(), sc.nextInt(), sc.nextInt() }); - things.add(cur); - } - int n = clean(things, size); - int ans = maxScore(things, n, money); - System.out.println(ans); - } - sc.close(); - } - - public static int clean(ArrayList> things, int size) { - for (int i = 1; i <= size; i++) { - int[] cur = things.get(i).get(0); - if (cur[2] != 0) { - things.get(i).clear(); - things.get(cur[2]).add(cur); - } - } - int n = 0; - for (int i = 0; i <= size; i++) { - if (!things.get(i).isEmpty()) { - things.set(n++, things.get(i)); - } - } - return n; - } - - public static int maxScore(ArrayList> things, int n, int money) { - int[][] dp = new int[n][money + 1]; - for (int i = 0; i < n; i++) { - for (int j = 0; j <= money; j++) { - dp[i][j] = -2; - } - } - return process(things, n, 0, money, dp); - } - - public static int process(ArrayList> things, int n, int index, int rest, int[][] dp) { - if (rest < 0) { - return -1; - } - if (index == n) { - return 0; - } - if (dp[index][rest] != -2) { - return dp[index][rest]; - } - ArrayList project = things.get(index); - int[] a = project.get(0); - int[] b = project.size() > 1 ? project.get(1) : null; - int[] c = project.size() > 2 ? project.get(2) : null; - int p1 = process(things, n, index + 1, rest, dp); - int p2 = process(things, n, index + 1, rest - a[0], dp); - if (p2 != -1) { - p2 += a[0] * a[1]; - } - int p3 = b != null ? process(things, n, index + 1, rest - a[0] - b[0], dp) : -1; - if (p3 != -1) { - p3 += a[0] * a[1] + b[0] * b[1]; - } - int p4 = c != null ? process(things, n, index + 1, rest - a[0] - c[0], dp) : -1; - if (p4 != -1) { - p4 += a[0] * a[1] + c[0] * c[1]; - } - int p5 = c != null ? process(things, n, index + 1, rest - a[0] - b[0] - c[0], dp) : -1; - if (p5 != -1) { - p5 += a[0] * a[1] + b[0] * b[1] + c[0] * c[1]; - } - int ans = Math.max(Math.max(Math.max(p1, p2), Math.max(p3, p4)), p5); - dp[index][rest] = ans; - return ans; - } - -} diff --git a/公开课/class075/Code04_BrickAll.java b/公开课/class075/Code04_BrickAll.java deleted file mode 100644 index be4bac2..0000000 --- a/公开课/class075/Code04_BrickAll.java +++ /dev/null @@ -1,50 +0,0 @@ -package class075; - -import java.util.Arrays; - -// 来自华为 -// 给定一个正数数组arr,其中每个值代表砖块长度 -// 所有砖块等高等宽,只有长度有区别 -// 每一层可以用1块或者2块砖来摆 -// 要求每一层的长度一样 -// 要求必须使用所有的砖块 -// 请问最多摆几层 -// 如果无法做到,返回-1 -public class Code04_BrickAll { - - public static int maxLevels(int[] arr) { - if (arr == null) { - return 0; - } - int n = arr.length; - if (n < 2) { - return n; - } - Arrays.sort(arr); - int p1 = levels(arr, arr[n - 1]); - int p2 = levels(arr, arr[n - 1] + arr[0]); - return Math.max(p1, p2); - } - - // 要求所有砖必须都使用,并且每一层最多两块砖,并且每一层长度都是len - // 返回能摆几层,如果无法做到返回-1 - public static int levels(int[] arr, int len) { - int ans = 0; - int L = 0; - int R = arr.length - 1; - while (L <= R) { - if (arr[R] == len) { - R--; - ans++; - } else if (L < R && arr[L] + arr[R] == len) { - L++; - R--; - ans++; - } else { - return -1; - } - } - return ans; - } - -} diff --git a/公开课/class076/Code01_SetAll.java b/公开课/class076/Code01_SetAll.java deleted file mode 100644 index 2179b51..0000000 --- a/公开课/class076/Code01_SetAll.java +++ /dev/null @@ -1,48 +0,0 @@ -package class076; - -import java.util.HashMap; - -public class Code01_SetAll { - - public static class MyValue { - public V value; - public long time; - - public MyValue(V v, long t) { - value = v; - time = t; - } - } - - public static class MyHashMap { - private HashMap> map; - private long time; - private MyValue setAll; - - public MyHashMap() { - map = new HashMap<>(); - time = 0; - setAll = new MyValue(null, -1); - } - - public void put(K key, V value) { - map.put(key, new MyValue(value, time++)); - } - - public void setAll(V value) { - setAll = new MyValue(value, time++); - } - - public V get(K key) { - if (!map.containsKey(key)) { - return null; - } - if (map.get(key).time > setAll.time) { - return map.get(key).value; - } else { - return setAll.value; - } - } - } - -} diff --git a/公开课/class076/Code02_4KeysKeyboard.java b/公开课/class076/Code02_4KeysKeyboard.java deleted file mode 100644 index 46ce34c..0000000 --- a/公开课/class076/Code02_4KeysKeyboard.java +++ /dev/null @@ -1,24 +0,0 @@ -package class076; - -// 测试链接 : https://leetcode.com/problems/4-keys-keyboard/ -public class Code02_4KeysKeyboard { - - public static int maxA(int n) { - int[] dp = new int[n + 1]; - // dp[1] : 1 - // dp[2] : 2 - // dp[5] : 5 - for (int i = 1; i <= 5 && i <= n; i++) { - dp[i] = i; - } - // i - //-1 -1 -1 粘贴 - for (int i = 6; i <= n; i++) { - dp[i] = Math.max( - Math.max(dp[i - 3] * 2, dp[i - 4] * 3), - Math.max(dp[i - 5] * 4, dp[i - 6] * 5)); - } - return dp[n]; - } - -} diff --git a/公开课/class076/Code03_BrickAll.java b/公开课/class076/Code03_BrickAll.java deleted file mode 100644 index 32e98d2..0000000 --- a/公开课/class076/Code03_BrickAll.java +++ /dev/null @@ -1,50 +0,0 @@ -package class076; - -import java.util.Arrays; - -// 来自华为 -// 给定一个正数数组arr,其中每个值代表砖块长度 -// 所有砖块等高等宽,只有长度有区别 -// 每一层可以用1块或者2块砖来摆 -// 要求每一层的长度一样 -// 要求必须使用所有的砖块 -// 请问最多摆几层 -// 如果无法做到,返回-1 -public class Code03_BrickAll { - - public static int maxLevels(int[] arr) { - if (arr == null) { - return 0; - } - int n = arr.length; - if (n < 2) { - return n; - } - Arrays.sort(arr); - int p1 = levels(arr, arr[n - 1]); - int p2 = levels(arr, arr[n - 1] + arr[0]); - return Math.max(p1, p2); - } - - // 要求所有砖必须都使用,并且每一层最多两块砖,并且每一层长度都是len - // 返回能摆几层,如果无法做到返回-1 - public static int levels(int[] arr, int len) { - int ans = 0; - int L = 0; - int R = arr.length - 1; - while (L <= R) { - if (arr[R] == len) { - R--; - ans++; - } else if (L < R && arr[L] + arr[R] == len) { - L++; - R--; - ans++; - } else { - return -1; - } - } - return ans; - } - -} diff --git a/公开课/class076/Code04_InsertDeleteGetRandom.java b/公开课/class076/Code04_InsertDeleteGetRandom.java deleted file mode 100644 index 141551d..0000000 --- a/公开课/class076/Code04_InsertDeleteGetRandom.java +++ /dev/null @@ -1,51 +0,0 @@ -package class076; - -import java.util.HashMap; - -// 测试链接 : https://leetcode.com/problems/insert-delete-getrandom-o1/ -public class Code04_InsertDeleteGetRandom { - - public class RandomizedSet { - private HashMap keyIndexMap; - private HashMap indexKeyMap; - private int size; - - public RandomizedSet() { - keyIndexMap = new HashMap(); - indexKeyMap = new HashMap(); - size = 0; - } - - public boolean insert(int key) { - if (!keyIndexMap.containsKey(key)) { - keyIndexMap.put(key, size); - indexKeyMap.put(size++, key); - return true; - } - return false; - } - - public boolean remove(int val) { - if (keyIndexMap.containsKey(val)) { - int deleteIndex = keyIndexMap.get(val); - int lastIndex = --size; - int lastKey = indexKeyMap.get(lastIndex); - keyIndexMap.put(lastKey, deleteIndex); - indexKeyMap.put(deleteIndex, lastKey); - keyIndexMap.remove(val); - indexKeyMap.remove(lastIndex); - return true; - } - return false; - } - - public int getRandom() { - if (size == 0) { - return -1; - } - int randomIndex = (int) (Math.random() * size); - return indexKeyMap.get(randomIndex); - } - } - -} diff --git a/公开课/class076/Code05_SplitApples.java b/公开课/class076/Code05_SplitApples.java deleted file mode 100644 index a08fc8f..0000000 --- a/公开课/class076/Code05_SplitApples.java +++ /dev/null @@ -1,161 +0,0 @@ -package class076; - -//有m个同样的苹果,认为苹果之间无差别 -//有n个同样的盘子,认为盘子之间也无差别 -//还有,比如5个苹果如果放进3个盘子, -//那么1、3、1和1、1、3和3、1、1的放置方法,也认为是一种方法 -//如上的设定下,返回有多少种放置方法 -//测试链接 : https://www.nowcoder.com/practice/bfd8234bb5e84be0b493656e390bdebf -//提交以下的code,提交时请把类名改成"Main" -import java.util.Arrays; -import java.util.Scanner; - -public class Code05_SplitApples { - - public static int test(int apples, int plates) { - // 1000 - // 1000 - int[][] dp = new int[apples + 1][plates + 1]; - for (int i = 0; i <= apples; i++) { - for (int j = 0; j <= plates; j++) { - dp[i][j] = -1; - } - } - return f(apples, plates, dp); - } - - // 摆法要符合题目的意思:排完序之后,如果数字分布一样,就认为是同一种摆法! - // 给你苹果数量apples,给你盘子数量plates - // 返回,几种摆法! - // 1000个 - // 1000个 - // 1000 * 1000 - public static int f(int apples, int plates, int[][] dp) { - if (dp[apples][plates] != -1) { - return dp[apples][plates]; - } - int ans = 0; - if (apples == 0) { - ans = 1; - } else if (plates == 0) { - ans = 0; - } else { - if (plates > apples) { - ans = f(apples, apples, dp); - } else { // apples >= plates; - ans = f(apples, plates - 1, dp) + f(apples - plates, plates, dp); - } - } - dp[apples][plates] = ans; - return ans; - } - - public static void main(String[] args) { - Scanner sc = new Scanner(System.in); - while (sc.hasNext()) { - int m = sc.nextInt(); - int n = sc.nextInt(); - int ways = ways3(m, n); - System.out.println(ways); - } - sc.close(); - } - - // 思路来自于分裂数问题 - // 体系学习班代码第22节,题目3,split number问题 - public static int ways1(int apples, int plates) { - return process1(1, apples, plates); - } - - // pre : 上一个盘子分到的苹果数量,当前的盘子分到的数量不能小于pre - // apples : 剩余的苹果数量 - // plates : 剩余的盘子数量 - // 在盘子够用的情况下,把苹果分完,有几种方法 - public static int process1(int pre, int apples, int plates) { - if (apples == 0) { - return 1; - } - // apples != 0 - if (plates == 0) { - return 0; - } - // apples != 0 && plates != 0 - if (pre > apples) { - return 0; - } - // apples != 0 && plates != 0 && pre <= apples - int way = 0; - // 之前的盘子分了3个苹果,现在还剩下8个苹果 - // 当前的盘子,可以装几个苹果:3、4、5、6、7、8 - for (int cur = pre; cur <= apples; cur++) { - way += process1(cur, apples - cur, plates - 1); - } - return way; - } - - // 新的尝试,最优解 - // 苹果有apples个,盘子有plates个 - // 返回有几种摆法 - // 如果苹果数为0,有1种摆法:什么也不摆 - // 如果苹果数不为0,但是盘子数为0,有0种摆法(做不到) - // 如果苹果数不为0,盘子数也不为0,进行如下的情况讨论: - // 假设苹果数为apples,盘子数为plates - // 可能性 1) apples < plates - // 这种情况下,一定有多余的盘子,这些盘子完全没用,所以砍掉 - // 后续是f(apples, apples) - // 可能性 2) apples >= plates - // 在可能性2)下,讨论摆法,有如下两种选择 - // 选择a) 不是所有的盘子都使用 - // 选择b) 就是所有的盘子都使用 - // 对于选择a),既然不是所有盘子都使用,那么后续就是f(apples, plates - 1) - // 意思是:既然不是所有盘子都使用,那盘子减少一个,然后继续讨论吧! - // 对于选择b),既然就是所有的盘子都使用,那么先把所有盘子都摆上1个苹果。 - // 剩余苹果数 = apples - plates - // 然后继续讨论,剩下的这些苹果,怎么摆进plates个盘子里, - // 所以后续是f(apples - plates, plates) - public static int ways2(int apples, int plates) { - if (apples == 0) { - return 1; - } - if (plates == 0) { - return 0; - } - if (plates > apples) { - return ways2(apples, apples); - } else { // apples >= plates; - return ways2(apples, plates - 1) + ways2(apples - plates, plates); - } - } - - // 上面最优解尝试的记忆化搜索版本 - public static int[][] dp = null; - - public static int ways3(int apples, int plates) { - if (dp == null) { - dp = new int[11][11]; - for (int i = 0; i <= 10; i++) { - Arrays.fill(dp[i], -1); - } - } - return process3(apples, plates, dp); - } - - public static int process3(int apples, int plates, int[][] dp) { - if (dp[apples][plates] != -1) { - return dp[apples][plates]; - } - int ans = 0; - if (apples == 0) { - ans = 1; - } else if (plates == 0) { - ans = 0; - } else if (plates > apples) { - ans = process3(apples, apples, dp); - } else { - ans = process3(apples, plates - 1, dp) + process3(apples - plates, plates, dp); - } - dp[apples][plates] = ans; - return ans; - } - -} \ No newline at end of file diff --git a/公开课/class076/Code06_SplitStrings.java b/公开课/class076/Code06_SplitStrings.java deleted file mode 100644 index 8bcd267..0000000 --- a/公开课/class076/Code06_SplitStrings.java +++ /dev/null @@ -1,11 +0,0 @@ -package class076; - -public class Code06_SplitStrings { -// 题目6 -// 给定一个非常大的List list -// 每一个字符串类似 : "hello,world,have,hello,world" -// 这一个字符串中,有2个hello,2个world,1个have -// 请设计一种多线程处理方案,统计list中每一个字符串, -// 切分出来的单词数量,并且汇总 -// 最终返回一个HashMap表示每个字符串出现几次 -} diff --git a/公开课/class076/Code07_ShortestSubarrayWithSumAtLeastK.java b/公开课/class076/Code07_ShortestSubarrayWithSumAtLeastK.java deleted file mode 100644 index 719aabf..0000000 --- a/公开课/class076/Code07_ShortestSubarrayWithSumAtLeastK.java +++ /dev/null @@ -1,74 +0,0 @@ -package class076; - -// 来自字节跳动 -// 给定一个数组arr,其中的值有可能正、负、0 -// 给定一个正数k -// 返回累加和>=k的所有子数组中,最短的子数组长度 -// 本题测试链接 : https://leetcode.com/problems/shortest-subarray-with-sum-at-least-k/ -public class Code07_ShortestSubarrayWithSumAtLeastK { - - public static int shortestSubarray1(int[] arr, int k) { - if (arr == null || arr.length < 1) { - return -1; - } - int n = arr.length + 1; - long[] sum = new long[n]; - for (int i = 1; i < n; i++) { - sum[i] = sum[i - 1] + arr[i - 1]; - } - int[] stack = new int[n]; - int size = 1; - int ans = Integer.MAX_VALUE; - for (int i = 1; i < n; i++) { - int mostRight = mostRight(sum, stack, size, sum[i] - k); - ans = Math.min(ans, mostRight == -1 ? Integer.MAX_VALUE : (i - mostRight)); - while (size > 0 && sum[stack[size - 1]] >= sum[i]) { - size--; - } - stack[size++] = i; - } - return ans == Integer.MAX_VALUE ? -1 : ans; - } - - public static int mostRight(long[] sum, int[] stack, int size, long aim) { - int l = 0; - int r = size - 1; - int m = 0; - int ans = -1; - while (l <= r) { - m = (l + r) / 2; - if (sum[stack[m]] <= aim) { - ans = stack[m]; - l = m + 1; - } else { - r = m - 1; - } - } - return ans; - } - - public static int shortestSubarray2(int[] arr, int K) { - int N = arr.length; - long[] sum = new long[N + 1]; - for (int i = 0; i < N; i++) { - sum[i + 1] = sum[i] + arr[i]; - } - int ans = Integer.MAX_VALUE; - int[] dq = new int[N + 1]; - int l = 0; - int r = 0; - for (int i = 0; i < N + 1; i++) { - // 头部开始,符合条件的,从头部弹出! - while (l != r && sum[i] - sum[dq[l]] >= K) { - ans = Math.min(ans, i - dq[l++]); - } - // 尾部开始,前缀和比当前的前缀和大于等于的,从尾部弹出! - while (l != r && sum[dq[r - 1]] >= sum[i]) { - r--; - } - dq[r++] = i; - } - return ans != Integer.MAX_VALUE ? ans : -1; - } - -} diff --git a/公开课/class077/Code01_MonotonousStack.java b/公开课/class077/Code01_MonotonousStack.java deleted file mode 100644 index 35e3fb2..0000000 --- a/公开课/class077/Code01_MonotonousStack.java +++ /dev/null @@ -1,178 +0,0 @@ -package class077; - -import java.util.List; -import java.util.ArrayList; -import java.util.Stack; - -public class Code01_MonotonousStack { - - // arr = [ 3, 1, 2, 3] - // 0 1 2 3 - // [ - // 0 : [-1, 1] - // 1 : [-1, -1] - // 2 : [ 1, -1] - // 3 : [ 2, -1] - // ] - public static int[][] getNearLessNoRepeat(int[] arr) { - int[][] res = new int[arr.length][2]; - // 只存位置! - Stack stack = new Stack<>(); - for (int i = 0; i < arr.length; i++) { // 当遍历到i位置的数,arr[i] - while (!stack.isEmpty() && arr[stack.peek()] > arr[i]) { - int j = stack.pop(); - int leftLessIndex = stack.isEmpty() ? -1 : stack.peek(); - res[j][0] = leftLessIndex; - res[j][1] = i; - } - stack.push(i); - } - while (!stack.isEmpty()) { - int j = stack.pop(); - int leftLessIndex = stack.isEmpty() ? -1 : stack.peek(); - res[j][0] = leftLessIndex; - res[j][1] = -1; - } - return res; - } - - - // arr中可能有重复值,[3,2,3,3,1] - // 0 1 2 3 4 - // - // 0 -> 3 : -1 1->2 - // 0 : [-1, 1] - // 1 : [-1, 4] - // 2 : [ 1, 4] - // n-1 : [ a, b] - public static int[][] getNearLess(int[] arr) { - int[][] res = new int[arr.length][2]; - Stack< List > stack = new Stack<>(); - for (int i = 0; i < arr.length; i++) { // i -> arr[i] 进栈 - // i -> arr[i] - while (!stack.isEmpty() && arr[stack.peek().get(0)] > arr[i]) { - List popIs = stack.pop(); - int leftLessIndex = stack.isEmpty() - ? -1 : stack.peek().get(stack.peek().size() - 1); - for (Integer popi : popIs) { - res[popi][0] = leftLessIndex; - res[popi][1] = i; - } - } - // 1) 弹出完之后,顶部有东西,和当前值一样 - if (!stack.isEmpty() && arr[stack.peek().get(0)] == arr[i]) { - stack.peek().add(Integer.valueOf(i)); - } else { // 2) 栈为空 or 栈顶值 < 当前值 - ArrayList list = new ArrayList<>(); - list.add(i); - stack.push(list); - } - } - // 单独清算栈里的东西! - while (!stack.isEmpty()) { - List popIs = stack.pop(); - int leftLessIndex = stack.isEmpty() ? -1 : stack.peek().get(stack.peek().size() - 1); - for (Integer popi : popIs) { - res[popi][0] = leftLessIndex; - res[popi][1] = -1; - } - } - return res; - } - - // for test - public static int[] getRandomArrayNoRepeat(int size) { - int[] arr = new int[(int) (Math.random() * size) + 1]; - for (int i = 0; i < arr.length; i++) { - arr[i] = i; - } - for (int i = 0; i < arr.length; i++) { - int swapIndex = (int) (Math.random() * arr.length); - int tmp = arr[swapIndex]; - arr[swapIndex] = arr[i]; - arr[i] = tmp; - } - return arr; - } - - // for test - public static int[] getRandomArray(int size, int max) { - int[] arr = new int[(int) (Math.random() * size) + 1]; - for (int i = 0; i < arr.length; i++) { - arr[i] = (int) (Math.random() * max) - (int) (Math.random() * max); - } - return arr; - } - - // for test - public static int[][] rightWay(int[] arr) { - int[][] res = new int[arr.length][2]; - for (int i = 0; i < arr.length; i++) { - int leftLessIndex = -1; - int rightLessIndex = -1; - int cur = i - 1; - while (cur >= 0) { - if (arr[cur] < arr[i]) { - leftLessIndex = cur; - break; - } - cur--; - } - cur = i + 1; - while (cur < arr.length) { - if (arr[cur] < arr[i]) { - rightLessIndex = cur; - break; - } - cur++; - } - res[i][0] = leftLessIndex; - res[i][1] = rightLessIndex; - } - return res; - } - - // for test - public static boolean isEqual(int[][] res1, int[][] res2) { - if (res1.length != res2.length) { - return false; - } - for (int i = 0; i < res1.length; i++) { - if (res1[i][0] != res2[i][0] || res1[i][1] != res2[i][1]) { - return false; - } - } - - return true; - } - - // for test - public static void printArray(int[] arr) { - for (int i = 0; i < arr.length; i++) { - System.out.print(arr[i] + " "); - } - System.out.println(); - } - - public static void main(String[] args) { - int size = 10; - int max = 20; - int testTimes = 2000000; - System.out.println("测试开始"); - for (int i = 0; i < testTimes; i++) { - int[] arr1 = getRandomArrayNoRepeat(size); - int[] arr2 = getRandomArray(size, max); - if (!isEqual(getNearLessNoRepeat(arr1), rightWay(arr1))) { - System.out.println("Oops!"); - printArray(arr1); - break; - } - if (!isEqual(getNearLess(arr2), rightWay(arr2))) { - System.out.println("Oops!"); - printArray(arr2); - break; - } - } - System.out.println("测试结束"); - } -} diff --git a/公开课/class077/Code02_AllTimesMinToMax.java b/公开课/class077/Code02_AllTimesMinToMax.java deleted file mode 100644 index d927278..0000000 --- a/公开课/class077/Code02_AllTimesMinToMax.java +++ /dev/null @@ -1,101 +0,0 @@ -package class077; - -import java.util.Stack; - -// 给定一个只包含正数的数组arr,arr中任何一个子数组sub, -// 一定都可以算出(sub累加和 )* (sub中的最小值)是什么, -// 那么所有子数组中,这个值最大是多少? -public class Code02_AllTimesMinToMax { - - public static int max1(int[] arr) { - int max = Integer.MIN_VALUE; - for (int i = 0; i < arr.length; i++) { - for (int j = i; j < arr.length; j++) { - int minNum = Integer.MAX_VALUE; - int sum = 0; - for (int k = i; k <= j; k++) { - sum += arr[k]; - minNum = Math.min(minNum, arr[k]); - } - max = Math.max(max, minNum * sum); - } - } - return max; - } - - public static int max2(int[] arr) { - int size = arr.length; - int[] sums = new int[size]; - sums[0] = arr[0]; - for (int i = 1; i < size; i++) { - sums[i] = sums[i - 1] + arr[i]; - } - int max = Integer.MIN_VALUE; - Stack stack = new Stack(); - for (int i = 0; i < size; i++) { - while (!stack.isEmpty() && arr[stack.peek()] >= arr[i]) { - int j = stack.pop(); - max = Math.max(max, (stack.isEmpty() ? sums[i - 1] : (sums[i - 1] - sums[stack.peek()])) * arr[j]); - } - stack.push(i); - } - while (!stack.isEmpty()) { - int j = stack.pop(); - max = Math.max(max, (stack.isEmpty() ? sums[size - 1] : (sums[size - 1] - sums[stack.peek()])) * arr[j]); - } - return max; - } - - public static int[] gerenareRondomArray() { - int[] arr = new int[(int) (Math.random() * 20) + 10]; - for (int i = 0; i < arr.length; i++) { - arr[i] = (int) (Math.random() * 101); - } - return arr; - } - - public static void main(String[] args) { - int testTimes = 2000000; - System.out.println("test begin"); - for (int i = 0; i < testTimes; i++) { - int[] arr = gerenareRondomArray(); - if (max1(arr) != max2(arr)) { - System.out.println("FUCK!"); - break; - } - } - System.out.println("test finish"); - } - - // 本题可以在leetcode上找到原题 - // 测试链接 : https://leetcode.com/problems/maximum-subarray-min-product/ - // 注意测试题目数量大,要取模,但是思路和课上讲的是完全一样的 - // 注意溢出的处理即可,也就是用long类型来表示累加和 - // 还有优化就是,你可以用自己手写的数组栈,来替代系统实现的栈,也会快很多 - public static int maxSumMinProduct(int[] arr) { - int size = arr.length; - long[] sums = new long[size]; - sums[0] = arr[0]; - for (int i = 1; i < size; i++) { - sums[i] = sums[i - 1] + arr[i]; - } - long max = Long.MIN_VALUE; - int[] stack = new int[size]; - int stackSize = 0; - for (int i = 0; i < size; i++) { - while (stackSize != 0 && arr[stack[stackSize - 1]] >= arr[i]) { - int j = stack[--stackSize]; - max = Math.max(max, - (stackSize == 0 ? sums[i - 1] : (sums[i - 1] - sums[stack[stackSize - 1]])) * arr[j]); - } - stack[stackSize++] = i; - } - while (stackSize != 0) { - int j = stack[--stackSize]; - max = Math.max(max, - (stackSize == 0 ? sums[size - 1] : (sums[size - 1] - sums[stack[stackSize - 1]])) * arr[j]); - } - return (int) (max % 1000000007); - } - -} diff --git a/公开课/class077/Code03_LargestRectangleInHistogram.java b/公开课/class077/Code03_LargestRectangleInHistogram.java deleted file mode 100644 index 45b11cd..0000000 --- a/公开课/class077/Code03_LargestRectangleInHistogram.java +++ /dev/null @@ -1,58 +0,0 @@ -package class077; - -import java.util.Stack; - -// 测试链接:https://leetcode.com/problems/largest-rectangle-in-histogram -public class Code03_LargestRectangleInHistogram { - - public static int largestRectangleArea1(int[] height) { - if (height == null || height.length == 0) { - return 0; - } - int maxArea = 0; - Stack stack = new Stack(); - for (int i = 0; i < height.length; i++) { - while (!stack.isEmpty() && height[i] <= height[stack.peek()]) { - int j = stack.pop(); - int k = stack.isEmpty() ? -1 : stack.peek(); - int curArea = (i - k - 1) * height[j]; - maxArea = Math.max(maxArea, curArea); - } - stack.push(i); - } - while (!stack.isEmpty()) { - int j = stack.pop(); - int k = stack.isEmpty() ? -1 : stack.peek(); - int curArea = (height.length - k - 1) * height[j]; - maxArea = Math.max(maxArea, curArea); - } - return maxArea; - } - - public static int largestRectangleArea2(int[] height) { - if (height == null || height.length == 0) { - return 0; - } - int N = height.length; - int[] stack = new int[N]; - int si = -1; - int maxArea = 0; - for (int i = 0; i < height.length; i++) { - while (si != -1 && height[i] <= height[stack[si]]) { - int j = stack[si--]; - int k = si == -1 ? -1 : stack[si]; - int curArea = (i - k - 1) * height[j]; - maxArea = Math.max(maxArea, curArea); - } - stack[++si] = i; - } - while (si != -1) { - int j = stack[si--]; - int k = si == -1 ? -1 : stack[si]; - int curArea = (height.length - k - 1) * height[j]; - maxArea = Math.max(maxArea, curArea); - } - return maxArea; - } - -} diff --git a/公开课/class077/Code04_ValidSequence.java b/公开课/class077/Code04_ValidSequence.java deleted file mode 100644 index b21c73a..0000000 --- a/公开课/class077/Code04_ValidSequence.java +++ /dev/null @@ -1,113 +0,0 @@ -package class077; - -// 来自腾讯 -// 给定一个长度为n的数组arr,求有多少个子数组满足 : -// 子数组两端的值,是这个子数组的最小值和次小值,最小值和次小值谁在最左和最右无所谓 -// n<=100000(10^5) n*logn O(N) -public class Code04_ValidSequence { - - - public static int nums(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int n = arr.length; - int[] values = new int[n]; - int[] times = new int[n]; - int size = 0; - int ans = 0; - for (int i = 0; i < arr.length; i++) { - while (size != 0 && values[size - 1] > arr[i]) { - size--; - ans += times[size] + cn2(times[size]); - } - if (size != 0 && values[size - 1] == arr[i]) { - times[size - 1]++; - } else { - values[size] = arr[i]; - times[size++] = 1; - } - } - while (size != 0) { - ans += cn2(times[--size]); - } - for (int i = arr.length - 1; i >= 0; i--) { - while (size != 0 && values[size - 1] > arr[i]) { - ans += times[--size]; - } - if (size != 0 && values[size - 1] == arr[i]) { - times[size - 1]++; - } else { - values[size] = arr[i]; - times[size++] = 1; - } - } - return ans; - } - - public static int cn2(int n) { - return (n * (n - 1)) >> 1; - } - - // 为了测试 - // 暴力方法 - public static int test(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int ans = 0; - for (int s = 0; s < arr.length; s++) { - for (int e = s + 1; e < arr.length; e++) { - int max = Math.max(arr[s], arr[e]); - boolean valid = true; - for (int i = s + 1; i < e; i++) { - if (arr[i] < max) { - valid = false; - break; - } - } - ans += valid ? 1 : 0; - } - } - return ans; - } - - // 为了测试 - public static int[] randomArray(int n, int v) { - int[] arr = new int[n]; - for (int i = 0; i < n; i++) { - arr[i] = (int) (Math.random() * v); - } - return arr; - } - - // 为了测试 - public static void printArray(int[] arr) { - for (int num : arr) { - System.out.print(num + " "); - } - System.out.println(); - } - - // 为了测试 - public static void main(String[] args) { - int n = 30; - int v = 30; - int testTime = 100000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int m = (int) (Math.random() * n); - int[] arr = randomArray(m, v); - int ans1 = nums(arr); - int ans2 = test(arr); - if (ans1 != ans2) { - System.out.println("出错了!"); - printArray(arr); - System.out.println(ans1); - System.out.println(ans2); - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class078/Code01_SplitSameNumberWays.java b/公开课/class078/Code01_SplitSameNumberWays.java deleted file mode 100644 index bde57ca..0000000 --- a/公开课/class078/Code01_SplitSameNumberWays.java +++ /dev/null @@ -1,36 +0,0 @@ -package class078; - -// 来自微软 -// 比如,str = "ayxbx" -// 有以下4种切法 : a | yxbx、ay | xbx、ayx | bx、ayxb | x -// 其中第1、3、4种切法符合:x和y的个数,至少在左右两块中的一块里有相同的数量 -// 所以返回3 -// 给定一个字符串str,长度为N -// 你有N-1种划分方法,把str切成左右两半,返回有几种切法满足: -// x和y的个数,至少在左右两块中的一块里有相同的数量 -public class Code01_SplitSameNumberWays { - - public static int splitSameNumberWays(char[] str) { - if (str == null || str.length == 0) { - return 0; - } - int xAll = 0; - int yAll = 0; - for (char c : str) { - xAll += c == 'x' ? 1 : 0; - yAll += c == 'y' ? 1 : 0; - } - int leftX = str[0] == 'x' ? 1 : 0; - int leftY = str[0] == 'y' ? 1 : 0; - int ans = 0; - for (int i = 1; i < str.length; i++) { - if (leftX == leftY || (xAll - leftX) == (yAll - leftY)) { - ans++; - } - leftX += str[i] == 'x' ? 1 : 0; - leftY += str[i] == 'y' ? 1 : 0; - } - return ans; - } - -} diff --git a/公开课/class078/Code02_NearBiggerNoSameNeighbour.java b/公开课/class078/Code02_NearBiggerNoSameNeighbour.java deleted file mode 100644 index af3ac1e..0000000 --- a/公开课/class078/Code02_NearBiggerNoSameNeighbour.java +++ /dev/null @@ -1,67 +0,0 @@ -package class078; - -// 来自微软 -// 给定一个正数num,要返回一个大于num的数,并且每一位和相邻位的数字不能相等 -// 返回达标的数字中,最小的那个 -// 10^9 -public class Code02_NearBiggerNoSameNeighbour { - - public static int near(int num) { - // "99998" - // [0, 9, 9, 9, 9, 9] - char[] raw = ("0" + String.valueOf(num + 1)).toCharArray(); - process(raw); - return Integer.valueOf(String.valueOf(raw)); - } - - public static void process(char[] raw) { - // 0 1 -> - // 1 2 -> - for (int i = 1; i < raw.length; i++) { - if (raw[i - 1] == raw[i]) { - addOne(raw, i); - for (int j = i + 1; j < raw.length; j++) { - raw[j] = '0'; - } - process(raw); - return; - } - } - } - - // 99..... - // +1 - //100 - public static void addOne(char[] r, int i) { - boolean up = true; - while (up && r[i] == '9') { - r[i--] = '0'; - } - r[i]++; - } - - public static void main(String[] args) { - char[] test = new char[] { '0', '1', '2', '3' }; - - System.out.println(Integer.valueOf(String.valueOf(test))); - - int num1 = 55; - System.out.println(near(num1)); - - int num2 = 1765; - System.out.println(near(num2)); - - int num3 = 98; - System.out.println(near(num3)); - - int num4 = 44432; - System.out.println(near(num4)); - - int num5 = 3298; - System.out.println(near(num5)); - - int num6 = 9999998; - System.out.println(near(num6)); - } - -} diff --git a/公开课/class078/Code03_MaxTeamNumber.java b/公开课/class078/Code03_MaxTeamNumber.java deleted file mode 100644 index 970be2f..0000000 --- a/公开课/class078/Code03_MaxTeamNumber.java +++ /dev/null @@ -1,129 +0,0 @@ -package class078; - -import java.util.Arrays; - -// 来自微软 -// 给定一个数组arr,一个正数num,一个正数k -// 可以把arr中的某些数字拿出来组成一组,要求该组中的最大值减去最小值<=num -// 且该组数字的个数一定要正好等于k -// 每个数字只能选择进某一组,不能进多个组 -// 返回arr中最多有多少组 -public class Code03_MaxTeamNumber { - - public static int maxSum1(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int n = arr.length; - int[] dp = new int[n]; - dp[0] = arr[0]; - int ans = dp[0]; - for (int i = 1; i < n; i++) { - int p1 = arr[i]; - int p2 = arr[i] + dp[i-1]; - dp[i] = Math.max(p1, p2); - ans = Math.max(ans, dp[i]); - } - return ans; - } - - - - public static int maxSum2(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int n = arr.length; - int lastStepAns = arr[0]; - int ans = lastStepAns; - for (int i = 1; i < n; i++) { - lastStepAns = Math.max(arr[i], arr[i] + lastStepAns); - ans = Math.max(ans, lastStepAns); - } - return ans; - } - - - - // 对数器方法 - public static int maxTeams1(int[] arr, int num, int k) { - Arrays.sort(arr); - return process1(arr, 0, new int[arr.length], 0, num, k); - } - - public static int process1(int[] arr, int index, int[] path, int size, int num, int k) { - if (index == arr.length) { - if (size % k != 0) { - return 0; - } else { - for (int start = 0; start < size; start += k) { - if (path[start + k - 1] - path[start] > num) { - return 0; - } - } - return size / k; - } - } else { - int p1 = process1(arr, index + 1, path, size, num, k); - path[size] = arr[index]; - int p2 = process1(arr, index + 1, path, size + 1, num, k); - return Math.max(p1, p2); - } - } - - // 正式方法 - // 时间复杂度O(N * logN) - public static int maxTeams2(int[] arr, int num, int k) { - int n = arr.length; - if (k > n) { - return 0; - } - Arrays.sort(arr); - int[] dp = new int[n]; - dp[k - 1] = arr[k - 1] - arr[0] <= num ? 1 : 0; - for (int i = k; i < n; i++) { - int p1 = dp[i - 1]; - int p2 = (arr[i] - arr[i - k + 1] <= num ? 1 : 0) + dp[i - k]; - dp[i] = Math.max(p1, p2); - } - return dp[n - 1]; - } - - // 为了测试 - public static int[] randomArray(int len, int value) { - int[] ans = new int[len]; - for (int i = 0; i < len; i++) { - ans[i] = (int) (Math.random() * value); - } - return ans; - } - - // 为了测试 - public static void main(String[] args) { - int n = 18; - int v = 50; - int testTimes = 20000; - System.out.println("测试开始"); - for (int i = 0; i < testTimes; i++) { - int len = (int) (Math.random() * n) + 1; - int[] arr = randomArray(len, v); - int num = (int) (Math.random() * v) + 1; - int k = (int) (Math.random() * len) + 1; - int ans1 = maxTeams1(arr, num, k); - int ans2 = maxTeams2(arr, num, k); - if (ans1 != ans2) { - for (int number : arr) { - System.out.print(number + " "); - } - System.out.println(); - System.out.println("num : " + num); - System.out.println("k : " + k); - System.out.println(ans1); - System.out.println(ans2); - break; - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class078/Code04_MinimumNumberOfDaysToEatNOranges.java b/公开课/class078/Code04_MinimumNumberOfDaysToEatNOranges.java deleted file mode 100644 index 5c6733a..0000000 --- a/公开课/class078/Code04_MinimumNumberOfDaysToEatNOranges.java +++ /dev/null @@ -1,59 +0,0 @@ -package class078; - -import java.util.HashMap; - -// 来自学员看到的腾讯面试 -// 测试链接 : https://leetcode.com/problems/minimum-number-of-days-to-eat-n-oranges/ -public class Code04_MinimumNumberOfDaysToEatNOranges { - - public static int zuo(int n) { - // 17 -> 5 - HashMap cache = new HashMap<>(); - return minDay(n, cache); - } - - public static int minDay(int n, HashMap cache) { - if (cache.containsKey(n)) { - return cache.get(n); - } - int ans = 0; - if (n == 0) { - ans = 0; - } else if (n == 1) { - ans = 1; - } else { - int p1 = n % 2 + 1 + minDay(n / 2, cache); - int p2 = n % 3 + 1 + minDay(n / 3, cache); - ans = Math.min(p1, p2); - } - cache.put(n, ans); - return ans; - } - - // 所有的答案都填在这个表里 - // 这个表对所有的过程共用 - public static HashMap dp = new HashMap<>(); - - public static int minDays(int n) { - if (n <= 1) { - return n; - } - if (dp.containsKey(n)) { - return dp.get(n); - } - // 1) 吃掉一个橘子 - // 2) 如果n能被2整除,吃掉一半的橘子,剩下一半 - // 3) 如果n能被3正数,吃掉三分之二的橘子,剩下三分之一 - // 因为方法2)和3),是按比例吃橘子,所以必然会非常快 - // 所以,决策如下: - // 可能性1:为了使用2)方法,先把橘子吃成2的整数倍,然后直接干掉一半,剩下的n/2调用递归 - // 即,n % 2 + 1 + minDays(n/2) - // 可能性2:为了使用3)方法,先把橘子吃成3的整数倍,然后直接干掉三分之二,剩下的n/3调用递归 - // 即,n % 3 + 1 + minDays(n/3) - // 至于方法1),完全是为了这两种可能性服务的,因为能按比例吃,肯定比一个一个吃快(显而易见的贪心) - int ans = Math.min(n % 2 + 1 + minDays(n / 2), n % 3 + 1 + minDays(n / 3)); - dp.put(n, ans); - return ans; - } - -} diff --git a/公开课/class078/Code05_MaxKLenSequence.java b/公开课/class078/Code05_MaxKLenSequence.java deleted file mode 100644 index 56e1fad..0000000 --- a/公开课/class078/Code05_MaxKLenSequence.java +++ /dev/null @@ -1,92 +0,0 @@ -package class078; - -import java.util.TreeSet; - -// 来自腾讯 -// 给定一个字符串str,和一个正数k -// 返回长度为k的所有子序列中,字典序最大的子序列 -public class Code05_MaxKLenSequence { - - public static String maxString(String s, int k) { - if (k <= 0 || s.length() < k) { - return ""; - } - char[] str = s.toCharArray(); - int n = str.length; - // 栈,栈大小 size 栈顶stack[size-1] - char[] stack = new char[n]; - int size = 0; - for (int i = 0; i < n; i++) { - // 当前字符 str[i] - while (size > 0 && stack[size - 1] < str[i] && size + n - i > k) { - size--; - } - if (size + n - i == k) { - return String.valueOf(stack, 0, size) + s.substring(i); - } - stack[size++] = str[i]; - } - return String.valueOf(stack, 0, k); - } - - // 为了测试 - // 纯暴力,我把str,所有的、长度为k的,子序列全生成了!找出一个最大的! - public static String test(String str, int k) { - if (k <= 0 || str.length() < k) { - return ""; - } - TreeSet ans = new TreeSet<>(); - process(0, 0, str.toCharArray(), new char[k], ans); - return ans.last(); - } - - // 为了测试 - public static void process(int si, int pi, char[] str, char[] path, TreeSet ans) { - if (si == str.length) { - if (pi == path.length) { - ans.add(String.valueOf(path)); - } - } else { - process(si + 1, pi, str, path, ans); - if (pi < path.length) { - path[pi] = str[si]; - process(si + 1, pi + 1, str, path, ans); - } - } - } - - // 为了测试 - public static String randomString(int len, int range) { - char[] str = new char[len]; - for (int i = 0; i < len; i++) { - str[i] = (char) ((int) (Math.random() * range) + 'a'); - } - return String.valueOf(str); - } - - public static void main(String[] args) { - System.out.println(maxString("ccfaa", 3)); - - int n = 12; - int r = 5; - int testTime = 10000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int len = (int) (Math.random() * (n + 1)); - String str = randomString(len, r); - int k = (int) (Math.random() * (str.length() + 1)); - String ans1 = maxString(str, k); - String ans2 = test(str, k); - if (!ans1.equals(ans2)) { - System.out.println("出错了!"); - System.out.println(str); - System.out.println(k); - System.out.println(ans1); - System.out.println(ans2); - break; - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class078/Code06_StringCheck.java b/公开课/class078/Code06_StringCheck.java deleted file mode 100644 index aad2291..0000000 --- a/公开课/class078/Code06_StringCheck.java +++ /dev/null @@ -1,65 +0,0 @@ -package class078; - -import java.util.Arrays; - -// 来自字节飞书团队 -// 小歪每次会给你两个字符串: -// 笔记s1和关键词s2,请你写一个函数 -// 判断s2的排列之一是否是s1的子串 -// 如果是,返回true -// 否则,返回false -public class Code06_StringCheck { - - public static boolean check1(String s1, String s2) { - if (s1.length() < s2.length()) { - return false; - } - char[] str2 = s2.toCharArray(); - Arrays.sort(str2); - s2 = String.valueOf(str2); - for (int L = 0; L < s1.length(); L++) { - for (int R = L; R < s1.length(); R++) { - char[] cur = s1.substring(L, R + 1).toCharArray(); - Arrays.sort(cur); - String curSort = String.valueOf(cur); - if (curSort.equals(s2)) { - return true; - } - } - } - return false; - } - - public static boolean check2(String s1, String s2) { - if (s1.length() < s2.length()) { - return false; - } - char[] str2 = s2.toCharArray(); - int[] count = new int[256]; - for (int i = 0; i < str2.length; i++) { - count[str2[i]]++; - } - int M = str2.length; - char[] st1 = s1.toCharArray(); - int inValidTimes = 0; - int R = 0; - for (; R < M; R++) { - if (count[st1[R]]-- <= 0) { - inValidTimes++; - } - } - for (; R < st1.length; R++) { - if (inValidTimes == 0) { - return true; - } - if (count[st1[R]]-- <= 0) { - inValidTimes++; - } - if (count[st1[R - M]]++ < 0) { - inValidTimes--; - } - } - return inValidTimes == 0; - } - -} diff --git a/公开课/class078/Code07_ShortestSubarrayWithSumAtLeastK.java b/公开课/class078/Code07_ShortestSubarrayWithSumAtLeastK.java deleted file mode 100644 index 5a1c651..0000000 --- a/公开课/class078/Code07_ShortestSubarrayWithSumAtLeastK.java +++ /dev/null @@ -1,74 +0,0 @@ -package class078; - -// 来自字节跳动 -// 给定一个数组arr,其中的值有可能正、负、0 -// 给定一个正数k -// 返回累加和>=k的所有子数组中,最短的子数组长度 -// 本题测试链接 : https://leetcode.com/problems/shortest-subarray-with-sum-at-least-k/ -public class Code07_ShortestSubarrayWithSumAtLeastK { - - public static int shortestSubarray1(int[] arr, int k) { - if (arr == null || arr.length < 1) { - return -1; - } - int n = arr.length + 1; - long[] sum = new long[n]; - for (int i = 1; i < n; i++) { - sum[i] = sum[i - 1] + arr[i - 1]; - } - int[] stack = new int[n]; - int size = 1; - int ans = Integer.MAX_VALUE; - for (int i = 1; i < n; i++) { - int mostRight = mostRight(sum, stack, size, sum[i] - k); - ans = Math.min(ans, mostRight == -1 ? Integer.MAX_VALUE : (i - mostRight)); - while (size > 0 && sum[stack[size - 1]] >= sum[i]) { - size--; - } - stack[size++] = i; - } - return ans == Integer.MAX_VALUE ? -1 : ans; - } - - public static int mostRight(long[] sum, int[] stack, int size, long aim) { - int l = 0; - int r = size - 1; - int m = 0; - int ans = -1; - while (l <= r) { - m = (l + r) / 2; - if (sum[stack[m]] <= aim) { - ans = stack[m]; - l = m + 1; - } else { - r = m - 1; - } - } - return ans; - } - - public static int shortestSubarray2(int[] arr, int K) { - int N = arr.length; - long[] sum = new long[N + 1]; - for (int i = 0; i < N; i++) { - sum[i + 1] = sum[i] + arr[i]; - } - int ans = Integer.MAX_VALUE; - int[] dq = new int[N + 1]; - int l = 0; - int r = 0; - for (int i = 0; i < N + 1; i++) { - // 头部开始,符合条件的,从头部弹出! - while (l != r && sum[i] - sum[dq[l]] >= K) { - ans = Math.min(ans, i - dq[l++]); - } - // 尾部开始,前缀和比当前的前缀和大于等于的,从尾部弹出! - while (l != r && sum[dq[r - 1]] >= sum[i]) { - r--; - } - dq[r++] = i; - } - return ans != Integer.MAX_VALUE ? ans : -1; - } - -} diff --git a/公开课/class079/Code01_StringCheck.java b/公开课/class079/Code01_StringCheck.java deleted file mode 100644 index 5833669..0000000 --- a/公开课/class079/Code01_StringCheck.java +++ /dev/null @@ -1,65 +0,0 @@ -package class079; - -import java.util.Arrays; - -// 来自字节飞书团队 -// 小歪每次会给你两个字符串: -// 笔记s1和关键词s2,请你写一个函数 -// 判断s2的排列之一是否是s1的子串 -// 如果是,返回true -// 否则,返回false -public class Code01_StringCheck { - - public static boolean check1(String s1, String s2) { - if (s1.length() < s2.length()) { - return false; - } - char[] str2 = s2.toCharArray(); - Arrays.sort(str2); - s2 = String.valueOf(str2); - for (int L = 0; L < s1.length(); L++) { - for (int R = L; R < s1.length(); R++) { - char[] cur = s1.substring(L, R + 1).toCharArray(); - Arrays.sort(cur); - String curSort = String.valueOf(cur); - if (curSort.equals(s2)) { - return true; - } - } - } - return false; - } - - public static boolean check2(String s1, String s2) { - if (s1.length() < s2.length()) { - return false; - } - char[] str2 = s2.toCharArray(); - int[] count = new int[256]; - for (int i = 0; i < str2.length; i++) { - count[str2[i]]++; - } - int M = str2.length; - char[] st1 = s1.toCharArray(); - int inValidTimes = 0; - int R = 0; - for (; R < M; R++) { - if (count[st1[R]]-- <= 0) { - inValidTimes++; - } - } - for (; R < st1.length; R++) { - if (inValidTimes == 0) { - return true; - } - if (count[st1[R]]-- <= 0) { - inValidTimes++; - } - if (count[st1[R - M]]++ < 0) { - inValidTimes--; - } - } - return inValidTimes == 0; - } - -} diff --git a/公开课/class079/Code02_NumberOfDivisibleByM.java b/公开课/class079/Code02_NumberOfDivisibleByM.java deleted file mode 100644 index f454bc3..0000000 --- a/公开课/class079/Code02_NumberOfDivisibleByM.java +++ /dev/null @@ -1,69 +0,0 @@ -package class079; - -// 来自微软 -// 给定一个数组arr,给定一个正数M -// 如果arr[i] + arr[j]可以被M整除,并且i < j,那么(i,j)叫做一个M整除对 -// 返回arr中M整除对的总数量 -public class Code02_NumberOfDivisibleByM { - - public static int num1(int[] arr, int m) { - int n = arr.length; - int ans = 0; - for (int i = 0; i < n; i++) { - for (int j = i + 1; j < n; j++) { - if (Math.abs(arr[i] + arr[j]) % m == 0) { - ans++; - } - } - } - return ans; - } - - public static int num2(int[] arr, int m) { - int n = arr.length; - int[] cnts = new int[m]; - int ans = 0; - for (int i = n - 1; i >= 0; i--) { - int cur = (arr[i] % m + m) % m; - ans += cnts[(m - cur) % m]; - cnts[cur]++; - } - return ans; - } - - // 为了测试 - public static int[] randomArray(int n, int v) { - int[] arr = new int[n]; - for (int i = 0; i < n; i++) { - arr[i] = (int) (Math.random() * v) - (int) (Math.random() * v); - } - return arr; - } - - public static void main(String[] args) { - int len = 50; - int value = 50; - int testTime = 20000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int n = (int) (Math.random() * len) + 1; - int[] arr = randomArray(n, value); - int m = (int) (Math.random() * value) + 1; - int ans1 = num1(arr, m); - int ans2 = num2(arr, m); - if (ans1 != ans2) { - System.out.println("出错了!"); - for (int num : arr) { - System.out.print(num + " "); - } - System.out.println(); - System.out.println("m = " + m); - System.out.println(ans1); - System.out.println(ans2); - break; - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class079/Code03_MinWaitingTime.java b/公开课/class079/Code03_MinWaitingTime.java deleted file mode 100644 index 85d9923..0000000 --- a/公开课/class079/Code03_MinWaitingTime.java +++ /dev/null @@ -1,95 +0,0 @@ -package class079; - -import java.util.PriorityQueue; - -// 来自谷歌 -// 给定一个数组arr,长度为n -// 表示n个服务员,每个人服务一个人的时间 -// 给定一个正数m,表示有m个人等位 -// 如果你是刚来的人,请问你需要等多久? -// 假设:m远远大于n,比如n<=1000, m <= 10的9次方,该怎么做? -public class Code03_MinWaitingTime { - - public static int minWaitingTime1(int[] arr, int m) { - if (arr == null || arr.length == 0) { - return -1; - } - PriorityQueue heap = new PriorityQueue<>((a, b) -> (a[0] - b[0])); - int n = arr.length; - for (int i = 0; i < n; i++) { - heap.add(new int[] { 0, arr[i] }); - } - for (int i = 0; i < m; i++) { - int[] cur = heap.poll(); - cur[0] += cur[1]; - heap.add(cur); - } - return heap.peek()[0]; - } - - public static int minWaitingTime2(int[] arr, int m) { - if (arr == null || arr.length == 0) { - return -1; - } - int best = Integer.MAX_VALUE; - for (int num : arr) { - best = Math.min(best, num); - } - int left = 0; - int right = best * m; - int mid = 0; - int near = 0; - while (left <= right) { - mid = (left + right) / 2; - int cover = 0; - for (int num : arr) { - cover += (mid / num) + 1; - } - if (cover >= m + 1) { - near = mid; - right = mid - 1; - } else { - left = mid + 1; - } - } - return near; - } - - // 为了测试 - public static int[] randomArray(int n, int v) { - int[] arr = new int[n]; - for (int i = 0; i < n; i++) { - arr[i] = (int) (Math.random() * v) + 1; - } - return arr; - } - - // 为了测试 - public static void main(String[] args) { - int len = 50; - int value = 30; - int mMax = 3000; - int testTime = 20000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int n = (int) (Math.random() * len) + 1; - int[] arr = randomArray(n, value); - int m = (int) (Math.random() * mMax); - int ans1 = minWaitingTime1(arr, m); - int ans2 = minWaitingTime2(arr, m); - if (ans1 != ans2) { - System.out.println("出错了!"); - for (int num : arr) { - System.out.print(num + " "); - } - System.out.println(); - System.out.println("m : " + m); - System.out.println(ans1); - System.out.println(ans2); - break; - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class079/Code04_LongestUncontinuousSet.java b/公开课/class079/Code04_LongestUncontinuousSet.java deleted file mode 100644 index 9bca43f..0000000 --- a/公开课/class079/Code04_LongestUncontinuousSet.java +++ /dev/null @@ -1,39 +0,0 @@ -package class079; - -import java.util.Arrays; - -// 来自美团 -// 给定一个数组arr,你可以随意挑选其中的数字 -// 但是你挑选的数中,任何两个数a和b,不能让Math.abs(a - b) <= 1 -// 返回你最多能挑选几个数 -public class Code04_LongestUncontinuousSet { - - public static int longestUncontinuous(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - Arrays.sort(arr); - int n = arr.length; - int size = 1; - for (int i = 1; i < n; i++) { - if (arr[i] != arr[size - 1]) { - arr[size++] = arr[i]; - } - } - int[] dp = new int[size]; - dp[0] = 1; - int ans = 1; - for (int i = 1; i < size; i++) { - dp[i] = 1; - if (arr[i] - arr[i - 1] > 1) { - dp[i] = 1 + dp[i - 1]; - } - if (i - 2 >= 0 && arr[i] - arr[i - 2] > 1) { - dp[i] = Math.max(dp[i], 1 + dp[i - 2]); - } - ans = Math.max(ans, dp[i]); - } - return ans; - } - -} diff --git a/公开课/class079/Code05_CutDouFu.java b/公开课/class079/Code05_CutDouFu.java deleted file mode 100644 index eaa1c52..0000000 --- a/公开课/class079/Code05_CutDouFu.java +++ /dev/null @@ -1,52 +0,0 @@ -package class079; - -import java.util.Arrays; - -// 来自美团 -// 有一块10000 * 10000 * 10000的立方体豆腐 -// 豆腐的前左下角放在(0,0,0)点,豆腐的后右上角放在(10000,10000,10000)点 -// 下面给出切法的数据结构 -// [a,b] -// a = 1,表示x = b处,一把无穷大的刀平行于yz面贯穿豆腐切过去 -// a = 2,表示y = b处,一把无穷大的刀平行于xz面贯穿豆腐切过去 -// a = 3,表示z = b处,一把无穷大的刀平行于xy面贯穿豆腐切过去 -// a = 1 or 2 or 3,0<=b<=10000 -// 给定一个n*2的二维数组,表示切了n刀 -// 返回豆腐中最大的一块体积是多少 -public class Code05_CutDouFu { - - public static long maxCut(int[][] cuts) { - if (cuts == null || cuts.length == 0) { - return 10000L * 10000L * 10000L; - } - Arrays.sort(cuts, (a, b) -> a[0] != b[0] ? (a[0] - b[0]) : (a[1] - b[1])); - int n = cuts.length; - int i = 0; - int xMaxDiff = 0; - int pre = 0; - while (i < n && cuts[i][0] == 1) { - xMaxDiff = Math.max(xMaxDiff, cuts[i][1] - pre); - pre = cuts[i][1]; - i++; - } - xMaxDiff = Math.max(xMaxDiff, 10000 - pre); - int yMaxDiff = 0; - pre = 0; - while (i < n && cuts[i][0] == 2) { - yMaxDiff = Math.max(yMaxDiff, cuts[i][1] - pre); - pre = cuts[i][1]; - i++; - } - yMaxDiff = Math.max(yMaxDiff, 10000 - pre); - int zMaxDiff = 0; - pre = 0; - while (i < n && cuts[i][0] == 3) { - zMaxDiff = Math.max(zMaxDiff, cuts[i][1] - pre); - pre = cuts[i][1]; - i++; - } - zMaxDiff = Math.max(zMaxDiff, 10000 - pre); - return (long) xMaxDiff * (long) yMaxDiff * (long) zMaxDiff; - } - -} diff --git a/公开课/class080/Code01_FinancialProduct.java b/公开课/class080/Code01_FinancialProduct.java deleted file mode 100644 index eab80db..0000000 --- a/公开课/class080/Code01_FinancialProduct.java +++ /dev/null @@ -1,51 +0,0 @@ -package class080; - -import java.util.Arrays; - -// 来自银联编程比赛,前500名获得内推资格 -// 某公司计划推出一批投资项目。 product[i] = price 表示第 i 个理财项目的投资金额 price 。 -// 客户在按需投资时,需要遵循以下规则: -// 客户在首次对项目 product[i] 投资时,需要投入金额 price -// 对已完成首次投资的项目 product[i] 可继续追加投入, -// 但追加投入的金额需小于上一次对该项目的投入(追加投入为大于 0 的整数) -// 为控制市场稳定,每人交易次数不得大于 limit。(首次投资和追加投入均记作 1 次交易) -// 若对所有理财项目中最多进行 limit 次交易,使得投入金额总和最大,请返回这个最大值的总和。 -// 测试链接 : https://leetcode-cn.com/contest/cnunionpay-2022spring/problems/I4mOGz/ -public class Code01_FinancialProduct { - - public static long mod = 1000000007L; - - public int maxInvestment(int[] arr, int limit) { - Arrays.sort(arr); - int n = arr.length; - long ans = 0; - int r = n - 1; - int l = r; - while (limit > 0 && r != -1) { - while (l >= 0 && arr[l] == arr[r]) { - l--; - } - int big = arr[r]; - int small = l == -1 ? 0 : arr[l]; - int teams = n - l - 1; - int all = (big - small) * teams; - if (limit >= all) { - ans += get(big, small + 1, teams); - ans %= mod; - limit -= all; - } else { - int a = limit / teams; - ans += get(big, big - a + 1, teams) + (long) (big - a) * (long) (limit - a * teams); - ans %= mod; - limit = 0; - } - r = l; - } - return (int) (ans % mod); - } - - public static long get(long up, long down, long num) { - return num * ((up + down) * (up - down + 1) / 2); - } - -} diff --git a/公开课/class080/Code02_EatFish.java b/公开课/class080/Code02_EatFish.java deleted file mode 100644 index f49d5c3..0000000 --- a/公开课/class080/Code02_EatFish.java +++ /dev/null @@ -1,106 +0,0 @@ -package class080; - -// 来自bilibili -// 现在有N条鱼,每条鱼的体积为Ai,从左到右排列,数组arr给出 -// 每一轮,左边的大鱼一定会吃掉右边比自己小的第一条鱼, -// 并且每条鱼吃比自己小的鱼的事件是同时发生的。 -// 返回多少轮之后,鱼的数量会稳定 -// 注意:6 6 3 3 -// 第一轮过后 : -// 对于两个6来说,右边比自己小的第一条鱼都是第1个3,所以只有这个3被吃掉, -// 数组变成 : 6 6 3(第2个3) -// 第二轮过后 : 6 6 -// 返回2 -public class Code02_EatFish { - - public static int minTurns1(int[] arr) { - int ans = 0; - for (;; ans++) { - int[] rest = eatRest(arr); - if (arr.length == rest.length) { - break; - } - arr = rest; - } - return ans; - } - - public static int[] eatRest(int[] arr) { - if (arr.length == 0) { - return new int[0]; - } - int n = arr.length; - boolean[] delete = new boolean[n]; - int len = n; - for (int i = 0; i < n; i++) { - for (int j = i + 1; j < n; j++) { - if (arr[i] > arr[j]) { - if (!delete[j]) { - delete[j] = true; - len--; - } - break; - } - } - } - int[] rest = new int[len]; - for (int i = 0, j = 0; i < n; i++) { - if (!delete[i]) { - rest[j++] = arr[i]; - } - } - return rest; - } - - public static int minTurns2(int[] arr) { - int n = arr.length; - int[][] stack = new int[n][2]; - int stackSize = 0; - int ans = 0; - for (int i = n - 1; i >= 0; i--) { - int curAns = 0; - while (stackSize > 0 && stack[stackSize - 1][0] < arr[i]) { - curAns = Math.max(curAns + 1, stack[--stackSize][1]); - } - stack[stackSize][0] = arr[i]; - stack[stackSize++][1] = curAns; - ans = Math.max(ans, curAns); - } - return ans; - } - - // 为了测试 - public static int[] randomArray(int n, int v) { - int[] arr = new int[n]; - for (int i = 0; i < n; i++) { - arr[i] = (int) (Math.random() * v); - } - return arr; - } - - // 为了测试 - public static void main(String[] args) { - int len = 50; - int value = 20; - int testTime = 20000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int n = (int) (Math.random() * len) + 1; - int[] arr = randomArray(n, value); - int ans1 = minTurns1(arr); - int ans2 = minTurns2(arr); - if (ans1 != ans2) { - System.out.println("出错了!"); - for (int num : arr) { - System.out.print(num + " "); - } - System.out.println(); - System.out.println(ans1); - System.out.println(ans2); - break; - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class080/Code03_BuyGoodsHaveDiscount.java b/公开课/class080/Code03_BuyGoodsHaveDiscount.java deleted file mode 100644 index 359288f..0000000 --- a/公开课/class080/Code03_BuyGoodsHaveDiscount.java +++ /dev/null @@ -1,89 +0,0 @@ -package class080; - -// 来自字节内部训练营 -// 某公司游戏平台的夏季特惠开始了,你决定入手一些游戏。现在你一共有X元的预算。 -// 该平台上所有的 n 个游戏均有折扣,标号为 i 的游戏的原价a_i元,现价只要b_i元 -// 也就是说该游戏可以优惠 a_i - b_i,并且你购买该游戏能获得快乐值为 w_i -// 由于优惠的存在,你可能做出一些冲动消费导致最终买游戏的总费用超过预算, -// 只要满足 : 获得的总优惠金额不低于超过预算的总金额 -// 那在心理上就不会觉得吃亏。 -// 现在你希望在心理上不觉得吃亏的前提下,获得尽可能多的快乐值。 -// 测试链接 : https://leetcode-cn.com/problems/tJau2o/ -// 提交以下的code,将主类名字改成"Main" -// 可以直接通过 -import java.util.Scanner; - -public class Code03_BuyGoodsHaveDiscount { - - public static void main(String[] args) { - Scanner sc = new Scanner(System.in); - while (sc.hasNext()) { - int n = sc.nextInt(); - int money = sc.nextInt(); - int[] costs = new int[n]; - long[] values = new long[n]; - int size = 0; - long ans = 0; - for (int i = 0; i < n; i++) { - // 打折前 - int pre = sc.nextInt(); - // 打折后 - int pos = sc.nextInt(); - // 满足度 - int happy = sc.nextInt(); - // 节省的钱(save) = 打折前(pre) - 打折后(pos) - int save = pre - pos; - // 带来的好处(well) = 节省的钱 - 打折后(pos) - int well = save - pos; - // 比如,一件"一定要买的商品": - // 预算 = 100,商品原价 = 10,打折后 = 3 - // 那么好处 = (10 - 3) - 3 = 4 - // 所以,这件商品把预算增加到了104,一定要买 - // 接下来,比如一件"需要考虑的商品",预算 = 104,商品原价 = 10,打折后 = 8 - // 那么好处 = (10 - 8) - 8 = -6 - // 这件商品,就花掉6元! - // 也就是说,以后花的不是打折后的值,是"坏处" - int cost = -well; - if (well >= 0) { - money += well; - ans += happy; - } else { - costs[size] = cost; - values[size++] = happy; - } - - } - long[][] dp = new long[size + 1][money + 1]; - for (int a = 0; a <= size; a++) { - for (int b = 0; b <= money; b++) { - dp[a][b] = -2; - } - } - ans += process(costs, values, size, 0, money, dp); - System.out.println(ans); - } - sc.close(); - } - - public static long process(int[] costs, long[] values, int size, int i, int money, long[][] dp) { - if (money < 0) { - return -1; - } - if (i == size) { - return 0; - } - if (dp[i][money] != -2) { - return dp[i][money]; - } - long p1 = process(costs, values, size, i + 1, money, dp); - long p2 = -1; - long next = process(costs, values, size, i + 1, money - costs[i], dp); - if (next != -1) { - p2 = values[i] + next; - } - long ans = Math.max(p1, p2); - dp[i][money] = ans; - return ans; - } - -} \ No newline at end of file diff --git a/公开课/class080/Code04_JumpToTargets.java b/公开课/class080/Code04_JumpToTargets.java deleted file mode 100644 index 3051e0d..0000000 --- a/公开课/class080/Code04_JumpToTargets.java +++ /dev/null @@ -1,56 +0,0 @@ -package class080; - -// 来自字节 -// 一开始在0位置,每一次都可以向左或者向右跳 -// 第i次能向左或者向右跳严格的i步 -// 请问从0到x位置,至少跳几次可以到达 -// 字节考的问题其实就是这个问题 -// 找到了测试链接 : https://www.luogu.com.cn/problem/CF11B -// 提交以下所有代码,把主类名改成"Main",可以直接通过 -import java.util.Scanner; - -public class Code04_JumpToTargets { - - public static void main(String[] args) { - Scanner sc = new Scanner(System.in); - while (sc.hasNext()) { - int x = Math.abs(sc.nextInt()); - System.out.println(minTimes(x)); - } - sc.close(); - } - - public static long minTimes(long x) { - if (x == 0) { - return 0; - } - long l = 0; - long r = x; - long m = 0; - long near = 0; - while (l <= r) { - m = (l + r) / 2; - if (sum(m) >= x) { - near = m; - r = m - 1; - } else { - l = m + 1; - } - } - if (sum(near) == x) { - return near; - } - if (((sum(near) - x) & 1) == 1) { - near++; - } - if (((sum(near) - x) & 1) == 1) { - near++; - } - return near; - } - - public static long sum(long n) { - return (n * (n + 1)) / 2; - } - -} diff --git a/公开课/class081/Code01_ArrangeJob.java b/公开课/class081/Code01_ArrangeJob.java deleted file mode 100644 index 03130d7..0000000 --- a/公开课/class081/Code01_ArrangeJob.java +++ /dev/null @@ -1,62 +0,0 @@ -package class081; - -import java.util.Arrays; -import java.util.PriorityQueue; - -// 来自华为面试 -// 给定一个n*2的二维数组,表示有n个任务 -// 一个信息是任务能够开始做的时间,另一个信息是任务的结束期限,后者一定大于前者,且数值上都是正数 -// 你作为单线程的人,不能并行处理任务,但是每个任务都只需要一个单位时间完成 -// 你需要将所有任务的执行时间,位于开始做的时间和最后期限之间 -// 返回你能否做到这一点 -public class Code01_ArrangeJob { - - public static class TimePoint { - // 时间 - public int time; - public int end; - // add = true time 任务的添加时间 - // add = false time 任务的结束时间 - public boolean add; - - public TimePoint(int t, int e, boolean a) { - time = t; - end = e; - add = a; - } - - } - - public static boolean canDo(int[][] jobs) { - if (jobs == null || jobs.length < 2) { - return true; - } - int n = jobs.length; - TimePoint[] arr = new TimePoint[n << 1]; - for (int i = 0; i < n; i++) { - arr[i] = new TimePoint(jobs[i][0], jobs[i][1], true); - arr[i + n] = new TimePoint(jobs[i][1], jobs[i][1], false); - } - Arrays.sort(arr, (a, b) -> a.time - b.time); - PriorityQueue heap = new PriorityQueue<>(); - for (int i = 0, lastTime = arr[0].time; i < arr.length; i++) { - if (arr[i].add) { - heap.add(arr[i].end); - } else { // 检查时间 - int curTime = arr[i].time; - for (int j = lastTime; j < curTime; j++) { - if (heap.isEmpty()) { - break; - } - heap.poll(); - } - if (heap.peek() <= curTime) { - return false; - } - lastTime = curTime; - } - } - return true; - } - -} diff --git a/公开课/class081/Code02_MinTowNumberSumABS.java b/公开课/class081/Code02_MinTowNumberSumABS.java deleted file mode 100644 index b07e161..0000000 --- a/公开课/class081/Code02_MinTowNumberSumABS.java +++ /dev/null @@ -1,159 +0,0 @@ -package class081; - -import java.util.Arrays; - -// 来自华为面试 -// 给定一个数组arr,可能有正、有负、有0,无序 -// 只能挑选两个数字,想尽量让两个数字加起来的绝对值尽量小 -// 返回可能的最小的值 -public class Code02_MinTowNumberSumABS { - - public static int minSumABS1(int[] arr) { - if (arr == null || arr.length < 2) { - return -1; - } - int ans = Integer.MAX_VALUE; - for (int i = 0; i < arr.length; i++) { - for (int j = i + 1; j < arr.length; j++) { - ans = Math.min(ans, Math.abs(arr[i] + arr[j])); - } - } - return ans; - } - - public static int minSumABS2(int[] arr) { - if (arr == null || arr.length < 2) { - return -1; - } - Arrays.sort(arr); - int n = arr.length; - int split = -1; - for (int i = 0; i < n; i++) { - if (arr[i] >= 0) { - split = i; - break; - } - } - if (split == 0) { - return arr[0] + arr[1]; - } - if (split == -1) { - return -arr[n - 2] - arr[n - 1]; - } - int ans = Integer.MAX_VALUE; - if (split + 1 < n) { - ans = arr[split] + arr[split + 1]; - } - if (split - 2 >= 0) { - ans = Math.min(ans, -arr[split - 1] - arr[split - 2]); - } - for (int i = 0; i < split; i++) { - ans = Math.min(ans, Math.abs(arr[i] + near(arr, split, -arr[i]))); - } - return ans; - } - - // arr[start...]是有序的 - // 返回离num最近的数字 - public static int near(int[] arr, int start, int num) { - int l = start; - int r = arr.length - 1; - int m = 0; - int ans = -1; - while (l <= r) { - m = (l + r) / 2; - if (arr[m] <= num) { - ans = m; - l = m + 1; - } else { - r = m - 1; - } - } - if (ans == -1) { - return arr[start]; - } else { - if (ans == arr.length - 1) { - return arr[arr.length - 1]; - } else { - if (Math.abs(arr[ans] - num) <= Math.abs(arr[ans + 1] - num)) { - return arr[ans]; - } else { - return arr[ans + 1]; - } - } - } - } - - public static int minSumABS3(int[] arr) { - if (arr == null || arr.length < 2) { - return -1; - } - Arrays.sort(arr); - int n = arr.length; - int split = -1; - for (int i = 0; i < n; i++) { - if (arr[i] >= 0) { - split = i; - break; - } - } - if (split == 0) { - return arr[0] + arr[1]; - } - if (split == -1) { - return -arr[n - 2] - arr[n - 1]; - } - int ans = Integer.MAX_VALUE; - if (split + 1 < n) { - ans = arr[split] + arr[split + 1]; - } - if (split - 2 >= 0) { - ans = Math.min(ans, -arr[split - 1] - arr[split - 2]); - } - int r = n - 1; - for (int l = 0; l < split; l++) { - ans = Math.min(ans, Math.abs(arr[l] + arr[r])); - while (r - 1 >= split && Math.abs(arr[l] + arr[r]) >= Math.abs(arr[l] + arr[r - 1])) { - ans = Math.min(ans, Math.abs(arr[l] + arr[--r])); - } - } - return ans; - } - - // 为了测试 - public static int[] randomArray(int n, int v) { - int[] arr = new int[n]; - for (int i = 0; i < n; i++) { - arr[i] = (int) (Math.random() * v) - (int) (Math.random() * v); - } - return arr; - } - - // 为了测试 - public static void main(String[] args) { - int len = 50; - int value = 500; - int testTime = 20000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int n = (int) (Math.random() * len) + 1; - int[] arr = randomArray(n, value); - int ans1 = minSumABS1(arr); - int ans2 = minSumABS2(arr); - int ans3 = minSumABS3(arr); - if (ans1 != ans2 || ans1 != ans3) { - System.out.println("出错了!"); - for (int num : arr) { - System.out.print(num + " "); - } - System.out.println(); - System.out.println(ans1); - System.out.println(ans2); - System.out.println(ans3); - break; - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class081/Code03_HowManyWaysFromBottomToTop.java b/公开课/class081/Code03_HowManyWaysFromBottomToTop.java deleted file mode 100644 index c585fa3..0000000 --- a/公开课/class081/Code03_HowManyWaysFromBottomToTop.java +++ /dev/null @@ -1,81 +0,0 @@ -package class081; - -// 来自理想汽车 -// a -> b,代表a在食物链中被b捕食 -// 给定一个有向无环图,返回 -// 这个图中从最初级动物到最顶级捕食者的食物链有几条 -// 线上测试链接 : https://www.luogu.com.cn/problem/P4017 -// 以下代码都提交,提交时把主类名改成"Main"即可 -// 注意:洛谷测试平台对java提交非常不友好,空间限制可能会卡住,C++的提交就完全不会 -// 所以提交时如果显示失败,就多提交几次,一定是能成功的 -// 这道题本身就是用到拓扑排序,没什么特别的 -// 但是为了提交能通过,逼迫我在空间上做的优化值得好好说一下,可以推广到其他题目 -import java.util.Arrays; -import java.util.Scanner; - -public class Code03_HowManyWaysFromBottomToTop { - - public static int[] in = new int[5001]; - public static boolean[] out = new boolean[5001]; - public static int[] lines = new int[5001]; - public static int[] headEdge = new int[5001]; - public static int[] queue = new int[5001]; - public static int mod = 80112002; - public static int n = 0; - - public static void main(String[] args) { - Scanner sc = new Scanner(System.in); - while (sc.hasNext()) { - Arrays.fill(in, 0); - Arrays.fill(out, false); - Arrays.fill(lines, 0); - Arrays.fill(headEdge, 0); - n = sc.nextInt(); - int m = sc.nextInt(); - int[] preEdge = new int[m + 1]; - int[] edgesTo = new int[m + 1]; - for (int i = 1; i <= m; i++) { - int from = sc.nextInt(); - int to = sc.nextInt(); - edgesTo[i] = to; - preEdge[i] = headEdge[from]; - headEdge[from] = i; - out[from] = true; - in[to]++; - } - System.out.println(howManyWays(preEdge, edgesTo)); - } - sc.close(); - } - - public static int howManyWays(int[] preEdge, int[] edgesTo) { - int ql = 0; - int qr = 0; - for (int i = 1; i <= n; i++) { - if (in[i] == 0) { - queue[qr++] = i; - lines[i] = 1; - } - } - while (ql < qr) { - int cur = queue[ql++]; - int edge = headEdge[cur]; - while (edge != 0) { - int next = edgesTo[edge]; - lines[next] = (lines[next] + lines[cur]) % mod; - if (--in[next] == 0) { - queue[qr++] = next; - } - edge = preEdge[edge]; - } - } - int ans = 0; - for (int i = 1; i <= n; i++) { - if (!out[i]) { - ans = (ans + lines[i]) % mod; - } - } - return ans; - } - -} diff --git a/公开课/class082/Code01_JumpToTargets.java b/公开课/class082/Code01_JumpToTargets.java deleted file mode 100644 index b2a485b..0000000 --- a/公开课/class082/Code01_JumpToTargets.java +++ /dev/null @@ -1,45 +0,0 @@ -package class082; - -// 来自字节 -// 一开始在0位置,每一次都可以向左或者向右跳 -// 第i次能向左或者向右跳严格的i步 -// 请问从0到x位置,至少跳几次可以到达 -// 字节考的问题其实就是这个问题 -// leetcode测试链接 : https://leetcode.com/problems/reach-a-number/ -public class Code01_JumpToTargets { - - public static int reachNumber(long target) { - if (target == 0) { - return 0; - } - target = Math.abs(target); - long l = 0; - long r = target; - long m = 0; - long near = 0; - while (l <= r) { - m = (l + r) / 2; - if (sum(m) >= target) { - near = m; - r = m - 1; - } else { - l = m + 1; - } - } - if (sum(near) == target) { - return (int)near; - } - if (((sum(near) - target) & 1) == 1) { - near++; - } - if (((sum(near) - target) & 1) == 1) { - near++; - } - return (int)near; - } - - public static long sum(long n) { - return (n * (n + 1)) / 2; - } - -} diff --git a/公开课/class082/Code02_ArrangeMeetingPosCancelPre.java b/公开课/class082/Code02_ArrangeMeetingPosCancelPre.java deleted file mode 100644 index 38d212f..0000000 --- a/公开课/class082/Code02_ArrangeMeetingPosCancelPre.java +++ /dev/null @@ -1,210 +0,0 @@ -package class082; - -import java.util.ArrayList; -import java.util.Arrays; - -// 来自通维数码 -// 每个会议给定开始和结束时间 -// 后面的会议如果跟前面的会议有任何冲突,完全取消冲突的、之前的会议,安排当前的 -// 给定一个会议数组,返回安排的会议列表 -public class Code02_ArrangeMeetingPosCancelPre { - - // 彻底暴力做的! - // 对数器! - public static ArrayList arrange1(int[][] meetings) { - int max = 0; - for (int[] meeting : meetings) { - max = Math.max(max, meeting[1]); - } - boolean[] occupy = new boolean[max + 1]; - ArrayList ans = new ArrayList<>(); - for (int i = meetings.length - 1; i >= 0; i--) { - int[] cur = meetings[i]; - boolean add = true; - for (int j = cur[0]; j < cur[1]; j++) { - if (occupy[j]) { - add = false; - break; - } - } - if (add) { - ans.add(cur); - } - for (int j = cur[0]; j < cur[1]; j++) { - occupy[j] = true; - } - } - return ans; - } - - public static ArrayList arrange2(int[][] meetings) { - int n = meetings.length; - int[] rank = new int[n << 1]; - for (int i = 0; i < meetings.length; i++) { - rank[i] = meetings[i][0]; - rank[i + n] = meetings[i][1] - 1; - } - Arrays.sort(rank); - SegmentTree st = new SegmentTree(n << 1); - ArrayList ans = new ArrayList<>(); - for (int i = meetings.length - 1; i >= 0; i--) { - int[] cur = meetings[i]; - int from = rank(rank, cur[0]); - int to = rank(rank, cur[1] - 1); - if (st.sum(from, to) == 0) { - ans.add(cur); - } - st.add(from, to, 1); - } - return ans; - } - - public static int rank(int[] rank, int num) { - int l = 0; - int r = rank.length - 1; - int m = 0; - int ans = 0; - while (l <= r) { - m = (l + r) / 2; - if (rank[m] >= num) { - ans = m; - r = m - 1; - } else { - l = m + 1; - } - } - return ans + 1; - } - - public static class SegmentTree { - private int n; - private int[] sum; - private int[] lazy; - - public SegmentTree(int size) { - n = size + 1; - sum = new int[n << 2]; - lazy = new int[n << 2]; - n--; - } - - private void pushUp(int rt) { - sum[rt] = sum[rt << 1] + sum[rt << 1 | 1]; - } - - private void pushDown(int rt, int ln, int rn) { - if (lazy[rt] != 0) { - lazy[rt << 1] += lazy[rt]; - sum[rt << 1] += lazy[rt] * ln; - lazy[rt << 1 | 1] += lazy[rt]; - sum[rt << 1 | 1] += lazy[rt] * rn; - lazy[rt] = 0; - } - } - - public void add(int L, int R, int C) { - add(L, R, C, 1, n, 1); - } - - private void add(int L, int R, int C, int l, int r, int rt) { - if (L <= l && r <= R) { - sum[rt] += C * (r - l + 1); - lazy[rt] += C; - return; - } - int mid = (l + r) >> 1; - pushDown(rt, mid - l + 1, r - mid); - if (L <= mid) { - add(L, R, C, l, mid, rt << 1); - } - if (R > mid) { - add(L, R, C, mid + 1, r, rt << 1 | 1); - } - pushUp(rt); - } - - public int sum(int L, int R) { - return query(L, R, 1, n, 1); - } - - private int query(int L, int R, int l, int r, int rt) { - if (L <= l && r <= R) { - return sum[rt]; - } - int mid = (l + r) >> 1; - pushDown(rt, mid - l + 1, r - mid); - int ans = 0; - if (L <= mid) { - ans += query(L, R, l, mid, rt << 1); - } - if (R > mid) { - ans += query(L, R, mid + 1, r, rt << 1 | 1); - } - return ans; - } - - } - - // 为了测试 - public static int[][] randomMeeting(int len, int time) { - int[][] meetings = new int[len][2]; - for (int i = 0; i < len; i++) { - int a = (int) (Math.random() * (time + 1)); - int b = (int) (Math.random() * (time + 1)); - if (a == b) { - b++; - } - meetings[i][0] = Math.min(a, b); - meetings[i][1] = Math.max(a, b); - } - return meetings; - } - - // 为了测试 - public static int[][] copyMeetings(int[][] meetings) { - int len = meetings.length; - int[][] ans = new int[len][2]; - for (int i = 0; i < len; i++) { - ans[i][0] = meetings[i][0]; - ans[i][1] = meetings[i][1]; - } - return ans; - } - - // 为了测试 - public static boolean equal(ArrayList arr1, ArrayList arr2) { - if (arr1.size() != arr2.size()) { - return false; - } - for (int i = 0; i < arr1.size(); i++) { - int[] a = arr1.get(i); - int[] b = arr2.get(i); - if (a[0] != b[0] || a[1] != b[1]) { - return false; - } - } - return true; - } - - public static void main(String[] args) { - int n = 100; - int t = 5000; - int testTime = 20000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int len = (int) (Math.random() * n) + 1; - int[][] meetings1 = randomMeeting(len, t); - int[][] meetings2 = copyMeetings(meetings1); - ArrayList ans1 = arrange1(meetings1); - ArrayList ans2 = arrange2(meetings2); - if (!equal(ans1, ans2)) { - System.out.println("出错了!"); - System.out.println(ans1.size()); - System.out.println(ans2.size()); - System.out.println("===="); - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class082/Code03_MaxScoreMoveInBoard.java b/公开课/class082/Code03_MaxScoreMoveInBoard.java deleted file mode 100644 index c750516..0000000 --- a/公开课/class082/Code03_MaxScoreMoveInBoard.java +++ /dev/null @@ -1,71 +0,0 @@ -package class082; - -// 来自小红书 -// 小红书第一题: -// 薯队长从北向南穿过一片红薯地(南北长M,东西宽N),红薯地被划分为1x1的方格, -// 他可以从北边的任何一个格子出发,到达南边的任何一个格子, -// 但每一步只能走到东南、正南、西南方向的三个格子之一, -// 而且不能跨出红薯地,他可以获得经过的格子上的所有红薯,请问他可以获得最多的红薯个数。 -public class Code03_MaxScoreMoveInBoard { - - public static int maxScore(int[][] map) { - int ans = 0; - for (int col = 0; col < map[0].length; col++) { - ans = Math.max(ans, process(map, 0, col)); - } - return ans; - } - - public static int process(int[][] map, int row, int col) { - if (col < 0 || col == map[0].length) { - return -1; - } - if (row == map.length - 1) { - return map[row][col]; - } - int cur = map[row][col]; - int next1 = process(map, row + 1, col - 1); - int next2 = process(map, row + 1, col); - int next3 = process(map, row + 1, col + 1); - return cur + Math.max(Math.max(next1, next2), next3); - } - - public static int maxScore2(int[][] map) { - int ans = 0; - int n = map.length; - int m = map[0].length; - int[][] dp = new int[n][m]; - for (int i = 0; i < n; i++) { - for (int j = 0; j < m; j++) { - dp[i][j] = -2; // -2表示,这个格子没算过! - } - } - for (int col = 0; col < map[0].length; col++) { - ans = Math.max(ans, process2(map, 0, col, dp)); - } - return ans; - } - - public static int process2(int[][] map, int row, int col, int[][] dp) { - if (col < 0 || col == map[0].length) { - return -1; - } - if (dp[row][col] != -2) { - return dp[row][col]; - } - // 继续算! - int ans = 0; - if (row == map.length - 1) { - ans = map[row][col]; - } else { - int cur = map[row][col]; - int next1 = process2(map, row + 1, col - 1, dp); - int next2 = process2(map, row + 1, col, dp); - int next3 = process2(map, row + 1, col + 1, dp); - ans = cur + Math.max(Math.max(next1, next2), next3); - } - dp[row][col] = ans; - return ans; - } - -} diff --git a/公开课/class082/Code04_FourNumbersMinusOne.java b/公开课/class082/Code04_FourNumbersMinusOne.java deleted file mode 100644 index b2b2cf0..0000000 --- a/公开课/class082/Code04_FourNumbersMinusOne.java +++ /dev/null @@ -1,58 +0,0 @@ -package class082; - -import java.util.Arrays; - -// 来自阿里笔试 -// 牛牛今年上幼儿园了,老师叫他学习减法 -// 老师给了他5个数字,他每次操作可以选择其中的4个数字减1 -// 减一之后的数字不能小于0,因为幼儿园的牛牛还没有接触过负数 -// 现在牛牛想知道,自己最多可以进行多少次这样的操作 -// 扩展问题来自leetcode 2141,掌握了这个题原始问题就非常简单了 -// leetcode测试链接 : https://leetcode.com/problems/maximum-running-time-of-n-computers/ -public class Code04_FourNumbersMinusOne { - - public static long maxRunTime(int n, int[] arr) { - Arrays.sort(arr); - int size = arr.length; - long[] sums = new long[size]; - sums[0] = arr[0]; - for (int i = 1; i < size; i++) { - sums[i] = sums[i - 1] + arr[i]; - } - long l = 0; - long m = 0; - long r = sums[size - 1] / n; - long ans = -1; - while (l <= r) { - m = (l + r) / 2; - if (ok(arr, sums, m, n)) { - ans = m; - l = m + 1; - } else { - r = m - 1; - } - } - return ans; - } - - public static boolean ok(int[] arr, long[] sum, long time, int num) { - int l = 0; - int m = 0; - int r = arr.length - 1; - int left = arr.length; - // >= time 最左 - while (l <= r) { - m = (l + r) / 2; - if (arr[m] >= time) { - left = m; - r = m - 1; - } else { - l = m + 1; - } - } - num -= arr.length - left; - long rest = left == 0 ? 0 : sum[left - 1]; - return time * (long) num <= rest; - } - -} diff --git a/公开课/class082/Code05_MaxSumOnReverseArray.java b/公开课/class082/Code05_MaxSumOnReverseArray.java deleted file mode 100644 index d8b0043..0000000 --- a/公开课/class082/Code05_MaxSumOnReverseArray.java +++ /dev/null @@ -1,105 +0,0 @@ -package class082; - -// 来自美团 -// 最大子段和是 -// 一个经典问题,即对于一个数组找出其和最大的子数组。 -// 现在允许你在求解该问题之前翻转这个数組的连续一段 -// 如翻转(1,2,3,4,5,6)的第三个到第五个元素組成的子数组得到的是(1,2,5,4,3,6), -// 则翻转后该数组的最大子段和最大能达到多少? -// 来自字节 -// 几乎一样的题,来自字节笔试第4题 -// 给定两个数組values和numbers, -// values[i]表示i号宝石的单品价值 -// numbers[i]表示i号宝石的数量 -// i号宝石的总价值 = values[i] * numbers[i] -// 如果有一种魔法,可以翻转任何区间L...R的宝石,也就是改变L..R的宝石排列,变成逆序的 -// 求在允许用一次魔法的情况下,任取一段连续区间,能达到的最大价值 -// 这两个问法解法都几乎一样,区别无非是: -// 美团的: 可进行一次翻转情况下,子数组最大累加和 -// 字节的: 可进行一次翻转情况下,子数组最大价值和 -public class Code05_MaxSumOnReverseArray { - - public static int maxSumReverse1(int[] arr) { - int ans = Integer.MIN_VALUE; - for (int L = 0; L < arr.length; L++) { - for (int R = L; R < arr.length; R++) { - reverse(arr, L, R); - ans = Math.max(ans, maxSum(arr)); - reverse(arr, L, R); - } - } - return ans; - } - - public static void reverse(int[] arr, int L, int R) { - while (L < R) { - int tmp = arr[L]; - arr[L++] = arr[R]; - arr[R--] = tmp; - } - } - - public static int maxSum(int[] arr) { - int pre = arr[0]; - int max = arr[0]; - for (int i = 1; i < arr.length; i++) { - pre = Math.max(arr[i], arr[i] + pre); - max = Math.max(max, pre); - } - return max; - } - - public static int maxSumReverse2(int[] arr) { - int n = arr.length; - int[] prefix = new int[n]; - prefix[n - 1] = arr[n - 1]; - for (int i = n - 2; i >= 0; i--) { - prefix[i] = arr[i] + Math.max(0, prefix[i + 1]); - } - int ans = prefix[0]; - int suffix = arr[0]; - int maxSuffix = suffix; - for (int i = 1; i < n; i++) { - ans = Math.max(ans, maxSuffix + prefix[i]); - suffix = arr[i] + Math.max(0, suffix); - maxSuffix = Math.max(maxSuffix, suffix); - } - ans = Math.max(ans, maxSuffix); - return ans; - } - - // 为了测试 - public static int[] randomArray(int n, int v) { - int[] arr = new int[n]; - for (int i = 0; i < n; i++) { - arr[i] = (int) (Math.random() * v) - (int) (Math.random() * v); - } - return arr; - } - - // 为了测试 - public static void main(String[] args) { - int len = 50; - int value = 20; - int testTime = 20000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int n = (int) (Math.random() * len) + 1; - int[] arr = randomArray(n, value); - int ans1 = maxSumReverse1(arr); - int ans2 = maxSumReverse2(arr); - if (ans1 != ans2) { - System.out.println("出错了!"); - for (int num : arr) { - System.out.print(num + " "); - } - System.out.println(); - System.out.println(ans1); - System.out.println(ans2); - break; - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class083/Code01_MaxOneNumbers.java b/公开课/class083/Code01_MaxOneNumbers.java deleted file mode 100644 index c2de66e..0000000 --- a/公开课/class083/Code01_MaxOneNumbers.java +++ /dev/null @@ -1,114 +0,0 @@ -package class083; - -// 小红书 -// 3.13 笔试 -// 数组里有0和1,一定要翻转一个区间,翻转:0变1,1变0 -// 请问翻转后可以使得1的个数最多是多少? -public class Code01_MaxOneNumbers { - - // arr中,子数组的最大累加和,返回 - public static int maxSum1(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int n = arr.length; - int[] dp = new int[n]; - dp[0] = arr[0]; - int max = dp[0]; - for (int i = 1; i < n; i++) { - int p1 = arr[i]; - int p2 = dp[i - 1] + arr[i]; - dp[i] = Math.max(p1, p2); - max = Math.max(max, dp[i]); - } - return max; - } - - public static int maxSum2(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int n = arr.length; - int pre = arr[0]; // pre -> dp[0]; - int max = pre; - for (int i = 1; i < n; i++) { - pre = Math.max(arr[i], pre + arr[i]); - max = Math.max(max, pre); - } - return max; - } - - - - - public static int maxOneNumbers1(int[] arr) { - int ans = 0; - for (int l = 0; l < arr.length; l++) { - for (int r = l; r < arr.length; r++) { - reverse(arr, l, r); - ans = Math.max(ans, oneNumbers(arr)); - reverse(arr, l, r); - } - } - return ans; - } - - public static void reverse(int[] arr, int l, int r) { - for (int i = l; i <= r; i++) { - arr[i] ^= 1; - } - } - - public static int oneNumbers(int[] arr) { - int ans = 0; - for (int num : arr) { - ans += num; - } - return ans; - } - - public static int maxOneNumbers2(int[] arr) { - int ans = 0; - for (int num : arr) { - ans += num; - } - for (int i = 0; i < arr.length; i++) { - arr[i] = arr[i] == 0 ? 1 : -1; - } - int max = Integer.MIN_VALUE; - int cur = 0; - for (int i = 0; i < arr.length; i++) { - cur += arr[i]; - max = Math.max(max, cur); - cur = cur < 0 ? 0 : cur; - } - return ans + max; - } - - // 为了测试 - public static int[] randomArray(int n) { - int[] arr = new int[n]; - for (int i = 0; i < n; i++) { - arr[i] = (int) (Math.random() * 2); - } - return arr; - } - - // 为了测试 - public static void main(String[] args) { - int N = 100; - int testTime = 20000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int n = (int) (Math.random() * N) + 1; - int[] arr = randomArray(n); - int ans1 = maxOneNumbers1(arr); - int ans2 = maxOneNumbers2(arr); - if (ans1 != ans2) { - System.out.println("出错了!"); - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class083/Code02_PerfectPairNumber.java b/公开课/class083/Code02_PerfectPairNumber.java deleted file mode 100644 index 88afae6..0000000 --- a/公开课/class083/Code02_PerfectPairNumber.java +++ /dev/null @@ -1,52 +0,0 @@ -package class083; - -// 来自阿里 -// x = { a, b, c, d } -// y = { e, f, g, h } -// x、y两个小数组长度都是4 -// 如果有: a + e = b + f = c + g = d + h -// 那么说x和y是一个完美对 -// 题目给定N个小数组,每个小数组长度都是K -// 返回这N个小数组中,有多少完美对 -// 本题测试链接 : https://www.nowcoder.com/practice/f5a3b5ab02ed4202a8b54dfb76ad035e -// 提交如下代码,把主类名改成Main -// 可以直接通过 -import java.util.HashMap; -import java.util.Scanner; - -public class Code02_PerfectPairNumber { - - public static void main(String[] args) { - Scanner sc = new Scanner(System.in); - while (sc.hasNext()) { - int n = sc.nextInt(); - int m = sc.nextInt(); - int[][] matrix = new int[n][m]; - for (int i = 0; i < n; i++) { - for (int j = 0; j < m; j++) { - matrix[i][j] = sc.nextInt(); - } - } - long ans = perfectPairs(matrix); - System.out.println(ans); - } - sc.close(); - } - - public static long perfectPairs(int[][] matrix) { - long ans = 0; - HashMap counts = new HashMap<>(); - for (int[] arr : matrix) { - StringBuilder self = new StringBuilder(); - StringBuilder minus = new StringBuilder(); - for (int i = 1; i < arr.length; i++) { - self.append("_" + (arr[i] - arr[i - 1])); - minus.append("_" + (arr[i - 1] - arr[i])); - } - ans += counts.getOrDefault(minus.toString(), 0); - counts.put(self.toString(), counts.getOrDefault(self.toString(), 0) + 1); - } - return ans; - } - -} \ No newline at end of file diff --git a/公开课/class083/Code03_TopMinSubsquenceSum.java b/公开课/class083/Code03_TopMinSubsquenceSum.java deleted file mode 100644 index 98488a6..0000000 --- a/公开课/class083/Code03_TopMinSubsquenceSum.java +++ /dev/null @@ -1,114 +0,0 @@ -package class083; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.PriorityQueue; - -// 给定一个数组arr,含有n个数字,都是非负数 -// 给定一个正数k -// 返回所有子序列中,累加和最小的前k个子序列累加和 -// 假设K不大,怎么算最快? -public class Code03_TopMinSubsquenceSum { - - public static int[] topMinSum1(int[] arr, int k) { - ArrayList allAns = new ArrayList<>(); - process(arr, 0, 0, allAns); - allAns.sort((a, b) -> a.compareTo(b)); - int[] ans = new int[k]; - for (int i = 0; i < k; i++) { - ans[i] = allAns.get(i); - } - return ans; - } - - public static void process(int[] arr, int index, int sum, ArrayList ans) { - if (index == arr.length) { - ans.add(sum); - } else { - process(arr, index + 1, sum, ans); - process(arr, index + 1, sum + arr[index], ans); - } - } - - public static int[] topMinSum2(int[] arr, int k) { - Arrays.sort(arr); - // (最右的下标,集合的累加和) - PriorityQueue heap = new PriorityQueue<>((a, b) -> a[1] - b[1]); - heap.add(new int[] { 0, arr[0] }); - int[] ans = new int[k]; - // ans[0] = 0 - // 0 1 2 k-1 - // k个! - for (int i = 1; i < k; i++) { - int[] cur = heap.poll(); - // (7, 100) - // 左 :8, 100 - arr[7] + arr[8] - // 右 :8, 100 + arr[8] - int last = cur[0]; - int sum = cur[1]; - ans[i] = sum; - if (last + 1 < arr.length) { - heap.add(new int[] { last + 1, sum - arr[last] + arr[last + 1] }); - heap.add(new int[] { last + 1, sum + arr[last + 1] }); - } - } - return ans; - } - - // 为了测试 - public static int[] randomArray(int len, int value) { - int[] arr = new int[len]; - for (int i = 0; i < len; i++) { - arr[i] = (int) (Math.random() * value); - } - return arr; - } - - // 为了测试 - public static boolean equals(int[] ans1, int[] ans2) { - if (ans1.length != ans2.length) { - return false; - } - for (int i = 0; i < ans1.length; i++) { - if (ans1[i] != ans2[i]) { - return false; - } - } - return true; - } - - // 为了测试 - public static void main(String[] args) { - int n = 10; - int v = 40; - int testTime = 5000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int len = (int) (Math.random() * n) + 1; - int[] arr = randomArray(len, v); - int k = (int) (Math.random() * ((1 << len) - 1)) + 1; - int[] ans1 = topMinSum1(arr, k); - int[] ans2 = topMinSum2(arr, k); - if (!equals(ans1, ans2)) { - System.out.println("出错了!"); - System.out.print("arr : "); - for (int num : arr) { - System.out.print(num + " "); - } - System.out.println(); - System.out.println("k : " + k); - for (int num : ans1) { - System.out.print(num + " "); - } - System.out.println(); - for (int num : ans2) { - System.out.print(num + " "); - } - System.out.println(); - break; - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class083/Code04_TopMaxSubsquenceSum.java b/公开课/class083/Code04_TopMaxSubsquenceSum.java deleted file mode 100644 index 87bc403..0000000 --- a/公开课/class083/Code04_TopMaxSubsquenceSum.java +++ /dev/null @@ -1,124 +0,0 @@ -package class083; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.PriorityQueue; - -// 来自Amazon -// 给定一个数组arr,含有n个数字,可能有正、有负、有0 -// 给定一个正数k -// 返回所有子序列中,累加和最大的前k个子序列累加和 -// 假设K不大,怎么算最快? -public class Code04_TopMaxSubsquenceSum { - - public static int[] topMaxSum1(int[] arr, int k) { - ArrayList allAns = new ArrayList<>(); - process(arr, 0, 0, allAns); - allAns.sort((a, b) -> a.compareTo(b)); - int[] ans = new int[k]; - for (int i = allAns.size() - 1, j = 0; j < k; i--, j++) { - ans[j] = allAns.get(i); - } - return ans; - } - - public static void process(int[] arr, int index, int sum, ArrayList ans) { - if (index == arr.length) { - ans.add(sum); - } else { - process(arr, index + 1, sum, ans); - process(arr, index + 1, sum + arr[index], ans); - } - } - - public static int[] topMaxSum2(int[] arr, int k) { - int sum = 0; - for (int i = 0; i < arr.length; i++) { - if (arr[i] >= 0) { - sum += arr[i]; - } else { - arr[i] = -arr[i]; - } - } - int[] ans = topMinSum(arr, k); - for (int i = 0; i < ans.length; i++) { - ans[i] = sum - ans[i]; - } - return ans; - } - - public static int[] topMinSum(int[] arr, int k) { - Arrays.sort(arr); - PriorityQueue heap = new PriorityQueue<>((a, b) -> a[1] - b[1]); - heap.add(new int[] { 0, arr[0] }); - int[] ans = new int[k]; - for (int i = 1; i < k; i++) { - int[] cur = heap.poll(); - int last = cur[0]; - int sum = cur[1]; - ans[i] = sum; - if (last + 1 < arr.length) { - heap.add(new int[] { last + 1, sum - arr[last] + arr[last + 1] }); - heap.add(new int[] { last + 1, sum + arr[last + 1] }); - } - } - return ans; - } - - // 为了测试 - public static int[] randomArray(int len, int value) { - int[] arr = new int[len]; - for (int i = 0; i < len; i++) { - arr[i] = (int) (Math.random() * value) + 1; - } - return arr; - } - - // 为了测试 - public static boolean equals(int[] ans1, int[] ans2) { - if (ans1.length != ans2.length) { - return false; - } - for (int i = 0; i < ans1.length; i++) { - if (ans1[i] != ans2[i]) { - return false; - } - } - return true; - } - - // 为了测试 - public static void main(String[] args) { - int n = 10; - int v = 40; - int testTime = 5000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int len = (int) (Math.random() * n) + 1; - int[] arr = randomArray(len, v); - int k = (int) (Math.random() * ((1 << len) - 1)) + 1; - int[] ans1 = topMaxSum1(arr, k); - int[] ans2 = topMaxSum2(arr, k); - if (!equals(ans1, ans2)) { - System.out.println("出错了!"); - System.out.print("arr : "); - for (int num : arr) { - System.out.print(num + " "); - } - System.out.println(); - System.out.println("k : " + k); - for (int num : ans1) { - System.out.print(num + " "); - } - System.out.println(); - for (int num : ans2) { - System.out.print(num + " "); - } - System.out.println(); - break; - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class084/Code01_MinDepth.java b/公开课/class084/Code01_MinDepth.java deleted file mode 100644 index c4e5f98..0000000 --- a/公开课/class084/Code01_MinDepth.java +++ /dev/null @@ -1,116 +0,0 @@ -package class084; - -// 美团面试题 -// 来自学员反馈的一面题目 -// 求二叉树最小深度 -// 本题测试链接 : https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/ -public class Code01_MinDepth { - - // 不提交这个类 - public static class TreeNode { - public int val; - public TreeNode left; - public TreeNode right; - - public TreeNode(int x) { - val = x; - } - } - - // head为头的二叉树,最小深度返回 - public static int ans = Integer.MAX_VALUE; - - public static int minDepth(TreeNode head) { - if(head == null) { - return 0; - } - ans = Integer.MAX_VALUE; - zuo(head, 1); - return ans; - } - - public static void zuo(TreeNode x, int level) { - if (x.left == null && x.right == null) { - ans = Math.min(ans, level); - } else { - if (x.left != null) { - zuo(x.left, level + 1); - } - if (x.right != null) { - zuo(x.right, level + 1); - } - } - } - - // 下面的方法是一般解 - public static int minDepth1(TreeNode head) { - if (head == null) { - return 0; - } - return p(head); - } - - // 返回x为头的树,最小深度是多少 - public static int p(TreeNode x) { - if (x.left == null && x.right == null) { - return 1; - } - // 左右子树起码有一个不为空 - int leftH = Integer.MAX_VALUE; - if (x.left != null) { - leftH = p(x.left); - } - int rightH = Integer.MAX_VALUE; - if (x.right != null) { - rightH = p(x.right); - } - return 1 + Math.min(leftH, rightH); - } - - // 下面的方法是morris遍历的解 - public static int minDepth2(TreeNode head) { - if (head == null) { - return 0; - } - TreeNode cur = head; - TreeNode mostRight = null; - int curLevel = 0; - int minHeight = Integer.MAX_VALUE; - while (cur != null) { - mostRight = cur.left; - if (mostRight != null) { - int rightBoardSize = 1; - while (mostRight.right != null && mostRight.right != cur) { - rightBoardSize++; - mostRight = mostRight.right; - } - if (mostRight.right == null) { // 第一次到达 - curLevel++; - mostRight.right = cur; - cur = cur.left; - continue; - } else { // 第二次到达 - if (mostRight.left == null) { - minHeight = Math.min(minHeight, curLevel); - } - curLevel -= rightBoardSize; - mostRight.right = null; - } - } else { // 只有一次到达 - curLevel++; - } - cur = cur.right; - } - int finalRight = 1; - cur = head; - while (cur.right != null) { - finalRight++; - cur = cur.right; - } - if (cur.left == null && cur.right == null) { - minHeight = Math.min(minHeight, finalRight); - } - return minHeight; - } - -} diff --git a/公开课/class084/Code02_DiameterOfBinarytree.java b/公开课/class084/Code02_DiameterOfBinarytree.java deleted file mode 100644 index 495d414..0000000 --- a/公开课/class084/Code02_DiameterOfBinarytree.java +++ /dev/null @@ -1,70 +0,0 @@ -package class084; - -// 来自学员反馈 -// 最近字节的面试题 -// 二叉树直径 -// 测试链接 : https://leetcode.com/problems/diameter-of-binary-tree/ -public class Code02_DiameterOfBinarytree { - - // 不要提交这个类 - public static class TreeNode { - public int val; - public TreeNode left; - public TreeNode right; - } - - public static int diameterOfBinaryTree(TreeNode root) { - return zuo(root).maxDistance; - } - - public static class Info { - public int maxDistance; - public int height; - - public Info(int m, int h) { - maxDistance = m; - height = h; - } - } - - public static Info zuo(TreeNode x) { - if (x == null) { - return new Info(0, 0); - } - Info leftInfo = zuo(x.left); - Info rightInfo = zuo(x.right); - int height = Math.max(leftInfo.height, rightInfo.height) + 1; - int p1 = Math.max(leftInfo.maxDistance, rightInfo.maxDistance); - int p2 = leftInfo.height + rightInfo.height; - int maxDistance = Math.max(p1, p2); - return new Info(maxDistance, height); - } - -// public static int diameterOfBinaryTree(TreeNode root) { -// return process(root).maxDistance; -// } -// -// public static class Info { -// public int maxDistance; -// public int height; -// -// public Info(int m, int h) { -// maxDistance = m; -// height = h; -// } -// } -// -// public static Info process(TreeNode x) { -// if (x == null) { -// return new Info(0, 0); -// } -// Info leftInfo = process(x.left); -// Info rightInfo = process(x.right); -// int maxDistance = Math.max( -// Math.max(leftInfo.maxDistance, rightInfo.maxDistance), -// leftInfo.height + rightInfo.height); -// int height = Math.max(leftInfo.height, rightInfo.height) + 1; -// return new Info(maxDistance, height); -// } - -} diff --git a/公开课/class084/Code03_AllJobFinishTime.java b/公开课/class084/Code03_AllJobFinishTime.java deleted file mode 100644 index 75b292d..0000000 --- a/公开课/class084/Code03_AllJobFinishTime.java +++ /dev/null @@ -1,51 +0,0 @@ -package class084; - -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.Queue; - -// 来自美团 -// 3.26笔试 -// 给定一个正数n, 表示有0~n-1号任务 -// 给定一个长度为n的数组time,time[i]表示i号任务做完的时间 -// 给定一个二维数组matrix -// matrix[j] = {a, b} 代表:a任务想要开始,依赖b任务的完成 -// 只要能并行的任务都可以并行,但是任何任务只有依赖的任务完成,才能开始 -// 返回一个长度为n的数组ans,表示每个任务完成的时间 -// 输入可以保证没有循环依赖 -public class Code03_AllJobFinishTime { - - // n : 0 ~ n-1 - // time : time[i]是i号任务自己完成需要的时间 - // matrix : 依赖关系 - public static int[] finishTime(int n, int[] time, int[][] matrix) { - ArrayList> nexts = new ArrayList<>(); - for (int i = 0; i < n; i++) { - nexts.add(new ArrayList<>()); - } - int[] in = new int[n]; - for (int[] line : matrix) { - nexts.get(line[1]).add(line[0]); - in[line[0]]++; - } - Queue zeroInQueue = new LinkedList<>(); - int[] ans = new int[n]; - for (int i = 0; i < n; i++) { - if (in[i] == 0) { - zeroInQueue.add(i); - } - } - while (!zeroInQueue.isEmpty()) { - int cur = zeroInQueue.poll(); - ans[cur] += time[cur]; - for (int next : nexts.get(cur)) { - ans[next] = Math.max(ans[next], ans[cur]); - if (--in[next] == 0) { - zeroInQueue.add(next); - } - } - } - return ans; - } - -} diff --git a/公开课/class084/Code04_ClassicDP.java b/公开课/class084/Code04_ClassicDP.java deleted file mode 100644 index ca4d82b..0000000 --- a/公开课/class084/Code04_ClassicDP.java +++ /dev/null @@ -1,56 +0,0 @@ -package class084; - -// 来自阿里 -// 测试链接 : https://www.nowcoder.com/practice/237ae40ea1e84d8980c1d5666d1c53bc -// 提交以下的代码,把类名改成Main -// 可以直接通过 -import java.util.Scanner; - -public class Code04_ClassicDP { - - public static void main(String[] args) { - Scanner sc = new Scanner(System.in); - while (sc.hasNext()) { - int n = sc.nextInt(); - int m = sc.nextInt(); - int[] cost = new int[n]; - int[] value = new int[n]; - for (int i = 0; i < n; i++) { - cost[i] = sc.nextInt(); - value[i] = sc.nextInt(); - } - int[][] dp = dp(cost, value, m); - int ans = 0; - for (int j = 0; j <= m; j++) { - ans = Math.max(ans, dp[n - 1][j]); - } - System.out.println(ans); - System.out.println(dp[n - 1][m] == -1 ? 0 : dp[n - 1][m]); - } - sc.close(); - } - - public static int[][] dp(int[] cost, int[] value, int m) { - int n = cost.length; - // dp[i][j] : 背包重量严格等于j,货物在0...i上随意选,最大价值是多少 - int[][] dp = new int[n][m + 1]; - for (int i = 0; i < n; i++) { - for (int j = 1; j <= m; j++) { - dp[i][j] = -1; - } - } - for (int k = 1; cost[0] * k <= m; k++) { - dp[0][cost[0] * k] = k * value[0]; - } - for (int i = 1; i < n; i++) { - for (int j = 1; j <= m; j++) { - dp[i][j] = dp[i - 1][j]; - if (j - cost[i] >= 0 && dp[i][j - cost[i]] != -1) { - dp[i][j] = Math.max(dp[i][j], dp[i][j - cost[i]] + value[i]); - } - } - } - return dp; - } - -} diff --git a/公开课/class085/Code01_WhoWin21Balls.java b/公开课/class085/Code01_WhoWin21Balls.java deleted file mode 100644 index 36465be..0000000 --- a/公开课/class085/Code01_WhoWin21Balls.java +++ /dev/null @@ -1,100 +0,0 @@ -package class085; - -// 来自微众 -// 人工智能岗 -// 一开始有21个球,甲和乙轮流拿球,甲先、乙后 -// 每个人在自己的回合,一定要拿不超过3个球,不能不拿 -// 最终谁的总球数为偶数,谁赢 -// 请问谁有必胜策略 -public class Code01_WhoWin21Balls { - - // 球数balls,值一定要是奇数! - // 返回String,"甲","乙" - public static String whoWin(int balls) { - return process(0, balls, 0, 0); - } - - // turn,谁的回合,turn = 0 甲回合,turn = 1 乙回合 - // 还剩多少球,rest - // 之前甲已经拿了几个球,jia - // 之前乙已经拿了几个球,yi - // 之前,甲拿了jia个球,乙拿了yi个球 - // 当前,是谁的回合,turn告诉你! - // 还剩几个球呢?rest告诉你 - // 返回,最终谁赢! - public static String process(int turn, int rest, int jia, int yi) { - if (rest == 0) { - return jia % 2 == 0 ? "甲" : "乙"; - } - // rest > 0 还有球剩下 - if (turn == 0) { // 甲的回合 - // pick 当前甲要拿几个球 - for (int pick = 1; pick <= Math.min(3, rest); pick++) { - // pick 是甲当前的选择 - String next = process(1, rest - pick, jia + pick, yi); - if(next.equals("甲")) { - return "甲"; - } - } - return "乙"; - } else { // 乙的回合 - // pick 当前乙要拿几个球 - for (int pick = 1; pick <= Math.min(3, rest); pick++) { - // pick 是乙当前的选择 - String next = process(0, rest - pick, jia, yi + pick); - if(next.equals("乙")) { - return "乙"; - } - } - return "甲"; - } - } - -// // balls = 21 -// // ball是奇数 -// public static String win(int balls) { -// return process(0, balls, 0, 0); -// } -// -// // 憋递归! -// // turn 谁的回合! -// // turn == 0 甲回合 -// // turn == 1 乙回合 -// // rest剩余球的数量 -// // 之前,jiaBalls、yiBalls告诉你! -// // 当前,根据turn,知道是谁的回合! -// // 当前,还剩多少球,rest -// // 返回:谁会赢! -// public static String process(int turn, int rest, int jia, int yi) { -// if (rest == 0) { -// return (jia & 1) == 0 ? "甲" : "乙"; -// } -// // rest > 0, 还剩下球! -// if (turn == 0) { // 甲的回合! -// // 甲,自己赢!甲赢! -// for (int pick = 1; pick <= Math.min(rest, 3); pick++) { -// // pick 甲当前做的选择 -// if (process(1, rest - pick, jia + pick, yi).equals("甲")) { -// return "甲"; -// } -// } -// return "乙"; -// } else { -// for (int pick = 1; pick <= Math.min(rest, 3); pick++) { -// // pick 甲当前做的选择 -// if (process(0, rest - pick, jia, yi + pick).equals("乙")) { -// return "乙"; -// } -// } -// return "甲"; -// } -// } - - // 为了测试 - public static void main(String[] args) { - for (int balls = 1; balls <= 500; balls += 2) { - System.out.println("球数为 " + balls + " 时 , 赢的是 " + whoWin(balls)); - } - } - -} \ No newline at end of file diff --git a/公开课/class085/Code02_ShortestSubarrayWithSumAtLeastK.java b/公开课/class085/Code02_ShortestSubarrayWithSumAtLeastK.java deleted file mode 100644 index 99f411d..0000000 --- a/公开课/class085/Code02_ShortestSubarrayWithSumAtLeastK.java +++ /dev/null @@ -1,122 +0,0 @@ -package class085; - -// 来自字节跳动 -// 给定一个数组arr,其中的值有可能正、负、0 -// 给定一个正数k -// 返回累加和>=k的所有子数组中,最短的子数组长度 -// 本题测试链接 : https://leetcode.com/problems/shortest-subarray-with-sum-at-least-k/ -public class Code02_ShortestSubarrayWithSumAtLeastK { - -// public static int shortestLenSumNolessK(int[] arr, int k) { -// int ans = Integer.MAX_VALUE; -// Box box = new Box(arr.length); -// box.add(0, -1); -// int sum = 0; -// for (int i = 0; i < arr.length; i++) { -// sum += arr[i]; -// // sum : 0...i 整体累加和! -// int find = sum - k; -// // box中 <= find 的最右位置! -// int right = box.find(find); -// if(right != -2) { -// ans = Math.min(ans, i - right); -// } -// box.add(sum, i); -// } -// return ans == Integer.MAX_VALUE ? -1 : ans; -// } -// -// public static class Box { -// -// public Node[] help;// 搞长一些,n长度 -// int size; -// public Box(int n) { -// help = new Node[n]; -// size = 0; -// } -// -// // 0...right sum -// // 保持单调性去更新 -// public void add(int sum, int right) { -// -// } -// -// // 在box中<=aim的最右位置,返回 -// // 如果不存在,返回-2 -// // 二分去找! -// public int find(int aim) { -// -// } -// -// } -// -// public static class Node{ -// public int sum; -// public int right; -// } - - public static int shortestSubarray1(int[] arr, int k) { - if (arr == null || arr.length < 1) { - return -1; - } - int n = arr.length + 1; - long[] sum = new long[n]; - for (int i = 1; i < n; i++) { - sum[i] = sum[i - 1] + arr[i - 1]; - } - int[] stack = new int[n]; - int size = 1; - int ans = Integer.MAX_VALUE; - for (int i = 1; i < n; i++) { - int mostRight = mostRight(sum, stack, size, sum[i] - k); - ans = Math.min(ans, mostRight == -1 ? Integer.MAX_VALUE : (i - mostRight)); - while (size > 0 && sum[stack[size - 1]] >= sum[i]) { - size--; - } - stack[size++] = i; - } - return ans == Integer.MAX_VALUE ? -1 : ans; - } - - public static int mostRight(long[] sum, int[] stack, int size, long aim) { - int l = 0; - int r = size - 1; - int m = 0; - int ans = -1; - while (l <= r) { - m = (l + r) / 2; - if (sum[stack[m]] <= aim) { - ans = stack[m]; - l = m + 1; - } else { - r = m - 1; - } - } - return ans; - } - - public static int shortestSubarray2(int[] arr, int K) { - int N = arr.length; - long[] preSums = new long[N + 1]; - for (int i = 0; i < N; i++) { - preSums[i + 1] = preSums[i] + arr[i]; - } - int ans = Integer.MAX_VALUE; - int[] dq = new int[N + 1]; - int l = 0; - int r = 0; - for (int i = 0; i < N + 1; i++) { - // 从尾巴干掉,box里的记录! - while (l != r && preSums[dq[r - 1]] >= preSums[i]) { - r--; - } - // 从头部干掉,box里的记录 - while (l != r && preSums[i] - preSums[dq[l]] >= K) { - ans = Math.min(ans, i - dq[l++]); - } - dq[r++] = i; - } - return ans != Integer.MAX_VALUE ? ans : -1; - } - -} diff --git a/公开课/class086/Code01_TwoObjectMaxValue.java b/公开课/class086/Code01_TwoObjectMaxValue.java deleted file mode 100644 index 6d2c9b2..0000000 --- a/公开课/class086/Code01_TwoObjectMaxValue.java +++ /dev/null @@ -1,225 +0,0 @@ -package class086; - -import java.util.Arrays; - -// 来自字节 -// 5.6笔试 -// 给定N件物品,每个物品有重量(w[i])、有价值(v[i]) -// 只能最多选两件商品,重量不超过bag,返回价值最大能是多少? -// N <= 10^5, w[i] <= 10^5, v[i] <= 10^5, bag <= 10^5 -// 本题的关键点:什么数据范围都很大,唯独只需要最多选两件商品,这个可以利用一下 -public class Code01_TwoObjectMaxValue { - - // 暴力方法 - // 为了验证而写的方法 - public static int max1(int[] w, int[] v, int bag) { - return process1(w, v, 0, 2, bag); - } - - public static int process1(int[] w, int[] v, int index, int restNumber, int restWeight) { - if (restNumber < 0 || restWeight < 0) { - return -1; - } - if (index == w.length) { - return 0; - } - int p1 = process1(w, v, index + 1, restNumber, restWeight); - int p2 = -1; - int next = process1(w, v, index + 1, restNumber - 1, restWeight - w[index]); - if (next != -1) { - p2 = v[index] + next; - } - return Math.max(p1, p2); - } - - // 正式方法 - // 时间复杂度O(N * logN) - public static int max2(int[] w, int[] v, int bag) { - int n = w.length; - int[][] arr = new int[n][2]; - // [ [20,6], [14,8] , [3, 2] ] - for (int i = 0; i < n; i++) { - arr[i][0] = w[i]; - arr[i][1] = v[i]; - } - // 根据重量排序 - // [ [20,6], [14,8] , [3, 2] ] - // [ [3,2] 、[14,8] 、 [20,6] ] - Arrays.sort(arr, (a, b) -> (a[0] - b[0])); - // arr是二维数组,但是,只使用价值,不使用重量! - RMQ rmq = new RMQ(arr); - int ans = 0; - for (int i = 0, j = 1; i < n && arr[i][0] <= bag; i++, j++) { - int right = right(arr, bag - arr[i][0]) + 1; - int rest = 0; - // right:查询的和你搭配的货,的范围! - // j - if (right == j) { - rest = rmq.max(1, right - 1); - } else if (right < j) { - rest = rmq.max(1, right); - } else { - rest = Math.max(rmq.max(1, j - 1), rmq.max(j + 1, right)); - } - ans = Math.max(ans, arr[i][1] + rest); - } - return ans; - } - - public static int right(int[][] arr, int limit) { - int l = 0; - int r = arr.length - 1; - int m = 0; - int ans = -1; - while (l <= r) { - m = (l + r) / 2; - if (arr[m][0] <= limit) { - ans = m; - l = m + 1; - } else { - r = m - 1; - } - } - return ans; - } - - public static class RMQ { - public int[][] max; - - public RMQ(int[][] arr) { - // n = 16个数 - int n = arr.length; - // k = 4 - int k = power2(n); - // 行:1~n - // 列:0~4 - // 请注意: - // 数组来说,下标从0开始 - // 对于RMQ来说,下标从1开始 - max = new int[n + 1][k + 1]; - for (int i = 1; i <= n; i++) { - max[i][0] = arr[i - 1][1]; - } - for (int j = 1; (1 << j) <= n; j++) { - for (int i = 1; i + (1 << j) - 1 <= n; i++) { - max[i][j] = Math.max(max[i][j - 1], max[i + (1 << (j - 1))][j - 1]); - } - } - } - - public int max(int l, int r) { - if (r < l) { - return 0; - } - int k = power2(r - l + 1); - return Math.max(max[l][k], max[r - (1 << k) + 1][k]); - } - - // 求2的几次方,离m最近,又不超过m - private int power2(int m) { - int ans = 0; - while ((1 << ans) <= (m >> 1)) { - ans++; - } - return ans; - } - - } - - - - public static class RMQZuo { - public int[][] max;// 如果传入的数组长度是N,max大小:N*logN大小 - - public RMQZuo(int[] arr) { - // n = 16个数 - int n = arr.length; - // k = 4 - int k = power2(n); - // 行:1~n - // 列:0~4 - // 请注意: - // 数组来说,下标从0开始 - // 对于RMQ来说,下标从1开始 - max = new int[n + 1][k + 1]; - for (int i = 1; i <= n; i++) { - max[i][0] = arr[i-1]; - } - for (int j = 1; (1 << j) <= n; j++) { - for (int i = 1; i + (1 << j) - 1 <= n; i++) { - // 10....8(2的3次方) - // 10...4 14...4 - - - // max[10][3] = ? - // max[10][2] 10...2的2次方个数(4个) - // i + (1 << (j - 1)) -> 10 + 4 -> 14...2的2次方个数(4个) - - max[i][j] = - Math.max(max[i][j - 1], - max[i + (1 << (j - 1))][j - 1]); - } - } - } - - // O(1) - public int max(int l, int r) { - if (r < l) { - return 0; - } - int k = power2(r - l + 1); - // l....r - // r - l + 1有几个数?2的k次方,离这个个数,最近,且不超过 - // l.... ?....r - // l...r -> 3...11 - // 11 - 3 + 1 = 9 - // 2的3次方 = 8 <= 9 - // k = 3 - // l...2的3次方个数: max[l][k] - // r - (1 << k) + 1 - // 11 - 8 + 1 -> 4 - return Math.max(max[l][k], max[r - (1 << k) + 1][k]); - } - - // 求2的几次方,离m最近,又不超过m - private int power2(int m) { - int ans = 0; - while ((1 << ans) <= (m >> 1)) { - ans++; - } - return ans; - } - - } - - // 为了测试 - public static int[] randomArray(int n, int v) { - int[] arr = new int[n]; - for (int i = 0; i < n; i++) { - arr[i] = (int) (Math.random() * v); - } - return arr; - } - - // 为了测试 - public static void main(String[] args) { - int N = 12; - int V = 20; - int testTimes = 5000; - System.out.println("测试开始"); - for (int i = 0; i < testTimes; i++) { - int n = (int) (Math.random() * N) + 1; - int[] w = randomArray(n, V); - int[] v = randomArray(n, V); - int bag = (int) (Math.random() * V * 3); - int ans1 = max1(w, v, bag); - int ans2 = max2(w, v, bag); - if (ans1 != ans2) { - System.out.println("出错了!"); - break; - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class086/Code02_ModifyOneNumberModXWays.java b/公开课/class086/Code02_ModifyOneNumberModXWays.java deleted file mode 100644 index b8fa3ea..0000000 --- a/公开课/class086/Code02_ModifyOneNumberModXWays.java +++ /dev/null @@ -1,84 +0,0 @@ -package class086; - -// 来自网易 -// 小红拿到了一个长度为N的数组arr,她准备只进行一次修改 -// 可以将数组中任意一个数arr[i],修改为不大于P的正数(修改后的数必须和原数不同) -// 并使得所有数之和为X的倍数 -// 小红想知道,一共有多少种不同的修改方案 -// 1 <= N, X <= 10^5 -// 1 <= arr[i], P <= 10^9 -public class Code02_ModifyOneNumberModXWays { - - public static int ways1(int[] arr, int p, int x) { - long sum = 0; - for (int num : arr) { - sum += num; - } - int ans = 0; - for (int num : arr) { - sum -= num; - for (int v = 1; v <= p; v++) { - if (v != num) { - if ((sum + v) % x == 0) { - ans++; - } - } - } - sum += num; - } - return ans; - } - - public static int ways2(int[] arr, int p, int x) { - long sum = 0; - for (int num : arr) { - sum += num; - } - int ans = 0; - for (int num : arr) { - ans += cnt(p, x, num, (x - (int) ((sum - num) % x)) % x); - } - return ans; - } - - // 当前数字num - // 1~p以内,不能是num的情况下,% x == mod的数字有几个 - // O(1) - public static int cnt(int p, int x, int num, int mod) { - // p/x 至少有几个 - // (p % x) >= mod ? 1 : 0 - // 在不考虑变出来的数,是不是num的情况下,算一下有几个数,符合要求 - int ans = (p / x) + ((p % x) >= mod ? 1 : 0) - (mod == 0 ? 1 : 0); - // 不能等于num! - return ans - ((num <= p && num % x == mod) ? 1 : 0); - } - - // 为了测试 - public static int[] randomArray(int n, int v) { - int[] ans = new int[n]; - for (int i = 0; i < n; i++) { - ans[i] = (int) (Math.random() * v) + 1; - } - return ans; - } - - public static void main(String[] args) { - int len = 100; - int value = 100; - int testTime = 100000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int n = (int) (Math.random() * len) + 1; - int[] arr = randomArray(n, value); - int p = (int) (Math.random() * value) + 1; - int x = (int) (Math.random() * value) + 1; - int ans1 = ways1(arr, p, x); - int ans2 = ways2(arr, p, x); - if (ans1 != ans2) { - System.out.println("出错了!"); - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class086/Code03_BattleshipsInABoard.java b/公开课/class086/Code03_BattleshipsInABoard.java deleted file mode 100644 index a96ff73..0000000 --- a/公开课/class086/Code03_BattleshipsInABoard.java +++ /dev/null @@ -1,21 +0,0 @@ -package class086; - -// 来自米哈游 -// 测试链接 : https://leetcode.com/problems/battleships-in-a-board/ -public class Code03_BattleshipsInABoard { - - public static int countBattleships(char[][] m) { - int ans = 0; - for (int i = 0; i < m.length; i++) { - for (int j = 0; j < m[0].length; j++) { - if ((m[i][j] == 'X') - && (i == 0 || m[i - 1][j] != 'X') - && (j == 0 || m[i][j - 1] != 'X')) { - ans++; - } - } - } - return ans; - } - -} diff --git a/公开课/class086/Code04_BrickAll.java b/公开课/class086/Code04_BrickAll.java deleted file mode 100644 index 9c5c62a..0000000 --- a/公开课/class086/Code04_BrickAll.java +++ /dev/null @@ -1,50 +0,0 @@ -package class086; - -import java.util.Arrays; - -// 来自华为 -// 给定一个正数数组arr,其中每个值代表砖块长度 -// 所有砖块等高等宽,只有长度有区别 -// 每一层可以用1块或者2块砖来摆 -// 要求每一层的长度一样 -// 要求必须使用所有的砖块 -// 请问最多摆几层 -// 如果无法做到,返回-1 -public class Code04_BrickAll { - - public static int maxLevels(int[] arr) { - if (arr == null) { - return 0; - } - int n = arr.length; - if (n < 2) { - return n; - } - Arrays.sort(arr); - int p1 = levels(arr, arr[n - 1]); - int p2 = levels(arr, arr[n - 1] + arr[0]); - return Math.max(p1, p2); - } - - // 要求所有砖必须都使用,并且每一层最多两块砖,并且每一层长度都是len - // 返回能摆几层,如果无法做到返回-1 - public static int levels(int[] arr, int len) { - int ans = 0; - int L = 0; - int R = arr.length - 1; - while (L <= R) { - if (arr[R] == len) { - R--; - ans++; - } else if (L < R && arr[L] + arr[R] == len) { - L++; - R--; - ans++; - } else { - return -1; - } - } - return ans; - } - -} diff --git a/公开课/class087/Code01_RedAndWhiteSquares.java b/公开课/class087/Code01_RedAndWhiteSquares.java deleted file mode 100644 index 18294d6..0000000 --- a/公开课/class087/Code01_RedAndWhiteSquares.java +++ /dev/null @@ -1,211 +0,0 @@ -package class087; - -// 来自网易 -// 小红拿到了一个大立方体,该大立方体由1*1*1的小方块拼成,初始每个小方块都是白色。 -// 小红可以每次选择一个小方块染成红色 -// 每次小红可能选择同一个小方块重复染色 -// 每次染色以后,你需要帮小红回答出当前的白色连通块数 -// 如果两个小方块共用同一个面,且颜色相同,则它们是连通的 -// 给定n、m、h,表示大立方体的长、宽、高 -// 给定k次操作,每一次操作用(a, b, c)表示在大立方体的该位置进行染色 -// 返回长度为k的数组,表示每一次操作后,白色方块的连通块数 -// n * m * h <= 10 ^ 5,k <= 10 ^ 5 -public class Code01_RedAndWhiteSquares { - - // 暴力方法 - // 时间复杂度(k * n * m * h); - public static int[] blocks1(int n, int m, int h, int[][] ops) { - int k = ops.length; - int[][][] cube = new int[n][m][h]; - int value = 1; - int[] ans = new int[k]; - for (int i = 0; i < k; i++) { - cube[ops[i][0]][ops[i][1]][ops[i][2]] = -1; - for (int x = 0; x < n; x++) { - for (int y = 0; y < m; y++) { - for (int z = 0; z < h; z++) { - if (cube[x][y][z] != -1 && cube[x][y][z] != value) { - ans[i]++; - infect(cube, x, y, z, value); - } - } - } - } - value++; - } - return ans; - } - - public static void infect(int[][][] cube, int a, int b, int c, int change) { - if (a < 0 || a == cube.length || b < 0 || b == cube[0].length || c < 0 || c == cube[0][0].length - || cube[a][b][c] == -1 || cube[a][b][c] == change) { - return; - } - cube[a][b][c] = change; - infect(cube, a - 1, b, c, change); - infect(cube, a + 1, b, c, change); - infect(cube, a, b - 1, c, change); - infect(cube, a, b + 1, c, change); - infect(cube, a, b, c - 1, change); - infect(cube, a, b, c + 1, change); - } - - // 最优解 - // O(k + n * m * h) - public static int[] blocks2(int n, int m, int h, int[][] ops) { - int k = ops.length; - int[][][] red = new int[n][m][h]; - for (int[] op : ops) { - red[op[0]][op[1]][op[2]]++; - } - UnionFind uf = new UnionFind(n, m, h, red); - int[] ans = new int[k]; - for (int i = k - 1; i >= 0; i--) { - ans[i] = uf.sets; - int x = ops[i][0]; - int y = ops[i][1]; - int z = ops[i][2]; - if (--red[x][y][z] == 0) { - // x, y ,z 这个格子,变白,建立自己的小集合 - // 然后6个方向,集合该合并合并 - uf.finger(x, y, z); - } - } - return ans; - } - - public static class UnionFind { - public int n; - public int m; - public int h; - public int[] father; - public int[] size; - public int[] help; - public int sets; - - public UnionFind(int a, int b, int c, int[][][] red) { - n = a; - m = b; - h = c; - int len = n * m * h; - father = new int[len]; - size = new int[len]; - help = new int[len]; - for (int x = 0; x < n; x++) { - for (int y = 0; y < m; y++) { - for (int z = 0; z < h; z++) { - if (red[x][y][z] == 0) { - finger(x, y, z); - } - } - } - } - } - - public void finger(int x, int y, int z) { - // x,y,z - // 一维数值 - int i = index(x, y, z); - father[i] = i; - size[i] = 1; - sets++; - union(i, x - 1, y, z); - union(i, x + 1, y, z); - union(i, x, y - 1, z); - union(i, x, y + 1, z); - union(i, x, y, z - 1); - union(i, x, y, z + 1); - } - - private int index(int x, int y, int z) { - return z * n * m + y * n + x; - } - - private void union(int i, int x, int y, int z) { - if (x < 0 || x == n || y < 0 || y == m || z < 0 || z == h) { - return; - } - int j = index(x, y, z); - if (size[j] == 0) { - return; - } - i = find(i); - j = find(j); - if (i != j) { - if (size[i] >= size[j]) { - father[j] = i; - size[i] += size[j]; - } else { - father[i] = j; - size[j] += size[i]; - } - sets--; - } - } - - private int find(int i) { - int s = 0; - while (i != father[i]) { - help[s++] = i; - i = father[i]; - } - while (s > 0) { - father[help[--s]] = i; - } - return i; - } - - } - - // 为了测试 - public static int[][] randomOps(int n, int m, int h) { - int size = (int) (Math.random() * (n * m * h)) + 1; - int[][] ans = new int[size][3]; - for (int i = 0; i < size; i++) { - ans[i][0] = (int) (Math.random() * n); - ans[i][1] = (int) (Math.random() * m); - ans[i][2] = (int) (Math.random() * h); - } - return ans; - } - - // 为了测试 - public static void main(String[] args) { - int size = 10; - int testTime = 5000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int n = (int) (Math.random() * size) + 1; - int m = (int) (Math.random() * size) + 1; - int h = (int) (Math.random() * size) + 1; - int[][] ops = randomOps(n, m, h); - int[] ans1 = blocks1(n, m, h, ops); - int[] ans2 = blocks2(n, m, h, ops); - for (int j = 0; j < ops.length; j++) { - if (ans1[j] != ans2[j]) { - System.out.println("出错了!"); - } - } - } - System.out.println("测试结束"); - - // 立方体达到10^6规模 - int n = 100; - int m = 100; - int h = 100; - int len = n * m * h; - // 操作条数达到10^6规模 - int[][] ops = new int[len][3]; - for (int i = 0; i < len; i++) { - ops[i][0] = (int) (Math.random() * n); - ops[i][1] = (int) (Math.random() * m); - ops[i][2] = (int) (Math.random() * h); - } - long start = System.currentTimeMillis(); - blocks2(n, m, h, ops); - long end = System.currentTimeMillis(); - System.out.println("运行时间(毫秒) : " + (end - start)); - - } - -} diff --git a/公开课/class087/Code02_MaxNumberUnderLimit.java b/公开课/class087/Code02_MaxNumberUnderLimit.java deleted file mode 100644 index 9d113e1..0000000 --- a/公开课/class087/Code02_MaxNumberUnderLimit.java +++ /dev/null @@ -1,203 +0,0 @@ -package class087; - -import java.util.Arrays; - -// 来自字节 -// 输入: -// 去重数组arr,里面的数只包含0~9 -// limit,一个数字 -// 返回: -// 要求比limit小的情况下,能够用arr拼出来的最大数字 -public class Code02_MaxNumberUnderLimit { - - public static int tmp = 0; - - // 暴力尝试的方法 - public static int maxNumber1(int[] arr, int limit) { - tmp = 0; - Arrays.sort(arr); - limit--; - int offset = 1; - while (offset <= limit / 10) { - offset *= 10; - } - process1(arr, 0, offset, limit); - if (tmp == 0) { - int rest = 0; - offset /= 10; - while (offset > 0) { - rest += arr[arr.length - 1] * offset; - offset /= 10; - } - return rest; - } - return tmp; - } - - public static void process1(int[] arr, int num, int offset, int limit) { - if (offset == 0) { - if (num <= limit) { - tmp = Math.max(tmp, num); - } - } else { - for (int cur : arr) { - process1(arr, num * 10 + cur, offset / 10, limit); - } - } - } - - // 正式方法 - public static int maxNumber2(int[] arr, int limit) { - // arr里面是不重复的数字,且只包含0~9 - // 5, 8 , 2 - // 2, 5, 8 - Arrays.sort(arr); - limit--; - // <= limit 且最大的数字 - // 68886 - // 10000 - // 为了取数而设计的! - // 457 - // 100 - int offset = 1; - while (offset <= limit / 10) { - offset *= 10; - } - // arr, 2 5 8 - // limit--, 试图去追平的数字 - // offset, 扣出limit中每一位的数字! - // 可以使用arr中的数字,期望得到尽可能接近limit的结果,并且位数一样 - // 能做到,返回的结果就是答案 - // 如果做不到和limit位数一样!返回-1 - int ans = process2(arr, limit, offset); - if (ans != -1) { - return ans; - } else { // ans = -1 一定要减少位数,才能做到 - offset /= 10; - int rest = 0; - while (offset > 0) { - rest += arr[arr.length - 1] * offset; - offset /= 10; - } - return rest; - } - } - - // 可以选哪些数字,都在arr里,arr是有序的,[2,5,8] - // limit : <= limit 且尽量的大! - // offset : 为limit服务的,就是为了提取limit的每一位数字 - public static int process2(int[] arr, int limit, int offset) { - // offset 1000 100 10 1 0 - // offset == 0,意味着,之前的数字,全都可以追平,返回limit - // 之前的数字和limit完全一样,且limit所有数字都一样 - if (offset == 0) { - return limit; - } - // limit中还有数字,没遍历到, - // (limit / offset) % 10 - // 当前数字是谁,提取出来 - int cur = (limit / offset) % 10; - - // 2 5 8 - // <=4 - // 2 ....8888 - int near = near(arr, cur); - if (near == -1) { - return -1; - } else if (arr[near] == cur) { // 找出来的数字,真的和当前数字cur一样! - // 当前位,追平了! - // 看看后续能不能走的通! - int ans = process2(arr, limit, offset / 10); - // 1) 走通了! - // 2) 走不通, - // A :当前位还有下降的空间! - // B :当前位没有下降的空间! - if (ans != -1) { - return ans; - } else if (near > 0) { // 虽然后续没成功,但是我自己还能下降!还能选更小的数字 - near--; - return (limit / (offset * 10)) * offset * 10 + (arr[near] * offset) + rest(arr, offset / 10); - } else { // 后续没成功,我自己也不能再下降了!宣告失败,往上返回! - return -1; - } - } else { // arr[near] < cur - return (limit / (offset * 10)) * offset * 10 + (arr[near] * offset) + rest(arr, offset / 10); - } - } - - // 比如offset = 100 - // 一共3位数 - // 那么就把arr中最大的数字x,拼成xxx,返回 - // 比如offset = 10000 - // 一共5位数 - // 那么就把arr中最大的数字x,拼成xxxxx,返回 - public static int rest(int[] arr, int offset) { - int rest = 0; - while (offset > 0) { - rest += arr[arr.length - 1] * offset; - offset /= 10; - } - return rest; - } - - // 在有序数组arr中,找到<=num,且最大的数字,在arr中的位置返回 - // 如果所有数字都大于num,返回-1 - // [3,6,9] num = 4 3 - // [5,7,9] num = 4 -1 - public static int near(int[] arr, int num) { - int l = 0; - int r = arr.length - 1; - int m = 0; - int near = -1; - while (l <= r) { - m = (l + r) / 2; - if (arr[m] <= num) { - near = m; - l = m + 1; - } else { - r = m - 1; - } - } - return near; - } - - // 为了测试 - public static int[] randomArray() { - int[] arr = new int[(int) (Math.random() * 10) + 1]; - boolean[] cnt = new boolean[10]; - for (int i = 0; i < arr.length; i++) { - do { - arr[i] = (int) (Math.random() * 10); - } while (cnt[arr[i]]); - cnt[arr[i]] = true; - } - return arr; - } - - public static void main(String[] args) { - int max = 3000; - int testTime = 100; - System.out.println("测试开始"); - for (int i = 0; i < max; i++) { - int[] arr = randomArray(); - for (int j = 0; j < testTime; j++) { - int ans1 = maxNumber1(arr, i); - int ans2 = maxNumber2(arr, i); - if (ans1 != ans2) { - System.out.println("出错了!"); - System.out.println("数组为 :"); - for (int num : arr) { - System.out.print(num + " "); - } - System.out.println(); - System.out.println("数字为 :" + i); - System.out.println(ans1); - System.out.println(ans2); - } - } - } - System.out.println("测试结束"); - - } - -} diff --git a/公开课/class087/Code03_NumberOfCannon.java b/公开课/class087/Code03_NumberOfCannon.java deleted file mode 100644 index 0be0f9e..0000000 --- a/公开课/class087/Code03_NumberOfCannon.java +++ /dev/null @@ -1,104 +0,0 @@ -package class087; - -import java.util.TreeMap; - -// 来自学员问题 -// 给定一个数组arr,表示从早到晚,依次会出现的导弹的高度 -// 大炮打导弹的时候,如果一旦大炮定了某个高度去打,那么这个大炮每次打的高度都必须下降一点 -// 1) 如果只有一个大炮,返回最多能拦截多少导弹 -// 2) 如果所有的导弹都必须拦截,返回最少的大炮数量 -public class Code03_NumberOfCannon { - - public static int numOfCannon(int[] arr) { - // key : 某个大炮打的结尾数值 - // value : 有多少个大炮有同样的结尾数值 - // 比如: - // 一共有A、B、C三个大炮 - // 如果A大炮此时打的高度是17,B大炮此时打的高度是7,C大炮此时打的高度是13 - // 那么在表中: - // 7, 1 - // 13, 1 - // 17, 1 - // 如果A大炮此时打的高度是13,B大炮此时打的高度是7,C大炮此时打的高度是13 - // 那么在表中: - // 7, 1 - // 13, 2 - TreeMap ends = new TreeMap<>(); - for (int num : arr) { - if (ends.ceilingKey(num + 1) == null) { - ends.put(Integer.MAX_VALUE, 1); - } - int ceilKey = ends.ceilingKey(num + 1); - if (ends.get(ceilKey) > 1) { - ends.put(ceilKey, ends.get(ceilKey) - 1); - } else { - ends.remove(ceilKey); - } - ends.put(num, ends.getOrDefault(num, 0) + 1); - } - int ans = 0; - for (int value : ends.values()) { - ans += value; - } - return ans; - } - - public static void main(String[] args) { - - // orderedMap C++ - TreeMap map = new TreeMap<>(); - map.put(1, "我是1"); - map.put(5, "我是5"); - map.put(50, "我是50"); - map.remove(5); - - System.out.println(map.get(5)); - - // 查 >= 15 , 并且离15最近的key - System.out.println(map.ceilingKey(55)); - - // 查 <= 15 - System.out.println(map.floorKey(15)); - - // put、get、remove、ceilingKey、floorKey - // 时间复杂度O(log N) - // TreeMap,key是Integer,去重的! - - // key : 大炮来到的高度,<=key以下高度的导弹 - // value : 这样高度的大炮有几门 - TreeMap cannonMap = new TreeMap(); - - // A : 80 B :80 C : 80 D : 20 - // 80 : 3 - // 20 : 1 - // 假设map中有一些大炮, - int h = 100; - // >= 100,的key存在? - if (cannonMap.ceilingKey(h) == null) { // 没有能打100高度的 - // 新开一门炮,100消灭!99 - if (cannonMap.containsKey(h - 1)) { - cannonMap.put(h - 1, cannonMap.get(h - 1) + 1); - } else { - cannonMap.put(h - 1, 1); - } - } else { // 有能打100高度的 - // 100 110 99 - int cannonH = cannonMap.ceilingKey(h); - if(cannonMap.get(cannonH) == 1) { - cannonMap.remove(cannonH); - }else { - cannonMap.put(cannonH , cannonMap.get(cannonH) - 1); - } - if (cannonMap.containsKey(h - 1)) { - cannonMap.put(h - 1, cannonMap.get(h - 1) + 1); - } else { - cannonMap.put(h - 1, 1); - } - } - - - // map ,values 累加 返回~ - - } - -} diff --git a/公开课/class088/Code01_FourNumbersMinusOne.java b/公开课/class088/Code01_FourNumbersMinusOne.java deleted file mode 100644 index 3f84bb4..0000000 --- a/公开课/class088/Code01_FourNumbersMinusOne.java +++ /dev/null @@ -1,74 +0,0 @@ -package class088; - -import java.util.Arrays; - -// 来自阿里笔试 -// 牛牛今年上幼儿园了,老师叫他学习减法 -// 老师给了他5个数字,他每次操作可以选择其中的4个数字减1 -// 减一之后的数字不能小于0,因为幼儿园的牛牛还没有接触过负数 -// 现在牛牛想知道,自己最多可以进行多少次这样的操作 -// 扩展问题来自leetcode 2141,掌握了这个题原始问题就非常简单了 -// leetcode测试链接 : https://leetcode.com/problems/maximum-running-time-of-n-computers/ -public class Code01_FourNumbersMinusOne { - - // n,电脑台数 - // arr,所有的电池 - public static long maxRunTime(int n, int[] arr) { - // 电量排个序 - // 2, 3, 5, 15, 23... - // 2, 5,10, 25, 48 - Arrays.sort(arr); - int size = arr.length; - long[] sums = new long[size]; - sums[0] = arr[0]; - for (int i = 1; i < size; i++) { - sums[i] = sums[i - 1] + arr[i]; - } - // 答案的范围,定好,因为要二分,最大流程! - // 所有电量加起来,1000,电脑有10台。 - // 0 ~ 100 - long l = 0; - long m = 0; - long r = sums[size - 1] / n; - long ans = -1; - while (l <= r) { - m = (l + r) / 2; - if (ok(arr, sums, m, n)) { - ans = m; - l = m + 1; - } else { - r = m - 1; - } - } - return ans; - } - - // 电池数组arr,前缀和数组sum - // 撑够的分钟数:time - // 几台电脑:num - // 返回:能不能做到! - public static boolean ok(int[] arr, long[] sum, long time, int num) { - int l = 0; - int m = 0; - int r = arr.length - 1; - int left = arr.length; - // 20分钟 - // arr,有序的! - // >=20分钟,有几块电池!7块 - // 电脑有10台,7台,3台(碎片电池去搞定!< 20) - // >= time 最左 - while (l <= r) { - m = (l + r) / 2; - if (arr[m] >= time) { - left = m; - r = m - 1; - } else { - l = m + 1; - } - } - num -= arr.length - left; - long rest = left == 0 ? 0 : sum[left - 1]; - return time * (long) num <= rest; - } - -} diff --git a/公开课/class088/Code02_MinWaitingTime.java b/公开课/class088/Code02_MinWaitingTime.java deleted file mode 100644 index 275b8f0..0000000 --- a/公开课/class088/Code02_MinWaitingTime.java +++ /dev/null @@ -1,97 +0,0 @@ -package class088; - -import java.util.PriorityQueue; - -// 来自谷歌 -// 给定一个数组arr,长度为n -// 表示n个服务员,每个人服务一个人的时间 -// 给定一个正数m,表示有m个人等位 -// 如果你是刚来的人,请问你需要等多久? -// 假设:m远远大于n,比如n<=1000, m <= 10的9次方,该怎么做? -public class Code02_MinWaitingTime { - - // 堆!堆模拟!方法1! - public static int minWaitingTime1(int[] arr, int m) { - if (arr == null || arr.length == 0) { - return -1; - } - PriorityQueue heap = new PriorityQueue<>((a, b) -> (a[0] - b[0])); - int n = arr.length; - for (int i = 0; i < n; i++) { - heap.add(new int[] { 0, arr[i] }); - } - for (int i = 0; i < m; i++) { - int[] cur = heap.poll(); - cur[0] += cur[1]; - heap.add(cur); - } - return heap.peek()[0]; - } - - // 二分答案! - public static int minWaitingTime2(int[] arr, int m) { - if (arr == null || arr.length == 0) { - return -1; - } - int best = Integer.MAX_VALUE; - for (int num : arr) { - best = Math.min(best, num); - } - int left = 0; - int right = best * m; - int mid = 0; - int near = 0; - while (left <= right) { - mid = (left + right) / 2; - int cover = 0; - for (int num : arr) { - cover += (mid / num) + 1; - } - if (cover >= m + 1) { - near = mid; - right = mid - 1; - } else { - left = mid + 1; - } - } - return near; - } - - // 为了测试 - public static int[] randomArray(int n, int v) { - int[] arr = new int[n]; - for (int i = 0; i < n; i++) { - arr[i] = (int) (Math.random() * v) + 1; - } - return arr; - } - - // 为了测试 - public static void main(String[] args) { - int len = 50; - int value = 30; - int mMax = 3000; - int testTime = 20000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int n = (int) (Math.random() * len) + 1; - int[] arr = randomArray(n, value); - int m = (int) (Math.random() * mMax); - int ans1 = minWaitingTime1(arr, m); - int ans2 = minWaitingTime2(arr, m); - if (ans1 != ans2) { - System.out.println("出错了!"); - for (int num : arr) { - System.out.print(num + " "); - } - System.out.println(); - System.out.println("m : " + m); - System.out.println(ans1); - System.out.println(ans2); - break; - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class088/Code03_UniqueSubstringsInWraparoundString.java b/公开课/class088/Code03_UniqueSubstringsInWraparoundString.java deleted file mode 100644 index e456add..0000000 --- a/公开课/class088/Code03_UniqueSubstringsInWraparoundString.java +++ /dev/null @@ -1,34 +0,0 @@ -package class088; - -// 把字符串 s 看作 "abcdefghijklmnopqrstuvwxyz" 的无限环绕字符串, -// 所以 s 看起来是这样的: -// ...zabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd.... -// 现在给定另一个字符串 p 。返回 s 中 不同 的 p 的 非空子串 的数量 -// 测试链接 : https://leetcode.com/problems/unique-substrings-in-wraparound-string/ -public class Code03_UniqueSubstringsInWraparoundString { - - public int findSubstringInWraproundString(String s) { - char[] str = s.toCharArray(); - int n = str.length; - int ans = 0; - int len = 1; - // 256 0~255 - int[] max = new int[256]; - max[str[0]]++; - for (int i = 1; i < n; i++) { - char cur = str[i]; - char pre = str[i - 1]; - if ((pre == 'z' && cur == 'a') || pre + 1 == cur) { - len++; - } else { - len = 1; - } - max[cur] = Math.max(max[cur], len); - } - for (int i = 0; i < 256; i++) { - ans += max[i]; - } - return ans; - } - -} diff --git a/公开课/class089/Code01_MostStonesRemovedWithSameRowOrColumn.java b/公开课/class089/Code01_MostStonesRemovedWithSameRowOrColumn.java deleted file mode 100644 index 2de73c5..0000000 --- a/公开课/class089/Code01_MostStonesRemovedWithSameRowOrColumn.java +++ /dev/null @@ -1,95 +0,0 @@ -package class089; - -import java.util.HashMap; - -// n块石头放置在二维平面中的一些整数坐标点上 -// 每个坐标点上最多只能有一块石头 -// 如果一块石头的 同行或者同列 上有其他石头存在,那么就可以移除这块石头。 -// 给你一个长度为 n 的数组 stones , -// 其中 stones[i] = [xi, yi] 表示第 i 块石头的位置, -// 返回 可以移除的石子 的最大数量。 -// 测试链接 : https://leetcode.com/problems/most-stones-removed-with-same-row-or-column/ -public class Code01_MostStonesRemovedWithSameRowOrColumn { - - // stones[i] = [a,b] i号石子,行所在a行,列所在b列 - public static int removeStones(int[][] stones) { - // n,石子数量 - int n = stones.length; - // 100万行,A石子,第17个石子 - // 100万(key) 17 - HashMap rowPre = new HashMap(); - // 200万列 R石子,第105个石子 - // 200万(key) 105 - HashMap colPre = new HashMap(); - // 并查集,n个石子,一开始都在各自的集合里! - UnionFind uf = new UnionFind(n); - for (int i = 0; i < n; i++) { // 遍历石子 - // 当前石子,i号,行 x 列 y - int x = stones[i][0]; - int y = stones[i][1]; - if (!rowPre.containsKey(x)) { - rowPre.put(x, i); - } else { - uf.union(i, rowPre.get(x)); - } - if (!colPre.containsKey(y)) { - colPre.put(y, i); - } else { - uf.union(i, colPre.get(y)); - } - } - return n - uf.sets(); - } - - public static class UnionFind { - - public int[] father; - public int[] size; - public int[] help; - public int sets; - - public UnionFind(int n) { - father = new int[n]; - size = new int[n]; - help = new int[n]; - for (int i = 0; i < n; i++) { - father[i] = i; - size[i] = 1; - } - sets = n; - } - - private int find(int i) { - int hi = 0; - while (i != father[i]) { - help[hi++] = i; - i = father[i]; - } - while (hi != 0) { - father[help[--hi]] = i; - } - return i; - } - - public void union(int i, int j) { - int fi = find(i); - int fj = find(j); - if (fi != fj) { - if (size[fi] >= size[fj]) { - father[fj] = fi; - size[fi] += size[fj]; - } else { - father[fi] = fj; - size[fj] += size[fi]; - } - sets--; - } - } - - public int sets() { - return sets; - } - - } - -} diff --git a/公开课/class089/Code02_ReachingPoints.java b/公开课/class089/Code02_ReachingPoints.java deleted file mode 100644 index 7e501d9..0000000 --- a/公开课/class089/Code02_ReachingPoints.java +++ /dev/null @@ -1,49 +0,0 @@ -package class089; - -// 测试链接 : https://leetcode.com/problems/reaching-points/ -public class Code02_ReachingPoints { - - // 会超时,但是揭示了大思路 - public static boolean reachingPoints1(int sx, int sy, int tx, int ty) { - while (tx != ty) { - if (tx < ty) { - ty -= tx; - } else { - tx -= ty; - } - if (sx == tx && sy == ty) { - return true; - } - } - return false; - } - - // 对大体思路的优化 - // s ( 5, 10) - // t (100, 65) - public static boolean reachingPoints2(int sx, int sy, int tx, int ty) { - // sx 出发点的x - // sy 出发点的y - // tx 目标点的x - // ty 目标点的y - // sx < tx 同时 sy < ty - // x和y,出发点都小才跳! - while (sx < tx && sy < ty) { - // tx ty 谁大,谁去%,然后用余数替换大数! - if (tx < ty) { - ty %= tx; - } else { - tx %= ty; - } - } - // 1) sx == tx 跳出来! - // 2) sy == ty 跳出来! - // 除此之外的所有,都认为返回false - // 什么情况下,会返回true - // 1) (sx == tx && sy <= ty && (ty - sy) % sx == 0) - // 2) (sy == ty && sx <= tx && (tx - sx) % sy == 0) - // false! - return (sx == tx && sy <= ty && (ty - sy) % sx == 0) || (sy == ty && sx <= tx && (tx - sx) % sy == 0); - } - -} diff --git a/公开课/class089/Code03_NumberOfDifferentSubsequencesGCDs.java b/公开课/class089/Code03_NumberOfDifferentSubsequencesGCDs.java deleted file mode 100644 index daf0d8f..0000000 --- a/公开课/class089/Code03_NumberOfDifferentSubsequencesGCDs.java +++ /dev/null @@ -1,64 +0,0 @@ -package class089; - -// 给你一个由正整数组成的数组 nums 。 -// 数字序列的 最大公约数 定义为序列中所有整数的共有约数中的最大整数。 -// 例如,序列 [4,6,16] 的最大公约数是 2 。 -// 数组的一个 子序列 本质是一个序列,可以通过删除数组中的某些元素(或者不删除)得到。 -// 例如,[2,5,10] 是 [1,2,1,2,4,1,5,10] 的一个子序列。 -// 计算并返回 nums 的所有 非空 子序列中 不同 最大公约数的 数目 。 -// 测试链接 : https://leetcode.com/problems/number-of-different-subsequences-gcds/ -public class Code03_NumberOfDifferentSubsequencesGCDs { - - // n不是数字的个数,是数组中的最大值 - // 体系学习班, - // 根据数据量猜解法, - // 要想通过测试,一定要让计算量不超过10的7次方~10的8次方 - // n/1 + n/2 + n/3 + n/4 + ... + n/n -> O(N * logN) - public static int countDifferentSubsequenceGCDs(int[] nums) { - // 找到数组中的最大数!max - int max = Integer.MIN_VALUE; - for (int num : nums) { - max = Math.max(max, num); - } - // 1~max,哪个数有哪个数没有 - boolean[] set = new boolean[max + 1]; - for (int num : nums) { - set[num] = true; - } - // 最终要返回的答案,所有子序列的不同最大公约数个数! - int ans = 0; - // a是当前想确定,是不是某个子序列的最大公约数,有a! - // 1 2 3 4 5 ... max - for (int a = 1; a <= max; a++) { - // a - // 1)找到,离a最近的,a的倍数!在数组中存在的! - int g = a; - for (; g <= max; g += a) { - if (set[g]) { - break; - } - } - // 2) 找到了离a最近的、a的倍数!是g - // g g(存在!) 最大公约数,是不是a,是,结束了!ans+1 - // g g + a(存在!) 最大公约数,是不是a,是,结束了!ans+1 - // g g + 2a(存在!) 最大公约数,是不是a,是,结束了!ans+1 - // g g + 3a(存在!) 最大公约数,是不是a,是,结束了!ans+1 - // g g + 4a(存在!) 最大公约数,是不是a,是,结束了!ans+1 - for (int b = g; b <= max; b += a) { - if (set[b]) { - g = gcd(g, b); - if (g == a) { - ans++; - break; - } - } - } - } - return ans; - } - - public static int gcd(int m, int n) { - return n == 0 ? m : gcd(n, m % n); - } - -} diff --git a/公开课/class090/Code01_LIS.java b/公开课/class090/Code01_LIS.java deleted file mode 100644 index 15fa4ac..0000000 --- a/公开课/class090/Code01_LIS.java +++ /dev/null @@ -1,94 +0,0 @@ -package class090; - -// 本题测试链接 : https://leetcode.com/problems/longest-increasing-subsequence -public class Code01_LIS { - -// // O(N^2) -// // 不够好 -// public static int lisMaxLen1(int[] arr) { -// if (arr == null || arr.length == 0) { -// return 0; -// } -// int n = arr.length; -// int[] dp = new int[n]; -// dp[0] = 1; -// int max = dp[0]; -// for (int i = 1; i < n; i++) { -// int pre = 0; -// for (int j = 0; j < i; j++) { -// if (arr[j] < arr[i]) { -// pre = Math.max(pre, dp[j]); -// } -// } -// dp[i] = pre + 1; -// max = Math.max(max, dp[i]); -// } -// return max; -// } -// -// public static int lisMaxLen2(int[] arr) { -// if (arr == null || arr.length == 0) { -// return 0; -// } -// int n = arr.length; -// int[] dp = new int[n]; -// int[] ends = new int[n]; -// dp[0] = 1; -// ends[0] = arr[0]; -// // ends数组,有效区 -// // ends = 1.... -// // 0...validSize-1 范围上去二分! -// int validSize = 1; -// int max = dp[0]; -// for (int i = 1; i < n; i++) { -// int cur = arr[i]; -// int endsi = find(ends, validSize, cur); -// if(endsi == -1) { // ends数组有效区里,都是 < num -// ends[validSize++] = cur; -// dp[i] = validSize; -// } else { // 查找>=num最左的位置,找到了! -// ends[endsi] = cur; -// dp[i] = endsi + 1; -// } -// max = Math.max(max, dp[i]); -// } -// return max; -// } -// -// // 在ends数组有效区里,查找>=num最左的位置 -// // 如果没有>=num最左的位置,返回-1 -// public static int find(int[] ends, int size, int num) { -// -// } - - // 最优解! - public static int lengthOfLIS(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int[] ends = new int[arr.length]; - ends[0] = arr[0]; - int right = 0; - int l = 0; - int r = 0; - int m = 0; - int max = 1; - for (int i = 1; i < arr.length; i++) { - l = 0; - r = right; - while (l <= r) { - m = (l + r) / 2; - if (arr[i] > ends[m]) { - l = m + 1; - } else { - r = m - 1; - } - } - right = Math.max(right, l); - ends[l] = arr[i]; - max = Math.max(max, l + 1); - } - return max; - } - -} \ No newline at end of file diff --git a/公开课/class090/Code02_MaxAnimalNumber.java b/公开课/class090/Code02_MaxAnimalNumber.java deleted file mode 100644 index 5080c7e..0000000 --- a/公开课/class090/Code02_MaxAnimalNumber.java +++ /dev/null @@ -1,116 +0,0 @@ -package class090; - -// 有n个动物重量分别是a1、a2、a3.....an, -// 这群动物一起玩叠罗汉游戏, -// 规定从左往右选择动物,每只动物左边动物的总重量不能超过自己的重量 -// 返回最多能选多少个动物,求一个高效的算法。 -// 比如有7个动物,从左往右重量依次为:1,3,5,7,9,11,21 -// 则最多能选5个动物:1,3,5,9,21 -// 注意本题给的例子是有序的,但是实际给定的动物数组,可能是无序的, -// 要求从左往右选动物,且不能打乱原始数组 -public class Code02_MaxAnimalNumber { - - // 普通动态规划 - // 非常一般的方法 - // 来自背包的思路 - public static int maxAnimals1(int[] arr) { - int sum = 0; - for (int num : arr) { - sum += num; - } - int[][] dp = new int[arr.length][sum + 1]; - for (int i = 0; i < arr.length; i++) { - for (int j = 0; j <= sum; j++) { - dp[i][j] = -1; - } - } - return process1(arr, 0, 0, dp); - } - - public static int process1(int[] arr, int index, int pre, int[][] dp) { - if (index == arr.length) { - return 0; - } - if (dp[index][pre] != -1) { - return dp[index][pre]; - } - int p1 = process1(arr, index + 1, pre, dp); - int p2 = 0; - if (arr[index] >= pre) { - p2 = 1 + process1(arr, index + 1, pre + arr[index], dp); - } - int ans = Math.max(p1, p2); - dp[index][pre] = ans; - return ans; - } - - // 最优解 - // 如果arr长度为N,时间复杂度O(N*logN) - public static int maxAnimals2(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int[] ends = new int[arr.length + 1]; - ends[0] = 0; - int endsSize = 1; - int max = 1; - for (int i = 0; i < arr.length; i++) { - int l = 0; - int r = endsSize - 1; - int m = 0; - int find = 0; - while (l <= r) { - m = (l + r) / 2; - if (ends[m] <= arr[i]) { - find = m; - l = m + 1; - } else { - r = m - 1; - } - } - if (find == endsSize - 1) { // 能扩充有效区! - ends[endsSize] = ends[endsSize - 1] + arr[i]; - endsSize++; - } else { // 不能扩充有效区 - if (ends[find + 1] > ends[find] + arr[i]) { - ends[find + 1] = ends[find] + arr[i]; - } - } - max = Math.max(max, find + 1); - } - return max; - } - - public static int[] randomArray(int n, int v) { - int[] arr = new int[n]; - for (int i = 0; i < n; i++) { - arr[i] = (int) (Math.random() * v) + 1; - } - return arr; - } - - public static void main(String[] args) { - int N = 100; - int V = 1000; - int testTime = 2000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int n = (int) (Math.random() * N) + 1; - int[] arr = randomArray(n, V); - int ans1 = maxAnimals1(arr); - int ans2 = maxAnimals2(arr); - if (ans1 != ans2) { - System.out.println("出错了"); - for (int num : arr) { - System.out.print(num + " "); - } - System.out.println(); - System.out.println(ans1); - System.out.println(ans2); - break; - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class090/Code03_EnvelopesProblem.java b/公开课/class090/Code03_EnvelopesProblem.java deleted file mode 100644 index c2d1d31..0000000 --- a/公开课/class090/Code03_EnvelopesProblem.java +++ /dev/null @@ -1,61 +0,0 @@ -package class090; - -import java.util.Arrays; -import java.util.Comparator; - -// 本题测试链接 : https://leetcode.com/problems/russian-doll-envelopes/ -public class Code03_EnvelopesProblem { - - public static int maxEnvelopes(int[][] matrix) { - // 生成信封,根据宽度从小到大,宽度一样的,高度从大到小 - Envelope[] arr = sort(matrix); - int[] ends = new int[matrix.length]; - ends[0] = arr[0].h; - int right = 0; - int l = 0; - int r = 0; - int m = 0; - for (int i = 1; i < arr.length; i++) { - l = 0; - r = right; - while (l <= r) { - m = (l + r) / 2; - if (arr[i].h > ends[m]) { - l = m + 1; - } else { - r = m - 1; - } - } - right = Math.max(right, l); - ends[l] = arr[i].h; - } - return right + 1; - } - - public static class Envelope { - public int l; - public int h; - - public Envelope(int weight, int hight) { - l = weight; - h = hight; - } - } - - public static class EnvelopeComparator implements Comparator { - @Override - public int compare(Envelope o1, Envelope o2) { - return o1.l != o2.l ? o1.l - o2.l : o2.h - o1.h; - } - } - - public static Envelope[] sort(int[][] matrix) { - Envelope[] res = new Envelope[matrix.length]; - for (int i = 0; i < matrix.length; i++) { - res[i] = new Envelope(matrix[i][0], matrix[i][1]); - } - Arrays.sort(res, new EnvelopeComparator()); - return res; - } - -} diff --git a/公开课/class091/Code01_SetAll.java b/公开课/class091/Code01_SetAll.java deleted file mode 100644 index 2de8ab7..0000000 --- a/公开课/class091/Code01_SetAll.java +++ /dev/null @@ -1,57 +0,0 @@ -package class091; - -import java.util.HashMap; - -// 设计有一个带有setAll功能的哈希表,有如下功能 -// 1) put(x, y) : 新增或者更新,key为x,value是y -// 2) get(x) : 返回key为x的时候,value是多少 -// 3) setAll(y) : 把调用这个方法之前所有的key,value都设置成y -// 要求三个方法的时间复杂度都是O(1) -public class Code01_SetAll { - - public static class MyValue { - public V value; - public long time; - - public MyValue(V v, long t) { - value = v; - time = t; - } - } - - public static class MyHashMap { - // key : 原始的key - // value : 封装好的一个MyValue结构:原始的value、时间戳 - private HashMap> map; - // 全局时间点,每一次put、或者setAll都会让时间点 + 1 - private long time; - // setAll区域:setAllValue,setAllTime - private MyValue setAll; - - public MyHashMap() { - map = new HashMap<>(); - time = 0; - setAll = new MyValue(null, -1); - } - - public void put(K key, V value) { - map.put(key, new MyValue(value, time++)); - } - - public void setAll(V value) { - setAll = new MyValue(value, time++); - } - - public V get(K key) { - if (!map.containsKey(key)) { - return null; - } - if (map.get(key).time > setAll.time) { - return map.get(key).value; - } else { - return setAll.value; - } - } - } - -} diff --git a/公开课/class091/Code02_Heaters.java b/公开课/class091/Code02_Heaters.java deleted file mode 100644 index a71ef8f..0000000 --- a/公开课/class091/Code02_Heaters.java +++ /dev/null @@ -1,132 +0,0 @@ -package class091; - -import java.util.Arrays; - -// 你的任务是设计一个有固定加热半径的供暖器向所有房屋供暖。 -// 在加热器的加热半径范围内的每个房屋都可以获得供暖。 -// 现在,给出位于一条水平线上的房屋 houses 和供暖器 heaters 的位置, -// 请你找出并返回可以覆盖所有房屋的最小加热半径。 -// 说明:所有供暖器都遵循你的半径标准,加热的半径都一样。 -// 测试链接 :https://leetcode.cn/problems/heaters -public class Code02_Heaters { - - // 比如地点是7, 9, 14 - // 供暖点的位置: 1 3 4 5 13 15 17 - // 先看地点7 - // 由1供暖,半径是6 - // 由3供暖,半径是4 - // 由4供暖,半径是3 - // 由5供暖,半径是2 - // 由13供暖,半径是6 - // 由此可知,地点7应该由供暖点5来供暖,半径是2 - // 再看地点9 - // 供暖点不回退 - // 由5供暖,半径是4 - // 由13供暖,半径是4 - // 由15供暖,半径是6 - // 由此可知,地点9应该由供暖点13来供暖,半径是4 - // 为什么是13而不是5?因为接下来的地点都会更靠右,所以半径一样的时候,就应该选更右的供暖点 - // 再看地点14 - // 供暖点不回退 - // 由13供暖,半径是1 - // 由15供暖,半径是1 - // 由17供暖,半径是3 - // 由此可知,地点14应该由供暖点15来供暖,半径是1 - // 以此类推 - public static int findRadius(int[] houses, int[] heaters) { - // 排序 - // 时间复杂度O(N*logN) - Arrays.sort(houses); - Arrays.sort(heaters); - // 至少的供暖半径 - int ans = 0; - // 时间复杂度O(N) - // i是地点,j是供暖点 - for (int i = 0, j = 0; i < houses.length; i++) { - // 3 9 13 17 - // 0 1 2 3 - // i就是房子的编号,houses[i]房子所在的位置 - // j火炉的编号 - // 2 5 8 13 16 - // 0 1 2 3 4 - // best : i号房,由j号火炉给其供暖,是不是最优的! - while (!best(houses, heaters, i, j)) { - j++; - } - ans = Math.max(ans, Math.abs(heaters[j] - houses[i])); - } - return ans; - } - - // 这个函数含义: - // 当前的地点houses[i]由heaters[j]来供暖是最优的吗? - // 当前的地点houses[i]由heaters[j]来供暖,产生的半径是a - // 当前的地点houses[i]由heaters[j + 1]来供暖,产生的半径是b - // 如果a < b, 说明是最优,供暖不应该跳下一个位置 - // 如果a >= b, 说明不是最优,应该跳下一个位置 - public static boolean best(int[] houses, int[] heaters, int i, int j) { - return - // 已经来到最后的火炉了!一定是最优! - j == heaters.length - 1 || - // 当前的火炉到当前的房子距离 < 下一个火炉到当前的房子距离 - Math.abs(heaters[j] - houses[i]) < Math.abs(heaters[j + 1] - houses[i]); - } - - // 下面这个方法不对,你能找出原因嘛?^_^ - public static int findRadius2(int[] houses, int[] heaters) { - Arrays.sort(houses); - Arrays.sort(heaters); - int ans = 0; - // 时间复杂度O(N) - // i是地点,j是供暖点 - for (int i = 0, j = 0; i < houses.length; i++) { - while (!best2(houses, heaters, i, j)) { - j++; - } - ans = Math.max(ans, Math.abs(heaters[j] - houses[i])); - } - return ans; - } - - public static boolean best2(int[] houses, int[] heaters, int i, int j) { - return j == heaters.length - 1 || Math.abs(heaters[j] - houses[i]) <= Math.abs(heaters[j + 1] - houses[i]); - } - - // 为了测试 - public static int[] randomArray(int len, int v) { - int[] arr = new int[len]; - for (int i = 0; i < len; i++) { - arr[i] = (int) (Math.random() * v) + 1; - } - return arr; - } - - // 为了测试 - public static void main(String[] args) { - int len = 5; - int v = 10; - int testTime = 10000; - for (int i = 0; i < testTime; i++) { - int[] a = randomArray(len, v); - int[] b = randomArray(len, v); - int ans1 = findRadius(a, b); - int ans2 = findRadius2(a, b); - if (ans1 != ans2) { - System.out.println("A : "); - for (int num : a) { - System.out.print(num + " "); - } - System.out.println(); - System.out.println("B : "); - for (int num : b) { - System.out.print(num + " "); - } - System.out.println(); - System.out.println(ans1); - System.out.println(ans2); - break; - } - } - } - -} diff --git a/公开课/class091/Code03_TrappingRainWater.java b/公开课/class091/Code03_TrappingRainWater.java deleted file mode 100644 index c3c016c..0000000 --- a/公开课/class091/Code03_TrappingRainWater.java +++ /dev/null @@ -1,116 +0,0 @@ -package class091; - -// 给定一个正整数数组arr,把arr想象成一个直方图。 -// 返回这个直方图如果装水,能装下几格水? -// 测试链接 : https://leetcode.cn/problems/trapping-rain-water -public class Code03_TrappingRainWater { - - public static int trap(int[] arr) { - if (arr == null || arr.length < 3) { - return 0; - } - int n = arr.length; - int maxLeft = arr[0]; - int maxRight = arr[n - 1]; - int L = 1; - int R = n - 2; - int ans = 0; - while (L <= R) { - // 左边部分最大值 < 右边部分最大值,让左侧动 - // 左边部分最大值 == 右边部分最大值,也让左侧动 - if (maxLeft <= maxRight) { - ans += Math.max(maxLeft - arr[L], 0); - maxLeft = Math.max(maxLeft, arr[L++]); - } else { // 左边部分最大值 > 右边部分最大值,让右侧动 - ans += Math.max(maxRight - arr[R], 0); - maxRight = Math.max(maxRight, arr[R--]); - } - } - return ans; - } - - public static int trap1(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int water = 0; - for (int i = 1; i < N - 1; i++) { - int leftMax = Integer.MIN_VALUE; - for (int j = 0; j < i; j++) { - leftMax = Math.max(leftMax, arr[j]); - } - int rightMax = Integer.MIN_VALUE; - for (int j = i + 1; j < N; j++) { - rightMax = Math.max(rightMax, arr[j]); - } - water += Math.max(Math.min(leftMax, rightMax) - arr[i], 0); - } - return water; - } - - public static int trap2(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int[] leftMaxs = new int[N]; - leftMaxs[0] = arr[0]; - for (int i = 1; i < N; i++) { - leftMaxs[i] = Math.max(leftMaxs[i - 1], arr[i]); - } - - int[] rightMaxs = new int[N]; - rightMaxs[N - 1] = arr[N - 1]; - for (int i = N - 2; i >= 0; i--) { - rightMaxs[i] = Math.max(rightMaxs[i + 1], arr[i]); - } - int water = 0; - for (int i = 1; i < N - 1; i++) { - water += Math.max(Math.min(leftMaxs[i - 1], rightMaxs[i + 1]) - arr[i], 0); - } - return water; - } - - public static int trap3(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int[] rightMaxs = new int[N]; - rightMaxs[N - 1] = arr[N - 1]; - for (int i = N - 2; i >= 0; i--) { - rightMaxs[i] = Math.max(rightMaxs[i + 1], arr[i]); - } - int water = 0; - int leftMax = arr[0]; - for (int i = 1; i < N - 1; i++) { - water += Math.max(Math.min(leftMax, rightMaxs[i + 1]) - arr[i], 0); - leftMax = Math.max(leftMax, arr[i]); - } - return water; - } - - public static int trap4(int[] arr) { - if (arr == null || arr.length < 2) { - return 0; - } - int N = arr.length; - int L = 1; - int leftMax = arr[0]; - int R = N - 2; - int rightMax = arr[N - 1]; - int water = 0; - while (L <= R) { - if (leftMax <= rightMax) { - water += Math.max(0, leftMax - arr[L]); - leftMax = Math.max(leftMax, arr[L++]); - } else { - water += Math.max(0, rightMax - arr[R]); - rightMax = Math.max(rightMax, arr[R--]); - } - } - return water; - } - -} diff --git a/公开课/class091/Code04_SplitApples.java b/公开课/class091/Code04_SplitApples.java deleted file mode 100644 index b3debb4..0000000 --- a/公开课/class091/Code04_SplitApples.java +++ /dev/null @@ -1,124 +0,0 @@ -package class091; - -// 有m个同样的苹果,认为苹果之间无差别 -// 有n个同样的盘子,认为盘子之间也无差别 -// 比如有3个苹果,有2个盘子 -// 方法有两种分别为:1、2 ; 3 -// 1、2和2、1的放置认为是一种方法 -// 返回有多少种放置苹果的方法 -// 测试链接 : https://www.nowcoder.com/practice/bfd8234bb5e84be0b493656e390bdebf -// 提交以下的code,提交时请把类名改成"Main" -import java.util.Arrays; -import java.util.Scanner; - -public class Code04_SplitApples { - - public static void main(String[] args) { - Scanner sc = new Scanner(System.in); - while (sc.hasNext()) { - int m = sc.nextInt(); - int n = sc.nextInt(); - int ways = ways3(m, n); - System.out.println(ways); - } - sc.close(); - } - - // 思路来自于分裂数问题 - // 体系学习班代码第22节,题目3,split number问题 - public static int ways1(int apples, int plates) { - return process1(1, apples, plates); - } - - // pre : 上一个盘子分到的苹果数量,当前的盘子分到的数量不能小于pre - // apples : 剩余的苹果数量 - // plates : 剩余的盘子数量 - // 在盘子够用的情况下,把苹果分完,有几种方法 - public static int process1(int pre, int apples, int plates) { - if (apples == 0) { - return 1; - } - // apples != 0 - if (plates == 0) { - return 0; - } - // apples != 0 && plates != 0 - if (pre > apples) { - return 0; - } - // apples != 0 && plates != 0 && pre <= apples - int way = 0; - // 之前的盘子分了3个苹果,现在还剩下8个苹果 - // 当前的盘子,可以装几个苹果:3、4、5、6、7、8 - for (int cur = pre; cur <= apples; cur++) { - way += process1(cur, apples - cur, plates - 1); - } - return way; - } - - // 新的尝试,最优解 - // 苹果有apples个,盘子有plates个 - // 返回有几种摆法 - // 如果苹果数为0,有1种摆法:什么也不摆 - // 如果苹果数不为0,但是盘子数为0,有0种摆法(做不到) - // 如果苹果数不为0,盘子数也不为0,进行如下的情况讨论: - // 假设苹果数为apples,盘子数为plates - // 可能性 1) apples < plates - // 这种情况下,一定有多余的盘子,这些盘子完全没用,所以砍掉 - // 后续是f(apples, apples) - // 可能性 2) apples >= plates - // 在可能性2)下,讨论摆法,有如下两种选择 - // 选择a) 不是所有的盘子都使用 - // 选择b) 就是所有的盘子都使用 - // 对于选择a),既然不是所有盘子都使用,那么后续就是f(apples, plates - 1) - // 意思是:既然不是所有盘子都使用,那盘子减少一个,然后继续讨论吧! - // 对于选择b),既然就是所有的盘子都使用,那么先把所有盘子都摆上1个苹果。 - // 剩余苹果数 = apples - plates - // 然后继续讨论,剩下的这些苹果,怎么摆进plates个盘子里, - // 所以后续是f(apples - plates, plates) - public static int ways2(int apples, int plates) { - if (apples == 0) { - return 1; - } - if (plates == 0) { - return 0; - } - if (plates > apples) { - return ways2(apples, apples); - } else { // apples >= plates; - return ways2(apples, plates - 1) + ways2(apples - plates, plates); - } - } - - // 上面最优解尝试的记忆化搜索版本 - public static int[][] dp = null; - - public static int ways3(int apples, int plates) { - if (dp == null) { - dp = new int[11][11]; - for (int i = 0; i <= 10; i++) { - Arrays.fill(dp[i], -1); - } - } - return process3(apples, plates, dp); - } - - public static int process3(int apples, int plates, int[][] dp) { - if (dp[apples][plates] != -1) { - return dp[apples][plates]; - } - int ans = 0; - if (apples == 0) { - ans = 1; - } else if (plates == 0) { - ans = 0; - } else if (plates > apples) { - ans = process3(apples, apples, dp); - } else { - ans = process3(apples, plates - 1, dp) + process3(apples - plates, plates, dp); - } - dp[apples][plates] = ans; - return ans; - } - -} \ No newline at end of file diff --git a/公开课/class092/Code01_ValidParentheses.java b/公开课/class092/Code01_ValidParentheses.java deleted file mode 100644 index 8ea317d..0000000 --- a/公开课/class092/Code01_ValidParentheses.java +++ /dev/null @@ -1,102 +0,0 @@ -package class092; - -// () -// ()() -// (()())(()) -// (() -// (())()...... -// -// cnt = 0 -// ( ++ -// ) -- -// ( ) ) ( -// 1 0 -1 false -// ( ( ( ) ) ) ( ) ( ( ( ) -// 1 2 3 2 1 0 1 0 1 2 3 2 false -// 前缀 : ( ( ) ( ( ) ) ) -// ()) -public class Code01_ValidParentheses { - - // 检查有效性,整体有效性! - public static boolean valid(String s) { - char[] str = s.toCharArray(); - int count = 0; - for (int i = 0; i < str.length; i++) { - count += str[i] == '(' ? 1 : -1; - if (count < 0) { - return false; - } - } - return count == 0; - } - - // )( -> 2个 - // ...... -> ? 能变合法! - // - // cnt = 0 - // add = 3 - // ( ++ - // ) -- - // 遍历的过程中,cnt < 0时刻! - // ( ) ) ) ( ( ) ) ) ( ( ( ) - // 1 0 0 0 1 2 1 0 0 1 2 3 2 - // cnt = -1 添加 ( , 使之平衡!cnt = 0 - // 到最后 add += cnt - public static int needParentheses(String s) { - char[] str = s.toCharArray(); - int count = 0; - int add = 0; - for (int i = 0; i < str.length; i++) { - if (str[i] == '(') { - count++; - } else { // 遇到的是')' - if (count == 0) { - add++; - } else { - count--; - } - } - } - return count + add; - } - - public static boolean isValid(char[] str) { - if (str == null || str.length == 0) { - return false; - } - int status = 0; - for (int i = 0; i < str.length; i++) { - if (str[i] != ')' && str[i] != '(') { - return false; - } - if (str[i] == ')' && --status < 0) { - return false; - } - if (str[i] == '(') { - status++; - } - } - return status == 0; - } - - - - // 4 - // ( () () ) ( ( ( ) ) ) ( ( ) ( ) ( ( ) ) ( )( ) ( ( ( ) ( ) ) ) ) - // cnt ( ++ - // cnt ) -- - public static int deep(String s) { - char[] str = s.toCharArray(); - if (!isValid(str)) { - return 0; - } - int count = 0; - int max = 0; - for (int i = 0; i < str.length; i++) { - count += str[i] == '(' ? 1 : -1; - max = Math.max(max, count); - } - return max; - } - -} diff --git a/公开课/class092/Code02_LongestParentheses.java b/公开课/class092/Code02_LongestParentheses.java deleted file mode 100644 index 6549115..0000000 --- a/公开课/class092/Code02_LongestParentheses.java +++ /dev/null @@ -1,84 +0,0 @@ -package class092; - -// s只由(和)组成 -// 求最长有效括号子串长度 -// 本题测试链接 : https://leetcode.com/problems/longest-valid-parentheses/ -public class Code02_LongestParentheses { - - // ( ) ) ) ( ( ) ) ( ) ( ( - // 0 1 2 3 4 5 6 7 8 9 10 11 - // 最长有效括号子串 - // dp[] 长度11, - // dp[i] : 子串必须以i位置结尾的情况下!向左最长能延伸多长!是有效的串! - // ( ) ) ) ( ( ) ) ( ) ( ( - // 0 1 2 3 4 5 6 7 8 9 10 11 - // dp 0 2 0 0 ................. - // 0 1 2 3 - // - // dp[i] : 重点关注 dp[i-1] - // 1) [i] == (, dp[i] = 0 - // ( - // i - // 2) [i] == ) - // ) ( ) ( ) ) - // i-1 i - // 4 0 - - // ( ( ) ( ) ) - // i-1 i - // 4 至少6 - // - // ( ) ( ) ( ( ) ( ) ) - // 0 1 2 3 4 5 6 7 8 9 - // 4 10 - // ( ) ( ) ( ) ( ( ) ) ( ( ( ) ) ) - // a b c d e f g h i j k l m n o p - // 0 2 0 4 0 6 0 0 2 10 - public static int longestValidParentheses(String s) { - if (s == null || s.length() < 2) { - return 0; - } - char[] str = s.toCharArray(); - int[] dp = new int[str.length]; - int pre = 0; - int ans = 0; - // dp[0] = 0 - for (int i = 1; i < str.length; i++) { - if (str[i] == ')') { - // pre 找到和当前 ) 括号配的位置! - // ? ( ( ) ) ) - // 4 5 6 7 8 9(i) - // 4 - // - // ? ( ) ) - // 4 5 6 7 8 9(i) - // 2 - // - // - // ( ) - // 4 5 6 7 8 9(i) - // 0 - // ? ) - // pre i - pre = i - dp[i - 1] - 1; - // pre < 0 - // ( ) ( ) ) - // 0 1 2 3 4 - // 0 - // ( ) - // pre i - // 0 - if (pre >= 0 && str[pre] == '(') { - // ( ........ ) - // pre-1 pre i - dp[i] = dp[i - 1] + 2 + (pre > 0 ? dp[pre - 1] : 0); - } - // dp[i] = 0 - } - // ( dp[i] = 0 - ans = Math.max(ans, dp[i]); - } - return ans; - } - -} diff --git a/公开课/class092/Code03_CompleteTreeNodeNumber.java b/公开课/class092/Code03_CompleteTreeNodeNumber.java deleted file mode 100644 index cf57943..0000000 --- a/公开课/class092/Code03_CompleteTreeNodeNumber.java +++ /dev/null @@ -1,105 +0,0 @@ -package class092; - -// 本题测试链接 : https://leetcode.cn/problems/count-complete-tree-nodes/ -public class Code03_CompleteTreeNodeNumber { - - // 提交时不要提交这个类 - public class TreeNode { - int val; - TreeNode left; - TreeNode right; - } - - // 1 - // 2 3 - // 4 5 6 7 - // .... - // 遍历做法!不行!所有节点要走一遍!O(N), N是节点个数! - // 1 1 - // 2 3 2 - // 4 5 6 7 3 - // 8 9 a b c d e f 4 - // g h i j k l 5 - // - // 先从1出发,看1的右树的最左节点,到了哪一层! - // c 没到 最深! 说明,1的右树是满的!高度是3,节点数: 7个 - // 1自己,1个节点! 1 + 1的右树 = 8个 - // 整棵树的所有节点: 8个 + 1的左树节点数(递归!) - // - // 再从2出发,看2的右树的最左节点,到了哪一层! - // k 到了最深! 说明,2的左树是满的!左树高度3,2的左树 = 7个 - // 2自己,1个节点! 2 + 2的左树 = 8个 - // 2这棵树所有的节点 = 8个节点 + 2的右树节点个数(递归!) - // - // 继续从5出发,看5的右树的最左节点,到了哪一层! - // b 没到 最深!说明,5的右树是满的!高度是1,节点数: 1个 - // 5自己,1个节点! 5 + 5的右树 = 2个 - // 5这棵树所有的节点 = 2个 + 5的左树节点数(递归!) - // - // 从a出发!看a的右树的最左节点,到了哪一层! - // - - - - // 最深到了4层!这个结论记录! - // - // 满二叉树,高度是h,满二叉树的节点数 2^h - 1 - // 提交如下的方法 - public static int countNodes(TreeNode head) { - if (head == null) { - return 0; - } - // 当前 几层的节点 最深层是几层 - return bs(head, 1, mostLeftLevel(head, 1)); - } - - // 当前来到node节点,node节点在level层,总层数是h - // 返回node为头的子树(必是完全二叉树),有多少个节点 - public static int bs(TreeNode node, int Level, int h) { - if (Level == h) { - return 1; - } - if (mostLeftLevel(node.right, Level + 1) == h) { - // node的右树的最左节点,到了最后一层! - // 说明node的左树,是满的! - // 左树的节点数 + 1个(node自己) + 右树去递归! - // 2^(h - level) -> 1 << (h - level) - // node 5(level) - // 6 - // 7 - // 8(最深h) - return (1 << (h - Level)) + bs(node.right, Level + 1, h); - } else { - // node的右树的最左节点,没到最后一层! - // 说明node的右树,是满的!-1 - return (1 << (h - Level - 1)) + bs(node.left, Level + 1, h); - } - } - - // 时间复杂度 - // 完全二叉树的节点数是N, 完全二叉树的高度 h -> log N - // - // x 去x右树上走个高度 - // a 去a右树上走个高度 - // d 去d右树上走个高度 - // f 去f右树上走个高度 - // y 去y右树上走个高度 - // h O(h^2) h logN - // O( (logN)平方 ) < O(N) - // 如果node在第level层, - // 求以node为头的子树,最大深度是多少 - // node为头的子树,一定是完全二叉树 - // x 19 - // a 20 - // b 21 - // c 22 - // null 23 - public static int mostLeftLevel(TreeNode node, int level) { - while (node != null) { - level++; - node = node.left; - } - return level - 1; - } - -} diff --git a/公开课/class093/Code01_FindDuplicateOnlyOne.java b/公开课/class093/Code01_FindDuplicateOnlyOne.java deleted file mode 100644 index b7f45d3..0000000 --- a/公开课/class093/Code01_FindDuplicateOnlyOne.java +++ /dev/null @@ -1,117 +0,0 @@ -package class093; - -import java.util.Arrays; -import java.util.HashSet; - -// 来自学员问题,阿里面试题 -// 1、2、3...n-1、n、n、n+1、n+2... -// 在这个序列中,只有一个数字有重复(n) -// 这个序列是无序的,找到重复数字n -// 这个序列是有序的,找到重复数字n -public class Code01_FindDuplicateOnlyOne { - - // 为了测试 - // 绝对正确,但是直接遍历+哈希表,没有得分的方法 - public static int right(int[] arr) { - HashSet set = new HashSet<>(); - for (int num : arr) { - if (set.contains(num)) { - return num; - } - set.add(num); - } - return -1; - } - - // 符合题目要求的、无序数组,找重复数 - // 时间复杂度O(N),额外空间复杂度O(1) - public static int findDuplicate(int[] arr) { - if (arr == null || arr.length < 2) { - return -1; - } - // 0位置开始跳,slow == 0,arr[0] - // 0位置开始跳,fast == 0,arr[arr[0]] - int slow = arr[0]; - int fast = arr[arr[0]]; - // slow 和 fast如果没相遇,就一直跳 ! - while (slow != fast) { - slow = arr[slow]; - fast = arr[arr[fast]]; - } - // slow == fast - fast = 0; - while (slow != fast) { - fast = arr[fast]; - slow = arr[slow]; - } - // 再相遇!一个结论 - return slow; - } - - // 符合题目要求的、有序数组,找重复数 - // 时间复杂度O(logN),额外空间复杂度O(1) - public static int findDuplicateSorted(int[] arr) { - if (arr == null || arr.length < 2) { - return -1; - } - int l = 0; - int r = arr.length - 1; - int m = 0; - int ans = -1; - while (l <= r) { - m = (l + r) / 2; - if ((m - 1 >= 0 && arr[m - 1] == arr[m]) || (m + 1 < arr.length && arr[m + 1] == arr[m])) { - ans = arr[m]; - break; - } - if (m - l == arr[m] - arr[l]) { - l = m + 1; - } else { - r = m - 1; - } - } - return ans; - } - - // 为了测试 - public static int[] randomArray(int n) { - int[] ans = new int[n + 1]; - for (int i = 0; i < n; i++) { - ans[i] = i + 1; - } - ans[n] = (int) (Math.random() * n) + 1; - for (int i = n; i > 0; i--) { - int j = (int) (Math.random() * (i + 1)); - int tmp = ans[i]; - ans[i] = ans[j]; - ans[j] = tmp; - } - return ans; - } - - // 为了测试 - public static void main(String[] args) { - int N = 10; - int testTime = 5000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int[] arr = randomArray((int) (Math.random() * N) + 1); - if (right(arr) != findDuplicate(arr)) { - System.out.println("未排序情况出错!"); - } - Arrays.sort(arr); - if (right(arr) != findDuplicateSorted(arr)) { - System.out.println("排序情况出错!"); - for (int num : arr) { - System.out.print(num + " "); - } - System.out.println(); - System.out.println(right(arr)); - System.out.println(findDuplicateSorted(arr)); - break; - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class093/Code02_SellingPiecesOfWood.java b/公开课/class093/Code02_SellingPiecesOfWood.java deleted file mode 100644 index d974266..0000000 --- a/公开课/class093/Code02_SellingPiecesOfWood.java +++ /dev/null @@ -1,165 +0,0 @@ -package class093; - -// 给你两个整数 m 和 n ,分别表示一块矩形木块的高和宽。 -// 同时给你一个二维整数数组 prices ,其中 prices[i] = [hi, wi, pricei]  -// 表示你可以以 pricei 元的价格卖一块高为 hi 宽为 wi 的矩形木块。 -// 每一次操作中,你必须按下述方式之一执行切割操作,以得到两块更小的矩形木块: -// 沿垂直方向按高度 完全 切割木块,或 -// 沿水平方向按宽度 完全 切割木块 -// 在将一块木块切成若干小木块后,你可以根据 prices 卖木块。 -// 你可以卖多块同样尺寸的木块。 -// 你不需要将所有小木块都卖出去。 -// 你 不能 旋转切好后木块的高和宽。 -// 请你返回切割一块大小为 m x n 的木块后,能得到的 最多 钱数。 -// 注意你可以切割木块任意次。 -// 测试链接 : https://leetcode.cn/problems/selling-pieces-of-wood/ -public class Code02_SellingPiecesOfWood { - - public static int zuo(int m, int n, int[][] projects) { - // 50 * 60 - int[][] prices = new int[m + 1][n + 1]; - for (int[] project : projects) { - int row = project[0]; - int col = project[1]; - int value = project[2]; - prices[row][col] = Math.max(prices[row][col], value); - } - return maxMoney(m, n, prices); - } - - // 当前还剩下的木板,规格 : m * n - // 请按照题目说的方式来切割! - // 每一种规格的报价,都在prices里面 - // 比如,想要查 10 * 20规格的木板,的最好报价,prices[10][20] 值! - // 返回最大的钱数! - public static int maxMoney(int m, int n, int[][] prices) { - if (m == 0 || n == 0) { - return 0; - } - // m > 0, n > 0 - // 可能性1 : 当前的木板根本不切,看看有没有报价 - int p1 = prices[m][n]; - // 可能性2 : 当前的木板水平切 - int p2 = 0; - for (int up = 1; up < m; up++) { - int down = m - up; - int upMoney = maxMoney(up, n, prices); - int downMoney = maxMoney(down, n, prices); - int cur = upMoney + downMoney; - p2 = Math.max(p2, cur); - } - // 可能性3 : 当前木板,垂直切 - int p3 = 0; - for (int left = 1; left < n; left++) { - int right = n - left; - int leftMoney = maxMoney(m, left, prices); - int rightMoney = maxMoney(m, right, prices); - int cur = leftMoney + rightMoney; - p3 = Math.max(p3, cur); - } - return Math.max(p1, Math.max(p2, p3)); - } - - // 递归尝试版本 - public static long sellingWood1(int m, int n, int[][] prices) { - // 单一报价 - long[][] values = new long[m + 1][n + 1]; - // 2 * 7 10元 - // 2 * 7 100元 - for (int[] p : prices) { - values[p[0]][p[1]] = Math.max(values[p[0]][p[1]], p[2]); - } - return f1(m, n, values); - } - - public static long f1(int m, int n, long[][] values) { - if (m == 0 || n == 0) { - return 0; - } - long ans = values[m][n]; - for (int split = 1; split < m; split++) { - ans = Math.max(ans, f1(split, n, values) + f1(m - split, n, values)); - } - for (int split = 1; split < n; split++) { - ans = Math.max(ans, f1(m, split, values) + f1(m, n - split, values)); - } - return ans; - } - - // 递归版本 + 记忆化搜索 - public static long sellingWood2(int m, int n, int[][] prices) { - long[][] values = new long[m + 1][n + 1]; - for (int[] p : prices) { - values[p[0]][p[1]] = Math.max(values[p[0]][p[1]], p[2]); - } - long[][] dp = new long[m + 1][n + 1]; - // dp[10][20] :没算过,-1 - for (int i = 1; i <= m; i++) { - for (int j = 1; j <= n; j++) { - dp[i][j] = -1; - } - } - return f2(m, n, values, dp); - } - - // m n 一旦确定,返回值,确定! - // dp[m][n] == -1 没算过! - // dp[m][n] != -1 之前算过!结果是什么呢?dp[m][n]的值 - public static long f2(int m, int n, long[][] values, long[][] dp) { - if (m == 0 || n == 0) { - return 0; - } - if (dp[m][n] != -1) { - return dp[m][n]; - } - long ans = values[m][n]; - for (int split = 1; split < m; split++) { - ans = Math.max(ans, f2(split, n, values, dp) + f2(m - split, n, values, dp)); - } - for (int split = 1; split < n; split++) { - ans = Math.max(ans, f2(m, split, values, dp) + f2(m, n - split, values, dp)); - } - dp[m][n] = ans; - return ans; - } - - // 严格位置依赖的动态规划版本 + 优化 - // 优化1 : 递归的形式,改成迭代形式,课上讲了 - // 优化2 : prices中的单块收益直接填入dp表即可,如果有更好的分割方案,更新掉 - // 优化3 : 分割只需要枚举一半即可 - public static long sellingWood3(int m, int n, int[][] prices) { - // dp表! - long[][] dp = new long[m + 1][n + 1]; - for (int[] p : prices) { - // {3, 5, 100} - // 0 1 2 - // dp[3][5] = 100 - dp[p[0]][p[1]] = p[2]; - } - for (int i = 1; i <= m; i++) { - for (int j = 1; j <= n; j++) { - // 垂直分割 - // i * j = 100 * 100 - // dp[100][1] + dp[100][99] - // dp[100][2] + dp[100][98] - // .. - for (int k = 1; k <= (j >> 1); k++) { - dp[i][j] = Math.max(dp[i][j], dp[i][k] + dp[i][j - k]); - } - // 水平分割 - // 100 * 100 - // 1) 1 * 100 + 99 * 100 - // 1) 2 * 100 + 98 * 100 - // i * j - // 1) 1 * j + (i - 1) * i; - // 2) 2 * j + (i - 2) * j; - // k) k * j + (i - k) * j; - for (int k = 1; k <= (i >> 1); k++) { - dp[i][j] = Math.max(dp[i][j], dp[k][j] + dp[i - k][j]); - } - } - } - return dp[m][n]; - } - -} diff --git a/公开课/class094/Code01_SortStackUsingRecursive.java b/公开课/class094/Code01_SortStackUsingRecursive.java deleted file mode 100644 index 0da47d5..0000000 --- a/公开课/class094/Code01_SortStackUsingRecursive.java +++ /dev/null @@ -1,205 +0,0 @@ -package class094; - -import java.util.Stack; - -// 栈只提供push、pop、isEmpty三个方法 -// 请完成无序栈的排序,要求排完序之后,从栈顶到栈底从小到大 -// 只能使用栈提供的push、pop、isEmpty三个方法、以及递归函数 -// 除此之外不能使用任何的容器,任何容器都不许,连数组也不行 -// 也不能自己定义任何结构体 -// 就是只用: -// 1) 栈提供的push、pop、isEmpty三个方法 -// 2) 简单返回值的递归函数 -public class Code01_SortStackUsingRecursive { - - public static void sortStack(Stack stack) { - int deep = deep(stack); - while (deep > 0) { - int max = max(stack, deep); - int k = times(stack, max, deep); - down(stack, deep, max, k); - deep -= k; - } - } - - // 返回栈的深度 - // stack push pop isEmpty - public static int deep(Stack stack) { - if (stack.isEmpty()) { - return 0; - } - int num = stack.pop(); - int deep = deep(stack) + 1; - stack.push(num); - return deep; - } - - // 从栈当前的顶部开始,往下数deep层 - //) 返回这deep层里的最大值 - public static int max(Stack stack, int deep) { - if (deep == 0) { - return Integer.MIN_VALUE; - } - int num = stack.pop(); - int restMax = max(stack, deep - 1); - int max = Math.max(num, restMax); - stack.push(num); - return max; - } - - // 从栈当前的顶部开始,往下数deep层,已知最大值是max了 - // 返回,max出现了几次,不改变栈的数据状况 - public static int times(Stack stack, int max, int deep) { - if (deep == 0) { - return 0; - } - int num = stack.pop(); - int restTimes = times(stack, max, deep - 1); - int times = restTimes + (num == max ? 1 : 0); - stack.push(num); - return times; - } - - // 从栈当前的顶部开始,往下数deep层,已知最大值是max,出现了k次 - // 请把这k个最大值沉底,剩下的数据状况不变 - public static void down(Stack stack, int deep, int max, int k) { - if (deep == 0) { - for (int i = 0; i < k; i++) { - stack.push(max); - } - } else { - int num = stack.pop(); - down(stack, deep - 1, max, k); - if (num != max) { - stack.push(num); - } - } - } - - public static void sort(Stack stack) { - int deep = size(stack); - while (deep > 0) { - int max = findMax(stack, deep); - int k = findMaxTimes(stack, deep, max); - maxDown(stack, deep, max, k); - deep -= k; - } - } - - // 求栈的大小 - // 但是不改变栈的任何数据状况 - public static int size(Stack stack) { - if (stack.isEmpty()) { - return 0; - } - int hold = stack.pop(); - int size = size(stack) + 1; - stack.push(hold); - return size; - } - - // 从stack顶部出发,只往下找deep层 - // 返回最大值 - // 完全不改变stack的任何数据状况 - public static int findMax(Stack stack, int deep) { - if (deep == 0) { - return Integer.MIN_VALUE; - } - int num = stack.pop(); - int restMax = findMax(stack, deep - 1); - int ans = Math.max(num, restMax); - stack.push(num); - return ans; - } - - // 已知从stack顶部出发,只往下找deep层,最大值是max - // 返回这个最大值出现了几次,只找到deep层!再往下不找了! - // 完全不改变stack的任何数据状况 - public static int findMaxTimes(Stack stack, int deep, int max) { - if (deep == 0) { - return 0; - } - int num = stack.pop(); - int times = findMaxTimes(stack, deep - 1, max); - times += num == max ? 1 : 0; - stack.push(num); - return times; - } - - // 已知从stack顶部出发,只往下找deep层,最大值是max - // 并且这个max出现了k次 - // 请把这k个max沉底,不是沉到stack整体的底部,而是到deep层 - // stack改变数据状况,但是只在从顶部到deep层的范围上改变 - public static void maxDown(Stack stack, int deep, int max, int k) { - if (deep == 0) { - for (int i = 0; i < k; i++) { - stack.push(max); - } - } else { - int cur = stack.pop(); - maxDown(stack, deep - 1, max, k); - if (cur < max) { - stack.push(cur); - } - } - } - - // 为了测试 - // 生成随机栈 - public static Stack generateRandomStack(int n, int v) { - Stack ans = new Stack(); - for (int i = 0; i < n; i++) { - ans.add((int) (Math.random() * v)); - } - return ans; - } - - // 为了测试 - // 检测栈是不是有序的 - public static boolean isSorted(Stack stack) { - int step = Integer.MIN_VALUE; - while (!stack.isEmpty()) { - if (step > stack.peek()) { - return false; - } - step = stack.pop(); - } - return true; - } - - // 为了测试 - public static void main(String[] args) { - Stack test = new Stack(); - test.add(7); - test.add(5); - test.add(4); - test.add(5); - test.add(3); - test.add(6); - test.add(3); - test.add(1); - test.add(4); - test.add(9); - // 1 5 4 5 3 2 3 1 4 2 - sortStack(test); - while (!test.isEmpty()) { - System.out.println(test.pop()); - } - - int N = 20; - int V = 20; - int testTimes = 20000; - System.out.println("测试开始"); - for (int i = 0; i < testTimes; i++) { - int n = (int) (Math.random() * N); - Stack stack = generateRandomStack(n, V); - sort(stack); - if (!isSorted(stack)) { - System.out.println("出错了!"); - break; - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class094/Code02_ReversePolishNotation.java b/公开课/class094/Code02_ReversePolishNotation.java deleted file mode 100644 index 90cf58d..0000000 --- a/公开课/class094/Code02_ReversePolishNotation.java +++ /dev/null @@ -1,101 +0,0 @@ -package class094; - -import java.util.Stack; - -// 给定一个逆波兰式 -// 转化成正确的中序表达式 -// 要求只有必要加括号的地方才加括号 -public class Code02_ReversePolishNotation { - - // 请保证给定的逆波兰式是正确的! - public static int getAns(String rpn) { - if (rpn == null || rpn.equals("")) { - return 0; - } - String[] parts = rpn.split(" "); - Stack stack = new Stack<>(); - for (String part : parts) { - if (part.equals("+") || part.equals("-") || part.equals("*") || part.equals("/")) { - int right = stack.pop(); - int left = stack.pop(); - int ans = 0; - if (part.equals("+")) { - ans = left + right; - } else if (part.equals("-")) { - ans = left - right; - } else if (part.equals("*")) { - ans = left * right; - } else { - ans = left / right; - } - stack.push(ans); - } else { - stack.push(Integer.valueOf(part)); - } - } - // stack 只有一个数,最终的结果 - return stack.pop(); - } - - enum Operation { - SingleNumber, AddOrMinus, MultiplyOrDivide; - } - - // 请保证输入的逆波兰式是正确的 - // 否则该函数不保证正确性 - // 逆波兰式仅支持+、-、*、/ - // 想支持更多算术运算符自己改 - public static String convert(String rpn) { - if (rpn == null || rpn.equals("")) { - return rpn; - } - String[] parts = rpn.split(" "); - // 表达式栈 - Stack stack1 = new Stack<>(); - // 类型栈 - Stack stack2 = new Stack<>(); - for (String cur : parts) { - if (cur.equals("+") || cur.equals("-")) { - String b = stack1.pop(); - String a = stack1.pop(); - stack2.pop(); - stack2.pop(); - stack1.push(a + cur + b); - stack2.push(Operation.AddOrMinus); - } else if (cur.equals("*") || cur.equals("/")) { - String b = stack1.pop(); - String a = stack1.pop(); - Operation bOp = stack2.pop(); - Operation aOp = stack2.pop(); - String left = aOp == Operation.AddOrMinus ? ("(" + a + ")") : (a); - String right = bOp == Operation.AddOrMinus ? ("(" + b + ")") : (b); - stack1.push(left + cur + right); - stack2.push(Operation.MultiplyOrDivide); - } else { - stack1.push(cur); - stack2.push(Operation.SingleNumber); - } - } - return stack1.pop(); - } - - public static void main(String[] args) { - - // 3 + 5 - // 3 5 + - - // 5 * ( 1 + 2) - // 5 1 2 + * - - // 3*(-5+13)+6/(2-3+2)-4*5*3 - // 24 + 6 - 60 - String rpn = "3 -5 13 + * 6 2 3 - 2 + / + 4 5 3 * * -"; - - System.out.println(getAns(rpn)); - - String ans = convert(rpn); - - System.out.println(ans); - } - -} diff --git a/公开课/class094/Code03_RightView.java b/公开课/class094/Code03_RightView.java deleted file mode 100644 index df65edf..0000000 --- a/公开课/class094/Code03_RightView.java +++ /dev/null @@ -1,97 +0,0 @@ -package class094; - -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.Queue; - -// 二叉树右视图, -// 有Leetcode测试链接 : https://leetcode.cn/problems/binary-tree-right-side-view/ -// 提交如下rightSideView方法,可以直接通过 -public class Code03_RightView { - - // 不要提交这个类 - public static class TreeNode { - int val; - TreeNode left; - TreeNode right; - - TreeNode(int v) { - val = v; - } - } - - public static void bfs(TreeNode head) { - Queue queue = new LinkedList<>(); - queue.add(head); - while (!queue.isEmpty()) { - TreeNode cur = queue.poll(); - if (cur.left != null) { - queue.add(cur.left); - } - if (cur.right != null) { - queue.add(cur.right); - } - } - } - - public static void bfs2(TreeNode head) { - Queue queue = new LinkedList<>(); - queue.add(head); - while (!queue.isEmpty()) { - int size = queue.size(); - for (int i = 0; i < size - 1; i++) { - TreeNode cur = queue.poll(); - if (cur.left != null) { - queue.add(cur.left); - } - if (cur.right != null) { - queue.add(cur.right); - } - } - - TreeNode cur = queue.poll(); - if (cur.left != null) { - queue.add(cur.left); - } - if (cur.right != null) { - queue.add(cur.right); - } - - } - } - - // 只提交下面的方法 - public static List rightSideView(TreeNode root) { - List ans = new ArrayList<>(); - if (root == null) { - return ans; - } - Queue queue = new LinkedList<>(); - queue.add(root); - while (!queue.isEmpty()) { - int size = queue.size(); - TreeNode cur = queue.poll(); - ans.add(cur.val); - if (cur.right != null) { - queue.add(cur.right); - } - if (cur.left != null) { - queue.add(cur.left); - } - size--; - while (size > 0) { - cur = queue.poll(); - if (cur.right != null) { - queue.add(cur.right); - } - if (cur.left != null) { - queue.add(cur.left); - } - size--; - } - } - return ans; - } - -} diff --git a/公开课/class095/Code01_NumberOfPeopleAwareOfASecret.java b/公开课/class095/Code01_NumberOfPeopleAwareOfASecret.java deleted file mode 100644 index fdf89a5..0000000 --- a/公开课/class095/Code01_NumberOfPeopleAwareOfASecret.java +++ /dev/null @@ -1,63 +0,0 @@ -package class095; - -// 在第 1 天,有一个人发现了一个秘密。 -// 给你一个整数 delay ,表示每个人会在发现秘密后的 delay 天之后, -// 每天 给一个新的人 分享 秘密。 -// 同时给你一个整数 forget ,表示每个人在发现秘密 forget 天之后会 忘记 这个秘密。 -// 一个人 不能 在忘记秘密那一天及之后的日子里分享秘密。 -// 给你一个整数 n ,请你返回在第 n 天结束时,知道秘密的人数。 -// 由于答案可能会很大,请你将结果对 109 + 7 取余 后返回。 -// 测试链接 : https://leetcode.cn/problems/number-of-people-aware-of-a-secret/ -public class Code01_NumberOfPeopleAwareOfASecret { - - // 1天 。。。。 n天 - public static int peopleAwareOfSecret(int n, int delay, int forget) { - long mod = 1000000007; - // 从第1天开始,每一天到来的时候,争取把这三个数组正确的人数填对 - // dpKnow[i], 第i天知道秘密的人 - long[] dpKnow = new long[n + 1]; - // dpForget[i], 第i天将要忘记秘密的人 - long[] dpForget = new long[n + 1]; - // dpShare[i], 第i天可以分享秘密的人 - long[] dpShare = new long[n + 1]; - - // 第1天的时候,知道秘密的人1个,A - // 第1天的时候,将要忘记秘密的人0个 - // 第1天的时候,可以分享秘密的人0个 - dpKnow[1] = 1; - if (1 + forget <= n) { - dpForget[1 + forget] = 1; - } - if (1 + delay <= n) { - dpShare[1 + delay] = 1; - } - // 从第2天开始!i - for (int i = 2; i <= n; i++) { - // 第i天 - // dpKnow[i - 1] - dpForget[i] + dpShare[i] - dpKnow[i] = (mod + dpKnow[i - 1] - dpForget[i] + dpShare[i]) % mod; - - - - - // 第i天,新增知道秘密的,dpShare[i] - if (i + forget <= n) { - - // dpShare[i] 是第i天,刚知道秘密的人! - // 这批人,会在i + forget天,都忘了! - dpForget[i + forget] = dpShare[i]; - } - if (i + delay <= n) { - // dpShare[i + delay - 1] + dpShare[i] - dpForget[i + delay] - // i + delay 天 , 100天后,会分享秘密的人 - // 第i天,有一些新人,i + delay天分享,一部分, dpShare[i] - // 第二部分呢?i + delay - 1天,知道秘密并且会散播的人,- dpForget[i + delay] - dpShare[i + delay] = - (mod + dpShare[i + delay - 1] - dpForget[i + delay] - + dpShare[i]) % mod; - } - } - return (int) dpKnow[n]; - } - -} diff --git a/公开课/class095/Code02_MaxNumberUnderLimit.java b/公开课/class095/Code02_MaxNumberUnderLimit.java deleted file mode 100644 index 2c6f765..0000000 --- a/公开课/class095/Code02_MaxNumberUnderLimit.java +++ /dev/null @@ -1,213 +0,0 @@ -package class095; - -import java.util.Arrays; - -// 来自字节 -// 输入: -// 去重数组arr,里面的数只包含0~9 -// limit,一个数字 -// 返回: -// 要求比limit小的情况下,能够用arr拼出来的最大数字 -public class Code02_MaxNumberUnderLimit { - - public static int tmp = 0; - - // 暴力尝试的方法 limit -1 -2 -3 -4 - public static int maxNumber1(int[] arr, int limit) { - tmp = 0; - Arrays.sort(arr); - limit--; - int offset = 1; - while (offset <= limit / 10) { - offset *= 10; - } - process1(arr, 0, offset, limit); - if (tmp == 0) { - int rest = 0; - offset /= 10; - while (offset > 0) { - rest += arr[arr.length - 1] * offset; - offset /= 10; - } - return rest; - } - return tmp; - } - - public static void process1(int[] arr, int num, int offset, int limit) { - if (offset == 0) { - if (num <= limit) { - tmp = Math.max(tmp, num); - } - } else { - for (int cur : arr) { - process1(arr, num * 10 + cur, offset / 10, limit); - } - } - } - - // 正式方法 - // 用arr中的数字去拼,< limit ,尽量大 - // 能拼出来尽量大的数字,返回 - public static int maxNumber2(int[] arr, int limit) { - // [6,2,8] [8,2,6] [2,6,8] - Arrays.sort(arr); - // limit - 1 - limit--; - // <= limit,尽量大即可 - // limit : 657321 - // offset: 100000 - // 当前数 : (limit / offset) % 10 -> 6 - // 下一个 : - // limit : 657321 - // offset: 10000 - // 当前数 : (limit / offset) % 10 -> 5 - // 下一个 : - // limit : 657321 - // offset: 1000 - // 当前数 : (limit / offset) % 10 -> 7 - int offset = 1; - while (offset <= limit / 10) { - offset *= 10; - } - - // 不要这么写,可能溢出! -// while(offset <= limit) { -// offset *=10; -// } -// offset /=10; - - - // limit : 65431098 - // offset: 10000000 - // arr中的数字,<=limit, offset方便我提取数字用的! - // limit : 65431098 - // process2 : 拼出来的数字,和limit位数一定要一样长!!!! - // 返回尽量大的数字! - // 如果拼出来的数字,无法和limit位数一样长,返回-1 - int ans = process2(arr, limit, offset); - if (ans != -1) { - return ans; - } else { - // limit : 65431098 - // offset: 1000000 - // arr[5] - // 5000000 -// 500000 -// 50000 - offset /= 10; - int rest = 0; - while (offset > 0) { - rest += arr[arr.length - 1] * offset; - offset /= 10; - } - return rest; - } - } - - // 可以用arr中的数字! - // 去拼<=limit,尽量大!位数一定要和limit一样长 - // offset是用来取数字的! - // limit = 876530 - // offset= 1000 - // 87这两位,一定做的决定是:追平!而且真的追平了! - public static int process2(int[] arr, int limit, int offset) { - // limit = 876530 - // offset= 0 - if (offset == 0) { - return limit; - } - // limit = 876530 - // offset= 1000 - int cur = (limit / offset) % 10; - // 当前数字已经知道了cur - // 去arr中拿数字试图追平! - // 6 - // 1) 拿到了能追平的数字 - // 2) 没拿到能追平的数字,但又较小的数字 - // 3) <=当前想追平的数字,都不存在 -1 - int near = near(arr, cur); - if (near == -1) { - return -1; - } else if (arr[near] == cur) { // 1) 拿到了能追平的数字 - // 当前位达成了! - int ans = process2(arr, limit, offset / 10); - if (ans != -1) { // 后续计算出了最优结果! - return ans; - } else if (near > 0) { - near--; - return (limit / (offset * 10)) * offset * 10 + (arr[near] * offset) + rest(arr, offset / 10); - } else { // 后续搞不定!当前位也没有办法再下降了 - return -1; - } - } else { - return (limit / (offset * 10)) * offset * 10 + (arr[near] * offset) + rest(arr, offset / 10); - } - } - - public static int rest(int[] arr, int offset) { - int rest = 0; - while (offset > 0) { - rest += arr[arr.length - 1] * offset; - offset /= 10; - } - return rest; - } - - public static int near(int[] arr, int num) { - int l = 0; - int r = arr.length - 1; - int m = 0; - int near = -1; - while (l <= r) { - m = (l + r) / 2; - if (arr[m] <= num) { - near = m; - l = m + 1; - } else { - r = m - 1; - } - } - return near; - } - - // 为了测试 - public static int[] randomArray() { - int[] arr = new int[(int) (Math.random() * 10) + 1]; - boolean[] cnt = new boolean[10]; - for (int i = 0; i < arr.length; i++) { - do { - arr[i] = (int) (Math.random() * 10); - } while (cnt[arr[i]]); - cnt[arr[i]] = true; - } - return arr; - } - - public static void main(String[] args) { - int max = 3000; - int testTime = 100; - System.out.println("测试开始"); - for (int i = 0; i < max; i++) { - int[] arr = randomArray(); - for (int j = 0; j < testTime; j++) { - int ans1 = maxNumber1(arr, i); - int ans2 = maxNumber2(arr, i); - if (ans1 != ans2) { - System.out.println("出错了!"); - System.out.println("数组为 :"); - for (int num : arr) { - System.out.print(num + " "); - } - System.out.println(); - System.out.println("数字为 :" + i); - System.out.println(ans1); - System.out.println(ans2); - } - } - } - System.out.println("测试结束"); - - } - -} diff --git a/公开课/class095/Code03_SwimInRisingWater.java b/公开课/class095/Code03_SwimInRisingWater.java deleted file mode 100644 index 4267297..0000000 --- a/公开课/class095/Code03_SwimInRisingWater.java +++ /dev/null @@ -1,155 +0,0 @@ -package class095; - -import java.util.Arrays; -import java.util.PriorityQueue; - -// 在一个 n x n 的整数矩阵 grid 中, -// 每一个方格的值 grid[i][j] 表示位置 (i, j) 的平台高度。 -// 当开始下雨时,在时间为 t 时,水池中的水位为 t 。 -// 你可以从一个平台游向四周相邻的任意一个平台,但是前提是此时水位必须同时淹没这两个平台。 -// 假定你可以瞬间移动无限距离,也就是默认在方格内部游动是不耗时的。 -// 当然,在你游泳的时候你必须待在坐标方格里面。 -// 你从坐标方格的左上平台 (0,0) 出发。 -// 返回 你到达坐标方格的右下平台 (n-1, n-1) 所需的最少时间 。 -// 测试链接 :https://leetcode.cn/problems/swim-in-rising-water -public class Code03_SwimInRisingWater { - - // 并查集的解法 - public static int swimInWater1(int[][] grid) { - // 行号 - int n = grid.length; - // 列号 - int m = grid[0].length; - // [0,0,5] - // [0,1,3].... - int[][] points = new int[n * m][3]; - int pi = 0; - for (int i = 0; i < n; i++) { - for (int j = 0; j < m; j++) { - points[pi][0] = i; - points[pi][1] = j; - points[pi++][2] = grid[i][j]; - } - } - // 所有格子小对象,生成好了! - // 排序![a,b,c] [d,e,f] - Arrays.sort(points, (a, b) -> a[2] - b[2]); - // 生成并查集!n * m - // 初始化的时候,把所有格子独自成一个集合! - UnionFind uf = new UnionFind(n, m); - int ans = 0; - for (int i = 0; i < points.length; i++) { - int r = points[i][0]; - int c = points[i][1]; - int v = points[i][2]; - if (r > 0 && grid[r - 1][c] <= v) { - uf.union(r, c, r - 1, c); - } - if (r < n - 1 && grid[r + 1][c] <= v) { - uf.union(r, c, r + 1, c); - } - if (c > 0 && grid[r][c - 1] <= v) { - uf.union(r, c, r, c - 1); - } - if (c < m - 1 && grid[r][c + 1] <= v) { - uf.union(r, c, r, c + 1); - } - if (uf.isSameSet(0, 0, n - 1, m - 1)) { - ans = v; - break; - } - } - return ans; - } - - public static class UnionFind { - public int col; - public int pointsSize; - public int[] father; - public int[] size; - public int[] help; - - public UnionFind(int n, int m) { - col = m; - pointsSize = n * m; - father = new int[pointsSize]; - size = new int[pointsSize]; - help = new int[pointsSize]; - for (int i = 0; i < pointsSize; i++) { - father[i] = i; - size[i] = 1; - } - } - - private int find(int i) { - int hi = 0; - while (i != father[i]) { - help[hi++] = i; - i = father[i]; - } - while (hi > 0) { - father[help[--hi]] = i; - } - return i; - } - - private int index(int i, int j) { - return i * col + j; - } - - public void union(int row1, int col1, int row2, int col2) { - int f1 = find(index(row1, col1)); - int f2 = find(index(row2, col2)); - if (f1 != f2) { - if (size[f1] >= size[f2]) { - father[f2] = f1; - size[f1] += size[f2]; - } else { - father[f1] = f2; - size[f2] += size[f1]; - } - } - } - - public boolean isSameSet(int row1, int col1, int row2, int col2) { - return find(index(row1, col1)) == find(index(row2, col2)); - } - - } - - // Dijkstra算法 - public static int swimInWater2(int[][] grid) { - int n = grid.length; - int m = grid[0].length; - PriorityQueue heap = new PriorityQueue<>((a, b) -> a[2] - b[2]); - boolean[][] visited = new boolean[n][m]; - heap.add(new int[] { 0, 0, grid[0][0] }); - int ans = 0; - while (!heap.isEmpty()) { - int r = heap.peek()[0]; - int c = heap.peek()[1]; - int v = heap.peek()[2]; - heap.poll(); - if (visited[r][c]) { - continue; - } - visited[r][c] = true; - if (r == n - 1 && c == m - 1) { - ans = v; - break; - } - add(grid, heap, visited, r - 1, c, v); - add(grid, heap, visited, r + 1, c, v); - add(grid, heap, visited, r, c - 1, v); - add(grid, heap, visited, r, c + 1, v); - } - return ans; - } - - public static void add(int[][] grid, PriorityQueue heap, boolean[][] visited, int r, int c, int preV) { - if (r >= 0 && r < grid.length && c >= 0 && c < grid[0].length && !visited[r][c]) { - heap.add(new int[] { r, c, preV + Math.max(0, grid[r][c] - preV) }); - } - } - -} diff --git a/公开课/class096/Code01_ParenthesesDye.java b/公开课/class096/Code01_ParenthesesDye.java deleted file mode 100644 index d779ea9..0000000 --- a/公开课/class096/Code01_ParenthesesDye.java +++ /dev/null @@ -1,169 +0,0 @@ -package class096; - -// 来自猿辅导 -// 2022.8.7笔试第三道 -// 给定一个数组arr,和一个正数k -// 如果arr[i] == 0,表示i这里既可以是左括号也可以是右括号, -// 而且可以涂上1~k每一种颜色 -// 如果arr[i] != 0,表示i这里已经确定是左括号,颜色就是arr[i]的值 -// 那么arr整体就可以变成某个括号字符串,并且每个括号字符都带有颜色 -// 返回在括号字符串合法的前提下,有多少种不同的染色方案 -// 不管是排列、还是颜色,括号字符串任何一点不一样,就算不同的染色方案 -// 最后的结果%10001,为了方便,我们不处理mod,就管核心思路 -// 2 <= arr长度 <= 5000 -// 1 <= k <= 1000 -// 0 <= arr[i] <= k -public class Code01_ParenthesesDye { - - // 暴力方法 - // 为了验证 - public static int ways1(int[] arr, int k) { - if ((arr.length & 1) != 0) { - return 0; - } - return process1(arr, 0, k); - } - - public static int process1(int[] arr, int index, int k) { - if (index == arr.length) { - int n = arr.length; - int[] stack = new int[n]; - int size = 0; - for (int i = 0; i < n; i++) { - if (arr[i] > 0) { - stack[size++] = arr[i]; - } else { - if (size == 0 || stack[--size] != -arr[i]) { - return 0; - } - } - } - return size == 0 ? 1 : 0; - } else if (arr[index] != 0) { - return process1(arr, index + 1, k); - } else { - int ans = 0; - for (int color = 1; color <= k; color++) { - arr[index] = color; - ans += process1(arr, index + 1, k); - arr[index] = -color; - ans += process1(arr, index + 1, k); - arr[index] = 0; - } - return ans; - } - } - - // 正式方法 - // 时间复杂度O(N^2), N是数组长度 - // 首先求合法的括号组合数量(忽略染色这件事), - // 就是combines方法,看注释 - // 当括号数量求出来,再看染色能有几种 - // 比如忽略颜色,某个合法的括号结合 长度为n, - // 如果已经有b个涂上了颜色,而且是左括号 - // 那么,因为该结合是合法的, - // 所以这b个涂上了颜色的左括号,和哪些右括号结合, - // 其实是确定的,这些右括号颜色也是确定的 - // 那么还剩n-(b*2)个字符 - // 这n-(b*2)个字符,就是(n-(b*2))/2对括号 - // 每对括号都可以自由发挥,所以,任何一个合法的组合,涂色方案为k^((n-(b*2))/2) - // 最终答案 : 合法括号组合数量 * k^((n-(b*2))/2) - public static int ways2(int[] arr, int k) { - int n = arr.length; - if ((n & 1) != 0) { - return 0; - } - int a = combines(arr); - int b = 0; - for (int num : arr) { - if (num != 0) { - b++; - } - } - return a * ((int) Math.pow((double) k, (double) ((n - (b << 1)) >> 1))); - } - - // 忽略染色这件事,求合法的括号结合数量 - public static int combines(int[] arr) { - int n = arr.length; - int[][] dp = new int[n][n]; - for (int i = 0; i < n; i++) { - for (int j = 0; j < n; j++) { - dp[i][j] = -1; - } - } - return f(arr, 0, 0, dp); - } - - // 在arr[i...]范围上做决定 - // 之前在arr[0...i-1]上的决定,使得左括号比右括号多了j个 - // 最终合法的括号结合是多少 - public static int f(int[] arr, int i, int j, int[][] dp) { - int n = arr.length; - if (i == n) { - return j == 0 ? 1 : 0; - } - if (j < 0) { - return 0; - } - // i.... n-i(10个) ...(11个) - if (n - i < j) { - return 0; - } - // 如果缓存命中,直接返回答案 - if (dp[i][j] != -1) { - return dp[i][j]; - } - int ans = 0; - if (arr[i] > 0) { - ans = f(arr, i + 1, j + 1, dp); - } else { - ans = f(arr, i + 1, j + 1, dp) + f(arr, i + 1, j - 1, dp); - } - dp[i][j] = ans; - return ans; - } - - // 生成长度随机的数组 - // 值在0~K之间,但是50%的概率值是0,50%的概率值是1~k中的一个 - public static int[] randomArray(int n, int k) { - int[] ans = new int[n]; - for (int i = 0; i < n; i++) { - ans[i] = Math.random() < 0.5 ? 0 : ((int) (Math.random() * k) + 1); - } - return ans; - } - - public static void main(String[] args) { - int N = 5; - int K = 4; - int testTimes = 1000; - System.out.println("功能测试开始"); - for (int i = 0; i < testTimes; i++) { - int n = ((int) (Math.random() * N) + 1) << 1; - int k = (int) (Math.random() * K) + 1; - int[] arr = randomArray(n, k); - int ans1 = ways1(arr, k); - int ans2 = ways2(arr, k); - if (ans1 != ans2) { - System.out.println("出错了!"); - } - } - System.out.println("功能测试结束"); - - System.out.println("性能测试开始"); - int n = 5000; - int k = 1000; - System.out.println("数组长度 : " + n); - System.out.println("颜色数量 : " + k); - int[] arr = randomArray(n, k); - long start = System.currentTimeMillis(); - ways2(arr, k); - long end = System.currentTimeMillis(); - System.out.println("运行时间 : " + (end - start) + "毫秒"); - System.out.println("性能测试结束"); - - System.out.println("注意 : 这个解答没有取mod,只展示了核心思路"); - } - -} diff --git a/公开课/class096/Code02_ShortestImpossibleSequenceOfRolls.java b/公开课/class096/Code02_ShortestImpossibleSequenceOfRolls.java deleted file mode 100644 index 9f02f9e..0000000 --- a/公开课/class096/Code02_ShortestImpossibleSequenceOfRolls.java +++ /dev/null @@ -1,38 +0,0 @@ -package class096; - -import java.util.Arrays; - -// 给你一个长度为 n 的整数数组 rolls 和一个整数 k 。 -// 你扔一个 k 面的骰子 n 次,骰子的每个面分别是 1 到 k , -// 其中第 i 次扔得到的数字是 rolls[i] 。 -// 请你返回 无法 从 rolls 中得到的 最短 骰子子序列的长度。 -// 扔一个 k 面的骰子 len 次得到的是一个长度为 len 的 骰子子序列 。 -// 注意 ,子序列只需要保持在原数组中的顺序,不需要连续。 -// 测试链接 : https://leetcode.cn/problems/shortest-impossible-sequence-of-rolls/ -public class Code02_ShortestImpossibleSequenceOfRolls { - - // 所有数字1~k - public static int shortestSequence(int[] rolls, int k) { - // 1~k上,某个数字是否收集到了! - // set[i] == true - // set[i] == false - boolean[] set = new boolean[k + 1]; - // 当前这一套,收集了几个数字了? - int size = 0; - // 一共能收集全几套 - int ans = 0; - for (int num : rolls) { - if (!set[num]) { - set[num] = true; - size++; - } - if (size == k) { - ans++; - Arrays.fill(set, false); - size = 0; - } - } - return ans + 1; - } - -} diff --git a/公开课/class096/Code03_SwimInRisingWater.java b/公开课/class096/Code03_SwimInRisingWater.java deleted file mode 100644 index 8253f5f..0000000 --- a/公开课/class096/Code03_SwimInRisingWater.java +++ /dev/null @@ -1,155 +0,0 @@ -package class096; - -import java.util.Arrays; -import java.util.PriorityQueue; - -// 在一个 n x n 的整数矩阵 grid 中, -// 每一个方格的值 grid[i][j] 表示位置 (i, j) 的平台高度。 -// 当开始下雨时,在时间为 t 时,水池中的水位为 t 。 -// 你可以从一个平台游向四周相邻的任意一个平台,但是前提是此时水位必须同时淹没这两个平台。 -// 假定你可以瞬间移动无限距离,也就是默认在方格内部游动是不耗时的。 -// 当然,在你游泳的时候你必须待在坐标方格里面。 -// 你从坐标方格的左上平台 (0,0) 出发。 -// 返回 你到达坐标方格的右下平台 (n-1, n-1) 所需的最少时间 。 -// 测试链接 :https://leetcode.cn/problems/swim-in-rising-water -public class Code03_SwimInRisingWater { - - // 并查集的解法 - public static int swimInWater1(int[][] grid) { - // 行号 - int n = grid.length; - // 列号 - int m = grid[0].length; - // [0,0,5] - // [0,1,3].... - int[][] points = new int[n * m][3]; - int pi = 0; - for (int i = 0; i < n; i++) { - for (int j = 0; j < m; j++) { - points[pi][0] = i; - points[pi][1] = j; - points[pi++][2] = grid[i][j]; - } - } - // 所有格子小对象,生成好了! - // 排序![a,b,c] [d,e,f] - Arrays.sort(points, (a, b) -> a[2] - b[2]); - // 生成并查集!n * m - // 初始化的时候,把所有格子独自成一个集合! - UnionFind uf = new UnionFind(n, m); - int ans = 0; - for (int i = 0; i < points.length; i++) { - int r = points[i][0]; - int c = points[i][1]; - int v = points[i][2]; - if (r > 0 && grid[r - 1][c] <= v) { - uf.union(r, c, r - 1, c); - } - if (r < n - 1 && grid[r + 1][c] <= v) { - uf.union(r, c, r + 1, c); - } - if (c > 0 && grid[r][c - 1] <= v) { - uf.union(r, c, r, c - 1); - } - if (c < m - 1 && grid[r][c + 1] <= v) { - uf.union(r, c, r, c + 1); - } - if (uf.isSameSet(0, 0, n - 1, m - 1)) { - ans = v; - break; - } - } - return ans; - } - - public static class UnionFind { - public int col; - public int pointsSize; - public int[] father; - public int[] size; - public int[] help; - - public UnionFind(int n, int m) { - col = m; - pointsSize = n * m; - father = new int[pointsSize]; - size = new int[pointsSize]; - help = new int[pointsSize]; - for (int i = 0; i < pointsSize; i++) { - father[i] = i; - size[i] = 1; - } - } - - private int find(int i) { - int hi = 0; - while (i != father[i]) { - help[hi++] = i; - i = father[i]; - } - while (hi > 0) { - father[help[--hi]] = i; - } - return i; - } - - private int index(int i, int j) { - return i * col + j; - } - - public void union(int row1, int col1, int row2, int col2) { - int f1 = find(index(row1, col1)); - int f2 = find(index(row2, col2)); - if (f1 != f2) { - if (size[f1] >= size[f2]) { - father[f2] = f1; - size[f1] += size[f2]; - } else { - father[f1] = f2; - size[f2] += size[f1]; - } - } - } - - public boolean isSameSet(int row1, int col1, int row2, int col2) { - return find(index(row1, col1)) == find(index(row2, col2)); - } - - } - - // Dijkstra算法 - public static int swimInWater2(int[][] grid) { - int n = grid.length; - int m = grid[0].length; - PriorityQueue heap = new PriorityQueue<>((a, b) -> a[2] - b[2]); - boolean[][] visited = new boolean[n][m]; - heap.add(new int[] { 0, 0, grid[0][0] }); - int ans = 0; - while (!heap.isEmpty()) { - int r = heap.peek()[0]; - int c = heap.peek()[1]; - int v = heap.peek()[2]; - heap.poll(); - if (visited[r][c]) { - continue; - } - visited[r][c] = true; - if (r == n - 1 && c == m - 1) { - ans = v; - break; - } - add(grid, heap, visited, r - 1, c, v); - add(grid, heap, visited, r + 1, c, v); - add(grid, heap, visited, r, c - 1, v); - add(grid, heap, visited, r, c + 1, v); - } - return ans; - } - - public static void add(int[][] grid, PriorityQueue heap, boolean[][] visited, int r, int c, int preV) { - if (r >= 0 && r < grid.length && c >= 0 && c < grid[0].length && !visited[r][c]) { - heap.add(new int[] { r, c, preV + Math.max(0, grid[r][c] - preV) }); - } - } - -} diff --git a/公开课/class096/Code04_LongestOneLetterManyNumberString.java b/公开课/class096/Code04_LongestOneLetterManyNumberString.java deleted file mode 100644 index a3cdb00..0000000 --- a/公开课/class096/Code04_LongestOneLetterManyNumberString.java +++ /dev/null @@ -1,108 +0,0 @@ -package class096; - -// 给定一个只由小写字母和数字字符组成的字符串str -// 要求子串必须只含有一个小写字母,数字字符数量随意 -// 求这样的子串最大长度是多少 -public class Code04_LongestOneLetterManyNumberString { - - // 一个绝对正确的暴力方法 - public static int right(String s) { - char[] str = s.toCharArray(); - int ans = 0; - for (int i = 0; i < str.length; i++) { - for (int j = i; j < str.length; j++) { - if (check(str, i, j)) { - ans = Math.max(ans, j - i + 1); - } - } - } - return ans; - } - - public static boolean check(char[] str, int l, int r) { - int letterNumber = 0; - for (int i = l; i <= r; i++) { - if (str[i] >= 'a' && str[i] <= 'z') { - letterNumber++; - } - } - return letterNumber == 1; - } - - // 用窗口 - // 时间复杂度O(N) - public static int zuo(String s) { - char[] str = s.toCharArray(); - int n = str.length; - // 窗口内小写字母的数量 - int letters = 0; - // 右边界 - // 0.....5 6(x) - // [Left, right) - // [Left, right-1] - // [0,0) -> 代表窗口一个数也没有 - int right = 0; - int ans = 0; - // 窗口开始的位置left - // 枚举了窗口每一个开始的位置 - for (int left = 0; left < n; left++) { - // left......right(停!) - while (right < n) { // right不能越界 - if (letters == 1 - && str[right] >= 'a' - && str[right] <= 'z') { - break; - } - // right往右扩! - if (str[right] >= 'a' && str[right] <= 'z') { - letters++; - } - right++; - } - // right已经来到X的位置 - // left......... X - if (letters == 1) { - ans = Math.max(ans, right - left); - } - // left 往右 吐出一个字符 - if (str[left] >= 'a' && str[left] <= 'z') { - letters--; - } - } - return ans; - } - - // 为了测试 - public static char[] chars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', - 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; - - // 为了测试 - public static String randomString(int n) { - char[] str = new char[n]; - for (int i = 0; i < n; i++) { - str[i] = chars[(int) (Math.random() * chars.length)]; - } - return String.valueOf(str); - } - - // 为了测试 - public static void main(String[] args) { - int N = 100; - int testTimes = 10000; - System.out.println("测试开始"); - for (int i = 0; i < testTimes; i++) { - int n = (int) (Math.random() * N) + 1; - String str = randomString(n); - int ans1 = right(str); - int ans2 = zuo(str); - if (ans1 != ans2) { - System.out.println(str); - System.out.println(ans1); - System.out.println(ans2); - break; - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class097/Code01_Cakes.java b/公开课/class097/Code01_Cakes.java deleted file mode 100644 index 79f6635..0000000 --- a/公开课/class097/Code01_Cakes.java +++ /dev/null @@ -1,116 +0,0 @@ -package class097; - -// 有a块草莓蛋糕,有b块芝士蛋糕,两人轮流拿蛋糕 -// 每次不管是谁只能选择在草莓蛋糕和芝士蛋糕中拿一种 -// 拿的数量在1~m之间随意 -// 谁先拿完最后的蛋糕谁赢 -// 返回先手赢还是后手赢 -public class Code01_Cakes { - - // 草莓蛋糕a块 - // 巧克力蛋糕b块 - // 每次可以在任意一种上拿1~m块 - // 返回谁会赢,"先手" or "后手" - public static String[][][] dp = new String[101][101][101]; - - // 暴力方法 - // 为了验证 - public static String whoWin1(int a, int b, int m) { - if (m >= Math.max(a, b)) { // nim博弈 - return a != b ? "先手" : "后手"; - } - if (a == b) { - // 蛋糕一样多 - // 先手必输,因为先手不管拿什么,拿多少 - // 后手都在另一堆上,拿同样多的蛋糕 - // 继续让两堆蛋糕一样多 - // 最终先手必输,后手必赢 - return "后手"; - } - if (dp[a][b][m] != null) { - return dp[a][b][m]; - } - String ans = "后手"; - for (int pick = 1; pick <= Math.min(a, m); pick++) { - if (whoWin1(a - pick, b, m).equals("后手")) { - ans = "先手"; - } - if (ans.equals("先手")) { - break; - } - } - for (int pick = 1; pick <= Math.min(b, m); pick++) { - if (whoWin1(a, b - pick, m).equals("后手")) { - ans = "先手"; - } - if (ans.equals("先手")) { - break; - } - } - dp[a][b][m] = ans; - return ans; - } - - // 正式解法 - // 时间复杂度O(1) - // 先看nim博弈 - public static String whoWin2(int a, int b, int m) { - if (m >= Math.max(a, b)) { // nim博弈 - return a != b ? "先手" : "后手"; - } - if (a == b) { - // 蛋糕一样多 - // 先手必输,因为先手不管拿什么,拿多少 - // 后手都在另一堆上,拿同样多的蛋糕 - // 继续让两堆蛋糕一样多 - // 最终先手必输,后手必赢 - return "后手"; - } - // 如果 a != b - // 关注a和b的差值, - // 谁最先遇到差值为0,谁输 - // 那么这就是巴什博奕 - // 差值蛋糕数量共rest个。 - // 每次从最少取1个,最多取m个,最后取光的人取胜。 - // 如果rest=(m+1)*k + s (s!=0) 那么先手一定必胜 - // 因为第一次取走s个, - // 接下来无论对手怎么取, - // 先手都能保证取到所有(m+1)倍数的点, - // 那么循环下去一定能取到差值最后一个。 - int rest = Math.max(a, b) - Math.min(a, b); - return rest % (m + 1) != 0 ? "先手" : "后手"; - } - - public static void main(String[] args) { - -// int a = 7; -// int b = 5; -// int c = 1; -// // [. . .....] ^ != 0 -// // ^ == 0 -// System.out.println((a ^ b ^ c)); - -// - int V = 100; - System.out.println("测试开始"); - for (int a = 0; a <= V; a++) { - for (int b = 0; b <= V; b++) { - for (int m = 0; m <= V; m++) { - String ans1 = whoWin1(a, b, m); - String ans2 = whoWin2(a, b, m); - if (!ans1.equals(ans2)) { - System.out.println("出错了!"); - System.out.println("a : " + a); - System.out.println("b : " + b); - System.out.println("m : " + m); - System.out.println("ans1 : " + ans1); - System.out.println("ans2 : " + ans2); - break; - } - } - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class097/Code02_MinAddToMatch.java b/公开课/class097/Code02_MinAddToMatch.java deleted file mode 100644 index e3afa3f..0000000 --- a/公开课/class097/Code02_MinAddToMatch.java +++ /dev/null @@ -1,121 +0,0 @@ -package class097; - -// 测试链接 : https://www.nowcoder.com/practice/e391767d80d942d29e6095a935a5b96b -// 提交如下代码,把主类名改成Main,可以直接通过 -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; - -public class Code02_MinAddToMatch { - - public static void main(String[] args) throws IOException { - BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); - String line; - while ((line = br.readLine()) != null) { - System.out.println(minAdd(line.toCharArray())); - } - } - - // 主 zuo(str, 0, str.length - 1) - // str[L.....R]这个范围的字符串 - // 整体变成合法的,返回至少添加几个字符,能做到! - public static int zuo(char[] str, int L, int R) { - if (L == R) { - // str[L...R]只剩一个字符了 - // ( or ) or [ or ] - return 1; - } - if (L == R - 1) { - // str[L...R]只剩两个字符了 - // () 0 - // [] 0 - if ((str[L] == '(' && str[R] == ')') || (str[L] == '[' && str[R] == ']')) { - return 0; - } - return 2; - } - // 第一大类 : str[L....R]本身是最大的嵌套! - // 可能性1 : str[L]和str[R],自消化! - int p1LRkill = Integer.MAX_VALUE; - if ((str[L] == '(' && str[R] == ')') || (str[L] == '[' && str[R] == ']')) { - p1LRkill = zuo(str, L + 1, R - 1); - } - // 可能性2 : str[L]和str[R],无法自消化! - int p1lastL = 1 + zuo(str, L + 1, R); - int p1LasrR = zuo(str, L, R - 1) + 1; - - int p1 = Math.max(Math.min(p1LRkill, p1lastL), p1LasrR); - - // 第二大类 : str[L....R] 合法 + 合法,并列关系! - - int p2 = Integer.MAX_VALUE; - for (int m = L; m < R; m++) { - p2 = Math.min(p2, zuo(str, L, m) + zuo(str, m + 1, R)); - } - return Math.min(p1, p2); - } - - public static int minAdd(char[] s) { - int n = s.length; - int[][] dp = new int[n][n]; - for (int i = 0; i < n; i++) { - for (int j = 0; j < n; j++) { - dp[i][j] = -1; - } - } - return process(s, 0, s.length - 1, dp); - } - - // 让s[l...r]都完美匹配 - // 至少需要加几个字符 - public static int process(char[] s, int l, int r, int[][] dp) { - // 只有一个字符,不管是什么,要想配对,都需要添加一个字符 - if (l == r) { - return 1; - } - // 只有两个字符, - // 如果是()、[],那什么也不需要添加 - // 否则,都需要添加2个字符 - if (l == r - 1) { - if ((s[l] == '(' && s[r] == ')') || (s[l] == '[' && s[r] == ']')) { - return 0; - } - return 2; - } - if (dp[l][r] != -1) { - return dp[l][r]; - } - // 重点是如下的过程 - // 可能性1,先搞定l+1...r,然后搞定l - // 比如s[l...r] = ([][] - // 先搞定[][],需要添加0个,然后搞定(,需要添加1个 - // 整体变成([][])搞定 - int p1 = 1 + process(s, l + 1, r, dp); - // 可能性2,先搞定l...r-1,然后搞定r - // 和可能性1同理 - int p2 = 1 + process(s, l, r - 1, dp); - // 可能性3,s[l]和s[r]天然匹配,需要搞定的就是l+1..r-1 - // 比如([[),搞定中间的[[,就是最优解了 - int p3 = Integer.MAX_VALUE; - if ((s[l] == '(' && s[r] == ')') || (s[l] == '[' && s[r] == ']')) { - p3 = process(s, l + 1, r - 1, dp); - } - // 可能性后续:可能,最优解并不是l....r整体变成最大的嵌套 - // 而是,并列关系! - // l....split 先变成合法 - // split+1...r 再变成合法 - // 是并列的关系! - // 比如(())[[]] - // l...split : (()) - // split+1...r : [[]] - // 这种并列关系下,有可能出最优解 - // 所以,枚举每一个可能的并列划分点(split) - int ans = Math.min(p1, Math.min(p2, p3)); - for (int split = l; split < r; split++) { - ans = Math.min(ans, process(s, l, split, dp) + process(s, split + 1, r, dp)); - } - dp[l][r] = ans; - return ans; - } - -} diff --git a/公开课/class098/Code01_ChangeToSame.java b/公开课/class098/Code01_ChangeToSame.java deleted file mode 100644 index ba2764f..0000000 --- a/公开课/class098/Code01_ChangeToSame.java +++ /dev/null @@ -1,115 +0,0 @@ -package class098; - -// 来自美团 -// 8.20笔试 -// 小团生日收到妈妈送的两个一模一样的数列作为礼物! -// 他很开心的把玩,不过不小心没拿稳将数列摔坏了! -// 现在他手上的两个数列分别为A和B,长度分别为n和m。 -// 小团很想再次让这两个数列变得一样。他现在能做两种操作: -// 操作一是将一个选定数列中的某一个数a改成数b,这会花费|b-a|的时间, -// 操作二是选择一个数列中某个数a,将它从数列中丢掉,花费|a|的时间。 -// 小团想知道,他最少能以多少时间将这两个数列变得再次相同! -// 输入描述: -// 第一行两个空格隔开的正整数n和m,分别表示数列A和B的长度。 -// 接下来一行n个整数,分别为A1 A2…An -// 接下来一行m个整数,分别为B1 B2…Bm -// 对于所有数据,1 ≤ n,m ≤ 2000, |Ai|,|Bi| ≤ 10000 -// 输出一行一个整数,表示最少花费时间,来使得两个数列相同。 -public class Code01_ChangeToSame { - - public static int minCost(int[] A, int[] B) { - int n = A.length; - int m = B.length; - int[][] dp = new int[n + 1][m + 1]; - for (int i = 0; i <= n; i++) { - for (int j = 0; j <= m; j++) { - dp[i][j] = -1; - } - } - return change(A, B, 0, 0, dp); - } - - // A, B - // zuo(A,B,0,0) - // A[ai.....] B[bi.....] 请变得一样! - // 返回最少代价! - public static int zuo(int[] A, int[] B, int ai, int bi) { - if (ai == A.length && bi == B.length) { - return 0; - } - if (ai == A.length && bi != B.length) { - return Math.abs(B[bi]) + zuo(A, B, ai, bi + 1); - } - if (ai != A.length && bi == B.length) { - return Math.abs(A[ai]) + zuo(A, B, ai + 1, bi); - } - // A[ai] 有数 - // B[bi] 有数 - // 可能性1 : A[ai]删掉! - int p1 = Math.abs(A[ai]) + zuo(A, B, ai + 1, bi); - // 可能性2 : B[bi]删掉! - int p2 = Math.abs(B[bi]) + zuo(A, B, ai, bi + 1); - // 可能性3 : A[ai]删掉!、B[bi]删掉! - // int p3 = Math.abs(A[ai]) + Math.abs(B[bi]) + zuo(A, B, ai + 1, bi + 1); - // 可能性4 : A[ai] -> B[bi]、B[bi] -> A[ai] - int p4 = Math.abs(A[ai] - B[bi]) - + zuo(A, B, ai + 1, bi + 1); - // 可能性5 : A[ai] == B[bi] -// int p5 = Integer.MAX_VALUE; -// if(A[ai] == B[bi]) { -// p5 = zuo(A, B, ai + 1, bi + 1); -// } - return Math.min(Math.min(p1, p2), p4); - } - - // 暴力递归 - // A[indexA....]和B[indexB....]完全一样 - // 需要付出最少的代价返回 - public static int change(int[] A, int[] B, int indexA, int indexB) { - if (indexA == A.length && indexB == B.length) { - return 0; - } - if (indexA == A.length && indexB != B.length) { - return B[indexB] + change(A, B, indexA, indexB + 1); - } - if (indexA != A.length && indexB == B.length) { - return A[indexA] + change(A, B, indexA + 1, indexB); - } - // indexA、indexB都没到最后 - // 可能性1,丢掉A[indexA] - int p1 = A[indexA] + change(A, B, indexA + 1, indexB); - // 可能性2,丢掉B[indexB] - int p2 = B[indexB] + change(A, B, indexA, indexB + 1); - // 可能性3,同时丢掉A[indexA]、B[indexB] - // 可能性4,把A[indexA]改成B[indexB](也是B[indexB]改成A[indexA],因为代价一样) - // 可能性5,A[indexA]本来就是等于B[indexB]的,改的代价为0 - // 可以分析出可能性3,肯定是不如可能性4、可能性5的 - // 所以舍弃掉可能性3 - int p45 = Math.abs(A[indexA] - B[indexB]) + change(A, B, indexA + 1, indexB + 1); - return Math.min(Math.min(p1, p2), p45); - } - - // 上面的暴力递归方法改动态规划 - public static int change(int[] A, int[] B, int indexA, int indexB, int[][] dp) { - if (indexA == A.length && indexB == B.length) { - return 0; - } - if (dp[indexA][indexB] != -1) { - return dp[indexA][indexB]; - } - int ans = 0; - if (indexA == A.length && indexB != B.length) { - ans = B[indexB] + change(A, B, indexA, indexB + 1); - } else if (indexA != A.length && indexB == B.length) { - ans = A[indexA] + change(A, B, indexA + 1, indexB); - } else { - int p1 = A[indexA] + change(A, B, indexA + 1, indexB); - int p2 = B[indexB] + change(A, B, indexA, indexB + 1); - int p45 = Math.abs(A[indexA] - B[indexB]) + change(A, B, indexA + 1, indexB + 1); - ans = Math.min(Math.min(p1, p2), p45); - } - dp[indexA][indexB] = ans; - return ans; - } - -} diff --git a/公开课/class098/Code02_MinCostMostE.java b/公开课/class098/Code02_MinCostMostE.java deleted file mode 100644 index 80d2805..0000000 --- a/公开课/class098/Code02_MinCostMostE.java +++ /dev/null @@ -1,203 +0,0 @@ -package class098; - -// 来自网易 -// 小红拿到了一个仅由r、e、d组成的字符串 -// 她定义一个字符e为"好e" : 当且仅当这个e字符和r、d相邻 -// 例如"reeder"只有一个"好e",前两个e都不是"好e",只有第三个e是"好e" -// 小红每次可以将任意字符修改为任意字符,即三种字符可以相互修改 -// 她希望"好e"的数量尽可能多 -// 小红想知道,自己最少要修改多少次 -// 输入一个只有r、e、d三种字符的字符串 -// 长度 <= 2 * 10^5 -// 输出最小修改次数 -public class Code02_MinCostMostE { - -// // int[] arr { d 0 e 1 r 2 } -// // 好e -> 好1 -// // arr[i....] 请整出最多的好1来! -// // 返回1:整出多少个好1 -// // 返回2: 低价是多少? -// // 返回最小代价 -// // prepre pre -// // i-2 i-1 -// -// -// -// // arr[0 0 0] 好1 左右0、2双全 -// // 0 1 2 -// // -// // 1) 0 0 i mostEminCost(arr, 2, 0 , 0) -// // 2) 0 1 i mostEminCost(arr, 2, 0 , 1) -// // 3) 0 2 i -// // 4) 1 0 i -// // 5) 1 1 i -// // -// // i 2 * 10^5 -// // prepre 0 1 2 -// // pre 0 1 2 -// // 9 * 2 * 10^5 -// public static Info mostEminCost(int[] arr, int i, int prepre, int pre) { -// if(i == arr.length) { -// return new Info(0,0); -// } -// // i位置不终止 -// // 可能性1 : [i] -> 0 -// int curCost1 = arr[i] == 0 ? 0 :1; -// int curValue1 = prepre == 2 && pre == 1 ? 1 : 0; -// Info info1 = mostEminCost(arr, i + 1, pre, 0); -// -// -// // 可能性2 : [i] -> 1 -// int curCost2 = arr[i] == 1 ? 0 : 1; -// int curValue2 = 0; -// Info info2 = mostEminCost(arr, i + 1, pre, 1); -// -// -// // 可能性3 : [i] -> 2 -// int curCost3 = arr[i] == 2 ? 0 : 1; -// int curValue3 = prepre == 0 && pre == 1 ? 1 : 0; -// Info info3 = mostEminCost(arr, i + 1, pre, 2); -// -// int p1Value = curValue1 + info1.value; -// int p1Cost = curCost1 + info1.cost; -// int p2Value = curValue2 + info2.value; -// int p2Cost = curCost2 + info2.cost; -// int p3Value = curValue3 + info3.value; -// int p3Cost = curCost3 + info3.cost; -// int bestValue = 0; -// int minCost = Integer.MAX_VALUE; -// -// if(bestValue < p1Value) { -// bestValue = p1Value; -// minCost = p1Cost; -// } else if(bestValue == p1Value) { -// minCost = Math.min(minCost, p1Cost); -// } -// if(bestValue < p2Value) { -// bestValue = p2Value; -// minCost = p2Cost; -// } else if(bestValue == p2Value) { -// minCost = Math.min(minCost, p2Cost); -// } -// if(bestValue < p3Value) { -// bestValue = p3Value; -// minCost = p3Cost; -// } else if(bestValue == p3Value) { -// minCost = Math.min(minCost, p3Cost); -// } -// return new Info(bestValue, minCost); -// } -// -// public static class Info{ -// public int value; -// public int cost; -// -// public Info(int v, int c) { -// value = v; -// cost = c; -// } -// } - - public static int minCost(String str) { - int n = str.length(); - if (n < 3) { - return -1; - } - int[] arr = new int[n]; - // d认为是0,e认为是1,r认为是2 - for (int i = 0; i < n; i++) { - char cur = str.charAt(i); - if (cur == 'd') { - arr[i] = 0; - } else if (cur == 'e') { - arr[i] = 1; - } else { - arr[i] = 2; - } - } - // 通过上面的转化,问题变成了: - // 1的左右,一定要被0和2包围,这个1才是"好1" - // 请让"好1"的尽量多,返回最少的修改代价 - int maxGood = 0; - int minCost = Integer.MAX_VALUE; - for (int prepre = 0; prepre < 3; prepre++) { - for (int pre = 0; pre < 3; pre++) { - int cost = arr[0] == prepre ? 0 : 1; - cost += arr[1] == pre ? 0 : 1; - Info cur = process(arr, 2, prepre, pre); - if (cur.maxGood > maxGood) { - maxGood = cur.maxGood; - minCost = cur.minCost + cost; - } else if (cur.maxGood == maxGood) { - minCost = Math.min(minCost, cur.minCost + cost); - } - } - } - return minCost; - } - - public static class Info { - public int maxGood; - public int minCost; - - public Info(int a, int b) { - maxGood = a; - minCost = b; - } - } - - // 暴力递归 - // 可以自己改成动态规划 - // arr[index-2]位置的数值是prepre - // arr[index-1]位置的数值是pre - // 在这种情况下,请让arr[index...]上的好1尽量多 - // 返回: - // 尽量多的"好1",是多少? - // 得到尽量多的"好1",最小代价是多少? - public static Info process(int[] arr, int index, int prepre, int pre) { - if (index == arr.length) { - return new Info(0, 0); - } - // 可能性1,arr[index],变成0 - int p1Value = prepre == 2 && pre == 1 ? 1 : 0; - int p1Cost = arr[index] == 0 ? 0 : 1; - Info info = process(arr, index + 1, pre, 0); - p1Value += info.maxGood; - p1Cost += info.minCost; - // 可能性2,arr[index],变成1 - int p2Value = 0; - int p2Cost = arr[index] == 1 ? 0 : 1; - info = process(arr, index + 1, pre, 1); - p2Value += info.maxGood; - p2Cost += info.minCost; - // 可能性3,arr[index],变成2 - int p3Value = prepre == 0 && pre == 1 ? 1 : 0; - int p3Cost = arr[index] == 2 ? 0 : 1; - info = process(arr, index + 1, pre, 2); - p3Value += info.maxGood; - p3Cost += info.minCost; - // 开始决策,选出三种可能性中的最优解 - int maxGood = 0; - int minCost = Integer.MAX_VALUE; - if (p1Value > maxGood) { - maxGood = p1Value; - minCost = p1Cost; - } else if (p1Value == maxGood) { - minCost = Math.min(minCost, p1Cost); - } - if (p2Value > maxGood) { - maxGood = p2Value; - minCost = p2Cost; - } else if (p2Value == maxGood) { - minCost = Math.min(minCost, p2Cost); - } - if (p3Value > maxGood) { - maxGood = p3Value; - minCost = p3Cost; - } else if (p3Value == maxGood) { - minCost = Math.min(minCost, p3Cost); - } - return new Info(maxGood, minCost); - } - -} diff --git a/公开课/class098/Code03_TravelMinFuel.java b/公开课/class098/Code03_TravelMinFuel.java deleted file mode 100644 index 352da94..0000000 --- a/公开课/class098/Code03_TravelMinFuel.java +++ /dev/null @@ -1,82 +0,0 @@ -package class098; - -import java.util.ArrayList; - -// 来自微软 -// 给定两个数组A和B,比如 -// A = { 0, 1, 1 } -// B = { 1, 2, 3 } -// A[0] = 0, B[0] = 1,表示0到1有双向道路 -// A[1] = 1, B[1] = 2,表示1到2有双向道路 -// A[2] = 1, B[2] = 3,表示1到3有双向道路 -// 给定数字N,编号从0~N,所以一共N+1个节点 -// 题目输入一定保证所有节点都联通,并且一定没有环 -// 默认办公室是0节点,其他1~N节点上,每个节点上都有一个居民 -// 每天所有居民都去往0节点上班 -// 所有的居民都有一辆5座的车,也都乐意和别人一起坐车 -// 车不管负重是多少,只要走过一条路,就耗费1的汽油 -// 比如A、B、C的居民,开着自己的车来到D居民的位置,一共耗费3的汽油 -// D居民和E居民之间,假设有一条路 -// 那么D居民可以接上A、B、C,4个人可以用一辆车,去往E的话,就再耗费1的汽油 -// 求所有居民去办公室的路上,最少耗费多少汽油 -public class Code03_TravelMinFuel { - - public static int cnt = 0; - - public static int minFuel(int[] a, int[] b, int n) { - // 先建图 - ArrayList> graph = new ArrayList<>(); - for (int i = 0; i <= n; i++) { - graph.add(new ArrayList<>()); - } - for (int i = 0; i < a.length; i++) { - graph.get(a[i]).add(b[i]); - graph.get(b[i]).add(a[i]); - } - // 建图完毕 - // 根据题目描述,办公室一定是0号点 - // 所有员工一定是往0号点汇聚 - int[] dfn = new int[n + 1]; - int[] size = new int[n + 1]; - int[] cost = new int[n + 1]; - cnt = 0; - dfs(graph, 0, dfn, size, cost); - return cost[0]; - } - - // 图graph - // 当前节点的编号cur - // 以cur为头的整棵树,每个节点,去分配dfn序号! - // 以cur为头的整棵树,每个节点,都去求子树的节点个数,size - // 以cur为头的整棵树,所有节点汇聚到cur,废了多少油,填入到cost - public static void dfs( - ArrayList> graph, - int cur, - int[] dfn, - int[] size, - int[] cost) { - dfn[cur] = ++cnt; - size[cur] = 1; - for (int next : graph.get(cur)) { - if (dfn[next] == 0) { - dfs(graph, next, dfn, size, cost); - size[cur] += size[next]; - cost[cur] += cost[next]; - cost[cur] += (size[next] + 4) / 5; - } - } - } - - public static void main(String[] args) { - int[] a1 = { 0, 1, 1 }; - int[] b1 = { 1, 2, 3 }; - int n1 = 3; - System.out.println(minFuel(a1, b1, n1)); - - int[] a2 = { 1, 1, 1, 9, 9, 9, 9, 7, 8 }; - int[] b2 = { 2, 0, 3, 1, 6, 5, 4, 0, 0 }; - int n2 = 9; - System.out.println(minFuel(a2, b2, n2)); - } - -} diff --git a/公开课/class099/Code01_MatchsticksToSquare.java b/公开课/class099/Code01_MatchsticksToSquare.java deleted file mode 100644 index cd60157..0000000 --- a/公开课/class099/Code01_MatchsticksToSquare.java +++ /dev/null @@ -1,96 +0,0 @@ -package class099; - -// 你将得到一个整数数组 matchsticks ,其中 matchsticks[i] 是第 i 个火柴棒的长度。 -// 你要用 所有的火柴棍 拼成一个正方形。 -// 你 不能折断 任何一根火柴棒,但你可以把它们连在一起,而且每根火柴棒必须 使用一次 。 -// 如果你能拼出正方形,则返回 true ,否则返回 false 。 -// 测试链接 : https://leetcode.cn/problems/matchsticks-to-square/ -public class Code01_MatchsticksToSquare { - - public static boolean zuo(int[] arr) { - int sum = 0; - for (int num : arr) { - sum += num; - } - - if (sum % 4 != 0) { - return false; - } - int len = sum / 4; - return f(arr, 0, 0, len, 4); - } - - // status = 000000110111,任何一个下标的火柴用没用 - // arr 0 1 2 3 4 - // y x y y x - // status 01101 - // arr[0] s 1 - // arr[1] s 1 - // - // status : 可变 - // cur : 可变 - // edges : 可变 - // cur 、 edges,被,status决定了! - public static boolean f(int[] arr, int status, int cur, int len, int edges) { - if (edges == 0) { - // 确定所有的火柴是否用光! - return (status == (1 << arr.length) - 1) ? true : false; - } - boolean ans = false; - // 还没都搞定! - // arr中,还没有尝试的火柴!当前全试一遍 - for (int i = 0; i < arr.length; i++) { - // i号火柴,有没有用过呢? - // 2 1 0 - // 00001110111 0 0 1 - if ((status & (1 << i)) == 0) { - if (cur + arr[i] > len) { // 不能用! - continue; - } else if (cur + arr[i] < len) { - ans |= f(arr, status | (1 << i), cur + arr[i], len, edges); - } else { // cur + arr[i] == len - ans |= f(arr, status | (1 << i), 0, len, edges - 1); - } - if (ans) { - break; - } - } - } - return ans; - } - - public static boolean makesquare(int[] matchsticks) { - int sum = 0; - for (int num : matchsticks) { - sum += num; - } - if ((sum & 3) != 0) { - return false; - } - int[] dp = new int[1 << matchsticks.length]; - return process(matchsticks, 0, 0, sum >> 2, 4, dp); - } - - public static boolean process(int[] arr, int status, int cur, int len, int edges, int[] dp) { - if (dp[status] != 0) { - return dp[status] == 1; - } - boolean ans = false; - if (edges == 0) { - ans = (status == (1 << arr.length) - 1) ? true : false; - } else { - for (int i = 0; i < arr.length && !ans; i++) { - if (((1 << i) & status) == 0 && cur + arr[i] <= len) { - if (cur + arr[i] == len) { - ans |= process(arr, status | (1 << i), 0, len, edges - 1, dp); - } else { - ans |= process(arr, status | (1 << i), cur + arr[i], len, edges, dp); - } - } - } - } - dp[status] = ans ? 1 : -1; - return ans; - } - -} diff --git a/公开课/class099/Code02_CutOrPoison.java b/公开课/class099/Code02_CutOrPoison.java deleted file mode 100644 index 556be5a..0000000 --- a/公开课/class099/Code02_CutOrPoison.java +++ /dev/null @@ -1,122 +0,0 @@ -package class099; - -// 来自学员问题 -// 给定怪兽的血量为hp -// 第i回合如果用刀砍,怪兽在这回合会直接掉血,没有后续效果 -// 第i回合如果用毒,怪兽在这回合不会掉血, -// 但是之后每回合都会掉血,并且所有中毒的后续效果会叠加 -// 给定的两个数组cuts、poisons,两个数组等长,长度都是n -// 表示你在n回合内的行动, -// 每一回合的刀砍的效果由cuts[i]表示 -// 每一回合的中毒的效果由poisons[i]表示 -// 如果你在n个回合内没有直接杀死怪兽,意味着你已经无法有新的行动了 -// 但是怪兽如果有中毒效果的话,那么怪兽依然会在hp耗尽的那回合死掉 -// 返回你最快能在多少回合内将怪兽杀死 -// 数据范围 : -// 1 <= n <= 10的5次方 -// 1 <= hp <= 10的9次方 -// 1 <= cuts[i]、poisons[i] <= 10的9次方 -public class Code02_CutOrPoison { - - // 不算好的方法 - // 为了验证 - public static int fast1(int[] cuts, int[] poisons, int hp) { - int sum = 0; - for (int num : poisons) { - sum += num; - } - int[][][] dp = new int[cuts.length][hp + 1][sum + 1]; - return process1(cuts, poisons, 0, hp, 0, dp); - } - - public static int process1(int[] cuts, int[] poisons, int index, int restHp, int poisonEffect, int[][][] dp) { - restHp -= poisonEffect; - if (restHp <= 0) { - return index + 1; - } - // restHp > 0 - if (index == cuts.length) { - if (poisonEffect == 0) { - return Integer.MAX_VALUE; - } else { - return cuts.length + 1 + (restHp + poisonEffect - 1) / poisonEffect; - } - } - if (dp[index][restHp][poisonEffect] != 0) { - return dp[index][restHp][poisonEffect]; - } - int p1 = restHp <= cuts[index] ? (index + 1) - : process1(cuts, poisons, index + 1, restHp - cuts[index], poisonEffect, dp); - int p2 = process1(cuts, poisons, index + 1, restHp, poisonEffect + poisons[index], dp); - int ans = Math.min(p1, p2); - dp[index][restHp][poisonEffect] = ans; - return ans; - } - - // 真正想实现的方法 - // O(N * log(hp)) - public static int fast2(int[] cuts, int[] poisons, int hp) { - // 怪兽可能的最快死亡回合 - int l = 1; - // 怪兽可能的最晚死亡回合 - //int r = hp / poisons[0]; - int r = hp + 1; - // 1 ~ hp + 1 二分找答案 - int m = 0; - int ans = Integer.MAX_VALUE; - while (l <= r) { - // m = (l + r) / 2 - m = l + ((r - l) >> 1); - if (ok(cuts, poisons, hp, m)) { - ans = m; - r = m - 1; - } else { - l = m + 1; - } - } - return ans; - } - - public static boolean ok(int[] cuts, int[] posions, long hp, int limit) { - int n = Math.min(cuts.length, limit); - for (int i = 0, j = 1; i < n; i++, j++) { - hp -= Math.max((long) cuts[i], (long) (limit - j) * (long) posions[i]); - if (hp <= 0) { - return true; - } - } - return false; - } - - // 为了测试 - public static int[] randomArray(int n, int v) { - int[] ans = new int[n]; - for (int i = 0; i < n; i++) { - ans[i] = (int) (Math.random() * v) + 1; - } - return ans; - } - - // 为了测试 - public static void main(String[] args) { - int N = 30; - int cutV = 20; - int posionV = 10; - int hpV = 200; - int testTimes = 10000; - System.out.println("测试开始"); - for (int i = 0; i < testTimes; i++) { - int n = (int) (Math.random() * N) + 1; - int[] cuts = randomArray(n, cutV); - int[] posions = randomArray(n, posionV); - int hp = (int) (Math.random() * hpV) + 1; - int ans1 = fast1(cuts, posions, hp); - int ans2 = fast2(cuts, posions, hp); - if (ans1 != ans2) { - System.out.println("出错了!"); - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class099/Code03_CorporateFlightBookings.java b/公开课/class099/Code03_CorporateFlightBookings.java deleted file mode 100644 index a099b6e..0000000 --- a/公开课/class099/Code03_CorporateFlightBookings.java +++ /dev/null @@ -1,33 +0,0 @@ -package class099; - -// 这里有 n 个航班,它们分别从 1 到 n 进行编号。 -// 有一份航班预订表 bookings , -// 表中第 i 条预订记录 bookings[i] = [firsti, lasti, seatsi] -// 意味着在从 firsti 到 lasti -//(包含 firsti 和 lasti )的 每个航班 上预订了 seatsi 个座位。 -// 请你返回一个长度为 n 的数组 answer,里面的元素是每个航班预定的座位总数。 -// 测试链接 : https://leetcode.cn/problems/corporate-flight-bookings/ -public class Code03_CorporateFlightBookings { - - public static int[] corpFlightBookings(int[][] bookings, int n) { - // 1 2 3 4 n - // 0 1 2 3 .. n n+1 - int[] cnt = new int[n + 2]; - for (int[] book : bookings) { - // start book[0] - // end book[1] - // 票 book[2] - cnt[book[0]] += book[2]; - cnt[book[1] + 1] -= book[2]; - } - for (int i = 1; i < cnt.length; i++) { - cnt[i] += cnt[i - 1]; - } - int[] ans = new int[n]; - for (int i = 0; i < n; i++) { - ans[i] = cnt[i + 1]; - } - return ans; - } - -} diff --git a/公开课/class100/Code01_EvenTimesMaxSubstring.java b/公开课/class100/Code01_EvenTimesMaxSubstring.java deleted file mode 100644 index 5655164..0000000 --- a/公开课/class100/Code01_EvenTimesMaxSubstring.java +++ /dev/null @@ -1,103 +0,0 @@ -package class100; - -import java.util.HashMap; - -// 来自微软面试 -// 给定一个字符串s,其中都是英文小写字母 -// 如果s中的子串含有的每种字符都是偶数个 -// 那么这样的子串就是达标子串,子串要求是连续串 -// 返回s中达标子串的最大长度 -// 1 <= s的长度 <= 10^5 -// 字符种类都是英文小写 -public class Code01_EvenTimesMaxSubstring { - - // 为了测试 - // 暴力方法 - public static int maxLen1(String s) { - int n = s.length(); - int ans = 0; - for (int i = 0; i < n; i++) { - for (int j = n - 1; j >= i; j--) { - if (ok(s, i, j)) { - ans = Math.max(ans, j - i + 1); - break; - } - } - } - return ans; - } - - // 为了测试 - // 暴力方法 - public static boolean ok(String s, int l, int r) { - if (((r - l + 1) & 1) == 1) { - return false; - } - int[] cnts = new int[26]; - for (int i = l; i <= r; i++) { - cnts[s.charAt(i) - 'a']++; - } - for (int cnt : cnts) { - if ((cnt & 1) == 1) { - return false; - } - } - return true; - } - - // 正式方法 - // 时间复杂度O(N) - public static int maxLen2(String s) { - // key : 状态int, 32位的,a~z一共26位,够用 - // value : 该状态最早出现的位置 - HashMap map = new HashMap<>(); - // 00000000..000000 - map.put(0, -1); - // 0...当前字符,总状态! - int status = 0; - int ans = 0; - int n = s.length(); - // ....0 .....1 .....2 .....i ....n-1 - for (int i = 0; i < n; i++) { - // 从开头....i位置的字符 - // 总状态,出来了! - status ^= 1 << (s.charAt(i) - 'a'); - if (map.containsKey(status)) { - ans = Math.max(ans, i - map.get(status)); - } else { - map.put(status, i); - } - } - return ans; - } - - // 为了测试 - public static String randomString(int n, int v) { - char[] s = new char[n]; - for (int i = 0; i < n; i++) { - s[i] = (char) ((int) (Math.random() * v) + 'a'); - } - return String.valueOf(s); - } - - // 为了测试 - public static void main(String[] args) { - int n = 50; - int v = 6; - int testTimes = 2000; - System.out.println("测试开始"); - for (int i = 0; i < testTimes; i++) { - String s = randomString(n, v); - int ans1 = maxLen1(s); - int ans2 = maxLen2(s); - if (ans1 != ans2) { - System.out.println(s); - System.out.println(ans1); - System.out.println(ans2); - break; - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class100/Code02_MaxLengthSameCharMChanges.java b/公开课/class100/Code02_MaxLengthSameCharMChanges.java deleted file mode 100644 index 35fa20e..0000000 --- a/公开课/class100/Code02_MaxLengthSameCharMChanges.java +++ /dev/null @@ -1,124 +0,0 @@ -package class100; - -// 来自字节笔试 -// 给定一个只由小写字母组成的字符串str,长度为N -// 给定一个只由0、1组成的数组arr,长度为N -// arr[i] == 0表示str中i位置的字符不许修改 -// arr[i] == 1表示str中i位置的字符允许修改 -// 给定一个正数m,表示在任意允许修改的位置,可以把该位置的字符变成a~z中的任何一个 -// 可以修改m次 -// 返回在最多修改m次的情况下,全是一种字符的最长子串是多长 -// 1 <= N, M <= 10^5 -// 所有字符都是小写 -public class Code02_MaxLengthSameCharMChanges { - - // 暴力方法 - // 为了测试 - public static int maxLen1(String str, int[] arr, int m) { - char[] s = str.toCharArray(); - int n = s.length; - int ans = 0; - for (char c = 'a'; c <= 'z'; c++) { - for (int i = 0; i < n; i++) { - for (int j = n - 1; j >= i; j--) { - if (ok(s, i, j, c, arr, m)) { - ans = Math.max(ans, j - i + 1); - break; - } - } - } - } - return ans; - } - - // 为了测试 - public static boolean ok(char[] s, int l, int r, char c, int[] arr, int m) { - for (int i = l; i <= r; i++) { - if (s[i] == c) { - continue; - } - if (arr[i] == 0 || m == 0) { - return false; - } - m--; - } - return true; - } - - // 正式方法 - // 时间复杂度O(N) - public static int maxLen2(String str, int[] arr, int m) { - char[] s = str.toCharArray(); - int n = s.length; - int ans = 0; - for (char c = 'a'; c <= 'z'; c++) { - int r = 0; - int change = 0; - for (int l = 0; l < n; l++) { - // [l..r) - // [l...r-1] r - while (r < n) { - if (s[r] == c) { - r++; - continue; - } - // s[r] != 你的要求 - if (arr[r] == 0 || change == m) { - break; - } - // arr[r] == 1 && change < m - change++; - r++; - } - // [l...r-1] r - ans = Math.max(ans, r - l); - // [l....r-1] [l]吐出来! - if (s[l] != c && arr[l] == 1) { - change--; - } - r = Math.max(r, l + 1); - } - } - return ans; - } - - // 为了测试 - public static String randomString(int n, int r) { - char[] ans = new char[n]; - for (int i = 0; i < n; i++) { - ans[i] = (char) ((int) (Math.random() * r) + 'a'); - } - return String.valueOf(ans); - } - - // 为了测试 - public static int[] randomArray(int n) { - int[] ans = new int[n]; - for (int i = 0; i < n; i++) { - ans[i] = (int) (Math.random() * 2); - } - return ans; - } - - // 为了测试 - public static void main(String[] args) { - int N = 100; - int R = 5; - int testTimes = 5000; - System.out.println("测试开始"); - for (int i = 0; i < testTimes; i++) { - int n = (int) (Math.random() * N) + 1; - int m = (int) (Math.random() * n) + 1; - String str = randomString(n, R); - int[] arr = randomArray(n); - int ans1 = maxLen1(str, arr, m); - int ans2 = maxLen2(str, arr, m); - if (ans1 != ans2) { - System.out.println("出错了!"); - break; - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class100/Code03_ExaminationPaperWays.java b/公开课/class100/Code03_ExaminationPaperWays.java deleted file mode 100644 index 1ec3f23..0000000 --- a/公开课/class100/Code03_ExaminationPaperWays.java +++ /dev/null @@ -1,119 +0,0 @@ -package class100; - -import java.util.Arrays; - -// 来自美团 -// 有三个题库A、B、C,每个题库均有n道题目,且题目都是从1到n进行编号 -// 每个题目都有一个难度值 -// 题库A中第i个题目的难度为ai -// 题库B中第i个题目的难度为bi -// 题库C中第i个题目的难度为ci -// 小美准备组合出一套试题,试题共有三道题, -// 第一题来自题库A,第二题来自题库B,第三题来自题库C -// 试题要求题目难度递增,且梯度不能过大 -// 具体地说,第二题的难度必须大于第一题的难度,但不能大于第一题难度的两倍 -// 第三题的难度必须大于第二题的难度,但不能大于第二题难度的两倍 -// 小美想知道在满足上述要求下,有多少种不同的题目组合 -//(三道题目中只要存在一道题目不同,则两个题目组合就视为不同 -// 输入描述 第一行一个正整数n, 表示每个题库的题目数量 -// 第二行为n个正整数a1, a2,...... an,其中ai表示题库A中第i个题目的难度值 -// 第三行为n个正整数b1, b2,...... bn,其中bi表示题库B中第i个题目的难度值 -// 第四行为n个正整数c1, c2,...... cn,其中ci表示题库C中第i个题目的难度值 -// 1 ≤ n ≤ 20000, 1 ≤ ai, bi, ci ≤ 10^9。 -public class Code03_ExaminationPaperWays { - - // 暴力方法 - // 时间复杂度O(N^3) - // 为了验证 - public static int ways1(int[] a, int[] b, int[] c) { - int n = a.length; - Arrays.sort(a); - Arrays.sort(b); - Arrays.sort(c); - int ans = 0; - for (int i = 0; i < n; i++) { - for (int j = 0; j < n && b[j] <= a[i] * 2; j++) { - if (b[j] > a[i]) { - for (int k = 0; k < n && c[k] <= b[j] * 2; k++) { - if (c[k] > b[j]) { - ans++; - } - } - } - } - } - return ans; - } - - // 正式方法 - // 时间复杂度O(N) - public static int ways2(int[] a, int[] b, int[] c) { - int n = a.length; - Arrays.sort(a); - Arrays.sort(b); - Arrays.sort(c); - int[] help = new int[n]; - for (int i = 0, l = -1, r = 0; i < n; i++) { - while (l + 1 < n && c[l + 1] <= b[i]) { - l++; - } - while (r < n && c[r] <= b[i] * 2) { - r++; - } - help[i] = Math.max(r - l - 1, 0); - } - for (int i = 1; i < n; i++) { - help[i] += help[i - 1]; - } - int ans = 0; - for (int i = 0, l = -1, r = 0; i < n; i++) { - while (l + 1 < n && b[l + 1] <= a[i]) { - l++; - } - while (r < n && b[r] <= a[i] * 2) { - r++; - } - if (r - l - 1 > 0) { - ans += sum(help, l + 1, r - 1); - } - } - return ans; - } - - public static int sum(int[] help, int l, int r) { - return l == 0 ? help[r] : help[r] - help[l - 1]; - } - - // 为了测试 - public static int[] randomArray(int n, int v) { - int[] ans = new int[n]; - for (int i = 0; i < n; i++) { - ans[i] = (int) (Math.random() * v); - } - return ans; - } - - // 为了测试 - public static void main(String[] args) { - int N = 100; - int V = 100; - int testTimes = 5000; - System.out.println("测试开始"); - for (int i = 0; i < testTimes; i++) { - int n = (int) (Math.random() * N) + 1; - int[] a = randomArray(n, V); - int[] b = randomArray(n, V); - int[] c = randomArray(n, V); - int ans1 = ways1(a, b, c); - int ans2 = ways2(a, b, c); - if (ans1 != ans2) { - System.out.println("出错了!"); - System.out.println(ans1); - System.out.println(ans2); - break; - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class101/Code01_SlidingWindowMaxArray.java b/公开课/class101/Code01_SlidingWindowMaxArray.java deleted file mode 100644 index 7d3ca61..0000000 --- a/公开课/class101/Code01_SlidingWindowMaxArray.java +++ /dev/null @@ -1,177 +0,0 @@ -package class101; - - -public class Code01_SlidingWindowMaxArray { - - public static class Window { - - public int[] arr; - - public int[] queue; - public int ql; - public int qr; - - public int l; - public int r; - - public Window(int[] a) { - arr = a; - queue = new int[a.length]; - l = 0; - r = 0; - ql = 0; - qr = 0; - } - - // 右边扩了! - public void add() { - if (r == arr.length) { - return; - } - // [l,r) - // 能扩! - // arr[r] - while (ql != qr && arr[queue[qr - 1]] <= arr[r]) { - qr--; - } - queue[qr++] = r++; - } - - // 左边缩了! - // 必须有窗口才能缩 - public void remove() { - if (l == r) { - return; - } - if (queue[ql] == l) { - ql++; - } - l++; - } - - public int max() { - if (l == r) { - return -1; - } - return arr[queue[ql]]; - } - - } - - public static void main(String[] args) { - int[] arr = { 6, 5, 7, 2, 9, 1, 3 }; - // l..r 无 - Window w = new Window(arr); - - w.add(); - System.out.println(w.max()); - w.add(); - System.out.println(w.max()); - w.add(); - System.out.println(w.max()); - w.add(); - System.out.println(w.max()); - w.remove(); - w.remove(); - w.remove(); - System.out.println(w.max()); - - } - -// -// -// -// -// // 暴力的对数器方法 -// public static int[] right(int[] arr, int w) { -// if (arr == null || w < 1 || arr.length < w) { -// return null; -// } -// int N = arr.length; -// int[] res = new int[N - w + 1]; -// int index = 0; -// int L = 0; -// int R = w - 1; -// while (R < N) { -// int max = arr[L]; -// for (int i = L + 1; i <= R; i++) { -// max = Math.max(max, arr[i]); -// -// } -// res[index++] = max; -// L++; -// R++; -// } -// return res; -// } -// -// public static int[] getMaxWindow(int[] arr, int w) { -// if (arr == null || w < 1 || arr.length < w) { -// return null; -// } -// // qmax 窗口最大值的更新结构 -// // 放下标 -// LinkedList qmax = new LinkedList(); -// int[] res = new int[arr.length - w + 1]; -// int index = 0; -// for (int R = 0; R < arr.length; R++) { -// while (!qmax.isEmpty() && arr[qmax.peekLast()] <= arr[R]) { -// qmax.pollLast(); -// } -// qmax.addLast(R); -// if (qmax.peekFirst() == R - w) { -// qmax.pollFirst(); -// } -// if (R >= w - 1) { -// res[index++] = arr[qmax.peekFirst()]; -// } -// } -// return res; -// } -// -// // for test -// public static int[] generateRandomArray(int maxSize, int maxValue) { -// int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; -// for (int i = 0; i < arr.length; i++) { -// arr[i] = (int) (Math.random() * (maxValue + 1)); -// } -// return arr; -// } -// -// // for test -// public static boolean isEqual(int[] arr1, int[] arr2) { -// if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) { -// return false; -// } -// if (arr1 == null && arr2 == null) { -// return true; -// } -// if (arr1.length != arr2.length) { -// return false; -// } -// for (int i = 0; i < arr1.length; i++) { -// if (arr1[i] != arr2[i]) { -// return false; -// } -// } -// return true; -// } -// -// public static void main(String[] args) { -// int testTime = 100000; -// int maxSize = 100; -// int maxValue = 100; -// System.out.println("test begin"); -// for (int i = 0; i < testTime; i++) { -// int[] arr = generateRandomArray(maxSize, maxValue); -// int w = (int) (Math.random() * (arr.length + 1)); -// int[] ans1 = getMaxWindow(arr, w); -// int[] ans2 = right(arr, w); -// if (!isEqual(ans1, ans2)) { -// System.out.println("Oops!"); -// } -// } -// System.out.println("test finish"); -// } - -} diff --git a/公开课/class101/Code02_WindPrevent.java b/公开课/class101/Code02_WindPrevent.java deleted file mode 100644 index 4fbf2cc..0000000 --- a/公开课/class101/Code02_WindPrevent.java +++ /dev/null @@ -1,110 +0,0 @@ -package class101; - -// 来自真实笔试 -// 给定一个二维数组matrix,数组中的每个元素代表一棵树的高度。 -// 你可以选定连续的若干行组成防风带,防风带每一列的防风高度为这一列的最大值 -// 防风带整体的防风高度为,所有列防风高度的最小值。 -// 比如,假设选定如下三行 -// 1 5 4 -// 7 2 6 -// 2 3 4 -// 1、7、2的列,防风高度为7 -// 5、2、3的列,防风高度为5 -// 4、6、4的列,防风高度为6 -// 防风带整体的防风高度为5,是7、5、6中的最小值 -// 给定一个正数k,k <= matrix的行数,表示可以取连续的k行,这k行一起防风。 -// 求防风带整体的防风高度最大值 -public class Code02_WindPrevent { - - public static int bestHeight1(int[][] matrix, int k) { - int n = matrix.length; - int m = matrix[0].length; - int ans = 0; - for (int startRow = 0; startRow < n; startRow++) { - int bottleNeck = Integer.MAX_VALUE; - for (int col = 0; col < m; col++) { - int height = 0; - for (int endRow = startRow; endRow < n && (endRow - startRow + 1 <= k); endRow++) { - height = Math.max(height, matrix[endRow][col]); - } - bottleNeck = Math.min(bottleNeck, height); - } - ans = Math.max(ans, bottleNeck); - } - return ans; - } - - public static int bestHeight2(int[][] matrix, int k) { - int n = matrix.length; - int m = matrix[0].length; - int[][] windowMaxs = new int[m][n]; - int[][] windowLR = new int[m][2]; - for (int i = 0; i < k; i++) { - addRow(matrix, m, i, windowMaxs, windowLR); - } - int ans = bottleNeck(matrix, m, windowMaxs, windowLR); - for (int i = k; i < n; i++) { - addRow(matrix, m, i, windowMaxs, windowLR); - deleteRow(m, i - k, windowMaxs, windowLR); - ans = Math.max(ans, bottleNeck(matrix, m, windowMaxs, windowLR)); - } - return ans; - } - - public static void addRow(int[][] matrix, int m, int row, int[][] windowMaxs, int[][] windowLR) { - for (int col = 0; col < m; col++) { - while (windowLR[col][0] != windowLR[col][1] - && matrix[windowMaxs[col][windowLR[col][1] - 1]][col] <= matrix[row][col]) { - windowLR[col][1]--; - } - windowMaxs[col][windowLR[col][1]++] = row; - } - } - - public static void deleteRow(int m, int row, int[][] windowMaxs, int[][] windowLR) { - for (int col = 0; col < m; col++) { - if (windowMaxs[col][windowLR[col][0]] == row) { - windowLR[col][0]++; - } - } - } - - public static int bottleNeck(int[][] matrix, int m, int[][] windowMaxs, int[][] windowLR) { - int ans = Integer.MAX_VALUE; - for (int col = 0; col < m; col++) { - ans = Math.min(ans, matrix[windowMaxs[col][windowLR[col][0]]][col]); - } - return ans; - } - - public static int[][] generateMatrix(int n, int m, int v) { - int[][] matrix = new int[n][m]; - for (int i = 0; i < n; i++) { - for (int j = 0; j < m; j++) { - matrix[i][j] = (int) (Math.random() * v) + 1; - } - } - return matrix; - } - - public static void main(String[] args) { - int nMax = 100; - int mMax = 100; - int vMax = 100; - int testTimes = 5000; - System.out.println("测试开始"); - for (int i = 0; i < testTimes; i++) { - int n = (int) (Math.random() * nMax) + 1; - int m = (int) (Math.random() * mMax) + 1; - int[][] matrix = generateMatrix(n, m, vMax); - int k = (int) (Math.random() * n) + 1; - int ans1 = bestHeight1(matrix, k); - int ans2 = bestHeight2(matrix, k); - if (ans1 != ans2) { - System.out.println("出错了!"); - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class101/Code03_DreamCity.java b/公开课/class101/Code03_DreamCity.java deleted file mode 100644 index 8a8a412..0000000 --- a/公开课/class101/Code03_DreamCity.java +++ /dev/null @@ -1,70 +0,0 @@ -package class101; - -// 来自学员问题 -// 给定n棵树,和两个长度为n的数组a和b -// i号棵树的初始重量为a[i],i号树每天的增长重量为b[i] -// 你每天最多能砍1棵树,这天收益 = 砍的树初始重量 + 砍的树增长到这天的总增重 -// 给定m,表示你有m天,返回m天内你获得的最大收益 -// 本题测试链接 : https://zoj.pintia.cn/problem-sets/91827364500/problems/91827367873 -// 请同学们务必参考如下代码中关于输入、输出的处理 -// 这是输入输出处理效率很高的写法 -// 提交如下方法,把主类名改成Main,可以直接通过 -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.io.StreamTokenizer; -import java.util.Arrays; - -public class Code03_DreamCity { - - public static int[][] tree = new int[250][2]; - - public static int[][] dp = new int[250][250]; - - public static void main(String[] args) throws IOException { - BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); - StreamTokenizer in = new StreamTokenizer(br); - PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out)); - in.nextToken(); - int testCases = (int) in.nval; - for (int i = 0; i < testCases; i++) { - in.nextToken(); - int n = (int) in.nval; - in.nextToken(); - int m = (int) in.nval; - for (int j = 0; j < n; j++) { - in.nextToken(); - tree[j][0] = (int) in.nval; - } - for (int j = 0; j < n; j++) { - in.nextToken(); - tree[j][1] = (int) in.nval; - } - out.println(maxWeight(n, m)); - out.flush(); - } - } - - // tree[][] - // i棵树,初始重量 , tree[i][0] - // i棵树,每天的增长重量 ,tree[i][1] - public static int maxWeight(int n, int m) { - Arrays.sort(tree, 0, n, (o1, o2) -> o1[1] - o2[1]); - dp[0][0] = tree[0][0]; - for (int i = 1; i < n; i++) { - dp[i][0] = Math.max(dp[i - 1][0], tree[i][0]); - } - for (int j = 1; j < m; j++) { - dp[0][j] = dp[0][j - 1] + tree[0][1]; - } - for (int i = 1; i < n; i++) { - for (int j = 1; j < m; j++) { - dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - 1] + tree[i][0] + tree[i][1] * j); - } - } - return dp[n - 1][m - 1]; - } - -} \ No newline at end of file diff --git a/公开课/class102/Code01_SortGame.java b/公开课/class102/Code01_SortGame.java deleted file mode 100644 index 5c970bd..0000000 --- a/公开课/class102/Code01_SortGame.java +++ /dev/null @@ -1,189 +0,0 @@ -package class102; - -import java.util.Arrays; -import java.util.Comparator; -import java.util.TreeSet; - -// 来自百度 -// 二狗买了一些小兵玩具,和大胖一起玩 -// 一共有n个小兵,这n个小兵拍成一列 -// 第i个小兵战斗力为hi,然后他们两个开始对小兵进行排列 -// 一共进行m次操作,二狗每次操作选择一个数k,将前k个小兵战斗力从小到大排列 -// 大胖每次操作选择一个数k,将前k个小兵战斗力从大到小排列 -// 问所有操作结束后,排列顺序什么样 -// 给定一个长度为n的数组arr,表示每个小兵的战斗力 -// 给定一个长度为m的数组op, -// op[i] = { k , 0 }, 表示对前k个士兵执行从小到大的操作 -// op[i] = { k , 1 }, 表示对前k个士兵执行从大到小的操作 -// 返回数组ans,表示最终的排列 -// 1 <= n, m <= 2 * 10^5 -// - 10^9 <= arr[i] <= + 10^9 -public class Code01_SortGame { - - // 暴力方法 - // 为了验证 - public static int[] game1(int[] arr, int[][] op) { - int n = arr.length; - Integer[] help = new Integer[n]; - for (int i = 0; i < n; i++) { - help[i] = arr[i]; - } - for (int[] o : op) { - if (o[1] == 0) { - Arrays.sort(help, 0, o[0], (a, b) -> a - b); - } else { - Arrays.sort(help, 0, o[0], (a, b) -> b - a); - } - } - int[] ans = new int[n]; - for (int i = 0; i < n; i++) { - ans[i] = help[i]; - } - return ans; - } - - // 正式方法 - // 时间复杂度O(M) + O(N*logN) - public static int[] game2(int[] arr, int[][] op) { - int n = arr.length; - int m = op.length; - int[] stack = new int[m]; - int r = 0; - for (int i = 0; i < m; i++) { - while (r != 0 && op[stack[r - 1]][0] <= op[i][0]) { - r--; - } - stack[r++] = i; - } - int[] ans = new int[n]; - int ansi = n - 1; - int l = 0; - for (; ansi >= op[stack[l]][0]; ansi--) { - ans[ansi] = arr[ansi]; - } - TreeSet sorted = new TreeSet<>(new NumberComparator()); - for (int i = 0; i < op[stack[l]][0]; i++) { - sorted.add(new Number(arr[i], i)); - } - while (l != r) { - // 当前处理的指令 - int[] cur = op[stack[l++]]; - if (l != r) { - int[] next = op[stack[l]]; - int num = cur[0] - next[0]; - if (cur[1] == 0) { - for (int i = 0; i < num; i++) { - ans[ansi--] = sorted.pollLast().value; - } - } else { - for (int i = 0; i < num; i++) { - ans[ansi--] = sorted.pollFirst().value; - } - } - } else { - if (cur[1] == 0) { - while (!sorted.isEmpty()) { - ans[ansi--] = sorted.pollLast().value; - } - } else { - while (!sorted.isEmpty()) { - ans[ansi--] = sorted.pollFirst().value; - } - } - } - } - return ans; - } - - public static class Number { - public int value; - public int index; - - public Number(int v, int i) { - value = v; - index = i; - } - } - - public static class NumberComparator implements Comparator { - - @Override - public int compare(Number o1, Number o2) { - if (o1.value != o2.value) { - return o1.value - o2.value; - } else { - return o1.index - o2.index; - } - } - - } - - // 为了测试 - public static int[] randomArray(int n, int v) { - int[] ans = new int[n]; - for (int i = 0; i < n; i++) { - ans[i] = (int) (Math.random() * v) + 1; - } - return ans; - } - - // 为了测试 - public static int[][] randomOp(int m, int n) { - int[][] ans = new int[m][2]; - for (int i = 0; i < m; i++) { - ans[i][0] = (int) (Math.random() * (n + 1)); - ans[i][1] = Math.random() < 0.5 ? 0 : 1; - } - return ans; - } - - // 为了测试 - public static boolean isEqual(int[] arr1, int[] arr2) { - if (arr1.length != arr2.length) { - return false; - } - for (int i = 0; i < arr1.length; i++) { - if (arr1[i] != arr2[i]) { - return false; - } - } - return true; - } - - // 为了测试 - public static void main(String[] args) { - -// int[] arr = { 3, 3, 7, 7, 7 }; -// -// TreeSet set = new TreeSet<>(new NumberComparator()); -// -// for (int i = 0; i < arr.length; i++) { -// set.add(new Number(arr[i], i)); -// } -// -//// System.out.println(set.size()); -// -// while(!set.isEmpty()) { -// System.out.println(set.pollLast().value); -// } - - int N = 100; - int M = 100; - int V = 200; - int testTimes = 5000; - System.out.println("测试开始"); - for (int i = 0; i < testTimes; i++) { - int n = (int) (Math.random() * N) + 1; - int m = (int) (Math.random() * M) + 1; - int[] arr = randomArray(n, V); - int[][] op = randomOp(m, n); - int[] ans1 = game1(arr, op); - int[] ans2 = game2(arr, op); - if (!isEqual(ans1, ans2)) { - System.out.println("出错了!"); - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class102/Code02_NLengthMValueLIS3.java b/公开课/class102/Code02_NLengthMValueLIS3.java deleted file mode 100644 index 943577a..0000000 --- a/公开课/class102/Code02_NLengthMValueLIS3.java +++ /dev/null @@ -1,176 +0,0 @@ -package class102; - -// 来自微众银行 -// 给定一个数字n,代表数组的长度 -// 给定一个数字m,代表数组每个位置都可以在1~m之间选择数字 -// 所有长度为n的数组中,最长递增子序列长度为3的数组,叫做达标数组 -// 返回达标数组的数量 -// 1 <= n <= 500 -// 1 <= m <= 10 -// 500 * 10 * 10 * 10 -// 结果对998244353取模 -// 实现的时候没有取模的逻辑,因为非重点 -public class Code02_NLengthMValueLIS3 { - - // 暴力方法 - // 为了验证 - public static int number1(int n, int m) { - return process1(0, n, m, new int[n]); - } - - public static int process1(int i, int n, int m, int[] path) { - if (i == n) { - return lengthOfLIS(path) == 3 ? 1 : 0; - } else { - int ans = 0; - for (int cur = 1; cur <= m; cur++) { - path[i] = cur; - ans += process1(i + 1, n, m, path); - } - return ans; - } - } - - public static int lengthOfLIS(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int[] ends = new int[arr.length]; - ends[0] = arr[0]; - int right = 0; - int max = 1; - for (int i = 1; i < arr.length; i++) { - int l = 0; - int r = right; - while (l <= r) { - int m = (l + r) / 2; - if (arr[i] > ends[m]) { - l = m + 1; - } else { - r = m - 1; - } - } - right = Math.max(right, l); - ends[l] = arr[i]; - max = Math.max(max, l + 1); - } - return max; - } - - // i : 目前来到的位置是i - // i f s t 四维参数的递归! - // dp[i][f][s][t] - // 500 * 10 * 10 * 10 = 5 * 10^5 -// public static int zuo(int i, int f, int s, int t, int n, int m) { -// if (i == n) { -// return t != 0 ? 1 : 0; -// } -// // i < n -// // 1 ~ m -// int ans = 0; -// for (int num = 1; num <= m; num++) { -// if (f == 0 || f >= num) { -// ans += zuo(i + 1, num, s, t, n, m); -// } else if (s == 0 || s >= num) { -// ans += zuo(i + 1, f, num, t, n, m); -// } else if (t == 0 || t >= num) { -// ans += zuo(i + 1, f, s, num, n, m); -// } else { // 都没拦住!最长递增子序列的长度将到达4!不合法了! -//// ans += 0; -// break; -// } -// } -// return ans; -// } - - // i : 当前来到的下标 - // f、s、t : ends数组中放置的数字! - // ? == 0,没放! - // n : 一共的长度! - // m : 每一位,都可以在1~m中随意选择数字 - // 返回值:i..... 有几个合法的数组! - public static int zuo(int i, int f, int s, int t, int n, int m) { - if (i == n) { - return f != 0 && s != 0 && t != 0 ? 1 : 0; - } - // i < n - int ans = 0; - for (int cur = 1; cur <= m; cur++) { - if (f == 0 || f >= cur) { - ans += zuo(i + 1, cur, s, t, n, m); - } else if (s == 0 || s >= cur) { - ans += zuo(i + 1, f, cur, t, n, m); - } else if (t == 0 || t >= cur) { - ans += zuo(i + 1, f, s, cur, n, m); - } - } - return ans; - } - - // 正式方法 - // 需要看最长递增子序列! - // 尤其是理解ends数组的意义! - public static int number2(int n, int m) { - int[][][][] dp = new int[n][m + 1][m + 1][m + 1]; - for (int i = 0; i < n; i++) { - for (int f = 0; f <= m; f++) { - for (int s = 0; s <= m; s++) { - for (int t = 0; t <= m; t++) { - dp[i][f][s][t] = -1; - } - } - } - } - return process2(0, 0, 0, 0, n, m, dp); - } - - public static int process2( - int i, int f, int s, int t, - int n, int m, int[][][][] dp) { - if (i == n) { - return f != 0 && s != 0 && t != 0 ? 1 : 0; - } - if (dp[i][f][s][t] != -1) { - return dp[i][f][s][t]; - } - int ans = 0; - for (int cur = 1; cur <= m; cur++) { - if (f == 0 || cur <= f) { - ans += process2(i + 1, cur, s, t, n, m, dp); - } else if (s == 0 || cur <= s) { - ans += process2(i + 1, f, cur, t, n, m, dp); - } else if (t == 0 || cur <= t) { - ans += process2(i + 1, f, s, cur, n, m, dp); - } - } - dp[i][f][s][t] = ans; - return ans; - } - - public static void main(String[] args) { - System.out.println("功能测试开始"); - for (int n = 4; n <= 8; n++) { - for (int m = 1; m <= 5; m++) { - int ans1 = number1(n, m); - int ans2 = number2(n, m); - if (ans1 != ans2) { - System.out.println(ans1); - System.out.println(ans2); - System.out.println("出错了!"); - } - } - } - System.out.println("功能测试结束"); - System.out.println("性能测试开始"); - int n = 2000; - int m = 20; - System.out.println("序列长度 : " + n); - System.out.println("数字范围 : " + m); - long start = System.currentTimeMillis(); - number2(n, m); - long end = System.currentTimeMillis(); - System.out.println("运行时间 : " + (end - start) + " 毫秒"); - System.out.println("性能测试结束"); - } - -} diff --git a/公开课/class102/Code03_LIS.java b/公开课/class102/Code03_LIS.java deleted file mode 100644 index 8320d35..0000000 --- a/公开课/class102/Code03_LIS.java +++ /dev/null @@ -1,55 +0,0 @@ -package class102; - -// 本题测试链接 : https://leetcode.com/problems/longest-increasing-subsequence -public class Code03_LIS { - - public static int lengthOfLIS(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - // ends数组 - // ends[i]表示 : 目前所有长度为i+1的递增子序列的最小结尾 - int[] ends = new int[arr.length]; - // 根据含义, 一开始ends[0] = arr[0] - ends[0] = arr[0]; - // ends有效区范围是0...right,right往右为无效区 - // 所以一开始right = 0, 表示有效区只有0...0范围 - int right = 0; - // 最长递增子序列的长度 - // 全局变量,抓取每一步的答案,取最大的结果 - int max = 1; - for (int i = 1; i < arr.length; i++) { - int l = 0; - int r = right; - // 在ends[l...r]范围上二分 - // 如果 当前数(arr[i]) > ends[m],砍掉左侧 - // 如果 当前数(arr[i]) <= ends[m],砍掉右侧 - // 整个二分就是在ends里寻找 >= 当前数(arr[i])的最左位置 - // 就是从while里面出来时,l所在的位置。 - // 如果ends中不存在 >= 当前数(arr[i])的情况,将返回有效区的越界位置 - // 也就是从while里面出来时,l所在的位置,是有效区的越界位置 - // 比如 : ends = { 3, 5, 9, 12, 再往右无效} - // 如果当前数为8, 从while里面出来时,l将来到2位置 - // 比如 : ends = { 3, 5, 9, 12, 再往右无效} - // 如果当前数为13, 从while里面出来时,l将来到有效区的越界位置,4位置 - while (l <= r) { - int m = (l + r) / 2; - if (arr[i] > ends[m]) { - l = m + 1; - } else { - r = m - 1; - } - } - // 从while里面出来,看l的位置 - // 如果l比right大,说明扩充了有效区,那么right变量要随之变大 - // 如果l不比right大,说明l没有来到有效区的越界位置,right不变 - right = Math.max(right, l); - // l的位置,就是当前数应该填到ends数组里的位置 - ends[l] = arr[i]; - // 更新全局变量 - max = Math.max(max, l + 1); - } - return max; - } - -} \ No newline at end of file diff --git a/公开课/class103/Code01_SoldierFindEnemy.java b/公开课/class103/Code01_SoldierFindEnemy.java deleted file mode 100644 index fd0af46..0000000 --- a/公开课/class103/Code01_SoldierFindEnemy.java +++ /dev/null @@ -1,185 +0,0 @@ -package class103; - -import java.util.PriorityQueue; - -// 来自华为 -// 给定一个N*M的二维矩阵,只由字符'O'、'X'、'S'、'E'组成 -// 'O'表示这个地方是可通行的平地 -// 'X'表示这个地方是不可通行的障碍 -// 'S'表示这个地方有一个士兵,全图保证只有一个士兵 -// 'E'表示这个地方有一个敌人,全图保证只有一个敌人 -// 士兵可以在上、下、左、右四个方向上移动 -// 走到相邻的可通行的平地上,走一步耗费a个时间单位 -// 士兵从初始地点行动时,不管去哪个方向,都不用耗费转向的代价 -// 但是士兵在行动途中,如果需要转向,需要额外再付出b个时间单位 -// 返回士兵找到敌人的最少时间 -// 如果因为障碍怎么都找不到敌人,返回-1 -// 1 <= N,M <= 1000 -// 1 <= a,b <= 100000 -// 只会有一个士兵、一个敌人 -public class Code01_SoldierFindEnemy { - - // 暴力dfs - // 为了验证 - public static int minCost1(char[][] map, int a, int b) { - int n = map.length; - int m = map[0].length; - int si = 0; - int sj = 0; - for (int i = 0; i < n; i++) { - for (int j = 0; j < m; j++) { - if (map[i][j] == 'S') { - si = i; - sj = j; - } - } - } - boolean[][][] visited = new boolean[n][m][4]; - int p1 = f(map, si, sj, 0, a, b, visited); - int p2 = f(map, si, sj, 1, a, b, visited); - int p3 = f(map, si, sj, 2, a, b, visited); - int p4 = f(map, si, sj, 3, a, b, visited); - int ans = Math.min(Math.min(p1, p2), Math.min(p3, p4)); - return ans == Integer.MAX_VALUE ? -1 : (ans - a); - } - - public static int f(char[][] map, int si, int sj, int d, int a, int b, boolean[][][] visited) { - if (si < 0 || si == map.length || sj < 0 || sj == map[0].length || map[si][sj] == 'X' || visited[si][sj][d]) { - return Integer.MAX_VALUE; - } - if (map[si][sj] == 'E') { - return a; - } - visited[si][sj][d] = true; - int p0 = f(map, si - 1, sj, 0, a, b, visited); - int p1 = f(map, si + 1, sj, 1, a, b, visited); - int p2 = f(map, si, sj - 1, 2, a, b, visited); - int p3 = f(map, si, sj + 1, 3, a, b, visited); - if (d != 0 && p0 != Integer.MAX_VALUE) { - p0 += b; - } - if (d != 1 && p1 != Integer.MAX_VALUE) { - p1 += b; - } - if (d != 2 && p2 != Integer.MAX_VALUE) { - p2 += b; - } - if (d != 3 && p3 != Integer.MAX_VALUE) { - p3 += b; - } - int ans = Math.min(Math.min(p0, p1), Math.min(p2, p3)); - ans = ans == Integer.MAX_VALUE ? ans : (ans + a); - visited[si][sj][d] = false; - return ans; - } - - // 正式方法 - // Dijkstra算法 - public static int minCost2(char[][] map, int a, int b) { - int n = map.length; - int m = map[0].length; - int si = 0; - int sj = 0; - for (int i = 0; i < n; i++) { - for (int j = 0; j < m; j++) { - if (map[i][j] == 'S') { - si = i; - sj = j; - } - } - } - PriorityQueue heap = new PriorityQueue<>((x, y) -> x[3] - y[3]); - heap.add(new int[] { si, sj, 0, 0 }); - heap.add(new int[] { si, sj, 1, 0 }); - heap.add(new int[] { si, sj, 2, 0 }); - heap.add(new int[] { si, sj, 3, 0 }); - boolean[][][] visited = new boolean[n][m][4]; - int ans = -1; - while (!heap.isEmpty()) { - int[] cur = heap.poll(); - if (visited[cur[0]][cur[1]][cur[2]]) { - continue; - } - if (map[cur[0]][cur[1]] == 'E') { - ans = cur[3]; - break; - } - visited[cur[0]][cur[1]][cur[2]] = true; - add(cur[0] - 1, cur[1], 0, cur[2], cur[3], a, b, map, visited, heap); - add(cur[0] + 1, cur[1], 1, cur[2], cur[3], a, b, map, visited, heap); - add(cur[0], cur[1] - 1, 2, cur[2], cur[3], a, b, map, visited, heap); - add(cur[0], cur[1] + 1, 3, cur[2], cur[3], a, b, map, visited, heap); - } - return ans; - } - - public static void add(int i, int j, int d, int preD, int preC, int a, int b, char[][] map, boolean[][][] visited, - PriorityQueue heap) { - if (i < 0 || i == map.length || j < 0 || j == map[0].length || map[i][j] == 'X' || visited[i][j][d]) { - return; - } - int cost = preC + a; - if (d != preD) { - cost += b; - } - heap.add(new int[] { i, j, d, cost }); - } - - // 为了测试 - public static char[][] randomMap(int n, int m) { - char[][] map = new char[n][m]; - for (int i = 0; i < n; i++) { - for (int j = 0; j < m; j++) { - map[i][j] = Math.random() < 0.5 ? 'O' : 'X'; - } - } - int si = (int) (Math.random() * n); - int sj = (int) (Math.random() * m); - map[si][sj] = 'S'; - int ei, ej; - do { - ei = (int) (Math.random() * n); - ej = (int) (Math.random() * m); - } while (ei == si && ej == sj); - map[ei][ej] = 'E'; - return map; - } - - public static void main(String[] args) { - int n = 3; - int m = 4; - int v = 10; - System.out.println("功能测试开始"); - for (int i = 0; i < 2000; i++) { - char[][] map = randomMap(n, m); - int a = (int) (Math.random() * v) + 1; - int b = (int) (Math.random() * v) + 1; - int ans1 = minCost1(map, a, b); - int ans2 = minCost2(map, a, b); - if (ans1 != ans2) { - System.out.println("出错了"); - System.out.println(ans1); - System.out.println(ans2); - } - } - System.out.println("功能测试结束"); - - System.out.println("性能测试开始"); - n = 1000; - m = 1000; - v = 100000; - int a = (int) (Math.random() * v) + 1; - int b = (int) (Math.random() * v) + 1; - char[][] map = randomMap(n, m); - System.out.println("数据规模 : " + n + " * " + m); - System.out.println("通行代价 : " + a); - System.out.println("转向代价 : " + b); - long start = System.currentTimeMillis(); - minCost2(map, a, b); - long end = System.currentTimeMillis(); - System.out.println("运行时间 : " + (end - start) + "毫秒"); - System.out.println("功能测试结束"); - - } - -} diff --git a/公开课/class103/Code02_RedPalindromeGoodStrings.java b/公开课/class103/Code02_RedPalindromeGoodStrings.java deleted file mode 100644 index 1e6edbc..0000000 --- a/公开课/class103/Code02_RedPalindromeGoodStrings.java +++ /dev/null @@ -1,93 +0,0 @@ -package class103; - -// 来自阿里 -// 小红定义一个仅有r、e、d三种字符的字符串中 -// 如果仅有一个长度不小于2的回文子串,那么这个字符串定义为"好串" -// 给定一个正整数n,输出长度为n的好串有多少个 -// 结果对10^9 + 7取模, 1 <= n <= 10^9 -// 示例: -// n = 1, 输出0 -// n = 2, 输出3 -// n = 3, 输出18 -public class Code02_RedPalindromeGoodStrings { - - // 暴力方法 - // 为了观察规律 - // 根据好串的定义 - // 长度为n的时候,返回好串的数量 - public static int goods(int n) { - char[] path = new char[n]; - return process(0, n, path); - } - - // 长度为n所有可能的字符串,请都得到! - public static int process(int i, int n, char[] path) { - if (i == n) { - return ok(path) ? 1 : 0; - } else { - int ans = 0; - path[i] = 'r'; - ans += process(i + 1, n, path); - path[i] = 'e'; - ans += process(i + 1, n, path); - path[i] = 'd'; - ans += process(i + 1, n, path); - return ans; - } - } - - // 如果是好串,返回true;不是好串,返回false - public static boolean ok(char[] path) { - int count = 0; - for (int l = 0; l < path.length; l++) { - for (int r = l + 1; r < path.length; r++) { - if (isP(path, l, r)) { - count++; - } - if (count > 1) { - return false; - } - } - } - return count == 1; - } - - // l.... r - // ? ? ? ? - public static boolean isP(char[] path, int l, int r) { - while (l < r) { - if (path[l] != path[r]) { - return false; - } - l++; - r--; - } - return true; - } - - // 正式方法 - // 观察规律之后,把规律变成代码 - public static int num2(int n) { - if (n == 1) { - return 0; - } - if (n == 2) { - return 3; - } - if (n == 3) { - return 18; - } - return 6 * (n + 1); - } - - public static void main(String[] args) { - System.out.println(goods(1)); - System.out.println(goods(2)); - System.out.println(goods(3)); - System.out.println(goods(4)); - System.out.println(goods(5)); - System.out.println(goods(6)); - System.out.println(goods(7)); - } - -} diff --git a/公开课/class104/Code01_RedPalindromeGoodStrings.java b/公开课/class104/Code01_RedPalindromeGoodStrings.java deleted file mode 100644 index d54a8dd..0000000 --- a/公开课/class104/Code01_RedPalindromeGoodStrings.java +++ /dev/null @@ -1,134 +0,0 @@ -package class104; - -// 来自阿里 -// 小红定义一个仅有r、e、d三种字符的字符串中 -// 如果仅有一个长度不小于2的回文子串,那么这个字符串定义为"好串" -// 给定一个正整数n,输出长度为n的好串有多少个 -// 结果对10^9 + 7取模, 1 <= n <= 10^9 -// 示例: -// n = 1, 输出0 -// n = 2, 输出3 -// n = 3, 输出18 -public class Code01_RedPalindromeGoodStrings { - - public static int cnt = 0; - - public static int num1(int n) { - cnt = 0; - process(new char[n], 0, n); - return cnt; - } - - // path = {r,r,e,d } .. n - public static void process(char[] path, int i, int n) { - if (i == n) { - if (isGood(path)) { - cnt++; - } - } else { - path[i] = 'r'; - process(path, i + 1, n); - path[i] = 'e'; - process(path, i + 1, n); - path[i] = 'd'; - process(path, i + 1, n); - } - } - - // 验证path,是不是好串 - // 好串:只有一个回文子串长度>=2 - public static boolean isGood(char[] path) { - int ans = 0; - for (int l = 0; l < path.length; l++) { - for (int r = l + 1; r < path.length; r++) { - // path[l...r]是不是回文串! - if (isP(path, l, r)) { - ans++; - } - if (ans > 1) { - return false; - } - } - } - return ans == 1; - } - - // 暴力方法 - // 为了观察规律 - // 根据好串的定义 - // 长度为n的时候,返回好串的数量 - public static int goods(int n) { - char[] path = new char[n]; - return process(0, n, path); - } - - // 长度为n所有可能的字符串,请都得到! - public static int process(int i, int n, char[] path) { - if (i == n) { - return ok(path) ? 1 : 0; - } else { - int ans = 0; - path[i] = 'r'; - ans += process(i + 1, n, path); - path[i] = 'e'; - ans += process(i + 1, n, path); - path[i] = 'd'; - ans += process(i + 1, n, path); - return ans; - } - } - - // 如果是好串,返回true;不是好串,返回false - public static boolean ok(char[] path) { - int count = 0; - for (int l = 0; l < path.length; l++) { - for (int r = l + 1; r < path.length; r++) { - if (isP(path, l, r)) { - count++; - } - if (count > 1) { - return false; - } - } - } - return count == 1; - } - - public static boolean isP(char[] path, int l, int r) { - while (l < r) { - if (path[l] != path[r]) { - return false; - } - l++; - r--; - } - return true; - } - - // 正式方法 - // 观察规律之后,把规律变成代码 - public static int num2(int n) { - if (n == 1) { - return 0; - } - if (n == 2) { - return 3; - } - if (n == 3) { - return 18; - } - return 6 * (n + 1); - } - - public static void main(String[] args) { - System.out.println(num1(1)); - System.out.println(num1(2)); - System.out.println(num1(3)); - System.out.println(num1(4)); - System.out.println(num1(5)); - System.out.println(num1(6)); - System.out.println(num1(7)); - System.out.println(num1(8)); - } - -} diff --git a/公开课/class104/Code02_MaxSumOnReverseArray.java b/公开课/class104/Code02_MaxSumOnReverseArray.java deleted file mode 100644 index f8226a7..0000000 --- a/公开课/class104/Code02_MaxSumOnReverseArray.java +++ /dev/null @@ -1,96 +0,0 @@ -package class104; - -// 来自美团 -// 最大子段和是 -// 一个经典问题,即对于一个数组找出其和最大的子数组。 -// 现在允许你在求解该问题之前翻转这个数組的连续一段 -// 如翻转(1,2,3,4,5,6)的第三个到第五个元素組成的子数组得到的是(1,2,5,4,3,6), -// 则翻转后该数组的最大子段和最大能达到多少? -public class Code02_MaxSumOnReverseArray { - - // 暴力解 - // 翻转每一个子数组,全求一遍 - public static int maxSumReverse1(int[] arr) { - int ans = Integer.MIN_VALUE; - for (int L = 0; L < arr.length; L++) { - for (int R = L; R < arr.length; R++) { - reverse(arr, L, R); - ans = Math.max(ans, maxSum(arr)); - reverse(arr, L, R); - } - } - return ans; - } - - public static void reverse(int[] arr, int L, int R) { - while (L < R) { - int tmp = arr[L]; - arr[L++] = arr[R]; - arr[R--] = tmp; - } - } - - public static int maxSum(int[] arr) { - int pre = arr[0]; - int max = arr[0]; - for (int i = 1; i < arr.length; i++) { - pre = Math.max(arr[i], arr[i] + pre); - max = Math.max(max, pre); - } - return max; - } - - public static int maxSumReverse2(int[] arr) { - int n = arr.length; - int[] prefix = new int[n]; - prefix[n - 1] = arr[n - 1]; - for (int i = n - 2; i >= 0; i--) { - prefix[i] = arr[i] + Math.max(0, prefix[i + 1]); - } - int ans = prefix[0]; - int suffix = arr[0]; - int maxSuffix = suffix; - for (int i = 1; i < n; i++) { - ans = Math.max(ans, maxSuffix + prefix[i]); - suffix = arr[i] + Math.max(0, suffix); - maxSuffix = Math.max(maxSuffix, suffix); - } - ans = Math.max(ans, maxSuffix); - return ans; - } - - // 为了测试 - public static int[] randomArray(int n, int v) { - int[] arr = new int[n]; - for (int i = 0; i < n; i++) { - arr[i] = (int) (Math.random() * v) - (int) (Math.random() * v); - } - return arr; - } - - // 为了测试 - public static void main(String[] args) { - int len = 50; - int value = 20; - int testTime = 20000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int n = (int) (Math.random() * len) + 1; - int[] arr = randomArray(n, value); - int ans1 = maxSumReverse1(arr); - int ans2 = maxSumReverse2(arr); - if (ans1 != ans2) { - System.out.println("出错了!"); - for (int num : arr) { - System.out.print(num + " "); - } - System.out.println(); - System.out.println(ans1); - System.out.println(ans2); - break; - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class104/Code03_ExaminationPaperWays.java b/公开课/class104/Code03_ExaminationPaperWays.java deleted file mode 100644 index 575acdb..0000000 --- a/公开课/class104/Code03_ExaminationPaperWays.java +++ /dev/null @@ -1,120 +0,0 @@ -package class104; - -import java.util.Arrays; - -// 来自美团 -// 有三个题库A、B、C,每个题库均有n道题目,且题目都是从1到n进行编号 -// 每个题目都有一个难度值 -// 题库A中第i个题目的难度为ai -// 题库B中第i个题目的难度为bi -// 题库C中第i个题目的难度为ci -// 小美准备组合出一套试题,试题共有三道题, -// 第一题来自题库A,第二题来自题库B,第三题来自题库C -// 试题要求题目难度递增,且梯度不能过大 -// 具体地说,第二题的难度必须大于第一题的难度,但不能大于第一题难度的两倍 -// 第三题的难度必须大于第二题的难度,但不能大于第二题难度的两倍 -// 小美想知道在满足上述要求下,有多少种不同的题目组合 -//(三道题目中只要存在一道题目不同,则两个题目组合就视为不同 -// 输入描述 第一行一个正整数n, 表示每个题库的题目数量 -// 第二行为n个正整数a1, a2,...... an,其中ai表示题库A中第i个题目的难度值 -// 第三行为n个正整数b1, b2,...... bn,其中bi表示题库B中第i个题目的难度值 -// 第四行为n个正整数c1, c2,...... cn,其中ci表示题库C中第i个题目的难度值 -// 1 <= n <= 20000, 1 <= ai, bi, ci <= 10^9。 -public class Code03_ExaminationPaperWays { - - // 暴力方法 - // 时间复杂度O(N^3) - // 为了验证 - public static int ways1(int[] a, int[] b, int[] c) { - int n = a.length; - Arrays.sort(a); - Arrays.sort(b); - Arrays.sort(c); - int ans = 0; - for (int i = 0; i < n; i++) { - for (int j = 0; j < n && b[j] <= a[i] * 2; j++) { - if (b[j] > a[i]) { - for (int k = 0; k < n && c[k] <= b[j] * 2; k++) { - if (c[k] > b[j]) { - ans++; - } - } - } - } - } - return ans; - } - - // 正式方法 - // 时间复杂度O(N * logN) - public static int ways2(int[] a, int[] b, int[] c) { - int n = a.length; - Arrays.sort(a); - Arrays.sort(b); - Arrays.sort(c); - // B里面的记录 - int[] help = new int[n]; - for (int i = 0, l = -1, r = 0; i < n; i++) { - while (l + 1 < n && c[l + 1] <= b[i]) { - l++; - } - while (r < n && c[r] <= b[i] * 2) { - r++; - } - help[i] = Math.max(r - l - 1, 0); - } - for (int i = 1; i < n; i++) { - help[i] += help[i - 1]; - } - int ans = 0; - for (int i = 0, l = -1, r = 0; i < n; i++) { - while (l + 1 < n && b[l + 1] <= a[i]) { - l++; - } - while (r < n && b[r] <= a[i] * 2) { - r++; - } - if (r - l - 1 > 0) { - ans += sum(help, l + 1, r - 1); - } - } - return ans; - } - - public static int sum(int[] help, int l, int r) { - return l == 0 ? help[r] : help[r] - help[l - 1]; - } - - // 为了测试 - public static int[] randomArray(int n, int v) { - int[] ans = new int[n]; - for (int i = 0; i < n; i++) { - ans[i] = (int) (Math.random() * v); - } - return ans; - } - - // 为了测试 - public static void main(String[] args) { - int N = 100; - int V = 100; - int testTimes = 5000; - System.out.println("测试开始"); - for (int i = 0; i < testTimes; i++) { - int n = (int) (Math.random() * N) + 1; - int[] a = randomArray(n, V); - int[] b = randomArray(n, V); - int[] c = randomArray(n, V); - int ans1 = ways1(a, b, c); - int ans2 = ways2(a, b, c); - if (ans1 != ans2) { - System.out.println("出错了!"); - System.out.println(ans1); - System.out.println(ans2); - break; - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class104/Code04_TopMinSubsquenceSum.java b/公开课/class104/Code04_TopMinSubsquenceSum.java deleted file mode 100644 index 9093050..0000000 --- a/公开课/class104/Code04_TopMinSubsquenceSum.java +++ /dev/null @@ -1,116 +0,0 @@ -package class104; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.PriorityQueue; - -// 来自亚马逊 -// 给定一个数组arr,含有n个数字,都是非负数 -// 给定一个正数k -// 返回所有子序列中,累加和最小的前k个子序列累加和 -// 假设K不大,怎么算最快? -public class Code04_TopMinSubsquenceSum { - - public static int[] topMinSum1(int[] arr, int k) { - ArrayList allAns = new ArrayList<>(); - process(arr, 0, 0, allAns); - allAns.sort((a, b) -> a.compareTo(b)); - int[] ans = new int[k]; - for (int i = 0; i < k; i++) { - ans[i] = allAns.get(i); - } - return ans; - } - - public static void process(int[] arr, int index, int sum, ArrayList ans) { - if (index == arr.length) { - ans.add(sum); - } else { - process(arr, index + 1, sum, ans); - process(arr, index + 1, sum + arr[index], ans); - } - } - - public static int[] topMinSum2(int[] arr, int k) { - Arrays.sort(arr); - // (最右的下标,集合的累加和) - PriorityQueue heap = new PriorityQueue<>((a, b) -> a[1] - b[1]); - heap.add(new int[] { 0, arr[0] }); - int[] ans = new int[k]; - // ans[0] = 0 - // 0 1 2 k-1 - // k个! - for (int i = 1; i < k; i++) { - int[] cur = heap.poll(); - // (7, 100) - // 左 :8, 100 - arr[7] + arr[8] - // 右 :8, 100 + arr[8] - int last = cur[0]; - int sum = cur[1]; - ans[i] = sum; - if (last + 1 < arr.length) { - heap.add(new int[] { last + 1, sum - arr[last] - + arr[last + 1] }); - heap.add(new int[] { last + 1, sum + arr[last + 1] }); - } - } - return ans; - } - - // 为了测试 - public static int[] randomArray(int len, int value) { - int[] arr = new int[len]; - for (int i = 0; i < len; i++) { - arr[i] = (int) (Math.random() * value); - } - return arr; - } - - // 为了测试 - public static boolean equals(int[] ans1, int[] ans2) { - if (ans1.length != ans2.length) { - return false; - } - for (int i = 0; i < ans1.length; i++) { - if (ans1[i] != ans2[i]) { - return false; - } - } - return true; - } - - // 为了测试 - public static void main(String[] args) { - int n = 10; - int v = 40; - int testTime = 5000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int len = (int) (Math.random() * n) + 1; - int[] arr = randomArray(len, v); - int k = (int) (Math.random() * ((1 << len) - 1)) + 1; - int[] ans1 = topMinSum1(arr, k); - int[] ans2 = topMinSum2(arr, k); - if (!equals(ans1, ans2)) { - System.out.println("出错了!"); - System.out.print("arr : "); - for (int num : arr) { - System.out.print(num + " "); - } - System.out.println(); - System.out.println("k : " + k); - for (int num : ans1) { - System.out.print(num + " "); - } - System.out.println(); - for (int num : ans2) { - System.out.print(num + " "); - } - System.out.println(); - break; - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class104/Code05_MaxLengthSameCharMChanges.java b/公开课/class104/Code05_MaxLengthSameCharMChanges.java deleted file mode 100644 index db2d00a..0000000 --- a/公开课/class104/Code05_MaxLengthSameCharMChanges.java +++ /dev/null @@ -1,130 +0,0 @@ -package class104; - -// 来自字节 -// 给定一个只由小写字母组成的字符串str,长度为N -// 给定一个只由0、1组成的数组arr,长度为N -// arr[i] == 0表示str中i位置的字符不许修改 -// arr[i] == 1表示str中i位置的字符允许修改 -// 给定一个正数m,表示在任意允许修改的位置 -// 可以把该位置的字符变成a~z中的任何一个 -// 可以修改m次 -// 返回在最多修改m次的情况下,全是一种字符的最长子串是多长 -// 1 <= N, M <= 10^5 -// 所有字符都是小写 -public class Code05_MaxLengthSameCharMChanges { - - // 暴力方法 - // 为了测试 - public static int maxLen1(String str, int[] arr, int m) { - char[] s = str.toCharArray(); - int n = s.length; - int ans = 0; - for (char c = 'a'; c <= 'z'; c++) { - for (int i = 0; i < n; i++) { - for (int j = n - 1; j >= i; j--) { - if (ok(s, i, j, c, arr, m)) { - ans = Math.max(ans, j - i + 1); - break; - } - } - } - } - return ans; - } - - // 为了测试 - public static boolean ok(char[] s, int l, int r, char c, int[] arr, int m) { - for (int i = l; i <= r; i++) { - if (s[i] == c) { - continue; - } - if (arr[i] == 0 || m == 0) { - return false; - } - m--; - } - return true; - } - - // 正式方法 - public static int maxLen2(String str, int[] arr, int m) { - char[] s = str.toCharArray(); - int n = s.length; - int ans = 0; - for (char aim = 'a'; aim <= 'z'; aim++) { - // 右边界 - // [l..r) - int r = 0; - // 用了几次修改了 - // change == m 用完的时候 - int change = 0; - for (int l = 0; l < n; l++) { - // l......r -> - while (r < n) { - if (s[r] == aim) { - r++; - continue; - } - // s[r] != aim - if (arr[r] == 0 || change == m) { - break; - } - // s[r] != aim && arr[r] == 1 && change < m - change++; - r++; - } - // l....r-1 r - // X l+1 - ans = Math.max(ans, r - l); - if (s[l] != aim && arr[l] == 1) { - change--; - } - // r r - // l l - // X - r = Math.max(r, l + 1); - } - } - return ans; - } - - // 为了测试 - public static String randomString(int n, int r) { - char[] ans = new char[n]; - for (int i = 0; i < n; i++) { - ans[i] = (char) ((int) (Math.random() * r) + 'a'); - } - return String.valueOf(ans); - } - - // 为了测试 - public static int[] randomArray(int n) { - int[] ans = new int[n]; - for (int i = 0; i < n; i++) { - ans[i] = (int) (Math.random() * 2); - } - return ans; - } - - // 为了测试 - public static void main(String[] args) { - int N = 100; - int R = 5; - int testTimes = 5000; - System.out.println("测试开始"); - for (int i = 0; i < testTimes; i++) { - int n = (int) (Math.random() * N) + 1; - int m = (int) (Math.random() * n) + 1; - String str = randomString(n, R); - int[] arr = randomArray(n); - int ans1 = maxLen1(str, arr, m); - int ans2 = maxLen2(str, arr, m); - if (ans1 != ans2) { - System.out.println("出错了!"); - break; - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class104/Code06_EvenTimesMaxSubstring.java b/公开课/class104/Code06_EvenTimesMaxSubstring.java deleted file mode 100644 index bf1d97b..0000000 --- a/公开课/class104/Code06_EvenTimesMaxSubstring.java +++ /dev/null @@ -1,118 +0,0 @@ -package class104; - -import java.util.HashMap; - -// 来自微软 -// 给定一个字符串s,其中都是英文小写字母 -// 如果s中的子串含有的每种字符都是偶数个 -// 那么这样的子串就是达标子串,子串要求是连续串 -// 返回s中达标子串的最大长度 -// 1 <= s的长度 <= 10^5 -// 字符种类都是英文小写 -public class Code06_EvenTimesMaxSubstring { - - // 一个经典问题 - // 累加和等于k的最长子数组是多长 - public static int maxLength(int[] arr, int k) { - if (arr == null || arr.length == 0) { - return 0; - } - // key : 某个前缀和 - // value : 最早出现的位置 - HashMap map = new HashMap(); - map.put(0, -1); - int len = 0; - int x = 0; - for (int i = 0; i < arr.length; i++) { - x += arr[i]; - if (map.containsKey(x - k)) { - len = Math.max(i - map.get(x - k), len); - } - if (!map.containsKey(x)) { - map.put(x, i); - } - } - return len; - } - - // 为了测试 - // 暴力方法 - public static int maxLen1(String s) { - int n = s.length(); - int ans = 0; - for (int i = 0; i < n; i++) { - for (int j = n - 1; j >= i; j--) { - if (ok(s, i, j)) { - ans = Math.max(ans, j - i + 1); - break; - } - } - } - return ans; - } - - // 为了测试 - // 暴力方法 - public static boolean ok(String s, int l, int r) { - if (((r - l + 1) & 1) == 1) { - return false; - } - int[] cnts = new int[26]; - for (int i = l; i <= r; i++) { - cnts[s.charAt(i) - 'a']++; - } - for (int cnt : cnts) { - if ((cnt & 1) == 1) { - return false; - } - } - return true; - } - - public static int maxLen2(String s) { - HashMap map = new HashMap<>(); - map.put(0, -1); - int status = 0; - int ans = 0; - int n = s.length(); - for (int i = 0; i < n; i++) { - status ^= 1 << (s.charAt(i) - 'a'); - if (map.containsKey(status)) { - ans = Math.max(ans, i - map.get(status)); - } else { - map.put(status, i); - } - } - return ans; - } - - // 为了测试 - public static String randomString(int n, int v) { - char[] s = new char[n]; - for (int i = 0; i < n; i++) { - s[i] = (char) ((int) (Math.random() * v) + 'a'); - } - return String.valueOf(s); - } - - // 为了测试 - public static void main(String[] args) { - int n = 50; - int v = 6; - int testTimes = 2000; - System.out.println("测试开始"); - for (int i = 0; i < testTimes; i++) { - String s = randomString(n, v); - int ans1 = maxLen1(s); - int ans2 = maxLen2(s); - if (ans1 != ans2) { - System.out.println(s); - System.out.println(ans1); - System.out.println(ans2); - break; - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class104/Code07_SortGame.java b/公开课/class104/Code07_SortGame.java deleted file mode 100644 index b1dc592..0000000 --- a/公开课/class104/Code07_SortGame.java +++ /dev/null @@ -1,189 +0,0 @@ -package class104; - -import java.util.Arrays; -import java.util.Comparator; -import java.util.TreeSet; - -// 来自百度 -// 二狗买了一些小兵玩具,和大胖一起玩 -// 一共有n个小兵,这n个小兵拍成一列 -// 第i个小兵战斗力为hi,然后他们两个开始对小兵进行排列 -// 一共进行m次操作,二狗每次操作选择一个数k,将前k个小兵战斗力从小到大排列 -// 大胖每次操作选择一个数k,将前k个小兵战斗力从大到小排列 -// 问所有操作结束后,排列顺序什么样 -// 给定一个长度为n的数组arr,表示每个小兵的战斗力 -// 给定一个长度为m的数组op, -// op[i] = { k , 0 }, 表示对前k个士兵执行从小到大的操作 -// op[i] = { k , 1 }, 表示对前k个士兵执行从大到小的操作 -// 返回数组ans,表示最终的排列 -// 1 <= n, m <= 2 * 10^5 -// - 10^9 <= arr[i] <= + 10^9 -public class Code07_SortGame { - - // 暴力方法 - // 为了验证 - public static int[] game1(int[] arr, int[][] op) { - int n = arr.length; - Integer[] help = new Integer[n]; - for (int i = 0; i < n; i++) { - help[i] = arr[i]; - } - for (int[] o : op) { - if (o[1] == 0) { - Arrays.sort(help, 0, o[0], (a, b) -> a - b); - } else { - Arrays.sort(help, 0, o[0], (a, b) -> b - a); - } - } - int[] ans = new int[n]; - for (int i = 0; i < n; i++) { - ans[i] = help[i]; - } - return ans; - } - - // 正式方法 - // 时间复杂度O(M) + O(N*logN) - public static int[] game2(int[] arr, int[][] op) { - int n = arr.length; - int m = op.length; - int[] stack = new int[m]; - int r = 0; - for (int i = 0; i < m; i++) { - while (r != 0 && op[stack[r - 1]][0] <= op[i][0]) { - r--; - } - stack[r++] = i; - } - int[] ans = new int[n]; - int ansi = n - 1; - int l = 0; - for (; ansi >= op[stack[l]][0]; ansi--) { - ans[ansi] = arr[ansi]; - } - TreeSet sorted = new TreeSet<>(new NumberComparator()); - for (int i = 0; i < op[stack[l]][0]; i++) { - sorted.add(new Number(arr[i], i)); - } - while (l != r) { - // 当前处理的指令 - int[] cur = op[stack[l++]]; - if (l != r) { - int[] next = op[stack[l]]; - int num = cur[0] - next[0]; - if (cur[1] == 0) { - for (int i = 0; i < num; i++) { - ans[ansi--] = sorted.pollLast().value; - } - } else { - for (int i = 0; i < num; i++) { - ans[ansi--] = sorted.pollFirst().value; - } - } - } else { - if (cur[1] == 0) { - while (!sorted.isEmpty()) { - ans[ansi--] = sorted.pollLast().value; - } - } else { - while (!sorted.isEmpty()) { - ans[ansi--] = sorted.pollFirst().value; - } - } - } - } - return ans; - } - - public static class Number { - public int value; - public int index; - - public Number(int v, int i) { - value = v; - index = i; - } - } - - public static class NumberComparator implements Comparator { - - @Override - public int compare(Number o1, Number o2) { - if (o1.value != o2.value) { - return o1.value - o2.value; - } else { - return o1.index - o2.index; - } - } - - } - - // 为了测试 - public static int[] randomArray(int n, int v) { - int[] ans = new int[n]; - for (int i = 0; i < n; i++) { - ans[i] = (int) (Math.random() * v) + 1; - } - return ans; - } - - // 为了测试 - public static int[][] randomOp(int m, int n) { - int[][] ans = new int[m][2]; - for (int i = 0; i < m; i++) { - ans[i][0] = (int) (Math.random() * (n + 1)); - ans[i][1] = Math.random() < 0.5 ? 0 : 1; - } - return ans; - } - - // 为了测试 - public static boolean isEqual(int[] arr1, int[] arr2) { - if (arr1.length != arr2.length) { - return false; - } - for (int i = 0; i < arr1.length; i++) { - if (arr1[i] != arr2[i]) { - return false; - } - } - return true; - } - - // 为了测试 - public static void main(String[] args) { - -// int[] arr = { 3, 3, 7, 7, 7 }; -// -// TreeSet set = new TreeSet<>(new NumberComparator()); -// -// for (int i = 0; i < arr.length; i++) { -// set.add(new Number(arr[i], i)); -// } -// -//// System.out.println(set.size()); -// -// while(!set.isEmpty()) { -// System.out.println(set.pollLast().value); -// } - - int N = 100; - int M = 100; - int V = 200; - int testTimes = 5000; - System.out.println("测试开始"); - for (int i = 0; i < testTimes; i++) { - int n = (int) (Math.random() * N) + 1; - int m = (int) (Math.random() * M) + 1; - int[] arr = randomArray(n, V); - int[][] op = randomOp(m, n); - int[] ans1 = game1(arr, op); - int[] ans2 = game2(arr, op); - if (!isEqual(ans1, ans2)) { - System.out.println("出错了!"); - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class105/Code01_EveryQueryUsers.java b/公开课/class105/Code01_EveryQueryUsers.java deleted file mode 100644 index e9c17e2..0000000 --- a/公开课/class105/Code01_EveryQueryUsers.java +++ /dev/null @@ -1,213 +0,0 @@ -package class105; - -import java.util.HashMap; -import java.util.HashSet; - -// 来自字节 -// 给定正数N,表示用户数量,用户编号从0~N-1 -// 给定正数M,表示实验数量,实验编号从0~M-1 -// 给定长度为N的二维数组A, -// A[i] = { a, b, c }表示,用户i报名参加了a号、b号、c号实验 -// 给定正数Q,表示查询的条数 -// 给定长度为Q的二维数组B, -// B[i] = { e, f }表示,第i条查询想知道e号、f号实验,一共有多少人(去重统计) -// 返回每一条查询的结果数组 -// 数据描述 : -// 1 <= N <= 10^5 -// 1 <= M <= 10^2 -// 所有查询所列出的所有实验编号数量 <= 10^5 -public class Code01_EveryQueryUsers { - -// public static void main(String[] args) { -//// int a = 11; -//// int b = 10; -//// // a / b向上取整 : -//// System.out.println((a + b - 1) / b); -//// -//// System.out.println(100000 / 32); -//// // 0 ~ 49999 -//// int n = 50000; -//// int[] sets = new int[(n + 31) / 32]; -//// int i = 34601; -//// // 34601 / 32 -//// // sets[0] : 0 ~ 31 -//// // sets[1] : 32 ~ 63 -//// // sets[2] : 64 ~ -//// int from = i / 32; -//// // 34601 % 32 -//// sets[from] |= 1 << (i % 32); -// -// int n = 100000; -// int m = 100; -// int parts = (n + 31) / 32; -// int[][] sets = new int[m][parts]; -// int[][] A = { { 3, 6, 9 }, // 0 -// { 5, 17, 23 }, // 1 -// { 89, 73, 13 }, // 2 -// -// }; -// -// for (int i = 0; i < A.length; i++) { -// for (int exp : A[i]) { -// int[] set = sets[exp]; -// set[i / 32] |= 1 << (1 % 32); -// } -// } -// -// int[][] B = { -// { 4, 17, 23 }, // 第0条查询 -// { 3, 4, 41 }, // 第1条查询 -// }; -// -// int[] ans = new int[B.length]; -// -// for (int i = 0; i < B.length; i++) { -// int ones = 0; -// // 4 : 0 1 ... parts-1 -// //17 : 0 1 ... parts-1 -// //23 : 0 1 ... parts-1 -// for (int j = 0; j < parts; j++) { -// int count = 0; -// for(int exp : B[i]) { -// count |= sets[exp][j]; -// } -// ones += countOnes(count); -// } -// ans[i] = ones; -// } -// -//// System.out.println(countOnes(set)); -// -// } - - // 暴力方法 - // 为了验证 - public static int[] record1(int n, int m, int q, int[][] A, int[][] B) { - HashMap> expUsersMap = new HashMap<>(); - for (int i = 0; i < m; i++) { - expUsersMap.put(i, new HashSet<>()); - } - for (int i = 0; i < n; i++) { - for (int exp : A[i]) { - expUsersMap.get(exp).add(i); - } - } - int[] ans = new int[q]; - HashSet help = new HashSet<>(); - for (int i = 0; i < q; i++) { - help.clear(); - for (int exp : B[i]) { - for (int user : expUsersMap.get(exp)) { - help.add(user); - } - } - ans[i] = help.size(); - } - return ans; - } - - // 正式方法 - public static int[] record2(int n, int m, int q, int[][] A, int[][] B) { - // n 一共有多少人 - // 任何一个实验,需要几个整数,能表示所有人谁出现谁没出现? - int parts = (n + 31) / 32; - // m 0 ~ m -1 - // [i] [.........] - int[][] bitMap = new int[m][parts]; - for (int i = 0; i < n; i++) { - // i 人的编号 : a b c - for (int exp : A[i]) { - bitMap[exp][i / 32] |= 1 << (i % 32); - } - } - int[] ans = new int[q]; - for (int i = 0; i < q; i++) { - // i号查询 : a、c、e,一共有多少去重的人 - // a[0] | c[0] | e[0] -> 几个1 - // a[1] | c[1] | e[1] -> 几个1 - int all = 0; - for (int j = 0; j < parts; j++) { - int status = 0; - for (int exp : B[i]) { - status |= bitMap[exp][j]; - } - all += countOnes(status); - } - ans[i] = all; - } - return ans; - } - - // 大厂刷题班,32节, - // leetcode专题 : https://leetcode.com/problems/number-of-1-bits/ - // 一个32位整数,求里面有几个1 - public static int countOnes(int n) { - n = (n & 0x55555555) + ((n >>> 1) & 0x55555555); - n = (n & 0x33333333) + ((n >>> 2) & 0x33333333); - n = (n & 0x0f0f0f0f) + ((n >>> 4) & 0x0f0f0f0f); - n = (n & 0x00ff00ff) + ((n >>> 8) & 0x00ff00ff); - n = (n & 0x0000ffff) + ((n >>> 16) & 0x0000ffff); - return n; - } - - // 为了测试 - public static int[][] randomMatrix(int n, int m, int v) { - int[][] ans = new int[n][m]; - for (int i = 0; i < n; i++) { - for (int j = 0; j < m; j++) { - ans[i][j] = (int) (Math.random() * v); - } - } - return ans; - } - - // 为了测试 - public static void main(String[] args) { - int N = 100; - int M = 20; - int Q = 50; - int testTime = 5000; - System.out.println("功能测试开始"); - for (int i = 0; i < testTime; i++) { - int n = (int) (Math.random() * N) + 1; - int m = (int) (Math.random() * M) + 1; - int[][] A = randomMatrix(n, (int) (Math.random() * m) + 1, m); - int q = (int) (Math.random() * Q) + 1; - int[][] B = randomMatrix(q, (int) (Math.random() * m) + 1, m); - int[] ans1 = record1(n, m, q, A, B); - int[] ans2 = record2(n, m, q, A, B); - boolean pass = true; - for (int j = 0; j < q; j++) { - if (ans1[j] != ans2[j]) { - pass = false; - break; - } - } - if (!pass) { - System.out.println("出错了!"); - break; - } - } - System.out.println("功能测试结束"); - - System.out.println("性能测试开始"); - int n = 100000; - int m = 100; - int[][] A = randomMatrix(n, m, m); - int q = 1000; - int c = 100; - int[][] B = randomMatrix(q, c, m); - System.out.println("用户数量 : " + n); - System.out.println("实验数量 : " + m); - System.out.println("用户参加的实验数量总和 : " + n * m); - System.out.println("查询条数 : " + q); - System.out.println("每条查询的实验数量 : " + c); - System.out.println("所有查询所列出的所有实验编号数量 : " + q * c); - long start = System.currentTimeMillis(); - record2(n, m, q, A, B); - long end = System.currentTimeMillis(); - System.out.println("运行时间 : " + (end - start) + " 毫秒"); - System.out.println("性能测试结束"); - } - -} diff --git a/公开课/class105/Code02_TwoTeamsSortedMinSwap.java b/公开课/class105/Code02_TwoTeamsSortedMinSwap.java deleted file mode 100644 index fa8658d..0000000 --- a/公开课/class105/Code02_TwoTeamsSortedMinSwap.java +++ /dev/null @@ -1,146 +0,0 @@ -package class105; - -import java.util.HashMap; - -// 来自美团 -// 两种颜色的球,蓝色和红色,都按1~n编号,共计2n个 -// 为方便放在一个数组中,红球编号取负,篮球不变,并打乱顺序, -// 要求同一种颜色的球按编号升序排列,可以进行如下操作: -// 交换相邻两个球,求最少操作次数。 -// [3,-3,1,-4,2,-2,-1,4] -// 最终交换结果为 -// [1,2,3,-1,-2,-3,-4,4] -// 最少交换次数为10 -// n <= 1000 -public class Code02_TwoTeamsSortedMinSwap { - -// public static int zuo(int lastA, int lastB, int[] arr) { -// if (lastA == 0 && lastB == 0) { -// return 0; -// } -// // lastA != 0 || lastB != 0 -// if (lastA == 0) { -// // lastB -// int curCost = lastB来到此时的终止位置的代价; -// int next = zuo(lastA, lastB - 1, arr); -// return curCost + next; -// } -// if(lastB == 0) { -// int curCost = lastA来到此时的终止位置的代价; -// int next = zuo(lastA - 1, lastB, arr); -// return curCost + next; -// } -// // lastA, lastB -// // 让lastA来到最后 -// int p1 = Integer.MAX_VALUE; -// int lastAComeCost = lastA来到此时的终止位置的代价; -// int next1 = zuo(lastA - 1, lastB, arr); -// p1 = lastAComeCost + next1; -// // 让lastB来到最后 -// int p2 = Integer.MAX_VALUE; -// int lastBComeCost = lastB来到此时的终止位置的代价; -// int next2 = zuo(lastA, lastB - 1, arr); -// p2 = lastBComeCost + next2; -// return Math.min(p1, p2); -// } - - // [3,-3,1,-4,2,-2,-1,4] - // -3 -4 -2 -1 -> -1 -2 -3 -4 - // 3 1 2 4 -> 1 2 3 4 - - // 这个题写对数器太麻烦了 - // 所以这就是正式解 - public static int minSwaps(int[] arr) { - int n = arr.length; - HashMap map = new HashMap<>(); - int topA = 0; - int topB = 0; - for (int i = 0; i < n; i++) { - if (arr[i] > 0) { - topA = Math.max(topA, arr[i]); - } else { - topB = Math.max(topB, Math.abs(arr[i])); - } - map.put(arr[i], i); - } - IndexTree it = new IndexTree(n); - for (int i = 0; i < n; i++) { - it.add(i, 1); - } - return f(topA, topB, it, n - 1, map); - } - - // 可以改二维动态规划! - // 因为it的状态,只由topA和topB决定 - // 所以it的状态不用作为可变参数! - public static int f(int lastA, int lastB, - IndexTree it, // 支持快速的距离计算 - int end, // 不变!永远n-1! - HashMap map // 位置表 - ) { - if (lastA == 0 && lastB == 0) { - return 0; - } - int p1 = Integer.MAX_VALUE; - int p2 = Integer.MAX_VALUE; - int index, cost, next; - if (lastA != 0) { - // 查出原数组中,lastA在哪? - index = map.get(lastA); - // - cost = it.sum(index, end) - 1; - // 既然搞定了lastA,indexTree - it.add(index, -1); - next = f(lastA - 1, lastB, it, end, map); - it.add(index, 1); - p1 = cost + next; - } - if (lastB != 0) { - index = map.get(-lastB); - cost = it.sum(index, end) - 1; - it.add(index, -1); - next = f(lastA, lastB - 1, it, end, map); - it.add(index, 1); - p2 = cost + next; - } - return Math.min(p1, p2); - } - - public static class IndexTree { - private int[] tree; - private int N; - - public IndexTree(int size) { - N = size; - tree = new int[N + 1]; - } - - public void add(int i, int v) { - i++; - while (i <= N) { - tree[i] += v; - i += i & -i; - } - } - - public int sum(int l, int r) { - return l == 0 ? sum(r + 1) : (sum(r + 1) - sum(l)); - } - - private int sum(int index) { - int ans = 0; - while (index > 0) { - ans += tree[index]; - index -= index & -index; - } - return ans; - } - - } - - public static void main(String[] args) { - int[] arr = { 3, -3, 1, -4, 2, -2, -1, 4 }; - System.out.println(minSwaps(arr)); - } - -} diff --git a/公开课/class106/Code01_MaximumWidthRamp.java b/公开课/class106/Code01_MaximumWidthRamp.java deleted file mode 100644 index 42fa302..0000000 --- a/公开课/class106/Code01_MaximumWidthRamp.java +++ /dev/null @@ -1,50 +0,0 @@ -package class106; - -// 给定一个整数数组 A,坡是元组 (i, j),其中  i < j 且 A[i] <= A[j] -// 这样的坡的宽度为 j - i -// 找出 A 中的坡的最大宽度,如果不存在,返回 0 -// 示例 1: -// 输入:[6,0,8,2,1,5] -// 输出:4 -// 解释: -// 最大宽度的坡为 (i, j) = (1, 5): A[1] = 0 且 A[5] = 5 -// 示例 2: -// 输入:[9,8,1,0,1,9,4,0,4,1] -// 输出:7 -// 解释: -// 最大宽度的坡为 (i, j) = (2, 9): A[2] = 1 且 A[9] = 1 -// 测试链接 : https://leetcode.cn/problems/maximum-width-ramp/ -public class Code01_MaximumWidthRamp { - - public static int maxWidthRamp(int[] arr) { - // 5 7 4 6 4 3.... - // 0 1 2 3 4 5.... - int n = arr.length; - int[] stack = new int[n]; - int r = 0; - for (int i = 0; i < n; i++) { - // 5 7 4 6 4 3.... - // 0 1 2 3 4 5.... - // i - if (r == 0 || arr[stack[r - 1]] > arr[i]) { - stack[r++] = i; - } - } - int ans = 0; - for (int j = n - 1; j >= 0; j--) { - // ? 34 - // 18 19 - // 13 -> 3 X - // 9 -> 7 X - // 3 -> 50 停 - // 2 -> 55 - // 0 -> 100 - while (r != 0 && arr[stack[r - 1]] <= arr[j]) { - int i = stack[--r]; - ans = Math.max(ans, j - i); - } - } - return ans; - } - -} diff --git a/公开课/class106/Code02_MakeASortedMinSwaps.java b/公开课/class106/Code02_MakeASortedMinSwaps.java deleted file mode 100644 index 287214e..0000000 --- a/公开课/class106/Code02_MakeASortedMinSwaps.java +++ /dev/null @@ -1,169 +0,0 @@ -package class106; - -import java.util.Arrays; - -// 来自学员问题 -// 商场中有一展柜A,其大小固定,现已被不同的商品摆满 -// 商家提供了一些新商品B,需要对A中的部分商品进行更新替换 -// B中的商品可以自由使用,也就是可以用B中的任何商品替换A中的任何商品 -// A中的商品一旦被替换,就认为消失了!而不是回到了B中! -// 要求更新过后的展柜中,商品严格按照价格由低到高进行排列 -// 不能有相邻商品价格相等的情况 -// A[i]为展柜中第i个位置商品的价格,B[i]为各个新商品的价格 -// 求能够满足A中商品价格严格递增的最小操作次数,若无法满足则返回-1 -// A数组长度、B数组长度 <= 1000 -public class Code02_MakeASortedMinSwaps { - -// public static int minSwapTimes(int[] A, int[] B) { -// int ans = zuo(A, B, 0, 0, 0); -// return ans == Integer.MAX_VALUE ? -1 : ans; -// } -// -// // B数组有序的! -// // A[ai.....] 都递增 -// // A[0...ai-1] 已经做到都递增了!可能用过B里的商品替换! -// // pre == 0,代表前一个数没换过! -// // pre == 1,代表前一个数换过! -// // 当前可以使用B[bi....]商品进行替换 -// // B[0..bi-1]这些商品认为,不能再用了! -// // 在这种情况下,做到 A[ai.....] 都递增,至少还要换几件?返回 -// public static int zuo(int[] A, int[] B, int ai, int bi, int pre) { -// if (ai == A.length) { -// return 0; -// } -// // A还有商品, 当前商品是[ai] -// // 前一件商品的价格,lastPrice -// int lastPrice = 0; -// if (ai == 0) { -// lastPrice = Integer.MIN_VALUE; -// } else { // 不是A里最左的商品 -// if (pre == 0) { -// lastPrice = A[ai - 1]; -// } else { // pre == 1 -// lastPrice = B[bi - 1]; -// } -// } -// // 当前商品 -// // 可能性1,不换! -// int p1 = Integer.MAX_VALUE; -// if (lastPrice < A[ai]) { -// p1 = zuo(A, B, ai + 1, bi, 0); -// } -// // 可能性2, 换! -// int p2 = Integer.MAX_VALUE; -// int findChangeIndex = findMostLeft(B, bi, lastPrice); -// if (findChangeIndex != -1) { -// int next2 = zuo(A, B, ai + 1, findChangeIndex + 1, 1); -// if (next2 != Integer.MAX_VALUE) { -// p2 = 1 + next2; -// } -// } -// return Math.min(p1, p2); -// } -// -// // B[bi.....] 找 >num 尽量左的位置返回!返回的是位置! -// // 如果B[bi.....] 没有 >num的数,返回-1 -// // 有的话,返回 >num, 最左的位置 -// // 二分 -// public static int findMostLeft(int[] B, int bi, int num) { -// -// } - - // 可以用B里的数字,替换A里的数字,想让A严格递增 - // 返回至少换几个数字 - public static int minSwaps(int[] A, int[] B) { - // 根据题意,B里的数字随意拿 - // 所以B里的数字排序,不会影响拿 - // 同时,A如果从左往右考虑,依次被B替换上去的数字,肯定是从小到大的 - // 这是一定的!比如B = {5,3,2,9} - // 可能先用5替换A的某个左边的数,再用2替换A的某个右边的数吗?不可能 - // 所以将B排序 - Arrays.sort(B); - int ans = process(A, B, 0, 0, 0); - return ans == Integer.MAX_VALUE ? -1 : ans; - } - - // 参数解释: - // A[0...ai-1]范围上已经做到升序了 - // 接下来请让A[ai....]范围上的数字做到升序 - // 之前的过程中,B里可能已经拿过一些数字了 - // 拿过的数字都在B[0...bi-1]范围上,不一定都拿了 - // 但是最后拿的数字一定是B[bi-1] - // 如果想用B里的数字替换当前的A[ai],请在B[bi....]范围上考虑拿数字 - // pre : 表示之前的A[ai-1]被替换了没有, - // 如果pre==0,表示A[ai-1]没被替换 - // 如果pre==1,表示A[ai-1]被替换了,被谁替换的?被B[bi-1]替换的! - // 返回值:让A[ai....]范围上的数字做到升序,最少还要在B[bi...]上拿几个数字 - // 如果返回值是Integer.MAX_VALUE,表示怎么都做不到 - // 这就是一个三维动态规划,自己改! - // ai 是N范围 - // bi 是M范围 - // pre 只有0、1两种值 - // 所以时间复杂度O(N*M*logM) - // 这个logM怎么来的,二分来的,看代码! - // ai 0...N - // bi 0...M - // pre 0、1 - // N*M*2 - public static int process(int[] A, int[] B, int ai, int bi, int pre) { - if (ai == A.length) { - return 0; - } - // 之前的数是什么 - int preNum = 0; - if (ai == 0) { - preNum = Integer.MIN_VALUE; - } else { - if (pre == 0) { - preNum = A[ai - 1]; - } else { - preNum = B[bi - 1]; - } - } - // 可能性1,搞定当前的A[ai],不依靠交换 - int p1 = preNum < A[ai] ? process(A, B, ai + 1, bi, 0) : Integer.MAX_VALUE; - // 可能性2,搞定当前的A[ai],依靠交换 - int p2 = Integer.MAX_VALUE; - // 在B[bi....]这个范围上,找到>preNum,最左的位置 - // 这一步是可以二分的!因为B整体有序 - int nearMoreIndex = bs(B, bi, preNum); - if (nearMoreIndex != -1) { - int next2 = process(A, B, ai + 1, nearMoreIndex + 1, 1); - if (next2 != Integer.MAX_VALUE) { - p2 = 1 + next2; - } - } - return Math.min(p1, p2); - } - - // 在B[start....]这个范围上,找到>num,最左的位置 - public static int bs(int[] B, int start, int num) { - int ans = -1; - int l = start; - int r = B.length - 1; - int m = 0; - while (l <= r) { - m = (l + r) / 2; - if (B[m] > num) { - ans = m; - r = m - 1; - } else { - l = m + 1; - } - } - return ans; - } - - public static void main(String[] args) { - int[] A1 = { 1, 8, 3, 6, 9 }; - int[] B1 = { 1, 3, 2, 4 }; - System.out.println(minSwaps(A1, B1)); - int[] A2 = { 4, 8, 3, 10, 5 }; - int[] B2 = { 1, 3, 2, 4 }; - System.out.println(minSwaps(A2, B2)); - int[] A3 = { 1, 8, 3, 6, 9 }; - int[] B3 = { 4, 3, 1 }; - System.out.println(minSwaps(A3, B3)); - } - -} diff --git a/公开课/class107/Code01_ScoreAllMatrix.java b/公开课/class107/Code01_ScoreAllMatrix.java deleted file mode 100644 index b1ce961..0000000 --- a/公开课/class107/Code01_ScoreAllMatrix.java +++ /dev/null @@ -1,75 +0,0 @@ -package class107; - -// 来自蚂蚁金服 -// 得分的定义 : -// 含有大小2*2的矩阵,要么: -// 1 0 -// 0 1 可以得1分 -// 要么 -// 0 1 -// 1 0 可以得1分 -// 那么一个任意大小的矩阵就有若干得分点,比如 -// 0 1 0 -// 1 0 1 -// 这个矩阵就有2个得分点 -// 给定正数N,正数M,求所有可能的情况里,所有的得分点总和 -// 1 <= N、M <= 10^9 -public class Code01_ScoreAllMatrix { - - public static int score1(int n, int m) { - if (n < 2 || m < 2) { - return 0; - } - int[][] matrix = new int[n][m]; - return process(matrix, 0, 0, n, m); - } - - public static int process(int[][] matrix, int i, int j, int n, int m) { - if (i == n) { - int score = 0; - for (int r = 1; r < n; r++) { - for (int c = 1; c < m; c++) { - if (check(matrix, r, c)) { - score++; - } - } - } - return score; - } - if (j == m) { - return process(matrix, i + 1, 0, n, m); - } - int score = 0; - matrix[i][j] = 1; - score += process(matrix, i, j + 1, n, m); - matrix[i][j] = 0; - score += process(matrix, i, j + 1, n, m); - return score; - } - - public static boolean check(int[][] m, int r, int c) { - return (m[r - 1][c - 1] == 0 && m[r][c - 1] == 1 && m[r - 1][c] == 1 && m[r][c] == 0) - || (m[r - 1][c - 1] == 1 && m[r][c - 1] == 0 && m[r - 1][c] == 0 && m[r][c] == 1); - } - - // 原始题目有取mod - // 本方法没有取mod,只展示大思路 - public static int score2(int n, int m) { - if (n < 2 || m < 2) { - return 0; - } - // 注意!这里要求掌握一个技巧点 - // 算一个数的k次方,怎么最快! - // 每算一次,都需要取mod! - // 快速幂来计算 - return (n * m - m - n + 1) * (1 << (n * m - 3)); - } - - public static void main(String[] args) { - int n = 4; - int m = 6; - System.out.println(score1(n, m)); - System.out.println(score2(n, m)); - } - -} diff --git a/公开课/class107/Code02_HappyLimitLessGap.java b/公开课/class107/Code02_HappyLimitLessGap.java deleted file mode 100644 index 9b33445..0000000 --- a/公开课/class107/Code02_HappyLimitLessGap.java +++ /dev/null @@ -1,124 +0,0 @@ -package class107; - -import java.util.Arrays; - -// 来自蚂蚁金服 -// 小红有n个朋友, 她准备开个宴会,邀请一些朋友 -// i号朋友的愉悦值为a[i],财富值为b[i] -// 如果两个朋友同时参加宴会,这两个朋友之间的隔阂是其财富值差值的绝对值 -// 宴会的隔阂值,是财富差距最大的两人产生的财富值差值的绝对值 -// 宴会的愉悦值,是所有参加宴会朋友的愉悦值总和 -// 小红希望宴会的愉悦值不能小于k的情况下, 宴会的隔阂值能最小是多少 -// 如果做不到,返回-1 -// 1 <= n <= 2 * 10^5 -// 1 <= 愉悦值、财富值 <= 10^9 -// 1 <= k <= 10^14 -public class Code02_HappyLimitLessGap { - - // 暴力方法 - // 为了验证 - public static int lessGap1(int[] a, int[] b, int k) { - long ans = process(a, b, 0, k, Integer.MAX_VALUE, Integer.MIN_VALUE); - return ans < Integer.MAX_VALUE ? (int) ans : -1; - } - - // 暴力方法 - // 为了验证 - public static long process(int[] a, int[] b, int i, int rest, int min, int max) { - if (rest <= 0) { - return (long) max - (long) min; - } - if (i == a.length) { - return (long) Integer.MAX_VALUE; - } - long p1 = process(a, b, i + 1, rest, min, max); - long p2 = process(a, b, i + 1, rest - a[i], Math.min(min, b[i]), Math.max(max, b[i])); - return Math.min(p1, p2); - } - - // 正式方法 - // 二分答案 - public static int lessGap2(int[] a, int[] b, long k) { - int n = a.length; - int[][] f = new int[n][2]; - int min = b[0]; - int max = b[0]; - // a : 30 13 - // b : 10 50 - // 0 1 .... - // [30,10] [13,50] [...] - // 财富排序 - for (int i = 0; i < n; i++) { - f[i][0] = a[i]; - f[i][1] = b[i]; - min = Math.min(min, b[i]); - max = Math.max(max, b[i]); - } - // 财富排序 - Arrays.sort(f, (x, y) -> x[1] - y[1]); - // 0 ~ max - min - int l = 0; - int r = max - min; - int m = 0; - int ans = -1; - while (l <= r) { - // 隔阂阈值 - m = (l + r) / 2; - if (maxHappy(f, m) >= k) { - ans = m; - r = m - 1; - } else { - l = m + 1; - } - } - return ans; - } - - // 所有的人,财富、愉悦 - // 隔阂阈值要求 limit - // 返回,最大宴会愉悦度 - public static long maxHappy(int[][] f, int limit) { - int n = f.length; - long sum = 0; - long ans = 0; - for (int l = 0, r = 0; l < n; l++) { - while (r < n && f[r][1] - f[l][1] <= limit) { - sum += f[r++][0]; - } - ans = Math.max(ans, sum); - sum -= f[l][0]; - r = Math.max(r, l + 1); - } - return ans; - } - - // 为了验证 - public static int[] randomArray(int n, int v) { - int[] arr = new int[n]; - for (int i = 0; i < n; i++) { - arr[i] = (int) (Math.random() * v) + 1; - } - return arr; - } - - // 为了验证 - public static void main(String[] args) { - int N = 15; - int V = 20; - int testTime = 5000; - System.out.println("功能测试开始"); - for (int i = 0; i < testTime; i++) { - int n = (int) (Math.random() * N) + 1; - int[] a = randomArray(n, V); - int[] b = randomArray(n, V); - int k = (int) (Math.random() * n * V) + 1; - int ans1 = lessGap1(a, b, k); - int ans2 = lessGap2(a, b, k); - if (ans1 != ans2) { - System.out.println("出错了!"); - } - } - System.out.println("功能测试结束"); - } - -} diff --git a/公开课/class107/Code03_RobotAndClothes.java b/公开课/class107/Code03_RobotAndClothes.java deleted file mode 100644 index 07f9344..0000000 --- a/公开课/class107/Code03_RobotAndClothes.java +++ /dev/null @@ -1,304 +0,0 @@ -package class107; - -import java.util.Arrays; - -// 来自美团 -// 给定一个正数n, 表示从0位置到n-1位置每个位置放着1件衣服 -// 从0位置到n-1位置不仅有衣服,每个位置还摆着1个机器人 -// 给定两个长度为n的数组,powers和rates -// powers[i]表示i位置的机器人的启动电量 -// rates[i]表示i位置的机器人收起1件衣服的时间 -// 使用每个机器人只需要付出启动电量 -// 当i位置的机器人收起i位置的衣服,它会继续尝试往右收起i+1位置衣服 -// 如果i+1位置的衣服已经被其他机器人收了或者其他机器人正在收 -// 这个机器人就会停机, 不再收衣服。 -// 不过如果它不停机,它会同样以rates[i]的时间来收起这件i+1位置的衣服 -// 也就是收衣服的时间为每个机器人的固定属性,当它收起i+1位置的衣服, -// 它会继续检查i+2位置...一直到它停机或者右边没有衣服可以收了 -// 形象的来说,机器人会一直尝试往右边收衣服,收k件的话就耗费k * rates[i]的时间 -// 但是当它遇见其他机器人工作的痕迹,就会认为后面的事情它不用管了,进入停机状态 -// 你手里总共有电量b,准备在0时刻将所有想启动的机器人全部一起启动 -// 过后不再启动新的机器人,并且启动机器人的电量之和不能大于b -// 返回在最佳选择下,假快多久能收完所有衣服 -// 如果无论如何都收不完所有衣服,返回-1 -// 给定数据: int n, int b, int[] powers, int[] rates -// 数据范围: -// powers长度 == rates长度 == n <= 1000 -// 1 <= b <= 10^5 -// 1 <= powers[i]、rates[i] <= 10^5 -public class Code03_RobotAndClothes { - - // 通过不了的简单动态规划方法 - // 只是为了对数器验证 - public static int fast1(int n, int b, int[] powers, int[] rates) { - int[][] dp = new int[n][b + 1]; - for (int i = 0; i < n; i++) { - for (int j = 0; j <= b; j++) { - dp[i][j] = -1; - } - } - int ans = process1(powers, rates, n, 0, b, dp); - return ans == Integer.MAX_VALUE ? -1 : ans; - } - - // i....这些衣服 - // 由i....这些机器人负责 - // 在剩余电量还有rest的情况下 - // 收完i....这些衣服最少时间是多少 - // 如果怎么都收不完 - // 返回Integer.MAX_VALUE - public static int process1(int[] powers, int[] rates, int n, int i, int rest, int[][] dp) { - if (i == n) { - return 0; - } - if (powers[i] > rest) { - return Integer.MAX_VALUE; - } - if (dp[i][rest] != -1) { - return dp[i][rest]; - } - int ans = Integer.MAX_VALUE; - for (int j = i; j < n; j++) { - int curCost = (j - i + 1) * rates[i]; - int nextCost = process1(powers, rates, n, j + 1, rest - powers[i], dp); - int curAns = Math.max(curCost, nextCost); - ans = Math.min(ans, curAns); - } - dp[i][rest] = ans; - return ans; - } - - // 正式方法 - // 时间复杂度O( N^2 * log(rates[0] * n)) - // 揭示了大的思路,可以继续用线段树优化枚举,详情看fast3 - // 解题思路: - // 二分答案 - // 定义函数minPower: - // 如果一定要在time时间内捡完所有衣服,请返回使用最少的电量 - // 如果minPower,这个函数能实现 - // 那么只要二分出最小的答案即可 - public static int fast2(int n, int b, int[] powers, int[] rates) { - if (n == 0) { - return 0; - } - if (b == 0 || powers[0] > b) { - return -1; - } - // 最小时间只可能在[1, rates[0] * n]范围上 - int l = 1; - int r = rates[0] * n; - int m = 0; - int ans = -1; - // 二分答案 - // 规定的时间就是m - // minPower(powers, rates, m): - // 如果一定要在time时间内捡完所有衣服,返回最小电量 - // 如果这个最小电量 <= 总电量,说明m时间可行,左侧继续二分答案 - // 如果这个最小电量 > 总电量,说明m时间不可行,右侧继续二分答案 - while (l <= r) { - m = (l + r) / 2; - if (minPower2(powers, rates, m) <= b) { - ans = m; - r = m - 1; - } else { - l = m + 1; - } - } - return ans; - } - - // 给定所有机器人的启动电量 powers[] - // 给定所有机器人的收一件衣服的时间 rates[] - // 一定要在time时间内,收完所有衣服! - // 返回 : 至少需要的电量! - public static int minPower2(int[] powers, int[] rates, int time) { - int[] dp = new int[powers.length]; - Arrays.fill(dp, -1); - return process2(powers, rates, 0, time, dp); - } - - // i....这么多的衣服 - // 在time时间内一定要收完 - // 返回最小电量 - // 如果怎么都收不完,返回系统最大值 - // N^2 - public static int process2(int[] powers, int[] rates, int i, int time, int[] dp) { - int n = powers.length; - if (i == n) { - return 0; - } - if (dp[i] != -1) { - return dp[i]; - } - // i..... - // 收当前i位置这一件衣服的时间 - int usedTime = rates[i]; - int nextMinPower = Integer.MAX_VALUE; - for (int j = i; j < n && usedTime <= time; j++) { - // i...i i+1.... - // i......i+1 i+2... - // i...........i+2 i+3... - // i....j j+1.... - nextMinPower = Math.min(nextMinPower, process2(powers, rates, j + 1, time, dp)); - usedTime += rates[i]; - } - int ans = nextMinPower == Integer.MAX_VALUE ? nextMinPower : (powers[i] + nextMinPower); - dp[i] = ans; - return ans; - } - - // fast2的思路 + 线段树优化枚举 - // 时间复杂度O(N * logN * log(rates[0] * N)) - public static int fast3(int n, int b, int[] powers, int[] rates) { - if (n == 0) { - return 0; - } - if (b == 0 || powers[0] > b) { - return -1; - } - int l = 1; - int r = rates[0] * n; - int m = 0; - int ans = -1; - while (l <= r) { - m = (l + r) / 2; - if (minPower3(powers, rates, m) <= b) { - ans = m; - r = m - 1; - } else { - l = m + 1; - } - } - return ans; - } - - public static int minPower3(int[] powers, int[] rates, int time) { - int n = powers.length; - int[] dp = new int[n + 1]; - // dp[n-1] dp[n] - // n-1 n - SegmentTree st = new SegmentTree(n + 1); - st.update(n, 0); - for (int i = n - 1; i >= 0; i--) { - if (rates[i] > time) { - dp[i] = Integer.MAX_VALUE; - } else { - int j = Math.min(i + (time / rates[i]) - 1, n - 1); - // for.... logN - int next = st.min(i + 1, j + 1); - int ans = next == Integer.MAX_VALUE ? next : (powers[i] + next); - dp[i] = ans; - } - st.update(i, dp[i]); - } - return dp[0]; - } - - public static class SegmentTree { - private int n; - private int[] min; - - public SegmentTree(int size) { - n = size + 1; - min = new int[n << 2]; - Arrays.fill(min, Integer.MAX_VALUE); - } - - private void pushUp(int rt) { - min[rt] = Math.min(min[rt << 1], min[rt << 1 | 1]); - } - - public void update(int i, int v) { - update(i + 1, i + 1, v, 1, n, 1); - } - - private void update(int L, int R, int C, int l, int r, int rt) { - if (L <= l && r <= R) { - min[rt] = C; - return; - } - int mid = (l + r) >> 1; - if (L <= mid) { - update(L, R, C, l, mid, rt << 1); - } - if (R > mid) { - update(L, R, C, mid + 1, r, rt << 1 | 1); - } - pushUp(rt); - } - - public int min(int l, int r) { - return min(l + 1, r + 1, 1, n, 1); - } - - private int min(int L, int R, int l, int r, int rt) { - if (L <= l && r <= R) { - return min[rt]; - } - int mid = (l + r) >> 1; - int left = Integer.MAX_VALUE; - int right = Integer.MAX_VALUE; - if (L <= mid) { - left = min(L, R, l, mid, rt << 1); - } - if (R > mid) { - right = min(L, R, mid + 1, r, rt << 1 | 1); - } - return Math.min(left, right); - } - - } - - // 为了测试 - public static int[] randomArray(int n, int v) { - int[] ans = new int[n]; - for (int i = 0; i < n; i++) { - ans[i] = (int) (Math.random() * v) + 1; - } - return ans; - } - - // 为了测试 - public static void main(String[] args) { - int N = 200; - int B = 100; - int P = 20; - int R = 10; - int testTimes = 5000; - System.out.println("功能测试开始"); - for (int i = 0; i < testTimes; i++) { - int n = (int) (Math.random() * N) + 1; - int b = (int) (Math.random() * B) + 1; - int[] powers = randomArray(n, P); - int[] rates = randomArray(n, R); - int ans1 = fast1(n, b, powers, rates); - int ans2 = fast2(n, b, powers, rates); - int ans3 = fast3(n, b, powers, rates); - if (ans1 != ans2 || ans1 != ans3) { - System.out.println("出错了!"); - System.out.println(ans1); - System.out.println(ans2); - System.out.println(ans3); - break; - } - } - System.out.println("功能测试结束"); - - System.out.println("性能测试开始"); - int n = 10000; - int b = 100000; - int[] powers = randomArray(n, b); - int[] rates = randomArray(n, b); - System.out.println("衣服规模 : " + n); - System.out.println("电量规模 : " + b); - System.out.println("机器人启动费用取值规模 : " + b); - System.out.println("机器人工作速度取值规模 : " + b); - long start = System.currentTimeMillis(); - fast3(n, b, powers, rates); - long end = System.currentTimeMillis(); - System.out.println("运行时间 : " + (end - start) + " 毫秒"); - System.out.println("性能测试结束"); - - } - -} diff --git a/公开课/class108/Code01_CordCoverMaxPoint.java b/公开课/class108/Code01_CordCoverMaxPoint.java deleted file mode 100644 index 7ee5359..0000000 --- a/公开课/class108/Code01_CordCoverMaxPoint.java +++ /dev/null @@ -1,92 +0,0 @@ -package class108; - -import java.util.Arrays; - -// 最简单的窗口题 -// 给定一个有序数组arr,代表坐落在X轴上的点 -// 给定一个正数K,代表绳子的长度 -// 返回绳子最多压中几个点 -// 即使绳子边缘处盖住点也算盖住 -public class Code01_CordCoverMaxPoint { - - public static int maxPoint1(int[] arr, int L) { - int res = 1; - for (int i = 0; i < arr.length; i++) { - int nearest = nearestIndex(arr, i, arr[i] - L); - res = Math.max(res, i - nearest + 1); - } - return res; - } - - public static int nearestIndex(int[] arr, int R, int value) { - int L = 0; - int index = R; - while (L <= R) { - int mid = L + ((R - L) >> 1); - if (arr[mid] >= value) { - index = mid; - R = mid - 1; - } else { - L = mid + 1; - } - } - return index; - } - - public static int maxPoint2(int[] arr, int L) { - int left = 0; - int right = 0; - int N = arr.length; - int max = 0; - while (left < N) { - while (right < N && arr[right] - arr[left] <= L) { - right++; - } - max = Math.max(max, right - (left++)); - } - return max; - } - - // for test - public static int test(int[] arr, int L) { - int max = 0; - for (int i = 0; i < arr.length; i++) { - int pre = i - 1; - while (pre >= 0 && arr[i] - arr[pre] <= L) { - pre--; - } - max = Math.max(max, i - pre); - } - return max; - } - - // for test - public static int[] generateArray(int len, int max) { - int[] ans = new int[(int) (Math.random() * len) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * max); - } - Arrays.sort(ans); - return ans; - } - - public static void main(String[] args) { - int len = 100; - int max = 1000; - int testTime = 100000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int L = (int) (Math.random() * max); - int[] arr = generateArray(len, max); - int ans1 = maxPoint1(arr, L); - int ans2 = maxPoint2(arr, L); - int ans3 = test(arr, L); - if (ans1 != ans2 || ans2 != ans3) { - System.out.println("oops!"); - break; - } - } - - } - -} diff --git a/公开课/class108/Code02_LongestSumSubArrayLengthInPositiveArray.java b/公开课/class108/Code02_LongestSumSubArrayLengthInPositiveArray.java deleted file mode 100644 index 8b01807..0000000 --- a/公开课/class108/Code02_LongestSumSubArrayLengthInPositiveArray.java +++ /dev/null @@ -1,94 +0,0 @@ -package class108; - -// 给定一个正整数组成的无序数组arr,给定一个正整数值K -// 找到arr的所有子数组里,哪个子数组的累加和等于K -// 并且是长度最大的,返回其长度 -public class Code02_LongestSumSubArrayLengthInPositiveArray { - - public static int getMaxLength(int[] arr, int K) { - if (arr == null || arr.length == 0 || K <= 0) { - return 0; - } - int left = 0; - int right = 0; - int sum = arr[0]; - int len = 0; - while (right < arr.length) { - if (sum == K) { - len = Math.max(len, right - left + 1); - sum -= arr[left++]; - } else if (sum < K) { - right++; - if (right == arr.length) { - break; - } - sum += arr[right]; - } else { - sum -= arr[left++]; - } - } - return len; - } - - // for test - public static int right(int[] arr, int K) { - int max = 0; - for (int i = 0; i < arr.length; i++) { - for (int j = i; j < arr.length; j++) { - if (valid(arr, i, j, K)) { - max = Math.max(max, j - i + 1); - } - } - } - return max; - } - - // for test - public static boolean valid(int[] arr, int L, int R, int K) { - int sum = 0; - for (int i = L; i <= R; i++) { - sum += arr[i]; - } - return sum == K; - } - - // for test - public static int[] generatePositiveArray(int size, int value) { - int[] ans = new int[size]; - for (int i = 0; i != size; i++) { - ans[i] = (int) (Math.random() * value) + 1; - } - return ans; - } - - // for test - public static void printArray(int[] arr) { - for (int i = 0; i != arr.length; i++) { - System.out.print(arr[i] + " "); - } - System.out.println(); - } - - public static void main(String[] args) { - int len = 50; - int value = 100; - int testTime = 500000; - System.out.println("test begin"); - for (int i = 0; i < testTime; i++) { - int[] arr = generatePositiveArray(len, value); - int K = (int) (Math.random() * value) + 1; - int ans1 = getMaxLength(arr, K); - int ans2 = right(arr, K); - if (ans1 != ans2) { - System.out.println("Oops!"); - printArray(arr); - System.out.println("K : " + K); - System.out.println(ans1); - System.out.println(ans2); - break; - } - } - System.out.println("test end"); - } - -} diff --git a/公开课/class108/Code03_LongestSumSubArrayLength.java b/公开课/class108/Code03_LongestSumSubArrayLength.java deleted file mode 100644 index ce49858..0000000 --- a/公开课/class108/Code03_LongestSumSubArrayLength.java +++ /dev/null @@ -1,104 +0,0 @@ -package class108; - -import java.util.HashMap; - -// 给定一个整数组成的无序数组arr,值可能正、可能负、可能0 -// 给定一个整数值K, 找到arr的所有子数组里,哪个子数组的累加和等于K -// 并且是长度最大的,返回其长度 -public class Code03_LongestSumSubArrayLength { - - // arr中,有正、有负、有0,都可能 - // 累加和 == k,且最长是多长? - public static int maxLength(int[] arr, int k) { - if (arr == null || arr.length == 0) { - return 0; - } - // key:前缀和 - // value : key这个前缀和,最早出现的位置 - HashMap map = new HashMap(); - map.put(0, -1); // important - int len = 0; - int sum = 0; - for (int i = 0; i < arr.length; i++) { - sum += arr[i]; - if (map.containsKey(sum - k)) { - // 0..................100 - // 1000 - // k = 300 - // 700 - // 0...10 - // 11.....100 - len = Math.max(i - map.get(sum - k), len); - } - // sum - if (!map.containsKey(sum)) { - map.put(sum, i); - } - } - return len; - } - - // for test - public static int right(int[] arr, int K) { - int max = 0; - for (int i = 0; i < arr.length; i++) { - for (int j = i; j < arr.length; j++) { - if (valid(arr, i, j, K)) { - max = Math.max(max, j - i + 1); - } - } - } - return max; - } - - // for test - public static boolean valid(int[] arr, int L, int R, int K) { - int sum = 0; - for (int i = L; i <= R; i++) { - sum += arr[i]; - } - return sum == K; - } - - // for test - public static int[] generateRandomArray(int size, int value) { - int[] ans = new int[(int) (Math.random() * size) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * value) - (int) (Math.random() * value); - } - return ans; - } - - // for test - public static void printArray(int[] arr) { - for (int i = 0; i != arr.length; i++) { - System.out.print(arr[i] + " "); - } - System.out.println(); - } - - public static void main(String[] args) { - int len = 50; - int value = 100; - int testTime = 500000; - - System.out.println("test begin"); - for (int i = 0; i < testTime; i++) { - int[] arr = generateRandomArray(len, value); - int K = (int) (Math.random() * value) - (int) (Math.random() * value); - int ans1 = maxLength(arr, K); - int ans2 = right(arr, K); - if (ans1 != ans2) { - System.out.println("Oops!"); - printArray(arr); - System.out.println("K : " + K); - System.out.println(ans1); - System.out.println(ans2); - break; - } - } - System.out.println("test end"); - - } - -} diff --git a/公开课/class108/Code04_SlidingWindowMaxArray.java b/公开课/class108/Code04_SlidingWindowMaxArray.java deleted file mode 100644 index be38b8b..0000000 --- a/公开课/class108/Code04_SlidingWindowMaxArray.java +++ /dev/null @@ -1,145 +0,0 @@ -package class108; - -import java.util.LinkedList; - -// 给你一个整数数组 nums,有一个大小为 k 的滑动窗口 -// 从数组的最左侧移动到数组的最右侧 -// 你只可以看到在滑动窗口内的 k 个数字 -// 滑动窗口每次只向右移动一位。 -// 返回每一步 滑动窗口中的最大值 -// 测试链接 : https://leetcode.cn/problems/sliding-window-maximum/ -public class Code04_SlidingWindowMaxArray { - -// public static class Window { -// -// // 一些结构 -// -// public int[] help; -// -// public Window(int[] arr) { -// help = arr; -// } -// -// public void addNumberFromRight() { -// -// } -// -// public void deleteNumberFromLeft() { -// -// } -// -// public int max() { -// -// } -// -// } -// -// public static void main(String[] args) { -// int[] arr = { 3, 5, 7, 2, 4, 2, 6 }; -// // [ 7, 2] -// Window w = new Window(arr); -// w.addNumberFromRight(); -// w.addNumberFromRight(); -// w.addNumberFromRight(); -// System.out.println(w.max()); -// w.deleteNumberFromLeft(); -// w.deleteNumberFromLeft(); -// w.addNumberFromRight(); -// System.out.println(w.max()); -// } - - - - // 暴力的对数器方法 - public static int[] right(int[] arr, int w) { - if (arr == null || w < 1 || arr.length < w) { - return null; - } - int N = arr.length; - int[] res = new int[N - w + 1]; - int index = 0; - int L = 0; - int R = w - 1; - while (R < N) { - int max = arr[L]; - for (int i = L + 1; i <= R; i++) { - max = Math.max(max, arr[i]); - - } - res[index++] = max; - L++; - R++; - } - return res; - } - - public static int[] getMaxWindow(int[] arr, int w) { - if (arr == null || w < 1 || arr.length < w) { - return null; - } - // qmax 窗口最大值的更新结构 - // 放下标 - LinkedList qmax = new LinkedList(); - int[] res = new int[arr.length - w + 1]; - int index = 0; - for (int R = 0; R < arr.length; R++) { - while (!qmax.isEmpty() && arr[qmax.peekLast()] <= arr[R]) { - qmax.pollLast(); - } - qmax.addLast(R); - if (qmax.peekFirst() == R - w) { - qmax.pollFirst(); - } - if (R >= w - 1) { - res[index++] = arr[qmax.peekFirst()]; - } - } - return res; - } - - // for test - public static int[] generateRandomArray(int maxSize, int maxValue) { - int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; - for (int i = 0; i < arr.length; i++) { - arr[i] = (int) (Math.random() * (maxValue + 1)); - } - return arr; - } - - // for test - public static boolean isEqual(int[] arr1, int[] arr2) { - if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) { - return false; - } - if (arr1 == null && arr2 == null) { - return true; - } - if (arr1.length != arr2.length) { - return false; - } - for (int i = 0; i < arr1.length; i++) { - if (arr1[i] != arr2[i]) { - return false; - } - } - return true; - } - - public static void main(String[] args) { - int testTime = 100000; - int maxSize = 100; - int maxValue = 100; - System.out.println("test begin"); - for (int i = 0; i < testTime; i++) { - int[] arr = generateRandomArray(maxSize, maxValue); - int w = (int) (Math.random() * (arr.length + 1)); - int[] ans1 = getMaxWindow(arr, w); - int[] ans2 = right(arr, w); - if (!isEqual(ans1, ans2)) { - System.out.println("Oops!"); - } - } - System.out.println("test finish"); - } - -} diff --git a/公开课/class108/Code05_WindPrevent.java b/公开课/class108/Code05_WindPrevent.java deleted file mode 100644 index 4c86b02..0000000 --- a/公开课/class108/Code05_WindPrevent.java +++ /dev/null @@ -1,149 +0,0 @@ -package class108; - -// 来自真实笔试 -// 给定一个二维数组matrix,数组中的每个元素代表一棵树的高度。 -// 你可以选定连续的若干行组成防风带,防风带每一列的防风高度为这一列的最大值 -// 防风带整体的防风高度为,所有列防风高度的最小值。 -// 比如,假设选定如下三行 -// 1 5 4 -// 7 2 6 -// 2 3 4 -// 1、7、2的列,防风高度为7 -// 5、2、3的列,防风高度为5 -// 4、6、4的列,防风高度为6 -// 防风带整体的防风高度为5,是7、5、6中的最小值 -// 给定一个正数k,k <= matrix的行数,表示可以取连续的k行,这k行一起防风。 -// 求防风带整体的防风高度最大值 -public class Code05_WindPrevent { - - public static int bestHeight1(int[][] matrix, int k) { - int n = matrix.length; - int m = matrix[0].length; - int ans = 0; - for (int startRow = 0; startRow < n; startRow++) { - int bottleNeck = Integer.MAX_VALUE; - for (int col = 0; col < m; col++) { - int height = 0; - for (int endRow = startRow; endRow < n && (endRow - startRow + 1 <= k); endRow++) { - height = Math.max(height, matrix[endRow][col]); - } - bottleNeck = Math.min(bottleNeck, height); - } - ans = Math.max(ans, bottleNeck); - } - return ans; - } - -// public static class WindowManager { -// -// // 建立出m个窗口! -// public WindowManager(int m) { -// -// } -// -// public void addRow(int[][] matrix, int row) { -// -// } -// -// public void deleteRow(int[][] matrix, int row) { -// -// } -// -// public int getAllWindowMaxMin() { -// return 100; -// } -// -// } -// -// public static int bestWindHeight(int[][] matrix, int k) { -// int n = matrix.length; -// int m = matrix[0].length; -// k = Math.min(k, n); -// WindowManager windowManager = new WindowManager(m); -// for (int i = 0; i < k - 1; i++) { -// windowManager.addRow(matrix, i); -// } -// int ans = 0; -// for (int i = k - 1; i < n; i++) { -// windowManager.addRow(matrix, i); -// int cur = windowManager.getAllWindowMaxMin(); -// ans = Math.max(ans, cur); -// windowManager.deleteRow(matrix, i - k + 1); -// } -// return ans; -// } - - public static int bestHeight2(int[][] matrix, int k) { - int n = matrix.length; - int m = matrix[0].length; - int[][] windowMaxs = new int[m][n]; - int[][] windowLR = new int[m][2]; - for (int i = 0; i < k; i++) { - addRow(matrix, m, i, windowMaxs, windowLR); - } - int ans = bottleNeck(matrix, m, windowMaxs, windowLR); - for (int i = k; i < n; i++) { - addRow(matrix, m, i, windowMaxs, windowLR); - deleteRow(m, i - k, windowMaxs, windowLR); - ans = Math.max(ans, bottleNeck(matrix, m, windowMaxs, windowLR)); - } - return ans; - } - - public static void addRow(int[][] matrix, int m, int row, int[][] windowMaxs, int[][] windowLR) { - for (int col = 0; col < m; col++) { - while (windowLR[col][0] != windowLR[col][1] - && matrix[windowMaxs[col][windowLR[col][1] - 1]][col] <= matrix[row][col]) { - windowLR[col][1]--; - } - windowMaxs[col][windowLR[col][1]++] = row; - } - } - - public static void deleteRow(int m, int row, int[][] windowMaxs, int[][] windowLR) { - for (int col = 0; col < m; col++) { - if (windowMaxs[col][windowLR[col][0]] == row) { - windowLR[col][0]++; - } - } - } - - public static int bottleNeck(int[][] matrix, int m, int[][] windowMaxs, int[][] windowLR) { - int ans = Integer.MAX_VALUE; - for (int col = 0; col < m; col++) { - ans = Math.min(ans, matrix[windowMaxs[col][windowLR[col][0]]][col]); - } - return ans; - } - - public static int[][] generateMatrix(int n, int m, int v) { - int[][] matrix = new int[n][m]; - for (int i = 0; i < n; i++) { - for (int j = 0; j < m; j++) { - matrix[i][j] = (int) (Math.random() * v) + 1; - } - } - return matrix; - } - - public static void main(String[] args) { - int nMax = 10; - int mMax = 10; - int vMax = 50; - int testTimes = 1000; - System.out.println("测试开始"); - for (int i = 0; i < testTimes; i++) { - int n = (int) (Math.random() * nMax) + 1; - int m = (int) (Math.random() * mMax) + 1; - int[][] matrix = generateMatrix(n, m, vMax); - int k = (int) (Math.random() * n) + 1; - int ans1 = bestHeight1(matrix, k); - int ans2 = bestHeight2(matrix, k); - if (ans1 != ans2) { - System.out.println("出错了!"); - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class108/Code06_RemoveMostKContinuousSameLongest.java b/公开课/class108/Code06_RemoveMostKContinuousSameLongest.java deleted file mode 100644 index 349b01f..0000000 --- a/公开课/class108/Code06_RemoveMostKContinuousSameLongest.java +++ /dev/null @@ -1,105 +0,0 @@ -package class108; - -import java.util.HashMap; -import java.util.LinkedList; - -// 来自亚马逊 -// 给定一个数组arr,和一个正数k -// 你可以随意删除arr中的数字,最多删除k个 -// 目的是让连续出现一种数字的长度尽量长 -// 返回这个尽量长的长度 -// 比如数组arr = { 3, -2, 3, 3, 5, 6, 3, -2 }, k = 3 -// 你可以删掉-2、5、6(最多3个),这样数组arr = { 3, 3, 3, 3, -2 } -// 可以看到连续出现3的长度为4 -// 这是所有删除方法里的最长结果,所以返回4 -// 1 <= arr长度 <= 3 * 10^5 -// -10^9 <= arr中的数值 <= 10^9 -// 0 <= k <= 3 * 10^5 -public class Code06_RemoveMostKContinuousSameLongest { - - // 暴力方法 - // 为了测试 - public static int longest1(int[] arr, int k) { - return process1(arr, 0, new int[arr.length], 0, k); - } - - public static int process1(int[] arr, int i, int[] path, int size, int k) { - if (k < 0) { - return 0; - } - if (i == arr.length) { - if (size == 0) { - return 0; - } - int ans = 0; - int cnt = 1; - for (int j = 1; j < size; j++) { - if (path[j - 1] != path[j]) { - ans = Math.max(ans, cnt); - cnt = 1; - } else { - cnt++; - } - } - ans = Math.max(ans, cnt); - return ans; - } else { - path[size] = arr[i]; - int p1 = process1(arr, i + 1, path, size + 1, k); - int p2 = process1(arr, i + 1, path, size, k - 1); - return Math.max(p1, p2); - } - } - - // 正式方法 - // 时间复杂度O(N) - public static int longest2(int[] arr, int k) { - HashMap> valueIndies = new HashMap<>(); - int ans = 1; - for (int i = 0; i < arr.length; i++) { - int value = arr[i]; - if (!valueIndies.containsKey(value)) { - valueIndies.put(value, new LinkedList<>()); - } - LinkedList indies = valueIndies.get(value); - while (!indies.isEmpty() && i - indies.peekFirst() - indies.size() > k) { - indies.pollFirst(); - } - indies.addLast(i); - ans = Math.max(ans, indies.size()); - } - return ans; - } - - // 为了测试 - // 生成长度为n的数组 - // 值在[-v,v]之间等概率随机 - public static int[] randomArray(int n, int v) { - int[] ans = new int[n]; - for (int i = 0; i < n; i++) { - ans[i] = (int) (Math.random() * (2 * v + 1)) - v; - } - return ans; - } - - // 为了测试 - public static void main(String[] args) { - int N = 20; - int V = 10; - int K = 5; - int testTime = 5000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int n = (int) (Math.random() * N) + 1; - int[] arr = randomArray(n, V); - int k = (int) (Math.random() * K); - int ans1 = longest1(arr, k); - int ans2 = longest2(arr, k); - if (ans1 != ans2) { - System.out.println("出错了!"); - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class108/Code07_RangesHasDominateNumber.java b/公开课/class108/Code07_RangesHasDominateNumber.java deleted file mode 100644 index 8b166a0..0000000 --- a/公开课/class108/Code07_RangesHasDominateNumber.java +++ /dev/null @@ -1,88 +0,0 @@ -package class108; - -import java.util.HashMap; - -// 来自小红书 -// 小A认为如果在数组中有一个数出现了至少k次 -// 且这个数是该数组的众数,即出现次数最多的数之一 -// 那么这个数组被该数所支配 -// 显然当k比较大的时候,有些数组不被任何数所支配 -// 现在小A拥有一个长度为n的数组,她想知道内部有多少个区间是被某个数支配的 -// 2 <= k <= n <= 100000 -// 1 <= 数组的值 <= n -public class Code07_RangesHasDominateNumber { - - // 暴力方法 - // 为了验证 - // 时间复杂度O(N^3) - public static int dominates1(int[] arr, int k) { - int n = arr.length; - int ans = 0; - for (int l = 0; l < n; l++) { - for (int r = l; r < n; r++) { - if (ok(arr, l, r, k)) { - ans++; - } - } - } - return ans; - } - - public static boolean ok(int[] arr, int l, int r, int k) { - HashMap map = new HashMap(); - for (int i = l; i <= r; i++) { - map.put(arr[i], map.getOrDefault(arr[i], 0) + 1); - } - for (int times : map.values()) { - if (times >= k) { - return true; - } - } - return false; - } - - // 正式方法 - // 时间复杂度O(N) - public static int dominates2(int[] arr, int k) { - int n = arr.length; - int all = n * (n + 1) / 2; - int except = 0; - int[] cnt = new int[n + 1]; - for (int l = 0, r = 0; l < n; l++) { - while (r < n && cnt[arr[r]] + 1 < k) { - cnt[arr[r++]]++; - } - except += r - l; - cnt[arr[l]]--; - } - return all - except; - } - - // 为了测试 - public static int[] randomArray(int n) { - int[] ans = new int[n]; - for (int i = 0; i < n; i++) { - ans[i] = (int) (Math.random() * n) + 1; - } - return ans; - } - - // 为了测试 - public static void main(String[] args) { - int N = 100; - int testTimes = 5000; - System.out.println("测试开始"); - for (int i = 0; i < testTimes; i++) { - int n = (int) (Math.random() * N) + 1; - int[] arr = randomArray(n); - int k = (int) (Math.random() * n) + 1; - int ans1 = dominates1(arr, k); - int ans2 = dominates2(arr, k); - if (ans1 != ans2) { - System.out.println("出错了!"); - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class108/Code08_LastStoneWeightII.java b/公开课/class108/Code08_LastStoneWeightII.java deleted file mode 100644 index 92830c9..0000000 --- a/公开课/class108/Code08_LastStoneWeightII.java +++ /dev/null @@ -1,40 +0,0 @@ -package class108; - -// 来自字节 -// 11.02笔试 -// leetcode原题 -// 有一堆石头,用整数数组 stones 表示 -// 其中 stones[i] 表示第 i 块石头的重量。 -// 每一回合,从中选出任意两块石头,然后将它们一起粉碎 -// 假设石头的重量分别为 x 和 y,且 x <= y -// 那么粉碎的可能结果如下: -// 如果 x == y,那么两块石头都会被完全粉碎; -// 如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x。 -// 最后,最多只会剩下一块 石头 -// 返回此石头 最小的可能重量 -// 如果没有石头剩下,就返回 0 -// 测试链接 : https://leetcode.cn/problems/last-stone-weight-ii/ -public class Code08_LastStoneWeightII { - - public int lastStoneWeightII(int[] arr) { - int n = arr.length; - int sum = 0; - for (int num : arr) { - sum += num; - } - int half = sum / 2; - int[][] dp = new int[n + 1][half + 1]; - for (int i = n - 1; i >= 0; i--) { - for (int rest = 0; rest <= half; rest++) { - int p1 = dp[i + 1][rest]; - int p2 = 0; - if (arr[i] <= rest) { - p2 = arr[i] + dp[i + 1][rest - arr[i]]; - } - dp[i][rest] = Math.max(p1, p2); - } - } - return Math.abs(sum - dp[0][half] - dp[0][half]); - } - -} diff --git a/公开课/class108/Code09_ScoreAllMatrix.java b/公开课/class108/Code09_ScoreAllMatrix.java deleted file mode 100644 index 3422620..0000000 --- a/公开课/class108/Code09_ScoreAllMatrix.java +++ /dev/null @@ -1,78 +0,0 @@ -package class108; - -// 来自蚂蚁金服 -// 得分的定义 : -// 含有大小2*2的矩阵,要么: -// 1 0 -// 0 1 可以得1分 -// 要么 -// 0 1 -// 1 0 可以得1分 -// 那么一个任意大小的矩阵就有若干得分点,比如 -// 0 1 0 -// 1 0 1 -// 这个矩阵就有2个得分点 -// 给定正数N,正数M,求所有可能的情况里,所有的得分点总和 -// 1 <= N、M <= 10^9 -public class Code09_ScoreAllMatrix { - - public static int score1(int n, int m) { - if (n < 2 || m < 2) { - return 0; - } - int[][] matrix = new int[n][m]; - return process(matrix, 0, 0, n, m); - } - - public static int process(int[][] matrix, int i, int j, int n, int m) { - if (i == n) { - int score = 0; - for (int r = 1; r < n; r++) { - for (int c = 1; c < m; c++) { - if (check(matrix, r, c)) { - score++; - } - } - } - return score; - } - if (j == m) { - return process(matrix, i + 1, 0, n, m); - } - int score = 0; - matrix[i][j] = 1; - score += process(matrix, i, j + 1, n, m); - matrix[i][j] = 0; - score += process(matrix, i, j + 1, n, m); - return score; - } - - public static boolean check(int[][] m, int r, int c) { - return (m[r - 1][c - 1] == 0 && m[r][c - 1] == 1 && m[r - 1][c] == 1 && m[r][c] == 0) - || (m[r - 1][c - 1] == 1 && m[r][c - 1] == 0 && m[r - 1][c] == 0 && m[r][c] == 1); - } - - public static int score2(int n, int m) { - if (n < 2 || m < 2) { - return 0; - } - // n <= 10^9 - // m <= 10^9 - // 取mod - // (n * m - m - n + 1) -> O(1) - // 2^(n * m - 3) ??? - // 真实的笔试场景下: - // 算2^(k)次方的 - // 体系学习班,章节27,学习快速幂 - // 本代码,不处理mod - return (n * m - m - n + 1) * (1 << (n * m - 3)); - } - - public static void main(String[] args) { - int n = 3; - int m = 4; - System.out.println(score1(n, m)); - System.out.println(score2(n, m)); - } - -} diff --git a/公开课/class109/Code01_ThreeEqualParts.java b/公开课/class109/Code01_ThreeEqualParts.java deleted file mode 100644 index f2d3bcb..0000000 --- a/公开课/class109/Code01_ThreeEqualParts.java +++ /dev/null @@ -1,80 +0,0 @@ -package class109; - -// 给定一个由 0 和 1 组成的数组 arr ,将数组分成 3 个非空的部分 -// 使得所有这些部分表示相同的二进制值。 -// 如果可以做到,请返回任何 [i, j],其中 i+1 < j,这样一来 -// arr[0], arr[1], ..., arr[i] 为第一部分 -// arr[i + 1], arr[i + 2], ..., arr[j - 1] 为第二部分 -// arr[j], arr[j + 1], ..., arr[arr.length - 1] 为第三部分 -// 这三个部分所表示的二进制值相等 -// 如果无法做到,就返回 [-1, -1] -// 注意,在考虑每个部分所表示的二进制时,应当将其看作一个整体 -// 例如,[1,1,0] 表示十进制中的 6,而不会是 3。此外,前导零也是被允许的 -// 所以 [0,1,1] 和 [1,1] 表示相同的值。 -// 测试链接 : https://leetcode.cn/problems/three-equal-parts/ -public class Code01_ThreeEqualParts { - - public static int[] threeEqualParts(int[] arr) { - // 计算arr中1的数量 - int ones = 0; - for (int num : arr) { - ones += num == 1 ? 1 : 0; - } - // 如果1的数量不能被3整除,肯定不存在方案 - if (ones % 3 != 0) { - return new int[] { -1, -1 }; - } - int n = arr.length; - // 如果1的数量是0,怎么划分都可以了,因为全是0 - if (ones == 0) { - return new int[] { 0, n - 1 }; - } - // 接下来的过程 - // 因为1的数量能被3整除,比如一共有12个1 - // 那么第一段肯定含有第1个1~第4个1 - // 那么第二段肯定含有第5个1~第8个1 - // 那么第三段肯定含有第9个1~第12个1 - // 所以把第1个1,当做第一段的开头,start1 - // 所以把第5个1,当做第二段的开头,start2 - // 所以把第9个1,当做第三段的开头,start3 - int part = ones / 3; - int start1 = -1; - int start2 = -1; - int start3 = -1; - int cnt = 0; - // 1个数21个 - // part = 7 - // 1 8 - for (int i = 0; i < n; i++) { - if (arr[i] == 1) { - cnt++; - if (start1 == -1 && cnt == 1) { - start1 = i; - } - if (start2 == -1 && cnt == part + 1) { - start2 = i; - } - if (start3 == -1 && cnt == 2 * part + 1) { - start3 = i; - } - } - } - // 第一段的开头往下的部分 - // 第二段的开头往下的部分 - // 第三段的开头往下的部分 - // 要都一样,这三段的状态才是一样的 - // 所以接下来就验证这一点,是不是每一步都一样 - while (start3 < n) { - if (arr[start1] != arr[start2] || arr[start1] != arr[start3]) { - // 一旦不一样,肯定没方案了 - return new int[] { -1, -1 }; - } - start1++; - start2++; - start3++; - } - // 如果验证通过,返回断点即可 - return new int[] { start1 - 1, start2 }; - } - -} diff --git a/公开课/class109/Code02_LongestSumSubArrayLength.java b/公开课/class109/Code02_LongestSumSubArrayLength.java deleted file mode 100644 index 9db0082..0000000 --- a/公开课/class109/Code02_LongestSumSubArrayLength.java +++ /dev/null @@ -1,114 +0,0 @@ -package class109; - -import java.util.HashMap; - -public class Code02_LongestSumSubArrayLength { - - // 该代码不得分! -// public static int targetSumMaxLen(int[] arr, int target) { -// int ans = 0; -// for(int 开头 = 0; 开头 < arr.length;开头++) { -// for(int 结尾 = 开头; 结尾 <= arr.length; 结尾++) { -// // arr[开头....结尾] -// // 统计一下arr[开头....结尾]累加和 -// // == target -// int cur = 结尾 - 开头 + 1; -// ans = Math.max(ans, cur); -// } -// } -// return ans; -// } - - public static int maxLength(int[] arr, int target) { - if (arr == null || arr.length == 0) { - return 0; - } - // key:前缀和 - // value : 0~value这个前缀和是最早出现key这个值的 - HashMap map = new HashMap(); - map.put(0, -1); // important - int len = 0; - int sum = 0; - // O(N) - for (int i = 0; i < arr.length; i++) { - // 0...i整体前缀和 - sum += arr[i]; - if (map.containsKey(sum - target)) { - // 0.....17 1000 target == 300 - // sum - target - // 0...4 700 - // 5.....17 300 - // 17 - 4 - len = Math.max(i - map.get(sum - target), len); - } - if (!map.containsKey(sum)) { - map.put(sum, i); - } - } - return len; - } - - // for test - public static int right(int[] arr, int K) { - int max = 0; - for (int i = 0; i < arr.length; i++) { - for (int j = i; j < arr.length; j++) { - if (valid(arr, i, j, K)) { - max = Math.max(max, j - i + 1); - } - } - } - return max; - } - - // for test - public static boolean valid(int[] arr, int L, int R, int K) { - int sum = 0; - for (int i = L; i <= R; i++) { - sum += arr[i]; - } - return sum == K; - } - - // for test - public static int[] generateRandomArray(int size, int value) { - int[] ans = new int[(int) (Math.random() * size) + 1]; - for (int i = 0; i < ans.length; i++) { - ans[i] = (int) (Math.random() * value) - (int) (Math.random() * value); - } - return ans; - } - - // for test - public static void printArray(int[] arr) { - for (int i = 0; i != arr.length; i++) { - System.out.print(arr[i] + " "); - } - System.out.println(); - } - - public static void main(String[] args) { - int len = 50; - int value = 100; - int testTime = 500000; - - System.out.println("test begin"); - for (int i = 0; i < testTime; i++) { - int[] arr = generateRandomArray(len, value); - int K = (int) (Math.random() * value) - (int) (Math.random() * value); - int ans1 = maxLength(arr, K); - int ans2 = right(arr, K); - if (ans1 != ans2) { - System.out.println("Oops!"); - printArray(arr); - System.out.println("K : " + K); - System.out.println(ans1); - System.out.println(ans2); - break; - } - } - System.out.println("test end"); - - } - -} diff --git a/公开课/class109/Code03_EvenTimesMaxSubstring.java b/公开课/class109/Code03_EvenTimesMaxSubstring.java deleted file mode 100644 index 777bc91..0000000 --- a/公开课/class109/Code03_EvenTimesMaxSubstring.java +++ /dev/null @@ -1,103 +0,0 @@ -package class109; - -import java.util.HashMap; - -// 来自微软面试 -// 给定一个字符串s,其中都是英文小写字母 -// 如果s中的子串含有的每种字符都是偶数个 -// 那么这样的子串就是达标子串,子串要求是连续串 -// 返回s中达标子串的最大长度 -// 1 <= s的长度 <= 10^5 -// 字符种类都是英文小写 -public class Code03_EvenTimesMaxSubstring { - - // 为了测试 - // 暴力方法 - public static int maxLen1(String s) { - int n = s.length(); - int ans = 0; - for (int i = 0; i < n; i++) { - for (int j = n - 1; j >= i; j--) { - if (ok(s, i, j)) { - ans = Math.max(ans, j - i + 1); - break; - } - } - } - return ans; - } - - // 为了测试 - // 暴力方法 - public static boolean ok(String s, int l, int r) { - if (((r - l + 1) & 1) == 1) { - return false; - } - int[] cnts = new int[26]; - for (int i = l; i <= r; i++) { - cnts[s.charAt(i) - 'a']++; - } - for (int cnt : cnts) { - if ((cnt & 1) == 1) { - return false; - } - } - return true; - } - - // 正式方法 - // 时间复杂度O(N) - public static int maxLen2(String s) { - // key : 状态int, 32位的,a~z一共26位,够用 - // value : 该状态最早出现的位置 - HashMap map = new HashMap<>(); - // 00000000..000000 - map.put(0, -1); - // 0...当前字符,总状态! - int status = 0; - int ans = 0; - int n = s.length(); - // ....0 .....1 .....2 .....i ....n-1 - for (int i = 0; i < n; i++) { - // 从开头....i位置的字符 - // 总状态,出来了! - status ^= 1 << (s.charAt(i) - 'a'); - if (map.containsKey(status)) { - ans = Math.max(ans, i - map.get(status)); - } else { - map.put(status, i); - } - } - return ans; - } - - // 为了测试 - public static String randomString(int n, int v) { - char[] s = new char[n]; - for (int i = 0; i < n; i++) { - s[i] = (char) ((int) (Math.random() * v) + 'a'); - } - return String.valueOf(s); - } - - // 为了测试 - public static void main(String[] args) { - int n = 50; - int v = 6; - int testTimes = 2000; - System.out.println("测试开始"); - for (int i = 0; i < testTimes; i++) { - String s = randomString(n, v); - int ans1 = maxLen1(s); - int ans2 = maxLen2(s); - if (ans1 != ans2) { - System.out.println(s); - System.out.println(ans1); - System.out.println(ans2); - break; - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class109/Code04_RemoveMostKContinuousSameLongest.java b/公开课/class109/Code04_RemoveMostKContinuousSameLongest.java deleted file mode 100644 index e28ee0c..0000000 --- a/公开课/class109/Code04_RemoveMostKContinuousSameLongest.java +++ /dev/null @@ -1,113 +0,0 @@ -package class109; - -import java.util.HashMap; -import java.util.LinkedList; - -// 来自亚马逊 -// 给定一个数组arr,和一个正数k -// 你可以随意删除arr中的数字,最多删除k个 -// 目的是让连续出现一种数字的长度尽量长 -// 返回这个尽量长的长度 -// 比如数组arr = { 3, -2, 3, 3, 5, 6, 3, -2 }, k = 3 -// 你可以删掉-2、5、6(最多3个),这样数组arr = { 3, 3, 3, 3, -2 } -// 可以看到连续出现3的长度为4 -// 这是所有删除方法里的最长结果,所以返回4 -// 1 <= arr长度 <= 3 * 10^5 -// -10^9 <= arr中的数值 <= 10^9 -// 0 <= k <= 3 * 10^5 -public class Code04_RemoveMostKContinuousSameLongest { - - // 暴力方法 - // 为了测试 - public static int longest1(int[] arr, int k) { - return process1(arr, 0, new int[arr.length], 0, k); - } - - public static int process1(int[] arr, int i, int[] path, int size, int k) { - if (k < 0) { - return 0; - } - if (i == arr.length) { - if (size == 0) { - return 0; - } - int ans = 0; - int cnt = 1; - for (int j = 1; j < size; j++) { - if (path[j - 1] != path[j]) { - ans = Math.max(ans, cnt); - cnt = 1; - } else { - cnt++; - } - } - ans = Math.max(ans, cnt); - return ans; - } else { - path[size] = arr[i]; - int p1 = process1(arr, i + 1, path, size + 1, k); - int p2 = process1(arr, i + 1, path, size, k - 1); - return Math.max(p1, p2); - } - } - - // 正式方法 - // 时间复杂度O(N) - public static int longest2(int[] arr, int k) { - // key : 某个数值 - // value : 双端列表 ,头部或者尾部,进入或者弹出,都是非常方便的 - // 哪些下标拥有这个数值 - HashMap> valueIndies = new HashMap<>(); - int ans = 1; - for (int i = 0; i < arr.length; i++) { - int value = arr[i]; - if (!valueIndies.containsKey(value)) { - valueIndies.put(value, new LinkedList<>()); - } - LinkedList indies = valueIndies.get(value); - // 依次考察开头是否能和当前i位置,连起来 - // i - indies.peekFirst() : 一共有几个数 - // 6 10 13 15 18 == 18 - 6 - // indies.size() 6 ~ 17 有几个当前数! - // 一共有几个数 - 6 ~ 17 有几个当前数 = 需要使用几次删除才能让i和开头连起来! - while (!indies.isEmpty() && i - indies.peekFirst() - indies.size() > k) { - indies.pollFirst(); - } - indies.addLast(i); - ans = Math.max(ans, indies.size()); - } - return ans; - } - - // 为了测试 - // 生成长度为n的数组 - // 值在[-v,v]之间等概率随机 - public static int[] randomArray(int n, int v) { - int[] ans = new int[n]; - for (int i = 0; i < n; i++) { - ans[i] = (int) (Math.random() * (2 * v + 1)) - v; - } - return ans; - } - - // 为了测试 - public static void main(String[] args) { - int N = 20; - int V = 10; - int K = 5; - int testTime = 5000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int n = (int) (Math.random() * N) + 1; - int[] arr = randomArray(n, V); - int k = (int) (Math.random() * K); - int ans1 = longest1(arr, k); - int ans2 = longest2(arr, k); - if (ans1 != ans2) { - System.out.println("出错了!"); - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class110/Code01_MoveCityGetMoney.java b/公开课/class110/Code01_MoveCityGetMoney.java deleted file mode 100644 index 595eef8..0000000 --- a/公开课/class110/Code01_MoveCityGetMoney.java +++ /dev/null @@ -1,236 +0,0 @@ -package class110; - -import java.util.Arrays; - -// 来自美团 -// 有n个城市,城市从0到n-1进行编号。小美最初住在k号城市中 -// 在接下来的m天里,小美每天会收到一个任务 -// 她可以选择完成当天的任务或者放弃该任务 -// 第i天的任务需要在ci号城市完成,如果她选择完成这个任务 -// 若任务开始前她恰好在ci号城市,则会获得ai的收益 -// 若她不在ci号城市,她会前往ci号城市,获得bi的收益 -// 当天的任务她都会当天完成 -// 任务完成后,她会留在该任务所在的ci号城市直到接受下一个任务 -// 如果她选择放弃任务,她会停留原地,且不会获得收益 -// 小美想知道,如果她合理地完成任务,最大能获得多少收益 -// 输入描述: 第一行三个正整数n, m和k,表示城市数量,总天数,初始所在城市 -// 第二行为m个整数c1, c2,...... cm,其中ci表示第i天的任务所在地点为ci -// 第三行为m个整数a1, a2,...... am,其中ai表示完成第i天任务且地点不变的收益 -// 第四行为m个整数b1, b2,...... bm,其中bi表示完成第i天的任务且地点改变的收益 -// 0 <= k, ci <= n <= 30000 -// 1 <= m <= 30000 -// 0 <= ai, bi <= 10^9 -// 输出描述 输出一个整数,表示小美合理完成任务能得到的最大收益 -public class Code01_MoveCityGetMoney { - - public static int max(int n, int m, int k, int[] c, int[] a, int[] b) { - return zuo(k, 0, c, a, b); - } - - // 假设,小美目前身在curCity - // 还有i....m-1这么多任务可以去选择 - // 返回最大的收益 - // curCity -> n种 - // i -> m种 - // n * m二维表 -> 9 * (10 ^ 8) - public static int zuo(int curCity, int i, int[] c, int[] a, int[] b) { - if (i == c.length) { - return 0; - } - // 任务没结束 i号任务 有 - // 可能性1,彻底放弃当前i任务 - int p1 = zuo(curCity, i + 1, c, a, b); - // 可能性2,要做当前任务 - // 小美在哪:curCity - // i号任务在哪:北京 - // 如果身在北京 : 50 a[i] - // 如果不在北京 : 20 b[i] - int comeCity = c[i]; - int p2 = curCity == comeCity ? a[i] : b[i]; - p2 += zuo(comeCity, i + 1, c, a, b); - return Math.max(p1, p2); - } - - // 暴力方法 - // 时间复杂度O(N^2) - // 为了验证 - public static int maxPorfit1(int n, int m, int k, int[] c, int[] a, int[] b) { - int[][] dp = new int[n][m]; - for (int i = 0; i < n; i++) { - for (int j = 0; j < m; j++) { - dp[i][j] = -1; - } - } - return process1(k, 0, m, c, a, b, dp); - } - - // cur : 小美当前在哪! - // i : 当前面临的是任务编号! - // m : 一共有多少任务,固定 - // c[i] : 第i号任务要在哪个城里完成 - // a[i] : 恰好在!收益 - // b[i] : 赶过去!收益 - // 返回 : i....... 小美获得的最大收益 - public static int process1(int cur, int i, int m, int[] c, int[] a, int[] b, int[][] dp) { - if (i == m) { - return 0; - } - if (dp[cur][i] != -1) { - return dp[cur][i]; - } - // 可能性1 : 不做任务,彻底放弃,留在原地 - int p1 = process1(cur, i + 1, m, c, a, b, dp); - // 可能性2 : 做任务,要看看cur在哪,来获得收益 - int p2 = 0; - if (cur == c[i]) { - p2 = a[i] + process1(c[i], i + 1, m, c, a, b, dp); - } else { - p2 = b[i] + process1(c[i], i + 1, m, c, a, b, dp); - } - int ans = Math.max(p1, p2); - dp[cur][i] = ans; - return ans; - } - - // 正式方法 - // 时间复杂度O(N*logN) - public static int maxPorfit2(int n, int m, int k, int[] c, int[] a, int[] b) { - SegmentTree st = new SegmentTree(n); - - // st : - // s s s s 0 s s s - // 0 1 2 3 4 5 6 7 - // k - st.update(k, 0); -// int ans = 0; - for (int i = 0; i < m; i++) { - // c[i] : 3 - // 外地 : 0 ~ 2 4 ~ 7 - // 0~2 max 4 ~ 7 max -> max - int curAns = Math.max( - // 可能性1,从外地赶过来 - Math.max(st.max(0, c[i] - 1), - st.max(c[i] + 1, n - 1)) + b[i], - // 可能性2,原地 - st.max(c[i], c[i]) + a[i]); -// ans = Math.max(ans, curAns); - st.update(c[i], curAns); - } - return st.max(0, n-1); - } - - public static class SegmentTree { - private int n; - private int[] max; - - public SegmentTree(int N) { - n = N; - max = new int[(n + 1) << 2]; - Arrays.fill(max, Integer.MIN_VALUE); - } - - public int max(int l, int r) { - l++; - r++; - if (l > r) { - return Integer.MIN_VALUE; - } - return max(l, r, 1, n, 1); - } - - public void update(int i, int v) { - i++; - update(i, i, v, 1, n, 1); - } - - private void pushUp(int rt) { - max[rt] = Math.max(max[rt << 1], max[rt << 1 | 1]); - } - - private void update(int L, int R, int C, int l, int r, int rt) { - if (L <= l && r <= R) { - max[rt] = Math.max(max[rt], C); - return; - } - int mid = (l + r) >> 1; - if (L <= mid) { - update(L, R, C, l, mid, rt << 1); - } - if (R > mid) { - update(L, R, C, mid + 1, r, rt << 1 | 1); - } - pushUp(rt); - } - - private int max(int L, int R, int l, int r, int rt) { - if (L <= l && r <= R) { - return max[rt]; - } - int mid = (l + r) >> 1; - int left = Integer.MIN_VALUE; - int right = Integer.MIN_VALUE; - if (L <= mid) { - left = max(L, R, l, mid, rt << 1); - } - if (R > mid) { - right = max(L, R, mid + 1, r, rt << 1 | 1); - } - return Math.max(left, right); - } - - } - - // 为了测试 - public static int[] randomArray(int n, int v) { - int[] ans = new int[n]; - for (int i = 0; i < n; i++) { - ans[i] = (int) (Math.random() * v); - } - return ans; - } - - // 为了测试 - public static void main(String[] args) { - int N = 100; - int M = 100; - int V = 10000; - int testTimes = 5000; - System.out.println("功能测试开始"); - for (int i = 0; i < testTimes; i++) { - int n = (int) (Math.random() * N) + 1; - int m = (int) (Math.random() * M) + 1; - int k = (int) (Math.random() * n); - int[] c = randomArray(m, n); - int[] a = randomArray(m, V); - int[] b = randomArray(m, V); - int ans1 = maxPorfit1(n, m, k, c, a, b); - int ans2 = maxPorfit2(n, m, k, c, a, b); - if (ans1 != ans2) { - System.out.println("出错了!"); - System.out.println(ans1); - System.out.println(ans2); - break; - } - } - System.out.println("功能测试结束"); - - System.out.println("性能测试开始"); - int n = 100000; - int m = 100000; - int v = 1000000; - int k = (int) (Math.random() * n); - int[] c = randomArray(m, n); - int[] a = randomArray(m, v); - int[] b = randomArray(m, v); - System.out.println("城市数量 : " + n); - System.out.println("任务天数 : " + m); - System.out.println("收益数值规模 : " + v); - long start = System.currentTimeMillis(); - maxPorfit2(n, m, k, c, a, b); - long end = System.currentTimeMillis(); - System.out.println("运行时间 : " + (end - start) + "毫秒"); - System.out.println("性能测试结束"); - - } - -} diff --git a/公开课/class110/Code02_EntryRoomGetMoney.java b/公开课/class110/Code02_EntryRoomGetMoney.java deleted file mode 100644 index 4e5dbd1..0000000 --- a/公开课/class110/Code02_EntryRoomGetMoney.java +++ /dev/null @@ -1,199 +0,0 @@ -package class110; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; - -// 来自美团 -// 某天小美进入了一个迷宫探险,根据地图所示,这个迷宫里有无数个房间 -// 序号分别为1、2、3、...入口房间的序号为1 -// 任意序号为正整数x的房间,都与序号 2*x 和 2*x + 1 的房间之间各有一条路径 -// 但是这些路径是单向的,即只能从序号为x的房间去到序号为 2*x 或 2*x+1 的房间 -// 而不能从 2*x 或 2*x+1 的房间去到序号为x的房间 -// 在任何时刻小美都可以选择结束探险并离开迷宫,但是离开之后将无法再次进入迷宫 -// 小美还提前了解了迷宫中宝藏的信息 -// 已知宝藏共有n个,其中第i个宝藏在序号为pi的房间,价值为wi -// 且一个房间中可能有多个宝藏 -// 小美为了得到更多的宝藏,需要精心规划路线,她找到你帮忙 -// 想请你帮她计算一下,能获得的宝藏价值和最大值为多少 -// 第一行一个正整数n,表示宝藏数量。 -// 第二行为n个正整数p1, p2,...... pn,其中pi表示第 i 个宝藏在序号为pi的房间。 -// 第三行为n个正整数w1, w2,...... wn,其中wi表示第i个宝藏的价值为wi。 -// 1 <= n <= 40000, 1 <= pi < 2^30, 1 <= wi <= 10^6。 -public class Code02_EntryRoomGetMoney { - - public static int pickMoney(int[][] values) { - // values : {5, 100}, {2, 3000}, {150, 80} {2^30, 18} - Arrays.sort(values, (a, b) -> a[0] - b[0]); - HashMap> graph = new HashMap<>(); - ArrayList starts = new ArrayList<>(); - for (int[] v : values) { - int room = v[0]; - int tmp = room; - while (tmp != 0) { - if (graph.containsKey(tmp)) { - graph.get(tmp).add(room); - break; - } - tmp /= 2; - } - graph.put(room, new ArrayList<>()); - if (tmp == 0) { - starts.add(room); - } - } - HashMap money = new HashMap<>(); - for (int[] v : values) { - money.put(v[0], v[1]); - } - int ans = 0; - for (int start : starts) { - ans = Math.max(ans, maxValue(start, graph, money)); - } - return ans; - } - - public static int maxValue(int room, HashMap> graph, HashMap money) { - if (graph.get(room).isEmpty()) { - return money.get(room); - } - int next = 0; - for (int child : graph.get(room)) { - next = Math.max(next, maxValue(child, graph, money)); - } - return next + money.get(room); - } - - // 为了测试 - // 普通动态规划 - public static int maxMoney1(int n, int[] p, int[] w) { - int[][] rooms = new int[n][2]; - for (int i = 0; i < n; i++) { - rooms[i][0] = p[i]; - rooms[i][1] = w[i]; - } - Arrays.sort(rooms, (a, b) -> a[0] - b[0]); - int ans = 0; - int[] dp = new int[n]; - Arrays.fill(dp, -1); - for (int i = 0; i < n; i++) { - ans = Math.max(ans, process1(i, rooms, n, dp)); - } - return ans; - } - - public static int process1(int index, int[][] rooms, int n, int[] dp) { - if (dp[index] != -1) { - return dp[index]; - } - int next = 0; - for (int i = index + 1; i < n; i++) { - if (reach(rooms[index][0], rooms[i][0])) { - next = Math.max(next, process1(i, rooms, n, dp)); - } - } - int ans = rooms[index][1] + next; - dp[index] = ans; - return dp[index]; - } - - public static boolean reach(int from, int to) { - while (to >= from) { - if (from == to) { - return true; - } else { - to /= 2; - } - } - return false; - } - - // 正式方法 - // 时间复杂度O(N)的动态规划 - // 利用图来优化枚举 - public static int maxMoney2(int n, int[] p, int[] w) { - int[][] rooms = new int[n][2]; - for (int i = 0; i < n; i++) { - rooms[i][0] = p[i]; - rooms[i][1] = w[i]; - } - Arrays.sort(rooms, (a, b) -> a[0] - b[0]); - HashMap first = new HashMap<>(); - ArrayList> graph = new ArrayList<>(); - for (int i = 0; i < n; i++) { - int to = rooms[i][0]; - while (to > 0) { - if (first.containsKey(to)) { - graph.get(first.get(to)).add(i); - break; - } else { - to >>= 1; - } - } - graph.add(new ArrayList<>()); - if (!first.containsKey(rooms[i][0])) { - first.put(rooms[i][0], i); - } - } - int ans = 0; - int[] dp = new int[n]; - for (int i = n - 1; i >= 0; i--) { - int post = 0; - for (int next : graph.get(i)) { - if (rooms[next][0] == rooms[i][0]) { - dp[i] += dp[next]; - } else { - post = Math.max(post, dp[next]); - } - } - dp[i] += post + rooms[i][1]; - ans = Math.max(ans, dp[i]); - } - return ans; - } - - // 为了测试 - public static int[] randomArray(int n, int v) { - int[] ans = new int[n]; - for (int i = 0; i < n; i++) { - ans[i] = (int) (Math.random() * v) + 1; - } - return ans; - } - - public static void main(String[] args) { - int N = 100; - int P = 5000; - int W = 5000; - int testTimes = 5000; - System.out.println("功能测试开始"); - for (int i = 0; i < testTimes; i++) { - int n = (int) (Math.random() * N) + 1; - int[] p = randomArray(n, P); - int[] w = randomArray(n, W); - int ans1 = maxMoney1(n, p, w); - int ans2 = maxMoney2(n, p, w); - if (ans1 != ans2) { - System.out.println("出错了"); - } - } - System.out.println("功能测试结束"); - - System.out.println("性能测试开始"); - N = 50000; - P = 2000000000; - W = 1000000; - int[] p = randomArray(N, P); - int[] w = randomArray(N, W); - System.out.println("房间个数 : " + N); - System.out.println("位置范围 : " + P); - System.out.println("价值范围 : " + W); - long start = System.currentTimeMillis(); - maxMoney2(N, p, w); - long end = System.currentTimeMillis(); - System.out.println("运行时间 : " + (end - start) + " 毫秒"); - System.out.println("性能测试结束"); - - } - -} diff --git a/公开课/class111/Code01_ComplementaryPairsInStringArray.java b/公开课/class111/Code01_ComplementaryPairsInStringArray.java deleted file mode 100644 index b2cc1c3..0000000 --- a/公开课/class111/Code01_ComplementaryPairsInStringArray.java +++ /dev/null @@ -1,145 +0,0 @@ -package class111; - -import java.util.HashMap; - -// 来自亚马逊 -// 给定一个字符串数组strs,其中每个字符串都是小写字母组成的 -// 如果i < j,并且strs[i]和strs[j]所有的字符随意去排列能组成回文串 -// 那么说(i,j)叫做一个互补对(complementary) -// 求strs中有多少个互补对 -// strs长度 <= 3 * 10^5 -// 单个字符串长度 <= 10^5 -// strs里所有字符串总长度 <= 10^6 -public class Code01_ComplementaryPairsInStringArray { - - public static int test(String[] strs) { - // key : 一种字符串的状态 - // value : 这种状态出现了多少次 - HashMap map = new HashMap<>(); - int ans = 0; - for (String str : strs) { - int status = 0; - for (int i = 0; i < str.length(); i++) { - status ^= 1 << (str.charAt(i) - 'a'); - } - // 之前的字符串,和当前字符串一样的状态,有多少个? - ans += map.get(status); - // 每一位都允许和当前字符串状态不一样,但是剩下的状态得一样 - // g f e d c b a - // status : 0 0 1 1 0 0 1 - // a上捣乱 : 0 0 1 1 0 0 0 - // b上捣乱 : 0 0 1 1 0 1 1 - // 0 ~ - // ~ 1 ~ - // ~ 2 ~ - for(int a = 0; a < 26; a++) { - ans += map.get(status ^ (1 << a)); - } - if (!map.containsKey(status)) { - map.put(status, 1); - } else { - map.put(status, map.get(status) + 1); - } - } - return ans; - } - - // 暴力方法 - // 为了测试 - public static int num1(String[] strs) { - int ans = 0; - for (int i = 0; i < strs.length; i++) { - for (int j = i + 1; j < strs.length; j++) { - if (complementary(strs[i], strs[j])) { - ans++; - } - } - } - return ans; - } - - public static boolean complementary(String a, String b) { - int[] cnt = new int[26]; - for (int i = 0; i < a.length(); i++) { - cnt[a.charAt(i) - 'a']++; - } - for (int i = 0; i < b.length(); i++) { - cnt[b.charAt(i) - 'a']++; - } - int odd = 0; - for (int num : cnt) { - if ((num & 1) != 0) { - odd++; - } - } - return odd < 2; - } - - // 正式方法 - // O(N*M),N字符串长,M字符串平均长度 - // 时间复杂度O(N) + O(M),一共有多少个字符串N,一共有多少字符M - public static int num2(String[] strs) { - // key : 某一种状态(int类型,状态) - // z..d c b a - // 3 2 1 0 - // 1 0 1 1 - // value : 这样状态的字符串,有几个 - HashMap status = new HashMap<>(); - int ans = 0; - for (String str : strs) { - // 当前str这个字符串 - // 它自己的状态,加工好 - // d c b a - // 0 0 0 1 - int cur = 0; - for (int i = 0; i < str.length(); i++) { - cur ^= 1 << (str.charAt(i) - 'a'); - } - // 一点点都不捣乱,cur,map有几个状态也是cur的字符串 - ans += status.getOrDefault(cur, 0); - for (int i = 0; i < 26; i++) { - // 每一位捣乱一下 - // a - // b - // c - // z - ans += status.getOrDefault(cur ^ (1 << i), 0); - } - status.put(cur, status.getOrDefault(cur, 0) + 1); - } - return ans; - } - - // 为了验证 - public static String[] randomStringArray(int n, int m, int r) { - String[] ans = new String[n]; - for (int i = 0; i < n; i++) { - int len = (int) (Math.random() * m) + 1; - char[] str = new char[len]; - for (int j = 0; j < len; j++) { - str[j] = (char) ((int) (Math.random() * r) + 'a'); - } - ans[i] = String.valueOf(str); - } - return ans; - } - - public static void main(String[] args) { - int N = 100; - int M = 20; - int R = 5; - int testTime = 5000; - System.out.println("测试开始"); - for (int i = 0; i < testTime; i++) { - int n = (int) (Math.random() * N) + 1; - String[] strs = randomStringArray(n, M, R); - int ans1 = num1(strs); - int ans2 = num2(strs); - if (ans1 != ans2) { - System.out.println("出错了!"); - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class111/Code02_CouplesHoldingHands.java b/公开课/class111/Code02_CouplesHoldingHands.java deleted file mode 100644 index fcbab3d..0000000 --- a/公开课/class111/Code02_CouplesHoldingHands.java +++ /dev/null @@ -1,76 +0,0 @@ -package class111; - -// 来自Facebook -// n对情侣坐在连续排列的 2n 个座位上,想要牵到对方的手 -// 人和座位由一个整数数组 row 表示,其中 row[i] 是坐在第 i 个座位上的人的ID -// 情侣们按顺序编号,第一对是 (0, 1),第二对是 (2, 3),以此类推,最后一对是 (2n-2, 2n-1) -// 返回 最少交换座位的次数,以便每对情侣可以并肩坐在一起 -// 每次交换可选择任意两人,让他们站起来交换座位 -// 测试链接 : https://leetcode.cn/problems/couples-holding-hands/ -public class Code02_CouplesHoldingHands { - - public int minSwapsCouples(int[] row) { - // n:人数 - int n = row.length; - // n / 2 - UnionFind uf = new UnionFind(n / 2); - for (int i = 0; i < n; i += 2) { - // row[i] / 2 -> 组 - // row[i+1] / 2 -> 组 - uf.union(row[i] / 2, row[i + 1] / 2); - } - return n / 2 - uf.sets(); - } - - public static class UnionFind { - public int[] father; - public int[] size; - public int[] help; - public int sets; - - public UnionFind(int n) { - father = new int[n]; - size = new int[n]; - help = new int[n]; - for (int i = 0; i < n; i++) { - father[i] = i; - size[i] = 1; - } - sets = n; - } - - private int find(int i) { - int hi = 0; - while (i != father[i]) { - help[hi++] = i; - i = father[i]; - } - while (hi != 0) { - father[help[--hi]] = i; - } - return i; - } - - // 极快,单次代价认为 : O(1) - public void union(int i, int j) { - int fi = find(i); - int fj = find(j); - if (fi != fj) { - if (size[fi] >= size[fj]) { - father[fj] = fi; - size[fi] += size[fj]; - } else { - father[fi] = fj; - size[fj] += size[fi]; - } - sets--; - } - } - - public int sets() { - return sets; - } - - } - -} diff --git a/公开课/class112/Code01_SortArrayByMovingItemsToEmptySpace.java b/公开课/class112/Code01_SortArrayByMovingItemsToEmptySpace.java deleted file mode 100644 index bb35552..0000000 --- a/公开课/class112/Code01_SortArrayByMovingItemsToEmptySpace.java +++ /dev/null @@ -1,106 +0,0 @@ -package class112; - -import java.util.Arrays; - -// 来自谷歌 -// 给定一个长度为N的数组,值一定在0~N-1范围,且每个值不重复 -// 比如,arr = [4, 2, 0, 3, 1] -// 0 1 2 3 4 -// 把0想象成洞,任何非0数字都可以来到这个洞里,然后在原本的位置留下洞 -// 比如4这个数字,来到0所代表的洞里,那么数组变成 : -// arr = [0, 2, 4, 3, 1] -// 也就是原来的洞被4填满,4走后留下了洞 -// 任何数字只能搬家到洞里,并且走后留下洞 -// 通过搬家的方式,想变成有序的,有序有两种形式 -// 比如arr = [4, 2, 0, 3, 1],变成 -// [0, 1, 2, 3, 4]或者[1, 2, 3, 4, 0]都叫有序 -// 返回变成任何一种有序的情况都可以,最少的数字搬动次数 -// 测试链接 : https://leetcode.cn/problems/sort-array-by-moving-items-to-empty-space/ -public class Code01_SortArrayByMovingItemsToEmptySpace { - - public static int sortArray(int[] nums) { - // 1) 0 1 2 3 4 .... 这个样子,至少交换几次 ans1 - // 2) 1 2 3 4 .... 0 这个样子,至少交换几次 ans2 - int n = nums.length, ans1 = 0, ans2 = 0, m, next; - // 标记,i位置,在之前的环里的话!touched[i] == true - // 如果i位置不在之前的环里的话!touched[i] == false - boolean[] touched = new boolean[n]; - // 0 1 2 3 4 ....方案1 -> ans1 - for (int i = 0; i < n; i++) { - if (!touched[i]) { - // 4 6 0 - // 0(i) -> 4 6 - // y y y - touched[i] = true; - m = 1; - next = nums[i]; - while (next != i) { - m++; - touched[next] = true; - next = nums[next]; - } - // m个 -> 几次? - if (m > 1) { - ans1 += i == 0 ? (m - 1) : (m + 1); - } - } - } - Arrays.fill(touched, false); - // 1 2 3 4 ... 0 方案2 -> ans2 - for (int i = n - 1; i >= 0; i--) { - if (!touched[i]) { - touched[i] = true; - m = 1; - // n = 7 : 下标 0 ~ 6 - // nums[i] - // i - // next = nums[next] - next = nums[i] == 0 ? (n - 1) : (nums[i] - 1); - while (next != i) { - m++; - touched[next] = true; - next = nums[next] == 0 ? (n - 1) : (nums[next] - 1); - } - if (m > 1) { - ans2 += i == n - 1 ? (m - 1) : (m + 1); - } - } - } - return Math.min(ans1, ans2); - } - - public static int sortYours(int[] arr) { - // ..... - return 100; - } - - public static int[] randomArray(int len) { - int[] arr = new int[len]; - for (int i = 0; i < len; i++) { - arr[i] = i; - } - for (int i = len - 1; i >= 0; i--) { - int swap = (int) (Math.random() * (i + 1)); - // 0 1 2 3 4 5(i) - // 0 ~ 5 5 - int tmp = arr[i]; - arr[i] = arr[swap]; - arr[swap] = tmp; - } - return arr; - } - -// public static void main(String[] args) { -// int testTimes = 10000; -// int Len = 10; -// for(int i = 0; i < testTimes;i++) { -// int[] arr = randomArray(10); -// int ans1 = my(); -// int ans2 = yours(); -// if(ans1!=ans2) { -// 打印错误 -// } -// } -// } - -} diff --git a/公开课/class112/Code02_ZigZagConversion.java b/公开课/class112/Code02_ZigZagConversion.java deleted file mode 100644 index 3689e8c..0000000 --- a/公开课/class112/Code02_ZigZagConversion.java +++ /dev/null @@ -1,37 +0,0 @@ -package class112; - -// 来自字节跳动 -// 将一个给定字符串 s 根据给定的行数 numRows -// 以从上往下、从左到右进行 Z 字形排列 -// 比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下 -// P A H N -// A P L S I I G -// Y I R -// 之后,你的输出需要从左往右逐行读取,产生出一个新的字符串 -// "PAHNAPLSIIGYIR" -// 请你实现这个将字符串进行指定行数变换的函数 -// string convert(string s, int numRows) -// 测试链接 : https://leetcode.cn/problems/zigzag-conversion/ -public class Code02_ZigZagConversion { - - public static String convert(String s, int row) { - int n = s.length(); - if (row == 1 || row >= n) { - return s; - } - int t = 2 * (row - 1); - char[] ans = new char[n]; - int fill = 0; - for (int i = 0; i < row; i++) { - // 来到i行,原始串开始下标j == i - for (int j = i, nextColTop = t; j < n; j += t, nextColTop += t) { - ans[fill++] = s.charAt(j); - if (i >= 1 && i <= row - 2 && nextColTop - i < n) { - ans[fill++] = s.charAt(nextColTop - i); - } - } - } - return String.valueOf(ans); - } - -} diff --git a/公开课/class113/Code01_TravelMinFuel.java b/公开课/class113/Code01_TravelMinFuel.java deleted file mode 100644 index 6d84436..0000000 --- a/公开课/class113/Code01_TravelMinFuel.java +++ /dev/null @@ -1,79 +0,0 @@ -package class113; - -// 来自微软 -// 给定两个数组A和B,比如 -// A = { 0, 1, 1 } -// B = { 1, 2, 3 } -// A[0] = 0, B[0] = 1,表示0到1有双向道路 -// A[1] = 1, B[1] = 2,表示1到2有双向道路 -// A[2] = 1, B[2] = 3,表示1到3有双向道路 -// 给定数字N,编号从0~N,所以一共N+1个节点 -// 题目输入一定保证所有节点都联通,并且一定没有环 -// 默认办公室是0节点,其他1~N节点上,每个节点上都有一个居民 -// 每天所有居民都去往0节点上班 -// 所有的居民都有一辆5座的车,也都乐意和别人一起坐车 -// 车不管负重是多少,只要走过一条路,就耗费1的汽油 -// 比如A、B、C的居民,开着自己的车来到D居民的位置,一共耗费3的汽油 -// D居民和E居民之间,假设有一条路 -// 那么D居民可以接上A、B、C,4个人可以用一辆车,去往E的话,就再耗费1的汽油 -// 求所有居民去办公室的路上,最少耗费多少汽油 -import java.util.ArrayList; - -public class Code01_TravelMinFuel { - - // a [ 2 .. - // b [ 3 .. - // n = 4,a、b数组的长度,a和b等长的! - // 0 : {} - // 1 : {} - // 2 : {} - // 3 : {} - // 4 : {} - public static int minFuel(int[] a, int[] b, int n) { - // 先建图 - ArrayList> graph = new ArrayList<>(); - for (int i = 0; i <= n; i++) { - graph.add(new ArrayList<>()); - } - for (int i = 0; i < a.length; i++) { - graph.get(a[i]).add(b[i]); - graph.get(b[i]).add(a[i]); - } - int[] size = new int[n+1]; - return cost(0, -1, graph, size); - } - - - - // cur : 点的编号! - // father : cur点的父节点! - // 返回 : cur整棵子树上的所有节点汇聚到cur,需要多少油! - public static int cost(int cur, int father, ArrayList> graph, int[] size) { - // cur的整棵子树上,包含cur自己的! - size[cur] = 1; - int cost = 0; - for (int next : graph.get(cur)) { - if (next != father) { // 不回到上级去! - // 下级节点的子树所有节点汇聚在下级节点的总消耗! - int nextDistance = cost(next, cur, graph, size); - cost += nextDistance; - cost += (size[next] + 4) / 5; // size[next] / 5向上取整! - size[cur] += size[next]; - } - } - return cost; - } - - public static void main(String[] args) { - int[] a1 = { 0, 1, 1 }; - int[] b1 = { 1, 2, 3 }; - int n1 = 3; - System.out.println(minFuel(a1, b1, n1)); - - int[] a2 = { 1, 1, 1, 9, 9, 9, 9, 7, 8 }; - int[] b2 = { 2, 0, 3, 1, 6, 5, 4, 0, 0 }; - int n2 = 9; - System.out.println(minFuel(a2, b2, n2)); - } - -} diff --git a/公开课/class113/Code02_MakingALargeIsland.java b/公开课/class113/Code02_MakingALargeIsland.java deleted file mode 100644 index d123e38..0000000 --- a/公开课/class113/Code02_MakingALargeIsland.java +++ /dev/null @@ -1,124 +0,0 @@ -package class113; - -import java.util.ArrayList; - -// 来自亚马逊、谷歌、微软、Facebook、Bloomberg -// 给你一个大小为 n x n 二进制矩阵 grid 。最多 只能将一格 0 变成 1 。 -// 返回执行此操作后,grid 中最大的岛屿面积是多少? -// 岛屿 由一组上、下、左、右四个方向相连的 1 形成。 -// 测试链接 : https://leetcode.cn/problems/making-a-large-island/ -public class Code02_MakingALargeIsland { - - public static int largestIsland(int[][] grid) { - int n = grid.length; - int m = grid[0].length; - ArrayList sizes = new ArrayList<>(); - sizes.add(0); - sizes.add(0); - int id = 2; - int ans = 0; - for (int i = 0; i < n; i++) { - for (int j = 0; j < m; j++) { - if (grid[i][j] == 1) { - int curSize = infect(grid, i, j, id, n, m); - ans = Math.max(ans, curSize); - sizes.add(id++, curSize); - } - } - } - boolean[] visited = new boolean[id]; - for (int i = 0; i < n; i++) { - for (int j = 0; j < m; j++) { - if (grid[i][j] == 0) { - int up = i - 1 >= 0 ? grid[i - 1][j] : 0; - int down = i + 1 < n ? grid[i + 1][j] : 0; - int left = j - 1 >= 0 ? grid[i][j - 1] : 0; - int right = j + 1 < m ? grid[i][j + 1] : 0; - int merge = 1 + sizes.get(up); - visited[up] = true; - if (!visited[down]) { - merge += sizes.get(down); - visited[down] = true; - } - if (!visited[left]) { - merge += sizes.get(left); - visited[left] = true; - } - if (!visited[right]) { - merge += sizes.get(right); - visited[right] = true; - } - ans = Math.max(ans, merge); - visited[up] = false; - visited[down] = false; - visited[left] = false; - visited[right] = false; - } - } - } - return ans; - } - - public static int infect(int[][] grid, int i, int j, int v, int n, int m) { - if (i < 0 || i == n || j < 0 || j == m || grid[i][j] != 1) { - return 0; - } - int ans = 1; - grid[i][j] = v; - ans += infect(grid, i - 1, j, v, n, m); - ans += infect(grid, i + 1, j, v, n, m); - ans += infect(grid, i, j - 1, v, n, m); - ans += infect(grid, i, j + 1, v, n, m); - return ans; - } - - // O(N * M) - public static int[] infect(int[][] map) { - int cnt = 2; - for (int i = 0; i < map.length; i++) { - for (int j = 0; j < map[0].length; j++) { - if (map[i][j] == 1) { // 一个新的岛! - zuo(map, i, j, cnt++); - } - } - } - int[] size = new int[cnt]; - for (int i = 0; i < map.length; i++) { - for (int j = 0; j < map[0].length; j++) { - if (map[i][j] > 1) { - size[map[i][j]]++; - } - } - } - return size; - } - - public static void zuo(int[][] map, int i, int j, int th) { - if (i < 0 || i == map.length || j < 0 || j == map[0].length || map[i][j] != 1) { - return; - } - // i,j 不越界 map[i][j] == 1 - map[i][j] = th; - zuo(map, i - 1, j, th); - zuo(map, i + 1, j, th); - zuo(map, i, j - 1, th); - zuo(map, i, j + 1, th); - } - - public static void main(String[] args) { - int[][] map = { { 0, 1, 0, 0, 1, 1 }, { 1, 1, 1, 0, 0, 0 }, { 1, 1, 0, 1, 1, 0 }, { 1, 1, 0, 0, 1, 0 }, }; - int[] size = infect(map); - for (int i = 0; i < map.length; i++) { - for (int j = 0; j < map[0].length; j++) { - System.out.print(map[i][j] + " "); - } - System.out.println(); - } - - for (int i = 2; i < size.length; i++) { - System.out.println("编号" + i + ", 大小" + size[i]); - } - - } - -} diff --git a/公开课/class113/Code03_MinimumCostToHireKWorkers.java b/公开课/class113/Code03_MinimumCostToHireKWorkers.java deleted file mode 100644 index 53f95d7..0000000 --- a/公开课/class113/Code03_MinimumCostToHireKWorkers.java +++ /dev/null @@ -1,54 +0,0 @@ -package class113; - -import java.util.Arrays; -import java.util.PriorityQueue; - -// 来自亚马逊 -// 有 n 名工人。 给定两个数组 quality 和 wage , -// 其中quality[i] 表示第 i 名工人的工作质量,其最低期望工资为 wage[i] 。 -// 现在我们想雇佣 k 名工人组成一个工资组。在雇佣 一组 k 名工人时, -// 我们必须按照下述规则向他们支付工资: -// 对工资组中的每名工人,应当按其工作质量与同组其他工人的工作质量的比例来支付工资。 -// 工资组中的每名工人至少应当得到他们的最低期望工资。 -// 测试链接 : https://leetcode.cn/problems/minimum-cost-to-hire-k-workers/ -public class Code03_MinimumCostToHireKWorkers { - - public static class Employee { - public double rubbishDegree; - public int quality; - - public Employee(int w, int q) { - rubbishDegree = (double) w / (double) q; - quality = q; - } - } - - public double mincostToHireWorkers(int[] quality, int[] wage, int k) { - int n = quality.length; - Employee[] employees = new Employee[n]; - for (int i = 0; i < n; i++) { - employees[i] = new Employee(wage[i], quality[i]); - } - Arrays.sort(employees, (a, b) -> a.rubbishDegree <= b.rubbishDegree ? -1 : 1); - PriorityQueue minTops = new PriorityQueue((a, b) -> b - a); - double ans = Double.MAX_VALUE; - for (int i = 0, qualitySum = 0; i < n; i++) { - int curQuality = employees[i].quality; - if (minTops.size() < k) { - qualitySum += curQuality; - minTops.add(curQuality); - if (minTops.size() == k) { - ans = Math.min(ans, qualitySum * employees[i].rubbishDegree); - } - } else { - if (minTops.peek() > curQuality) { - qualitySum += curQuality - minTops.poll(); - minTops.add(curQuality); - } - ans = Math.min(ans, qualitySum * employees[i].rubbishDegree); - } - } - return ans; - } - -} diff --git a/公开课/class114/Code01_KthMissingPositiveNumber.java b/公开课/class114/Code01_KthMissingPositiveNumber.java deleted file mode 100644 index 21d82f0..0000000 --- a/公开课/class114/Code01_KthMissingPositiveNumber.java +++ /dev/null @@ -1,26 +0,0 @@ -package class114; - -// 给你一个 严格升序排列 的正整数数组 arr 和一个整数 k 。 -// 请你找到这个数组里第 k 个缺失的正整数。 -// 测试链接 : https://leetcode.cn/problems/kth-missing-positive-number/ -public class Code01_KthMissingPositiveNumber { - - public int findKthPositive(int[] arr, int k) { - int l = 0; - int r = arr.length - 1; - int m = 0; - int find = arr.length; - while (l <= r) { - m = (l + r) / 2; - if (arr[m] - (m + 1) >= k) { - find = m; - r = m - 1; - } else { - l = m + 1; - } - } - int preValue = find == 0 ? 0 : arr[find - 1]; - int under = preValue - find; - return preValue + (k - under); - } -} diff --git a/公开课/class114/Code02_ZigZagConversion.java b/公开课/class114/Code02_ZigZagConversion.java deleted file mode 100644 index 6bd44e4..0000000 --- a/公开课/class114/Code02_ZigZagConversion.java +++ /dev/null @@ -1,40 +0,0 @@ -package class114; - -// 将一个给定字符串 s 根据给定的行数 numRows -// 以从上往下、从左到右进行 Z 字形排列 -// 比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下 -// P A H N -// A P L S I I G -// Y I R -// 之后,你的输出需要从左往右逐行读取,产生出一个新的字符串 -// "PAHNAPLSIIGYIR" -// 请你实现这个将字符串进行指定行数变换的函数 -// string convert(string s, int numRows) -// 测试链接 : https://leetcode.cn/problems/zigzag-conversion/ -public class Code02_ZigZagConversion { - - public static String convert(String s, int row) { - int n = s.length(); - if (row == 1 || row >= n) { - return s; - } - // 周期! - int t = 2 * row - 2; - char[] ans = new char[n]; - int fill = 0; - for (int i = 0; i < row; i++) { // 行号 - for (int j = i, nextColTop = t; j < n; j += t, nextColTop += t) { - // nextColTop - i - // j ? j+t - ans[fill++] = s.charAt(j); - // 如果在中间行、并且多出来的下标不越界(真的有) - if (i >= 1 && i <= row - 2 && nextColTop - i < n) { - // 把多出来的那个,填进去 - ans[fill++] = s.charAt(nextColTop - i); - } - } - } - return String.valueOf(ans); - } - -} diff --git a/公开课/class114/Code03_MaximumWidthRamp.java b/公开课/class114/Code03_MaximumWidthRamp.java deleted file mode 100644 index 25999dd..0000000 --- a/公开课/class114/Code03_MaximumWidthRamp.java +++ /dev/null @@ -1,42 +0,0 @@ -package class114; - -// 给定一个整数数组 A,坡是元组 (i, j),其中  i < j 且 A[i] <= A[j] -// 这样的坡的宽度为 j - i -// 找出 A 中的坡的最大宽度,如果不存在,返回 0 -// 示例 1: -// 输入:[6,0,8,2,1,5] -// 输出:4 -// 解释: -// 最大宽度的坡为 (i, j) = (1, 5): A[1] = 0 且 A[5] = 5 -// 示例 2: -// 输入:[9,8,1,0,1,9,4,0,4,1] -// 输出:7 -// 解释: -// 最大宽度的坡为 (i, j) = (2, 9): A[2] = 1 且 A[9] = 1 -// 测试链接 : https://leetcode.cn/problems/maximum-width-ramp/ -public class Code03_MaximumWidthRamp { - - public static int maxWidthRamp(int[] arr) { - int n = arr.length; - // 栈中只放下标 - int[] stack = new int[n]; - // 栈的大小 - int r = 0; - for (int i = 0; i < n; i++) { - if (r == 0 || arr[stack[r - 1]] > arr[i]) { - stack[r++] = i; - } - } - int ans = 0; - // 从右往左遍历 - // j = n - 1 - for (int j = n - 1; j >= 0; j--) { - while (r != 0 && arr[stack[r - 1]] <= arr[j]) { - int i = stack[--r]; - ans = Math.max(ans, j - i); - } - } - return ans; - } - -} diff --git a/公开课/class114/Code04_ThreeEqualParts.java b/公开课/class114/Code04_ThreeEqualParts.java deleted file mode 100644 index 7547ab8..0000000 --- a/公开课/class114/Code04_ThreeEqualParts.java +++ /dev/null @@ -1,80 +0,0 @@ -package class114; - -// 给定一个由 0 和 1 组成的数组 arr ,将数组分成 3 个非空的部分 -// 使得所有这些部分表示相同的二进制值。 -// 如果可以做到,请返回任何 [i, j],其中 i+1 < j,这样一来 -// arr[0], arr[1], ..., arr[i] 为第一部分 -// arr[i + 1], arr[i + 2], ..., arr[j - 1] 为第二部分 -// arr[j], arr[j + 1], ..., arr[arr.length - 1] 为第三部分 -// 这三个部分所表示的二进制值相等 -// 如果无法做到,就返回 [-1, -1] -// 注意,在考虑每个部分所表示的二进制时,应当将其看作一个整体 -// 例如,[1,1,0] 表示十进制中的 6,而不会是 3。此外,前导零也是被允许的 -// 所以 [0,1,1] 和 [1,1] 表示相同的值。 -// 测试链接 : https://leetcode.cn/problems/three-equal-parts/ -public class Code04_ThreeEqualParts { - - public static int[] threeEqualParts(int[] arr) { - // 计算arr中1的数量 - int ones = 0; - for (int num : arr) { - ones += num == 1 ? 1 : 0; - } - // 如果1的数量不能被3整除,肯定不存在方案 - if (ones % 3 != 0) { - return new int[] { -1, -1 }; - } - int n = arr.length; - // 如果1的数量是0,怎么划分都可以了,因为全是0 - if (ones == 0) { - return new int[] { 0, n - 1 }; - } - // 接下来的过程 - // 因为1的数量能被3整除,比如一共有12个1 - // 那么第一段肯定含有第1个1~第4个1 - // 那么第二段肯定含有第5个1~第8个1 - // 那么第三段肯定含有第9个1~第12个1 - // 所以把第1个1,当做第一段的开头,start1 - // 所以把第5个1,当做第二段的开头,start2 - // 所以把第9个1,当做第三段的开头,start3 - int part = ones / 3; - int start1 = -1; - int start2 = -1; - int start3 = -1; - int cnt = 0; - // 1个数21个 - // part = 7 - // 1 8 - for (int i = 0; i < n; i++) { - if (arr[i] == 1) { - cnt++; - if (start1 == -1 && cnt == 1) { - start1 = i; - } - if (start2 == -1 && cnt == part + 1) { - start2 = i; - } - if (start3 == -1 && cnt == 2 * part + 1) { - start3 = i; - } - } - } - // 第一段的开头往下的部分 - // 第二段的开头往下的部分 - // 第三段的开头往下的部分 - // 要都一样,这三段的状态才是一样的 - // 所以接下来就验证这一点,是不是每一步都一样 - while (start3 < n) { - if (arr[start1] != arr[start2] || arr[start1] != arr[start3]) { - // 一旦不一样,肯定没方案了 - return new int[] { -1, -1 }; - } - start1++; - start2++; - start3++; - } - // 如果验证通过,返回断点即可 - return new int[] { start1 - 1, start2 }; - } - -} diff --git a/公开课/class114/Code05_CouplesHoldingHands.java b/公开课/class114/Code05_CouplesHoldingHands.java deleted file mode 100644 index f7f865e..0000000 --- a/公开课/class114/Code05_CouplesHoldingHands.java +++ /dev/null @@ -1,74 +0,0 @@ -package class114; - -// n对情侣坐在连续排列的 2n 个座位上,想要牵到对方的手 -// 人和座位由一个整数数组 row 表示,其中 row[i] 是坐在第 i 个座位上的人的ID -// 情侣们按顺序编号,第一对是 (0, 1),第二对是 (2, 3),以此类推,最后一对是 (2n-2, 2n-1) -// 返回 最少交换座位的次数,以便每对情侣可以并肩坐在一起 -// 每次交换可选择任意两人,让他们站起来交换座位 -// 测试链接 : https://leetcode.cn/problems/couples-holding-hands/ -public class Code05_CouplesHoldingHands { - - public int minSwapsCouples(int[] row) { - // n人数,偶数 - int n = row.length; - // n/2 - // 0 1 -> 0 0 - // 4 5 -> 2 2 - UnionFind uf = new UnionFind(n / 2); - for (int i = 0; i < n; i += 2) { - uf.union(row[i] / 2, row[i + 1] / 2); - } - return n / 2 - uf.sets(); - } - - public static class UnionFind { - public int[] father; - public int[] size; - public int[] help; - public int sets; - - public UnionFind(int n) { - father = new int[n]; - size = new int[n]; - help = new int[n]; - for (int i = 0; i < n; i++) { - father[i] = i; - size[i] = 1; - } - sets = n; - } - - private int find(int i) { - int hi = 0; - while (i != father[i]) { - help[hi++] = i; - i = father[i]; - } - while (hi != 0) { - father[help[--hi]] = i; - } - return i; - } - - public void union(int i, int j) { - int fi = find(i); - int fj = find(j); - if (fi != fj) { - if (size[fi] >= size[fj]) { - father[fj] = fi; - size[fi] += size[fj]; - } else { - father[fi] = fj; - size[fj] += size[fi]; - } - sets--; - } - } - - public int sets() { - return sets; - } - - } - -} diff --git a/公开课/class114/Code06_AbsToArrayFinalLength.java b/公开课/class114/Code06_AbsToArrayFinalLength.java deleted file mode 100644 index 6575e85..0000000 --- a/公开课/class114/Code06_AbsToArrayFinalLength.java +++ /dev/null @@ -1,130 +0,0 @@ -package class114; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; - -// 来自国外题目论坛 -// 给定一个非负数组arr -// 任何两个数差值的绝对值,如果arr中没有,都要加入到arr里 -// 然后新的arr继续,任何两个数差值的绝对值,如果arr中没有,都要加入到arr里 -// 一直到arr大小固定 -// 请问最终arr长度是多少 -// 1 <= arr的长度 <= 10^5 -// 0 <= arr的数值 <= 10^5 -public class Code06_AbsToArrayFinalLength { - - // 暴力方法 - // 为了验证 - public static int finalLen1(int[] arr) { - ArrayList list = new ArrayList<>(); - HashSet set = new HashSet<>(); - for (int num : arr) { - list.add(num); - set.add(num); - } - while (!finish(list, set)) - ; - return list.size(); - } - - public static boolean finish(ArrayList list, HashSet set) { - int len = list.size(); - for (int i = 0; i < len; i++) { - for (int j = i + 1; j < len; j++) { - int abs = Math.abs(list.get(i) - list.get(j)); - if (!set.contains(abs)) { - list.add(abs); - set.add(abs); - } - } - } - return len == list.size(); - } - - // 正式方法 - // 时间复杂O(N) - public static int finalLen2(int[] arr) { - // 收集最大的数 - int max = 0; - // 随便的一个非0的数,最后遇到的非0的数 - int gcd = 0; - for (int num : arr) { - max = Math.max(max, num); - if (num != 0) { - gcd = num; - } - } - // 最大值有了,max - // 最后遇到的非0的数, gcd - if (gcd == 0) { // 如果数组中所有数都是0,数组长度不会变化的! - return arr.length; - } - // 统计每一种数出现的次数 - // 求所有数的最大公约数 - HashMap counts = new HashMap<>(); - for (int num : arr) { - if (num != 0) { - gcd = gcd(gcd, num); - } - counts.put(num, counts.getOrDefault(num, 0) + 1); - } - // 假设不考虑0、也不考虑有没有重复值 - // 经典的max / gcd,有几个数 - int ans = max / gcd; - // 考虑0,考虑数组中原本有的0,而不是重复数值减出来的0 - // 长度变成多少 - ans += counts.getOrDefault(0, 0); - boolean add = false; - for (int key : counts.keySet()) { - // 遍历每一种数的词频 - // 2 7个 + 6 - // 5 4个 + 3 - // 0 ?个 - if (key != 0) { - ans += counts.get(key) - 1; - } - // 因为重复数字的出现,会不会减出来多一个0 - if (!add && counts.get(key) > 1 && !counts.containsKey(0)) { - ans++; - add = true; - } - } - return ans; - } - - public static int gcd(int m, int n) { - return n == 0 ? m : gcd(n, m % n); - } - - // 为了测试 - public static int[] randomArray(int n, int v) { - int[] ans = new int[n]; - for (int i = 0; i < n; i++) { - ans[i] = (int) (Math.random() * v); - } - return ans; - } - - // 为了测试 - public static void main(String[] args) { - int N = 15; - int V = 50; - int testTime = 8000; - System.out.println("功能测试开始"); - for (int i = 0; i < testTime; i++) { - int n = (int) (Math.random() * N) + 1; - int[] arr = randomArray(n, V); - int ans1 = finalLen1(arr); - int ans2 = finalLen2(arr); - if (ans1 != ans2) { - for (int num : arr) { - System.out.print(num + " "); - } - System.out.println("出错了!"); - } - } - System.out.println("功能测试结束"); - } - -} diff --git a/公开课/class114/Code07_HeightAfterSubtreeRemoval.java b/公开课/class114/Code07_HeightAfterSubtreeRemoval.java deleted file mode 100644 index df0976b..0000000 --- a/公开课/class114/Code07_HeightAfterSubtreeRemoval.java +++ /dev/null @@ -1,75 +0,0 @@ -package class114; - -// 给你一棵 二叉树 的根节点 root ,树中有 n 个节点 -// 每个节点都可以被分配一个从 1 到 n 且互不相同的值 -// 另给你一个长度为 m 的数组 queries -// 你必须在树上执行 m 个 独立 的查询,其中第 i 个查询你需要执行以下操作: -// 从树中 移除 以 queries[i] 的值作为根节点的子树 -// 题目所用测试用例保证 queries[i] 不 等于根节点的值。 -// 返回一个长度为 m 的数组 answer ,其中 answer[i] 是执行第 i 个查询后树的高度。 -// 注意: -// 查询之间是独立的,所以在每个查询执行后,树会回到其 初始 状态。 -// 树的高度是从根到树中某个节点的 最长简单路径中的边数 。 -// 测试链接 : https://leetcode.cn/problems/height-of-binary-tree-after-subtree-removal-queries/ -public class Code07_HeightAfterSubtreeRemoval { - - // 提交时不用提交这个类 - public static class TreeNode { - public int val; - public TreeNode left; - public TreeNode right; - } - - // 提交如下方法 - public static final int MAXN = 100010; - public static int[] dfn = new int[MAXN]; - public static int[] deep = new int[MAXN]; - public static int[] size = new int[MAXN]; - public static int[] maxl = new int[MAXN]; - public static int[] maxr = new int[MAXN]; - public static int n; - - public static int[] treeQueries(TreeNode root, int[] queries) { - n = 0; - // 每个val,编号 - // 每个val,深度 - // 每个val的子树,大小 - dfs(root, 0); - for (int i = 1; i <= n; i++) { - maxl[i] = Math.max(maxl[i - 1], deep[i]); - } - maxr[n + 1] = 0; - for (int i = n; i >= 1; i--) { - maxr[i] = Math.max(maxr[i + 1], deep[i]); - } - int m = queries.length; - int[] ans = new int[m]; - for (int i = 0; i < m; i++) { - // queries[i] -> a - // a -> 编号x - // a -> 子树大小 - // x ... 子树大小这么多范围 删掉 - int leftMax = maxl[dfn[queries[i]] - 1]; - int rightMax = maxr[dfn[queries[i]] + size[dfn[queries[i]]]]; - ans[i] = Math.max(leftMax, rightMax); - } - return ans; - } - - // n = 0 1 2 3 4 5 6 7 - public static void dfs(TreeNode head, int h) { - int i = ++n; - dfn[head.val] = i; - deep[i] = h; - size[i] = 1; - if (head.left != null) { - dfs(head.left, h + 1); - size[i] += size[dfn[head.left.val]]; - } - if (head.right != null) { - dfs(head.right, h + 1); - size[i] += size[dfn[head.right.val]]; - } - } - -} diff --git a/公开课/class114/Code08_AsFarFromLandAsPossible.java b/公开课/class114/Code08_AsFarFromLandAsPossible.java deleted file mode 100644 index b5aae73..0000000 --- a/公开课/class114/Code08_AsFarFromLandAsPossible.java +++ /dev/null @@ -1,84 +0,0 @@ -package class114; - -// 你现在手里有一份大小为 n x n 的 网格 grid -// 上面的每个 单元格 都用 0 和 1 标记好了其中 0 代表海洋,1 代表陆地。 -// 请你找出一个海洋单元格,这个海洋单元格到离它最近的陆地单元格的距离是最大的 -// 并返回该距离。如果网格上只有陆地或者海洋,请返回 -1。 -// 我们这里说的距离是「曼哈顿距离」( Manhattan Distance): -// (x0, y0) 和 (x1, y1) 这两个单元格之间的距离是 |x0 - x1| + |y0 - y1| 。 -// 测试链接 : https://leetcode.cn/problems/as-far-from-land-as-possible/ -public class Code08_AsFarFromLandAsPossible { - - // 队列接受一个东西,比如(i,j),就加到r位置 - // queue[r][0] = i - // queue[r++][1] = j - // 队列弹出一个东西,就把l位置的东西弹出 - public static int[][] queue = new int[10000][2]; - public static int l; - public static int r; - // 一个东西进入了队列,比如(i,j)进入了,visited[i][j] = true - // 如果(i,j)没进入过,visited[i][j] = false - public static boolean[][] visited = new boolean[100][100]; - // find表示发现了多少海洋 - public static int find; - - public static int maxDistance(int[][] grid) { - // 清空变量 - // 只要l = 0,r = 0,队列就算被清空了 - l = 0; - r = 0; - find = 0; - int n = grid.length; - int m = grid[0].length; - // 清空visited - for (int i = 0; i < n; i++) { - for (int j = 0; j < m; j++) { - visited[i][j] = false; - } - } - // 大体思路 : - // 1) 先把所有的陆地加入队列,并且统计一共有多少海洋 - int seas = 0; - for (int i = 0; i < n; i++) { - for (int j = 0; j < m; j++) { - if (grid[i][j] == 1) { - visited[i][j] = true; - queue[r][0] = i; - queue[r++][1] = j; - } else { - seas++; - } - } - } - // 2) 从陆地开始广播出去(bfs),每一块陆地的上、下、左、右所能找到的海洋都是第一层海洋 - // 3) 第一层海洋继续bfs,每一块海洋的上、下、左、右所能找到的海洋都是第二层海洋 - // 4) 第二层海洋继续bfs,每一块海洋的上、下、左、右所能找到的海洋都是第三层海洋 - // ... - // 也就是说,以陆地做起点,每一层bfs都只找海洋! - // 看看最深能找到多少层海洋 - int distance = 0; // 这个变量就是最深的海洋层数 - while (l < r && find < seas) { // find < seas说明所有的海洋块没有找全,继续找! - int size = r - l; - for (int i = 0; i < size && find < seas; i++, l++) { - int row = queue[l][0]; - int col = queue[l][1]; - add(row - 1, col, n, m, grid); - add(row + 1, col, n, m, grid); - add(row, col - 1, n, m, grid); - add(row, col + 1, n, m, grid); - } - distance++; - } - return find == 0 ? -1 : distance; - } - - public static void add(int i, int j, int n, int m, int[][] grid) { - if (i >= 0 && i < n && j >= 0 && j < m && grid[i][j] == 0 && !visited[i][j]) { - find++; - visited[i][j] = true; - queue[r][0] = i; - queue[r++][1] = j; - } - } - -} diff --git a/公开课/class114/Code09_OrderlyQueue.java b/公开课/class114/Code09_OrderlyQueue.java deleted file mode 100644 index 48c1522..0000000 --- a/公开课/class114/Code09_OrderlyQueue.java +++ /dev/null @@ -1,181 +0,0 @@ -package class114; - -import java.util.Arrays; - -// 给定一个字符串 s 和一个整数 k 。你可以从 s 的前 k 个字母中选择一个 -// 并把它加到字符串的末尾 -// 返回 在应用上述步骤的任意数量的移动后,字典上最小的字符串 -// 测试链接 : https://leetcode.cn/problems/orderly-queue/ -public class Code09_OrderlyQueue { - - public static String orderlyQueue(String s, int k) { - if (k > 1) { - // 时间复杂度O(N*logN) - // 证明 : - // 如果k == 2 - // 总可以做到 : 1小 2小 ... - // 总可以做到 : 3小 .... 1小 2小 ... - // 总可以做到 : 3小 1小 2小 ... - // 总可以做到 : 4小 .... 1小 2小 3小 ... - // 总可以做到 : 4小 1小 2小 3小 ..... - // 总可以做到 : 5小 ..... 1小 2小 3小 4小 ... - // ... - // 所以总可以做到有序 - // k > 2就更能做到了,所以k > 1直接排序返回 - char[] str = s.toCharArray(); - Arrays.sort(str); - return String.valueOf(str); - } else { - // 时间复杂度O(N) - // k == 1时 - // 把字符串看做一个环,就是看看从哪切开字典序最小 - // 通过s = s + s的方式,长度2n,可以得到所有环 - // 然后用DC3算法看看前n个位置,谁的字典序最小即可 - // 虽然从通过百分比来看并不优异 - // 但那是因为leetcode准备的数据量太小了,字符串才1000长度所以显不出优势 - // 如果字符串很长优势就明显了 - // 因为时间复杂度O(N)一定是最优解 - String s2 = s + s; - int n = s2.length(); - int[] arr = new int[n]; - for (int i = 0; i < n; i++) { - arr[i] = s2.charAt(i) - 'a' + 1; - } - DC3 dc3 = new DC3(arr, 26); - n >>= 1; - int minRankIndex = 0; - for (int i = 1; i < n; i++) { - if (dc3.rank[i] < dc3.rank[minRankIndex]) { - minRankIndex = i; - } - } - return s.substring(minRankIndex) + s.substring(0, minRankIndex); - } - } - - // 如果字符串长度N, - // DC3算法搞定字符串所有后缀串字典序排名的时间复杂度O(N) - // 体系学习班有讲,有兴趣的同学可以看看 - public static class DC3 { - - public int[] sa; - - public int[] rank; - - public DC3(int[] nums, int max) { - sa = sa(nums, max); - rank = rank(); - } - - private int[] sa(int[] nums, int max) { - int n = nums.length; - int[] arr = new int[n + 3]; - for (int i = 0; i < n; i++) { - arr[i] = nums[i]; - } - return skew(arr, n, max); - } - - private int[] skew(int[] nums, int n, int K) { - int n0 = (n + 2) / 3, n1 = (n + 1) / 3, n2 = n / 3, n02 = n0 + n2; - int[] s12 = new int[n02 + 3], sa12 = new int[n02 + 3]; - for (int i = 0, j = 0; i < n + (n0 - n1); ++i) { - if (0 != i % 3) { - s12[j++] = i; - } - } - radixPass(nums, s12, sa12, 2, n02, K); - radixPass(nums, sa12, s12, 1, n02, K); - radixPass(nums, s12, sa12, 0, n02, K); - int name = 0, c0 = -1, c1 = -1, c2 = -1; - for (int i = 0; i < n02; ++i) { - if (c0 != nums[sa12[i]] || c1 != nums[sa12[i] + 1] || c2 != nums[sa12[i] + 2]) { - name++; - c0 = nums[sa12[i]]; - c1 = nums[sa12[i] + 1]; - c2 = nums[sa12[i] + 2]; - } - if (1 == sa12[i] % 3) { - s12[sa12[i] / 3] = name; - } else { - s12[sa12[i] / 3 + n0] = name; - } - } - if (name < n02) { - sa12 = skew(s12, n02, name); - for (int i = 0; i < n02; i++) { - s12[sa12[i]] = i + 1; - } - } else { - for (int i = 0; i < n02; i++) { - sa12[s12[i] - 1] = i; - } - } - int[] s0 = new int[n0], sa0 = new int[n0]; - for (int i = 0, j = 0; i < n02; i++) { - if (sa12[i] < n0) { - s0[j++] = 3 * sa12[i]; - } - } - radixPass(nums, s0, sa0, 0, n0, K); - int[] sa = new int[n]; - for (int p = 0, t = n0 - n1, k = 0; k < n; k++) { - int i = sa12[t] < n0 ? sa12[t] * 3 + 1 : (sa12[t] - n0) * 3 + 2; - int j = sa0[p]; - if (sa12[t] < n0 ? leq(nums[i], s12[sa12[t] + n0], nums[j], s12[j / 3]) - : leq(nums[i], nums[i + 1], s12[sa12[t] - n0 + 1], nums[j], nums[j + 1], s12[j / 3 + n0])) { - sa[k] = i; - t++; - if (t == n02) { - for (k++; p < n0; p++, k++) { - sa[k] = sa0[p]; - } - } - } else { - sa[k] = j; - p++; - if (p == n0) { - for (k++; t < n02; t++, k++) { - sa[k] = sa12[t] < n0 ? sa12[t] * 3 + 1 : (sa12[t] - n0) * 3 + 2; - } - } - } - } - return sa; - } - - private void radixPass(int[] nums, int[] input, int[] output, int offset, int n, int k) { - int[] cnt = new int[k + 1]; - for (int i = 0; i < n; ++i) { - cnt[nums[input[i] + offset]]++; - } - for (int i = 0, sum = 0; i < cnt.length; ++i) { - int t = cnt[i]; - cnt[i] = sum; - sum += t; - } - for (int i = 0; i < n; ++i) { - output[cnt[nums[input[i] + offset]]++] = input[i]; - } - } - - private boolean leq(int a1, int a2, int b1, int b2) { - return a1 < b1 || (a1 == b1 && a2 <= b2); - } - - private boolean leq(int a1, int a2, int a3, int b1, int b2, int b3) { - return a1 < b1 || (a1 == b1 && leq(a2, a3, b2, b3)); - } - - private int[] rank() { - int n = sa.length; - int[] ans = new int[n]; - for (int i = 0; i < n; i++) { - ans[sa[i]] = i; - } - return ans; - } - - } - -} diff --git a/公开课/class115/Code01_StampingTheGrid.java b/公开课/class115/Code01_StampingTheGrid.java deleted file mode 100644 index c1f8c9d..0000000 --- a/公开课/class115/Code01_StampingTheGrid.java +++ /dev/null @@ -1,69 +0,0 @@ -package class115; - -// 给你一个 m x n 的二进制矩阵 grid -// 每个格子要么为 0 (空)要么为 1 (被占据) -// 给你邮票的尺寸为 stampHeight x stampWidth -// 我们想将邮票贴进二进制矩阵中,且满足以下 限制 和 要求 : -// 覆盖所有空格子,不覆盖任何被占据的格子 -// 可以放入任意数目的邮票,邮票可以相互有重叠部分 -// 邮票不允许旋转,邮票必须完全在矩阵内 -// 如果在满足上述要求的前提下,可以放入邮票,请返回 true ,否则返回 false -// 测试链接 : https://leetcode.cn/problems/stamping-the-grid/ -public class Code01_StampingTheGrid { - - public static boolean possibleToStamp(int[][] grid, int h, int w) { - int n = grid.length; - int m = grid[0].length; - // 左上角累加和数组 - // 查询原始矩阵中的某块儿累加和,快! - int[][] sum = new int[n + 1][m + 1]; - for (int i = 0; i < n; i++) { - for (int j = 0; j < m; j++) { - sum[i + 1][j + 1] = grid[i][j]; - } - } - build(sum); - // 差分矩阵 - // 当贴邮票的时候,不再原始矩阵里贴 - // 在差分里贴 - int[][] diff = new int[n + 2][m + 2]; - for (int a = 1, c = a + h - 1; c <= n; a++, c++) { - for (int b = 1, d = b + w - 1; d <= m; b++, d++) { - // (a,b) (c,d) - if (empty(sum, a, b, c, d)) { - set(diff, a, b, c, d); - } - } - } - build(diff); - // 检查所有的格子! - for (int i = 0; i < n; i++) { - for (int j = 0; j < m; j++) { - if (grid[i][j] == 0 && diff[i + 1][j + 1] == 0) { - return false; - } - } - } - return true; - } - - public static void build(int[][] m) { - for (int i = 1; i < m.length; i++) { - for (int j = 1; j < m[0].length; j++) { - m[i][j] += m[i - 1][j] + m[i][j - 1] - m[i - 1][j - 1]; - } - } - } - - public static boolean empty(int[][] sum, int a, int b, int c, int d) { - return sum[c][d] - sum[c][b - 1] - sum[a - 1][d] + sum[a - 1][b - 1] == 0; - } - - public static void set(int[][] diff, int a, int b, int c, int d) { - diff[a][b] += 1; - diff[c + 1][d + 1] += 1; - diff[c + 1][b] -= 1; - diff[a][d + 1] -= 1; - } - -} diff --git a/公开课/class115/Code02_SumOfSubSequenceWidths.java b/公开课/class115/Code02_SumOfSubSequenceWidths.java deleted file mode 100644 index a046e73..0000000 --- a/公开课/class115/Code02_SumOfSubSequenceWidths.java +++ /dev/null @@ -1,32 +0,0 @@ -package class115; - -import java.util.Arrays; - -// 一个序列的 宽度 定义为该序列中最大元素和最小元素的差值。 -// 给你一个整数数组 nums ,返回 nums 的所有非空 子序列 的 宽度之和 -// 由于答案可能非常大,请返回对 109 + 7 取余 后的结果。 -// 子序列 定义为从一个数组里删除一些(或者不删除)元素, -// 但不改变剩下元素的顺序得到的数组 -// 例如,[3,6,2,7] 就是数组 [0,3,1,6,2,2,7] 的一个子序列。 -// 测试链接 : https://leetcode.cn/problems/sum-of-subsequence-widths/ -public class Code02_SumOfSubSequenceWidths { - - public static int sumSubseqWidths(int[] nums) { - Arrays.sort(nums); - int mod = 1000000007; - long ans = 0; - long A = 0; - long B = 0; - long C = 1; - long D = C; - for (int i = 1; i < nums.length; i++) { - A = (D * nums[i]) % mod; - B = (B * 2 + nums[i - 1]) % mod; - ans = (ans + A - B + mod) % mod; - C = (C * 2) % mod; - D = (D + C) % mod; - } - return (int) (ans); - } - -} diff --git a/公开课/class115/Code03_SumOfDistancesInTree.java b/公开课/class115/Code03_SumOfDistancesInTree.java deleted file mode 100644 index 3a60b1f..0000000 --- a/公开课/class115/Code03_SumOfDistancesInTree.java +++ /dev/null @@ -1,54 +0,0 @@ -package class115; - -import java.util.ArrayList; - -// 给定一个无向、连通的树 -// 树中有 n 个标记为 0...n-1 的节点以及 n-1 条边 。 -// 给定整数 n 和数组 edges , -// edges[i] = [ai, bi]表示树中的节点 ai 和 bi 之间有一条边。 -// 返回长度为 n 的数组 answer ,其中 answer[i] : -// 树中第 i 个节点与所有其他节点之间的距离之和。 -// 测试链接 : https://leetcode.cn/problems/sum-of-distances-in-tree/ -public class Code03_SumOfDistancesInTree { - - public int N = 30001; - public int[] size = new int[N]; - public int[] distance = new int[N]; - - public int[] sumOfDistancesInTree(int n, int[][] edges) { - ArrayList> graph = new ArrayList<>(); - for (int i = 0; i < n; i++) { - graph.add(new ArrayList<>()); - } - for (int[] edge : edges) { - graph.get(edge[0]).add(edge[1]); - graph.get(edge[1]).add(edge[0]); - } - collect(0, -1, graph); - int[] ans = new int[n]; - setAns(0, -1, 0, graph, ans); - return ans; - } - - public void collect(int cur, int father, ArrayList> graph) { - size[cur] = 1; - distance[cur] = 0; - for (int next : graph.get(cur)) { - if (next != father) { - collect(next, cur, graph); - distance[cur] += distance[next] + size[next]; - size[cur] += size[next]; - } - } - } - - public void setAns(int cur, int father, int upDistance, ArrayList> graph, int[] ans) { - ans[cur] = distance[cur] + upDistance; - for (int next : graph.get(cur)) { - if (next != father) { - setAns(next, cur, ans[cur] - distance[next] + size[0] - (size[next] << 1), graph, ans); - } - } - } - -} diff --git a/公开课/class116/Code01_MinimumNumberOfDaysToEatNOranges.java b/公开课/class116/Code01_MinimumNumberOfDaysToEatNOranges.java deleted file mode 100644 index 01e27a1..0000000 --- a/公开课/class116/Code01_MinimumNumberOfDaysToEatNOranges.java +++ /dev/null @@ -1,81 +0,0 @@ -package class116; - -import java.util.HashMap; - -// 来自腾讯面试 -// 厨房里总共有 n 个橘子,你决定每一天选择如下方式之一吃这些橘子: -// 吃掉一个橘子。 -// 如果剩余橘子数 n 能被 2 整除,那么你可以吃掉 n/2 个橘子。 -// 如果剩余橘子数 n 能被 3 整除,那么你可以吃掉 2*(n/3) 个橘子。 -// 每天你只能从以上 3 种方案中选择一种方案。 -// 请你返回吃掉所有 n 个橘子的最少天数。 -// 测试链接 : https://leetcode.cn/problems/minimum-number-of-days-to-eat-n-oranges/ -public class Code01_MinimumNumberOfDaysToEatNOranges { - - // 斐波那契数列,求第n项 - // 1 1 2 3 5 8 13 .... - - public static HashMap fdp = new HashMap<>(); - - public static int f(int n) { - if (fdp.containsKey(n)) { - return fdp.get(n); - } - int ans = 0; - if (n == 1) { - ans = 1; - } else if (n == 2) { - ans = 2; - } else { - ans = f(n - 1) + f(n - 2); - } - fdp.put(n, ans); - return ans; - } - - // 所有的答案都填在这个表里 - // 这个表对所有的过程共用 - // 有橘子数量key,至少几天吃完这个结果 - // key -> value - public static HashMap dp = new HashMap<>(); - - public static int minDays(int n) { - // 0 0天 - // 1 1天 - if (n <= 1) { - return n; - } - // n >= 2 - if (dp.containsKey(n)) { - return dp.get(n); - } - // 1) 吃掉一个橘子 - // 2) 如果n能被2整除,吃掉一半的橘子,剩下一半 - // 3) 如果n能被3正数,吃掉三分之二的橘子,剩下三分之一 - // 因为方法2)和3),是按比例吃橘子,所以必然会非常快 - // 所以,决策如下: - // 可能性1:为了使用2)方法,先把橘子吃成2的整数倍,然后直接干掉一半,剩下的n/2调用递归 - // 即,n % 2 + 1 + minDays(n/2) - // 可能性2:为了使用3)方法,先把橘子吃成3的整数倍,然后直接干掉三分之二,剩下的n/3调用递归 - // 即,n % 3 + 1 + minDays(n/3) - // 至于方法1),完全是为了这两种可能性服务的,因为能按比例吃,肯定比一个一个吃快(显而易见的贪心) - // 1) 吃成,能被2整除,减一半 - // n = 16 - // 1天 吃掉8个橘子 + minDays(8) - // n = 17 - // 1天 吃掉1个橘子,一天 吃掉8个橘子 + minDays(8) - int p1 = n % 2 + 1 + minDays(n / 2); - // 2) 吃成,能被3整除,减2/3, 1/3 - // n = 9 - // 0天,3的整数倍,1天,6个(2/3) + minDays(n / 3) - // n = 10 - // 1天,3的整数倍,1天,6个(2/3) + minDays(n / 3) - // n = 11 - // 2天,3的整数倍,1天,6个(2/3) + minDays(n / 3) - int p2 = n % 3 + 1 + minDays(n / 3); - int ans = Math.min(p1, p2); - dp.put(n, ans); - return ans; - } - -} diff --git a/公开课/class116/Code02_HowManyObtuseAngles.java b/公开课/class116/Code02_HowManyObtuseAngles.java deleted file mode 100644 index b8393b8..0000000 --- a/公开课/class116/Code02_HowManyObtuseAngles.java +++ /dev/null @@ -1,44 +0,0 @@ -package class116; - -import java.util.Arrays; - -// 来自hulu -// 有一个以原点为圆心,半径为1的圆 -// 在这个圆的圆周上,有一些点 -// 因为所有的点都在圆周上,所以每个点可以有很简练的表达 -// 比如:用0来表示一个圆周上的点,这个点就在(1,0)位置 -// 比如:用6000来表示一个点,这个点是(1,0)点沿着圆周逆时针转60.00度之后所在的位置 -// 比如:用18034来表示一个点,这个点是(1,0)点沿着圆周逆时针转180.34度之后所在的位置 -// 这样一来,所有的点都可以用[0, 36000)范围上的数字来表示 -// 那么任意三个点都可以组成一个三角形,返回能组成钝角三角形的数量 -public class Code02_HowManyObtuseAngles { - - public static long obtuseAngles(int[] arr) { - // 30.15 3015 - // 30.7 3070 - // n长度的排序,O(N * logN) - // O(N) - int n = arr.length; - int m = n << 1; - int[] enlarge = new int[m]; - Arrays.sort(arr); - for (int i = 0; i < n; i++) { - enlarge[i] = arr[i]; - enlarge[i + n] = arr[i] + 36000; - } - long ans = 0; - // 这里不用二分查找(太慢),能做一个不回退的优化 - for (int L = 0, R = 0; L < n; L++) { - while (R < m && enlarge[R] - enlarge[L] < 18000) { - R++; - } - ans += num(R - L - 1); - } - return ans; - } - - public static long num(long nodes) { - return nodes < 2 ? 0 : ((nodes - 1) * nodes) >> 1; - } - -} diff --git a/公开课/class116/Code03_CherryPickup.java b/公开课/class116/Code03_CherryPickup.java deleted file mode 100644 index cb00d66..0000000 --- a/公开课/class116/Code03_CherryPickup.java +++ /dev/null @@ -1,84 +0,0 @@ -package class116; - -// 来自字节跳动 -// 牛客的测试链接: -// https://www.nowcoder.com/questionTerminal/8ecfe02124674e908b2aae65aad4efdf -// 请同学们务必参考如下代码中关于输入、输出的处理 -// 这是输入输出处理效率很高的写法 -// 把如下的全部代码拷贝进java编辑器 -// 把文件大类名字改成Main,可以直接通过 -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.io.StreamTokenizer; - -public class Code03_CherryPickup { - - public static void main(String[] args) throws IOException { - BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); - StreamTokenizer in = new StreamTokenizer(br); - PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out)); - while (in.nextToken() != StreamTokenizer.TT_EOF) { - int N = (int) in.nval; - in.nextToken(); - int M = (int) in.nval; - int[][] matrix = new int[N][M]; - for (int i = 0; i < N; i++) { - for (int j = 0; j < M; j++) { - in.nextToken(); - matrix[i][j] = (int) in.nval; - } - } - out.println(cherryPickup(matrix)); - out.flush(); - } - } - - // 如下方法,在leetcode上提交也能通过 - // 测试链接 : https://leetcode.cn/problems/cherry-pickup/ - public static int cherryPickup(int[][] grid) { - int N = grid.length; - int M = grid[0].length; - int[][][] dp = new int[N][M][N]; - for (int i = 0; i < N; i++) { - for (int j = 0; j < M; j++) { - for (int k = 0; k < N; k++) { - dp[i][j][k] = Integer.MIN_VALUE; - } - } - } - int ans = process(grid, 0, 0, 0, dp); - return ans < 0 ? 0 : ans; - } - - public static int process(int[][] grid, int x1, int y1, int x2, int[][][] dp) { - if (x1 == grid.length || y1 == grid[0].length || x2 == grid.length || x1 + y1 - x2 == grid[0].length) { - return Integer.MIN_VALUE; - } - if (dp[x1][y1][x2] != Integer.MIN_VALUE) { - return dp[x1][y1][x2]; - } - if (x1 == grid.length - 1 && y1 == grid[0].length - 1) { - dp[x1][y1][x2] = grid[x1][y1]; - return dp[x1][y1][x2]; - } - int next = Integer.MIN_VALUE; - next = Math.max(next, process(grid, x1 + 1, y1, x2 + 1, dp)); - next = Math.max(next, process(grid, x1 + 1, y1, x2, dp)); - next = Math.max(next, process(grid, x1, y1 + 1, x2, dp)); - next = Math.max(next, process(grid, x1, y1 + 1, x2 + 1, dp)); - if (grid[x1][y1] == -1 || grid[x2][x1 + y1 - x2] == -1 || next == -1) { - dp[x1][y1][x2] = -1; - return dp[x1][y1][x2]; - } - if (x1 == x2) { - dp[x1][y1][x2] = grid[x1][y1] + next; - return dp[x1][y1][x2]; - } - dp[x1][y1][x2] = grid[x1][y1] + grid[x2][x1 + y1 - x2] + next; - return dp[x1][y1][x2]; - } - -} \ No newline at end of file diff --git a/公开课/class117/Code01_BoatsToSavePeople.java b/公开课/class117/Code01_BoatsToSavePeople.java deleted file mode 100644 index e125c68..0000000 --- a/公开课/class117/Code01_BoatsToSavePeople.java +++ /dev/null @@ -1,34 +0,0 @@ -package class117; - -import java.util.Arrays; - -// 测试链接 : https://leetcode.com/problems/boats-to-save-people/ -public class Code01_BoatsToSavePeople { - - // 数组里一定不会有大于limit的数值 - public static int numRescueBoats(int[] people, int limit) { - Arrays.sort(people); - // 最终的船数 - int ans = 0; - // 左指针 - int l = 0; - // 右指针 - int r = people.length - 1; - int sum = 0; - while (l <= r) { - // ? ? - // 17 39 - // l r - sum = l == r ? people[l] : people[l] + people[r]; - if (sum > limit) { - r--; - } else { - l++; - r--; - } - ans++; - } - return ans; - } - -} diff --git a/公开课/class117/Code02_MaximumProductSubarray.java b/公开课/class117/Code02_MaximumProductSubarray.java deleted file mode 100644 index 8429d67..0000000 --- a/公开课/class117/Code02_MaximumProductSubarray.java +++ /dev/null @@ -1,28 +0,0 @@ -package class117; - -// 测试链接:https://leetcode.cn/problems/maximum-product-subarray/ -public class Code02_MaximumProductSubarray { - - public static int maxProduct(int[] nums) { - // 0结尾时,最好答案; - // 1结尾时,最好答案;... max -> ans - int ans = nums[0]; - int min = nums[0]; - int max = nums[0]; - for (int i = 1; i < nums.length; i++) { - // i 结尾 - // 1) nums[i] - // 2) nums[i] * 之前的最大乘积 -> max - // 3) nums[i] * 之前的最小乘积 -> min - // i 结尾 最大乘积 : 1) 2) 3) 取最大! - // i 结尾 最小乘积 : 1) 2) 3) 取最小! - int curmin = Math.min(nums[i], Math.min(min * nums[i], max * nums[i])); - int curmax = Math.max(nums[i], Math.max(min * nums[i], max * nums[i])); - min = curmin; - max = curmax; - ans = Math.max(ans, max); - } - return ans; - } - -} diff --git a/公开课/class117/Code03_RotateImage.java b/公开课/class117/Code03_RotateImage.java deleted file mode 100644 index f7e96e4..0000000 --- a/公开课/class117/Code03_RotateImage.java +++ /dev/null @@ -1,30 +0,0 @@ -package class117; - -// 测试链接 : https://leetcode.cn/problems/rotate-image/ -public class Code03_RotateImage { - - // 保证传入的参数是正方形矩阵 - public static void rotate(int[][] matrix) { - // 左上角点,(a,b) - int a = 0; - int b = 0; - // 右下角点,(c,d) - int c = matrix.length - 1; - int d = matrix[0].length - 1; - while (a < c) { - rotateEdge(matrix, a++, b++, c--, d--); - } - } - - public static void rotateEdge(int[][] m, int a, int b, int c, int d) { - int tmp = 0; - for (int i = 0; i < d - b; i++) { - tmp = m[a][b + i]; - m[a][b + i] = m[c - i][b]; - m[c - i][b] = m[c][d - i]; - m[c][d - i] = m[a + i][d]; - m[a + i][d] = tmp; - } - } - -} diff --git a/公开课/class117/Code04_SmallestRangeCoveringElementsfromKLists.java b/公开课/class117/Code04_SmallestRangeCoveringElementsfromKLists.java deleted file mode 100644 index cecb3af..0000000 --- a/公开课/class117/Code04_SmallestRangeCoveringElementsfromKLists.java +++ /dev/null @@ -1,75 +0,0 @@ -package class117; - -import java.util.Comparator; -import java.util.List; -import java.util.TreeSet; - -// 本题测试链接 : https://leetcode.com/problems/smallest-range-covering-elements-from-k-lists/ -public class Code04_SmallestRangeCoveringElementsfromKLists { - - public static void main(String[] args) { - TreeSet set = new TreeSet<>(); - set.add(700); - set.add(72); - set.add(70000); - set.add(7000); - set.add(7); - set.add(70); - set.add(17); - // log N - System.out.println(set.first()); - System.out.println(set.last()); - System.out.println(set.contains(170)); - System.out.println(set.floor(23)); - System.out.println(set.ceiling(23)); - } - - public static class Node { - public int value; - public int arrid; - public int index; - - public Node(int v, int ai, int i) { - value = v; - arrid = ai; - index = i; - } - } - - public static class NodeComparator implements Comparator { - - @Override - public int compare(Node o1, Node o2) { - return o1.value != o2.value ? o1.value - o2.value : o1.arrid - o2.arrid; - } - - } - - public static int[] smallestRange(List> nums) { - int N = nums.size(); - TreeSet orderSet = new TreeSet<>(new NodeComparator()); - for (int i = 0; i < N; i++) { - orderSet.add(new Node(nums.get(i).get(0), i, 0)); - } - boolean set = false; - int a = 0; - int b = 0; - while (orderSet.size() == N) { - Node min = orderSet.first(); - Node max = orderSet.last(); - if (!set || (max.value - min.value < b - a)) { - set = true; - a = min.value; - b = max.value; - } - min = orderSet.pollFirst(); - int arrid = min.arrid; - int index = min.index + 1; - if (index != nums.get(arrid).size()) { - orderSet.add(new Node(nums.get(arrid).get(index), arrid, index)); - } - } - return new int[] { a, b }; - } - -} diff --git a/公开课/class117/Code05_CandyProblem.java b/公开课/class117/Code05_CandyProblem.java deleted file mode 100644 index 9993c8c..0000000 --- a/公开课/class117/Code05_CandyProblem.java +++ /dev/null @@ -1,74 +0,0 @@ -package class117; - -// 测试链接 : https://leetcode.com/problems/candy/ -public class Code05_CandyProblem { - - public static int candy(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - int N = arr.length; - int[] left = new int[N]; - for (int i = 1; i < N; i++) { - if (arr[i - 1] < arr[i]) { - left[i] = left[i - 1] + 1; - } - } - int[] right = new int[N]; - for (int i = N - 2; i >= 0; i--) { - if (arr[i] > arr[i + 1]) { - right[i] = right[i + 1] + 1; - } - } - int ans = 0; - for (int i = 0; i < N; i++) { - ans += Math.max(left[i], right[i]); - } - return ans + N; - } - - public static int circleCandy(int[] arr) { - if (arr == null || arr.length == 0) { - return 0; - } - if (arr.length == 1) { - return 1; - } - int n = arr.length; - int minIndex = 0; - for (int i = 0; i < n; i++) { - if (arr[i] <= arr[lastIndex(i, n)] && arr[i] <= arr[nextIndex(i, n)]) { - minIndex = i; - break; - } - } - int[] nums = new int[n + 1]; - for (int i = 0; i <= n; i++, minIndex = nextIndex(minIndex, n)) { - nums[i] = arr[minIndex]; - } - int[] left = new int[n + 1]; - left[0] = 1; - for (int i = 1; i <= n; i++) { - left[i] = nums[i] > nums[i - 1] ? (left[i - 1] + 1) : 1; - } - int[] right = new int[n + 1]; - right[n] = 1; - for (int i = n - 1; i >= 0; i--) { - right[i] = nums[i] > nums[i + 1] ? (right[i + 1] + 1) : 1; - } - int ans = 0; - for (int i = 0; i < n; i++) { - ans += Math.max(left[i], right[i]); - } - return ans; - } - - public static int nextIndex(int i, int n) { - return i == n - 1 ? 0 : (i + 1); - } - - public static int lastIndex(int i, int n) { - return i == 0 ? (n - 1) : (i - 1); - } - -} diff --git a/公开课/class117/Code06_MinWindowLength.java b/公开课/class117/Code06_MinWindowLength.java deleted file mode 100644 index c17bb3f..0000000 --- a/公开课/class117/Code06_MinWindowLength.java +++ /dev/null @@ -1,44 +0,0 @@ -package class117; - -// 测试链接 : https://leetcode.com/problems/minimum-window-substring/ -public class Code06_MinWindowLength { - - public static String minWindow(String s, String t) { - if (s.length() < t.length()) { - return ""; - } - char[] str = s.toCharArray(); - char[] target = t.toCharArray(); - int[] map = new int[256]; - for (char cha : target) { - map[cha]++; - } - int all = target.length; - int L = 0; - int R = 0; - int minLen = Integer.MAX_VALUE; - int ansl = -1; - int ansr = -1; - while (R != str.length) { - map[str[R]]--; - if (map[str[R]] >= 0) { - all--; - } - if (all == 0) { - while (map[str[L]] < 0) { - map[str[L++]]++; - } - if (minLen > R - L + 1) { - minLen = R - L + 1; - ansl = L; - ansr = R; - } - all++; - map[str[L++]]++; - } - R++; - } - return minLen == Integer.MAX_VALUE ? "" : s.substring(ansl, ansr + 1); - } - -} diff --git a/公开课/class117/Code07_RangesHasDominateNumber.java b/公开课/class117/Code07_RangesHasDominateNumber.java deleted file mode 100644 index 5c4eebf..0000000 --- a/公开课/class117/Code07_RangesHasDominateNumber.java +++ /dev/null @@ -1,107 +0,0 @@ -package class117; - -import java.util.HashMap; - -// 来自小红书 -// 小A认为如果在数组中有一个数出现了至少k次 -// 且这个数是该数组的众数,即出现次数最多的数之一 -// 那么这个数组被该数所支配 -// 显然当k比较大的时候,有些数组不被任何数所支配 -// 现在小A拥有一个长度为n的数组,她想知道内部有多少个区间是被某个数支配的 -// 2 <= k <= n <= 100000 -// 1 <= 数组的值 <= n -public class Code07_RangesHasDominateNumber { - - // 暴力方法 - // 为了验证 - // 时间复杂度O(N^3) - public static int dominates1(int[] arr, int k) { - int n = arr.length; - int ans = 0; - for (int l = 0; l < n; l++) { - for (int r = l; r < n; r++) { - if (ok(arr, l, r, k)) { - ans++; - } - } - } - return ans; - } - - public static boolean ok(int[] arr, int l, int r, int k) { - HashMap map = new HashMap(); - for (int i = l; i <= r; i++) { - map.put(arr[i], map.getOrDefault(arr[i], 0) + 1); - } - for (int times : map.values()) { - if (times >= k) { - return true; - } - } - return false; - } - - // 正式方法 - // 时间复杂度O(N) - public static int dominates2(int[] arr, int k) { - int n = arr.length; - // 总数量 - int all = n * (n + 1) / 2; - // 不被支配的区间数量 - int except = 0; - // 次数表 - // 0 : 0 - // 1 : 0 - // 2 : 0 - int[] cnt = new int[n + 1]; - // l ... r - // 窗口用这个形式[l,r) - // l...r-1 r(x) - // l == 0 r == 0 [l,r) 一个数也没有 - // l == 0 r == 1 [0..0] - for (int l = 0, r = 0; l < n; l++) { - // [r] 即将要进来的 - // cnt[arr[r]] + 1 < k - while (r < n && cnt[arr[r]] + 1 < k) { - // cnt[arr[r]]++; - // r++ - cnt[arr[r++]]++; - } - // l..l - // l..l+1 - // l..l+2 - // l..r-1 - except += r - l; - cnt[arr[l]]--; - } - return all - except; - } - - // 为了测试 - public static int[] randomArray(int n) { - int[] ans = new int[n]; - for (int i = 0; i < n; i++) { - ans[i] = (int) (Math.random() * n) + 1; - } - return ans; - } - - // 为了测试 - public static void main(String[] args) { - int N = 100; - int testTimes = 5000; - System.out.println("测试开始"); - for (int i = 0; i < testTimes; i++) { - int n = (int) (Math.random() * N) + 1; - int[] arr = randomArray(n); - int k = (int) (Math.random() * n) + 1; - int ans1 = dominates1(arr, k); - int ans2 = dominates2(arr, k); - if (ans1 != ans2) { - System.out.println("出错了!"); - } - } - System.out.println("测试结束"); - } - -} diff --git a/公开课/class118/Code01_ExpressionCompute.java b/公开课/class118/Code01_ExpressionCompute.java deleted file mode 100644 index f5e687a..0000000 --- a/公开课/class118/Code01_ExpressionCompute.java +++ /dev/null @@ -1,68 +0,0 @@ -package class118; - -import java.util.LinkedList; - -// 给定一个字符串表达式str,str表示一个公式, -// 公式里可能有整数、加减乘除符号和左右括号 -// 返回公式的计算结果 -// 难点在于括号可能嵌套很多层, -// str="48*((70-65)-43)+8*1",返回-1816 -// str="3+1*4",返回7。str="3+(1*4)",返回7。 -// 1,可以认为给定的字符串一定是正确的公式,即不需要对str做公式有效性检查 -// 2,如果是负数,就需要用括号括起来, -// 比如"4*(-3)"但如果负数作为公式的开头或括号部分的开头则可以没有括号, -// 比如"-3*4"和"(-3*4)"都是合法的 -// 3,不用考虑计算过程中会发生溢出的情况。 -// 测试链接 : https://leetcode.cn/problems/basic-calculator-iii/ -public class Code01_ExpressionCompute { - - public static int calculate(String str) { - return f(str.toCharArray(), 0)[0]; - } - - // 请从str[i...]往下算,遇到字符串终止位置或者右括号,就停止 - // 返回两个值,长度为2的数组 - // 0) 负责的这一段的结果是多少 - // 1) 负责的这一段计算到了哪个位置 - public static int[] f(char[] str, int i) { - LinkedList queue = new LinkedList(); - int cur = 0; - int[] bra = null; - // 从i出发,开始撸串 - while (i < str.length && str[i] != ')') { - if (str[i] >= '0' && str[i] <= '9') { - cur = cur * 10 + str[i++] - '0'; - } else if (str[i] != '(') { // 遇到的是运算符号 - addNum(queue, cur, str[i++]); - cur = 0; - } else { // 遇到左括号了 - bra = f(str, i + 1); - cur = bra[0]; - i = bra[1] + 1; - } - } - addNum(queue, cur, '+'); - return new int[] { getAns(queue), i }; - } - - public static void addNum(LinkedList queue, int num, char op) { - if (!queue.isEmpty() && (queue.peekLast().equals("*") || queue.peekLast().equals("/"))) { - String top = queue.pollLast(); - int pre = Integer.valueOf(queue.pollLast()); - num = top.equals("*") ? (pre * num) : (pre / num); - } - queue.addLast(String.valueOf(num)); - queue.addLast(String.valueOf(op)); - } - - public static int getAns(LinkedList queue) { - int ans = Integer.valueOf(queue.pollFirst()); - while (queue.size() > 1) { - String op = queue.pollFirst(); - int num = Integer.valueOf(queue.pollFirst()); - ans += op.equals("+") ? num : -num; - } - return ans; - } - -} diff --git a/公开课/class118/Code02_ComputeExpressionValue.java b/公开课/class118/Code02_ComputeExpressionValue.java deleted file mode 100644 index 6a2a0e9..0000000 --- a/公开课/class118/Code02_ComputeExpressionValue.java +++ /dev/null @@ -1,58 +0,0 @@ -package class118; - -// 来自美团 -// () 分值为2 -// (()) 分值为3 -// ((())) 分值为4 -// 也就是说,每包裹一层,分数就是里面的分值+1 -// ()() 分值为2 * 2 -// (())() 分值为3 * 2 -// 也就是说,每连接一段,分数就是各部分相乘,以下是一个结合起来的例子 -// (()())()(()) -> (2 * 2 + 1) * 2 * 3 -> 30 -// 给定一个括号字符串str,已知str一定是正确的括号结合,不会有违规嵌套 -// 返回分数 -public class Code02_ComputeExpressionValue { - - public static int sores(String s) { - return compute(s.toCharArray(), 0)[0]; - } - - // s[i.....]一旦遇到 ) 或者 字符串终止位置,停! - // 返回值: - // 0) 负责这一段的结果(得分)是多少? - // 1) 计算到了什么位置也返回 - public static int[] compute(char[] s, int i) { - if (s[i] == ')') { - return new int[] { 1, i }; - } - int ans = 1; - while (i < s.length && s[i] != ')') { - int[] info = compute(s, i + 1); - ans *= info[0] + 1; - i = info[1] + 1; - } - return new int[] { ans, i }; - } - - public static void main(String[] args) { - - String str1 = "(()())()(())"; - System.out.println(sores(str1)); - - // (()()) + (((()))) + ((())()) - // (()()) -> 2 * 2 + 1 -> 5 - // (((()))) -> 5 - // ((())()) -> ((2 + 1) * 2) + 1 -> 7 - // 所以下面的结果应该是175 - String str2 = "(()())(((())))((())())"; - System.out.println(sores(str2)); - - // (()()()) + (()(())) - // (()()()) -> 2 * 2 * 2 + 1 -> 9 - // (()(())) -> 2 * 3 + 1 -> 7 - // 所以下面的结果应该是63 - String str3 = "(()()())(()(()))"; - System.out.println(sores(str3)); - } - -} diff --git a/公开课/class118/Code03_RegularExpressionMatch.java b/公开课/class118/Code03_RegularExpressionMatch.java deleted file mode 100644 index 97ae0bf..0000000 --- a/公开课/class118/Code03_RegularExpressionMatch.java +++ /dev/null @@ -1,65 +0,0 @@ -package class118; - -// 给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配 -// '.' 匹配任意单个字符 -// '*' 匹配零个或多个前面的那一个元素 -// 所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串 -// 测试链接 : https://leetcode.cn/problems/regular-expression-matching/ -public class Code03_RegularExpressionMatch { - - // 暴力递归方法 - public static boolean isMatch1(String str, String exp) { - char[] s = str.toCharArray(); - char[] e = exp.toCharArray(); - return f1(s, e, 0, 0); - } - - public static boolean f1(char[] s, char[] e, int si, int ei) { - if (ei == e.length) { - return si == s.length; - } - if (si == s.length) { - return ei + 1 < e.length && e[ei + 1] == '*' && f1(s, e, si, ei + 2); - } - if (ei + 1 >= e.length || e[ei + 1] != '*') { - return (s[si] == e[ei] || e[ei] == '.') && f1(s, e, si + 1, ei + 1); - } - // e[ei + 1] == '*' - boolean ans = f1(s, e, si, ei + 2); - if (s[si] == e[ei] || e[ei] == '.') { - ans |= f1(s, e, si + 1, ei); - } - return ans; - } - - // 暴力递归改的动态规划方法 - // 有套路的!课上讲这个套路的!非常有用! - public static boolean isMatch2(String str, String exp) { - char[] s = str.toCharArray(); - char[] e = exp.toCharArray(); - int[][] dp = new int[s.length + 1][e.length + 1]; - return f2(s, e, 0, 0, dp); - } - - public static boolean f2(char[] s, char[] e, int si, int ei, int[][] dp) { - if (dp[si][ei] != 0) { - return dp[si][ei] == 1; - } - boolean ans = false; - if (ei == e.length) { - ans = si == s.length; - } else if (si == s.length) { - ans = ei + 1 < e.length && e[ei + 1] == '*' && f2(s, e, si, ei + 2, dp); - } else if (ei + 1 >= e.length || e[ei + 1] != '*') { - ans = (s[si] == e[ei] || e[ei] == '.') && f2(s, e, si + 1, ei + 1, dp); - } else { - ans = f2(s, e, si, ei + 2, dp); - if (s[si] == e[ei] || e[ei] == '.') { - ans |= f2(s, e, si + 1, ei, dp); - } - } - dp[si][ei] = ans ? 1 : -1; - return ans; - } - -}