├── LICENSE ├── README.md └── src └── com └── hncboy ├── AddBinary.java ├── AddDigits.java ├── AddStrings.java ├── AddToArrayFormOfInteger.java ├── AddTwoNumbersII.java ├── AdditiveNumber.java ├── AdvantageShuffle.java ├── AllElementsInTwoBinarySearchTrees.java ├── AllOoneDataStructure.java ├── AngleBetweenHandsOfAClock.java ├── ApplyDiscountEveryNOrders.java ├── ArrangingCoins.java ├── ArrayNesting.java ├── ArrayOfDoubledPairs.java ├── ArrayPartitionI.java ├── AsFarFromLandAsPossible.java ├── AssignCookies.java ├── AsteroidCollision.java ├── AvailableCapturesForRook.java ├── BalancedBinaryTree.java ├── Base7.java ├── BaseballGame.java ├── BattleshipsInABoard.java ├── BeautifulArrangement.java ├── BeautifulArrangementII.java ├── BestSightseeingPair.java ├── BestTimeToBuyAndSellStock.java ├── BestTimeToBuyAndSellStockII.java ├── BestTimeToBuyAndSellStockIII.java ├── BestTimeToBuyAndSellStockIV.java ├── BestTimeToBuyAndSellStockWithCooldown.java ├── BestTimeToBuyAndSellStockWithTransactionFee.java ├── BinaryNumberWithAlternatingBits.java ├── BinaryPrefixDivisibleBy5.java ├── BinarySearch.java ├── BinarySearchTreeIterator.java ├── BinarySearchTreeToGreaterSumTree.java ├── BinaryTreeInorderTraversal.java ├── BinaryTreeLevelOrderTraversal.java ├── BinaryTreeLevelOrderTraversalII.java ├── BinaryTreeMaximumPathSum.java ├── BinaryTreePostorderTraversal.java ├── BinaryTreePreorderTraversal.java ├── BinaryTreePruning.java ├── BinaryTreeRightSideView.java ├── BinaryTreeTilt.java ├── BinaryTreeZigzagLevelOrderTraversal.java ├── BinaryWatch.java ├── BuddyStrings.java ├── BulbSwitcher.java ├── BullsAndCows.java ├── CalculateMoneyInLeetcodeBank.java ├── CanPlaceFlowers.java ├── Candy.java ├── CapacityToShipPackagesWithinDDays.java ├── CatAndMouse.java ├── CellsWithOddValuesInAMatrix.java ├── CheckIfItIsAStraightLine.java ├── CheckIfWordIsValidAfterSubstitutions.java ├── CircularArrayLoop.java ├── ClimbingStairs.java ├── CloneGraph.java ├── ClosestDivisors.java ├── CoinChange.java ├── ColoringABorder.java ├── CombinationSum.java ├── CombinationSumII.java ├── CombinationSumIII.java ├── CombinationSumIv.java ├── Combinations.java ├── ComplementOfBase10Integer.java ├── CompleteBinaryTreeInserter.java ├── ComplexNumberMultiplication.java ├── ConcatenatedWords.java ├── ConsecutiveCharacters.java ├── ConstructBinaryTreeFromInorderAndPostorderTraversal.java ├── ConstructBinaryTreeFromPreorderAndInorderTraversal.java ├── ConstructStringFromBinaryTree.java ├── ConstructTheRectangle.java ├── ContainerWithMostWater.java ├── ContainsDuplicate.java ├── ContainsDuplicateII.java ├── ContainsDuplicateIii.java ├── ContiguousArray.java ├── Convert1dArrayInto2dArray.java ├── ConvertANumberToHexadecimal.java ├── ConvertBinaryNumberInALinkedListToInteger.java ├── ConvertBstToGreaterTree.java ├── ConvertIntegerToTheSumOfTwoNoZeroIntegers.java ├── ConvertSortedArrayToBinarySearchTree.java ├── ConvertSortedListToBinarySearchTree.java ├── CopyListWithRandomPointer.java ├── CorporateFlightBookings.java ├── CountAllValidPickupAndDeliveryOptions.java ├── CountAndSay.java ├── CountNodesWithTheHighestScore.java ├── CountNumberOfMaximumBitwiseOrSubsets.java ├── CountNumberOfNiceSubarrays.java ├── CountNumberOfPairsWithAbsoluteDifferenceK.java ├── CountNumbersWithUniqueDigits.java ├── CountOfMatchesInTournament.java ├── CountPrimes.java ├── CountSpecialQuadruplets.java ├── CountSquareSubmatricesWithAllOnes.java ├── CountVowelsPermutation.java ├── CountingBits.java ├── CourseSchedule.java ├── CourseScheduleII.java ├── CourseScheduleIii.java ├── CrawlerLogFolder.java ├── DailyTemperatures.java ├── DataStreamAsDisjointIntervals.java ├── DayOfTheWeek.java ├── DayOfTheYear.java ├── DecodeWays.java ├── DecodeWaysIi.java ├── DecompressRunLengthEncodedList.java ├── DecreaseElementsToMakeArrayZigzag.java ├── DecryptStringFromAlphabetToIntegerMapping.java ├── DeepestLeavesSum.java ├── DegreeOfAnArray.java ├── DeleteNodeInALinkedList.java ├── DeleteOperationForTwoStrings.java ├── DesignAddAndSearchWordsDataStructure.java ├── DestinationCity.java ├── DetectCapital.java ├── DetectSquares.java ├── DetermineColorOfAChessboardSquare.java ├── DiameterOfBinaryTree.java ├── DistinctSubsequences.java ├── DistributeCandies.java ├── DistributeCandiesToPeople.java ├── DivideArrayInSetsOfKConsecutiveNumbers.java ├── DivideTwoIntegers.java ├── DivisorGame.java ├── DuplicateZeros.java ├── EditDistance.java ├── ElementAppearingMoreThan25InSortedArray.java ├── EliminationGame.java ├── EqualSumArraysWithMinimumNumberOfOperations.java ├── EscapeALargeMaze.java ├── EvaluateDivision.java ├── EvaluateReversePolishNotation.java ├── EvenOddTree.java ├── ExcelSheetColumnNumber.java ├── ExcelSheetColumnTitle.java ├── ExpressionAddOperators.java ├── FactorialTrailingZeroes.java ├── FairCandySwap.java ├── FibonacciNumber.java ├── FindAllAnagramsInAString.java ├── FindAllDuplicatesInAnArray.java ├── FindAllNumbersDisappearedInAnArray.java ├── FindBottomLeftTreeValue.java ├── FindCenterOfStarGraph.java ├── FindCommonCharacters.java ├── FindDuplicateSubtrees.java ├── FindFirstAndLastPositionOfElementInSortedArray.java ├── FindGoodDaysToRobTheBank.java ├── FindKPairsWithSmallestSums.java ├── FindLargestValueInEachTreeRow.java ├── FindMedianFromDataStream.java ├── FindMinimumInRotatedSortedArray.java ├── FindMinimumInRotatedSortedArrayII.java ├── FindMissingObservations.java ├── FindNUniqueIntegersSumUpToZero.java ├── FindNumbersWithEvenNumberOfDigits.java ├── FindPeakElement.java ├── FindPivotIndex.java ├── FindPositiveIntegerSolutionForAGivenEquation.java ├── FindServersThatHandledMostNumberOfRequests.java ├── FindSmallestLetterGreaterThanTarget.java ├── FindTheClosestPalindrome.java ├── FindTheDuplicateNumber.java ├── FindTheMinimumNumberOfFibonacciNumbersWhoseSumIsK.java ├── FindTheSmallestDivisorGivenAThreshold.java ├── FindTheTownJudge.java ├── FindTheWinnerOfTheCircularGame.java ├── FindWinnerOnATicTacToeGame.java ├── FindWordsThatCanBeFormedByCharacters.java ├── FirstBadVersion.java ├── FirstMissingPositive.java ├── FirstUniqueCharacterInAString.java ├── FizzBuzz.java ├── FlattenAMultilevelDoublyLinkedList.java ├── FlipStringToMonotoneIncreasing.java ├── FlippingAnImage.java ├── FourSum.java ├── FractionToRecurringDecimal.java ├── FriendsOfAppropriateAges.java ├── GameOfLife.java ├── GasStation.java ├── GenerateParentheses.java ├── GetWatchedVideosByYourFriends.java ├── GlobalAndLocalInversions.java ├── GrayCode.java ├── GreatestCommonDivisorOfStrings.java ├── GreatestSumDivisibleByThree.java ├── GridIllumination.java ├── GroupAnagrams.java ├── GroupThePeopleGivenTheGroupSizeTheyBelongTo.java ├── GrumpyBookstoreOwner.java ├── GuessNumberHigherOrLower.java ├── GuessNumberHigherOrLowerII.java ├── HIndex.java ├── HIndexII.java ├── HandOfStraights.java ├── HappyNumber.java ├── Heaters.java ├── HeightChecker.java ├── HouseRobber.java ├── HouseRobberII.java ├── ImageOverlap.java ├── ImageSmoother.java ├── ImplementMagicDictionary.java ├── ImplementStackUsingQueues.java ├── ImplementStrstr.java ├── ImplementTriePrefixTree.java ├── IncreasingOrderSearchTree.java ├── IncreasingTripletSubsequence.java ├── InsertDeleteGetrandomO1.java ├── InsertDeleteGetrandomO1DuplicatesAllowed.java ├── InsertInterval.java ├── InsertionSortList.java ├── IntegerBreak.java ├── IntegerReplacement.java ├── IntegerToEnglishWords.java ├── IntegerToRoman.java ├── InterleavingString.java ├── IntersectionOfTwoArrays.java ├── IntersectionOfTwoArraysII.java ├── IntersectionOfTwoLinkedLists.java ├── InvalidTransactions.java ├── InvertBinaryTree.java ├── IsSubsequence.java ├── IslandPerimeter.java ├── IsomorphicStrings.java ├── JewelsAndStones.java ├── JumpGame.java ├── JumpGameII.java ├── JumpGameIII.java ├── JumpGameIv.java ├── KDiffPairsInAnArray.java ├── KInversePairsArray.java ├── KThSmallestInLexicographicalOrder.java ├── KThSmallestPrimeFraction.java ├── KeyboardRow.java ├── KnightProbabilityInChessboard.java ├── KokoEatingBananas.java ├── KthLargestElementInAStream.java ├── KthLargestElementInAnArray.java ├── KthSmallestElementInABst.java ├── LargestNumber.java ├── LargestNumberAtLeastTwiceOfOthers.java ├── LargestPalindromeProduct.java ├── LargestRectangleInHistogram.java ├── LatestTimeByReplacingHiddenDigits.java ├── LengthOfLastWord.java ├── LengthOfLongestFibonacciSubsequence.java ├── LetterCombinationsOfAPhoneNumber.java ├── LexicographicalNumbers.java ├── LicenseKeyFormatting.java ├── LinkedListCycle.java ├── LinkedListCycleII.java ├── LinkedListRandomNode.java ├── LongestAbsoluteFilePath.java ├── LongestArithmeticSubsequenceOfGivenDifference.java ├── LongestCommonPrefix.java ├── LongestCommonSubsequence.java ├── LongestConsecutiveSequence.java ├── LongestContinuousIncreasingSubsequence.java ├── LongestHappyString.java ├── LongestHarmoniousSubsequence.java ├── LongestIncreasingSubsequence.java ├── LongestNiceSubstring.java ├── LongestPalindrome.java ├── LongestPalindromicSubstring.java ├── LongestSubstringWithoutRepeatingCharacters.java ├── LongestTurbulentSubarray.java ├── LongestUncommonSubsequenceI.java ├── LongestValidParentheses.java ├── LongestWordInDictionary.java ├── LoudAndRich.java ├── LowestCommonAncestorOfABinarySearchTree.java ├── LowestCommonAncestorOfABinaryTree.java ├── LruCache.java ├── LuckyNumbersInAMatrix.java ├── MagicSquaresInGrid.java ├── MajorityElement.java ├── MajorityElementII.java ├── MapOfHighestPeak.java ├── MapSumPairs.java ├── MaxAreaOfIsland.java ├── MaxChunksToMakeSorted.java ├── MaxConsecutiveOnes.java ├── MaxConsecutiveOnesIii.java ├── MaxIncreaseToKeepCitySkyline.java ├── MaxPointsOnALine.java ├── MaximalRectangle.java ├── MaximalSquare.java ├── MaximizeDistanceToClosestPerson.java ├── MaximizeSumOfArrayAfterKNegations.java ├── MaximizeTheConfusionOfAnExam.java ├── MaximumAverageSubarrayI.java ├── MaximumCandiesYouCanGetFromBoxes.java ├── MaximumDepthOfBinaryTree.java ├── MaximumDepthOfNAryTree.java ├── MaximumDifferenceBetweenIncreasingElements.java ├── MaximumLengthOfRepeatedSubarray.java ├── MaximumNestingDepthOfTheParentheses.java ├── MaximumNestingDepthOfTwoValidParenthesesStrings.java ├── MaximumNumberOfAchievableTransferRequests.java ├── MaximumNumberOfBalloons.java ├── MaximumNumberOfEatenApples.java ├── MaximumNumberOfOccurrencesOfASubstring.java ├── MaximumNumberOfVisiblePoints.java ├── MaximumProductOfSplittedBinaryTree.java ├── MaximumProductOfThreeNumbers.java ├── MaximumProductOfWordLengths.java ├── MaximumProductSubarray.java ├── MaximumSubarray.java ├── MaximumSumCircularSubarray.java ├── MaximumSumOf3NonOverlappingSubarrays.java ├── MaximumSwap.java ├── MaximumWidthRamp.java ├── MaximumXorOfTwoNumbersInAnArray.java ├── MedianOfTwoSortedArrays.java ├── MergeIntervals.java ├── MergeKSortedLists.java ├── MergeSortedArray.java ├── MergeTwoSortedLists.java ├── MiddleOfTheLinkedList.java ├── MinCostClimbingStairs.java ├── MinStack.java ├── MiniParser.java ├── MinimumAbsoluteDifference.java ├── MinimumDepthOfBinaryTree.java ├── MinimumDifferenceBetweenHighestAndLowestOfKScores.java ├── MinimumDistanceBetweenBstNodes.java ├── MinimumDominoRotationsForEqualRow.java ├── MinimumHeightTrees.java ├── MinimumIncrementToMakeArrayUnique.java ├── MinimumIndexSumOfTwoLists.java ├── MinimumMovesToConvertString.java ├── MinimumMovesToEqualArrayElements.java ├── MinimumOperationsToMakeAUniValueGrid.java ├── MinimumPathSum.java ├── MinimumSizeSubarraySum.java ├── MinimumSwapsToMakeStringsEqual.java ├── MinimumTimeDifference.java ├── MinimumWindowSubstring.java ├── MissingNumber.java ├── MonotonicArray.java ├── MostCommonWord.java ├── MostStonesRemovedWithSameRowOrColumn.java ├── MoveZeroes.java ├── MultiplyStrings.java ├── MyCalendarI.java ├── NAryTreePostorderTraversal.java ├── NAryTreePreorderTraversal.java ├── NQueens.java ├── NQueensII.java ├── NRepeatedElementInSize2nArray.java ├── NThTribonacciNumber.java ├── NetworkDelayTime.java ├── NextGreaterElementI.java ├── NextGreaterNodeInLinkedList.java ├── NextPermutation.java ├── NimGame.java ├── NonDecreasingArray.java ├── NthDigit.java ├── NumberComplement.java ├── NumberOf1Bits.java ├── NumberOfBurgersWithNoWasteOfIngredients.java ├── NumberOfDaysBetweenTwoDates.java ├── NumberOfDifferentIntegersInAString.java ├── NumberOfDigitOne.java ├── NumberOfEnclaves.java ├── NumberOfEquivalentDominoPairs.java ├── NumberOfLinesToWriteString.java ├── NumberOfMatchingSubsequences.java ├── NumberOfRecentCalls.java ├── NumberOfRectanglesThatCanFormTheLargestSquare.java ├── NumberOfSegmentsInAString.java ├── NumberOfStepsToReduceANumberToZero.java ├── NumberOfSubArraysOfSizeKAndAverageGreaterThanOrEqualToThreshold.java ├── NumberOfSubarraysWithBoundedMaximum.java ├── NumberOfSubstringsContainingAllThreeCharacters.java ├── NumberOfValidWordsInASentence.java ├── NumberOfWaysToReconstructATree.java ├── NumbersWithSameConsecutiveDifferences.java ├── OccurrencesAfterBigram.java ├── OddEvenLinkedList.java ├── OneBitAndTwoBitCharacters.java ├── OnlineElection.java ├── OptimalDivision.java ├── PairsOfSongsWithTotalDurationsDivisibleBy60.java ├── PalindromeLinkedList.java ├── PalindromeNumber.java ├── PalindromePartitioning.java ├── PalindromicSubstrings.java ├── PancakeSorting.java ├── PartitionArrayIntoDisjointIntervals.java ├── PartitionArrayIntoThreePartsWithEqualSum.java ├── PartitionList.java ├── PascalsTriangle.java ├── PascalsTriangleII.java ├── PatchingArray.java ├── PathSum.java ├── PathSumII.java ├── PathSumIII.java ├── PathWithMaximumGold.java ├── PeakIndexInAMountainArray.java ├── PeekingIterator.java ├── PerfectNumber.java ├── PerfectRectangle.java ├── PerfectSquares.java ├── PermutationInString.java ├── PermutationSequence.java ├── Permutations.java ├── PermutationsII.java ├── PlatesBetweenCandles.java ├── PlayWithChips.java ├── PlusOne.java ├── PoorPigs.java ├── PopulatingNextRightPointersInEachNode.java ├── PositionsOfLargeGroups.java ├── PowerOfThree.java ├── PowerOfTwo.java ├── PowxN.java ├── PreviousPermutationWithOneSwap.java ├── ProductOfArrayExceptSelf.java ├── PushDominoes.java ├── QueensThatCanAttackTheKing.java ├── QueueReconstructionByHeight.java ├── RLEIterator.java ├── RandomFlipMatrix.java ├── RandomPickWithWeight.java ├── RangeAdditionII.java ├── RangeSumQuery2dImmutable.java ├── RangeSumQueryImmutable.java ├── RangeSumQueryMutable.java ├── RansomNote.java ├── ReachingPoints.java ├── ReconstructItinerary.java ├── ReconstructOriginalDigitsFromEnglish.java ├── RecoverBinarySearchTree.java ├── RectangleArea.java ├── RectangleOverlap.java ├── ReduceArraySizeToTheHalf.java ├── RegularExpressionMatching.java ├── RelativeRanks.java ├── RelativeSortArray.java ├── RemoveColoredPiecesIfBothNeighborsAreTheSameColor.java ├── RemoveDuplicateLetters.java ├── RemoveDuplicatesFromSortedArray.java ├── RemoveDuplicatesFromSortedArrayII.java ├── RemoveDuplicatesFromSortedList.java ├── RemoveDuplicatesFromSortedListII.java ├── RemoveElement.java ├── RemoveInvalidParentheses.java ├── RemoveLinkedListElements.java ├── RemoveNthNodeFromEndOfList.java ├── RemovePalindromicSubsequences.java ├── RemoveZeroSumConsecutiveNodesFromLinkedList.java ├── ReorderDataInLogFiles.java ├── ReorderList.java ├── ReorderedPowerOf2.java ├── RepeatedDnaSequences.java ├── RepeatedStringMatch.java ├── ReplaceAllSToAvoidConsecutiveRepeatingCharacters.java ├── ReplaceElementsWithGreatestElementOnRightSide.java ├── ReplaceWords.java ├── ReshapeTheMatrix.java ├── RestoreIpAddresses.java ├── RevealCardsInIncreasingOrder.java ├── ReverseBits.java ├── ReverseInteger.java ├── ReverseLinkedList.java ├── ReverseLinkedListII.java ├── ReverseNodesInKGroup.java ├── ReverseOnlyLetters.java ├── ReversePrefixOfWord.java ├── ReverseString.java ├── ReverseWordsInAString.java ├── RomanToInteger.java ├── RotateArray.java ├── RotateImage.java ├── RotateList.java ├── RotateString.java ├── RottingOranges.java ├── SameTree.java ├── ScoreAfterFlippingMatrix.java ├── SearchA2dMatrix.java ├── SearchA2dMatrixII.java ├── SearchInABinarySearchTree.java ├── SearchInRotatedSortedArray.java ├── SearchInRotatedSortedArrayII.java ├── SearchInsertPosition.java ├── SecondMinimumTimeToReachDestination.java ├── SelfCrossing.java ├── SelfDividingNumbers.java ├── SequentialDigits.java ├── SerializeAndDeserializeBinaryTree.java ├── SetMatrixZeroes.java ├── Shift2dGrid.java ├── ShoppingOffers.java ├── ShortEncodingOfWords.java ├── ShortestCompletingWord.java ├── ShortestDistanceToACharacter.java ├── ShortestUnsortedOntinuousSubarray.java ├── ShuffleAnArray.java ├── SimpleBankSystem.java ├── SimplifiedFractions.java ├── SimplifyPath.java ├── SingleElementInASortedArray.java ├── SingleNumber.java ├── SingleNumberII.java ├── SingleNumberIII.java ├── SlidingWindowMaximum.java ├── SlowestKey.java ├── SmallestRotationWithHighestScore.java ├── SmallestSubsequenceOfDistinctCharacters.java ├── SortAnArray.java ├── SortArrayByParity.java ├── SortArrayByParityII.java ├── SortColors.java ├── SortIntegersByTheNumberOf1Bits.java ├── SortList.java ├── SpiralMatrix.java ├── SpiralMatrixII.java ├── SplitAStringInBalancedStrings.java ├── SplitLinkedListInParts.java ├── SqrtX.java ├── SquaresOfASortedArray.java ├── StockPriceFluctuation.java ├── StoneGameIx.java ├── StringToIntegerAtoi.java ├── StrongPasswordChecker.java ├── SubarrayProductLessThanK.java ├── SubarraySumEqualsK.java ├── SubarraySumsDivisibleByK.java ├── Subsets.java ├── SubsetsII.java ├── SubstringWithConcatenationOfAllWords.java ├── SubtractTheProductAndSumOfDigitsOfAnInteger.java ├── SubtreeOfAnotherTree.java ├── SudokuSolver.java ├── SumOfAllOddLengthSubarrays.java ├── SumOfEvenNumbersAfterQueries.java ├── SumOfMutatedArrayClosestToTarget.java ├── SumOfNodesWithEvenValuedGrandparent.java ├── SumOfSubarrayMinimums.java ├── SumOfSubarrayRanges.java ├── SumOfTwoIntegers.java ├── SumOfUniqueElements.java ├── SumRootToLeafNumbers.java ├── SummaryRanges.java ├── SuperPow.java ├── SuperUglyNumber.java ├── SuperWashingMachines.java ├── SurfaceAreaOf3dShapes.java ├── SurroundedRegions.java ├── SwapNodesInPairs.java ├── SymmetricTree.java ├── TagValidator.java ├── TeemoAttacking.java ├── TheKWeakestRowsInAMatrix.java ├── TheNumberOfGoodSubsets.java ├── TheNumberOfWeakCharactersInTheGame.java ├── TheTimeWhenTheNetworkBecomesIdle.java ├── ThirdMaximumNumber.java ├── ThreeSum.java ├── ThreeSumClosest.java ├── ToLowerCase.java ├── ToeplitzMatrix.java ├── TopKFrequentElements.java ├── TransposeMatrix.java ├── TrappingRainWater.java ├── TrappingRainWaterII.java ├── Triangle.java ├── TruncateSentence.java ├── TwoOutOfThree.java ├── TwoSum.java ├── TwoSumIIInputArrayIsSorted.java ├── TwoSumIvInputIsABst.java ├── UglyNumber.java ├── UglyNumberII.java ├── UncommonWordsFromTwoSentences.java ├── UncrossedLines.java ├── UniqueBinarySearchTrees.java ├── UniqueBinarySearchTreesII.java ├── UniqueMorseCodeWords.java ├── UniquePaths.java ├── UniquePathsII.java ├── Utf8Validation.java ├── ValidAnagram.java ├── ValidMountainArray.java ├── ValidPalindrome.java ├── ValidPalindromeII.java ├── ValidParentheses.java ├── ValidPerfectSquare.java ├── ValidSudoku.java ├── ValidTicTacToeState.java ├── ValidTriangleNumber.java ├── ValidateBinarySearchTree.java ├── ValidateBinaryTreeNodes.java ├── ValidateStackSequences.java ├── VerbalArithmeticPuzzle.java ├── VerifyingAnAlienDictionary.java ├── WaterAndJugProblem.java ├── WaterBottles.java ├── WhereWillTheBallFall.java ├── WildcardMatching.java ├── WordBreak.java ├── WordBreakII.java ├── WordLadder.java ├── WordLadderII.java ├── WordSearch.java ├── XOfAKindInADeckOfCards.java ├── XorQueriesOfASubarray.java ├── ZigZagConversion.java ├── ZumaGame.java ├── lcci ├── CompressStringLcci.java ├── RotateMatrixLcci.java ├── SortedMergeLcci.java └── TheMasseuseLcci.java ├── multithread ├── PrintFoobarAlternately.java ├── PrintInOrder.java └── PrintZeroEvenOdd.java ├── swordreferstooffer ├── Question03.java ├── Question04.java ├── Question05.java ├── Question06.java ├── Question07.java ├── Question09.java ├── Question10_I.java ├── Question10_II.java ├── Question11.java ├── Question12.java ├── Question13.java ├── Question14_I.java ├── Question14_II.java ├── Question15.java ├── Question16.java ├── Question17.java ├── Question18.java ├── Question19.java ├── Question20.java ├── Question21.java ├── Question22.java ├── Question24.java ├── Question25.java ├── Question26.java ├── Question27.java ├── Question28.java ├── Question29.java ├── Question30.java ├── Question31.java ├── Question32_I.java ├── Question32_II.java ├── Question32_III.java ├── Question33.java ├── Question34.java ├── Question35.java ├── Question36.java ├── Question37.java ├── Question38.java ├── Question39.java ├── Question40.java ├── Question41.java ├── Question42.java ├── Question43.java ├── Question44.java ├── Question45.java ├── Question46.java ├── Question47.java ├── Question48.java ├── Question49.java ├── Question50.java ├── Question51.java ├── Question52.java ├── Question53_I.java ├── Question53_II.java ├── Question54.java ├── Question55_I.java ├── Question55_II.java ├── Question56_I.java ├── Question56_II.java ├── Question57.java ├── Question57_II.java ├── Question58_I.java ├── Question58_II.java ├── Question59_I.java ├── Question59_II.java ├── Question60.java ├── Question61.java ├── Question62.java ├── Question63.java ├── Question64.java ├── Question65.java ├── Question66.java ├── Question67.java ├── Question68_I.java └── Question68_II.java ├── swordreferstoofferspecial ├── Question001.java ├── Question002.java ├── Question003.java ├── Question004.java ├── Question005.java ├── Question006.java ├── Question007.java ├── Question008.java ├── Question009.java ├── Question010.java ├── Question011.java ├── Question012.java ├── Question013.java ├── Question014.java ├── Question015.java ├── Question016.java ├── Question017.java ├── Question018.java ├── Question019.java ├── Question020.java ├── Question021.java ├── Question022.java ├── Question023.java ├── Question024.java ├── Question025.java ├── Question026.java ├── Question027.java ├── Question028.java ├── Question029.java ├── Question030.java ├── Question031.java ├── Question032.java ├── Question033.java ├── Question034.java ├── Question035.java ├── Question036.java ├── Question037.java ├── Question038.java ├── Question039.java ├── Question040.java ├── Question041.java ├── Question042.java ├── Question043.java ├── Question044.java ├── Question045.java ├── Question046.java ├── Question047.java ├── Question048.java ├── Question049.java ├── Question050.java ├── Question051.java ├── Question052.java ├── Question053.java ├── Question054.java ├── Question055.java ├── Question056.java ├── Question057.java ├── Question058.java ├── Question059.java ├── Question060.java ├── Question061.java ├── Question062.java ├── Question063.java ├── Question064.java ├── Question065.java ├── Question066.java ├── Question067.java ├── Question068.java ├── Question069.java ├── Question070.java ├── Question071.java ├── Question072.java ├── Question073.java ├── Question074.java ├── Question075.java ├── Question076.java ├── Question077.java ├── Question078.java ├── Question079.java ├── Question080.java ├── Question081.java ├── Question082.java ├── Question083.java ├── Question084.java ├── Question085.java ├── Question086.java ├── Question087.java ├── Question088.java ├── Question089.java ├── Question090.java ├── Question091.java ├── Question092.java ├── Question093.java ├── Question095.java ├── Question096.java ├── Question097.java ├── Question099.java ├── Question100.java ├── Question103.java ├── Question104.java ├── Question105.java └── Question119.java └── util └── NamingConversionUtil.java /src/com/hncboy/AddBinary.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/12/7 9:19 6 | * @description 67.二进制求和 7 | * 8 | * 给定两个二进制字符串,返回他们的和(用二进制表示)。 9 | * 输入为非空字符串且只包含数字 1 和 0。 10 | * 11 | * 示例 1: 12 | * 输入: a = "11", b = "1" 13 | * 输出: "100" 14 | * 15 | * 示例 2: 16 | * 输入: a = "1010", b = "1011" 17 | * 输出: "10101" 18 | */ 19 | public class AddBinary { 20 | 21 | public static void main(String[] args) { 22 | AddBinary a = new AddBinary(); 23 | System.out.println(a.addBinary("11", "1")); 24 | System.out.println(a.addBinary("1010", "1011")); 25 | } 26 | 27 | private String addBinary(String a, String b) { 28 | StringBuilder result = new StringBuilder(); 29 | int sum = 0; 30 | for (int i = a.length() - 1, j = b.length() - 1; i >= 0 || j >= 0; i--, j--) { 31 | sum += i >= 0 ? a.charAt(i) - '0' : 0; 32 | sum += j >= 0 ? b.charAt(j) - '0' : 0; 33 | result.append(sum % 2); 34 | // 计算进位 35 | sum /= 2; 36 | } 37 | // 进位是1的话补1 38 | result.append(sum == 1 ? sum : ""); 39 | return result.reverse().toString(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/com/hncboy/AddDigits.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/12/21 13:47 6 | * 258.各位相加 7 | * 8 | * 给定一个非负整数 num,反复将各个位上的数字相加,直到结果为一位数。返回这个结果。 9 | * 10 | * 示例 1: 11 | * 输入: num = 38 12 | * 输出: 2 13 | * 解释: 各位相加的过程为: 14 | * 38 --> 3 + 8 --> 11 15 | * 11 --> 1 + 1 --> 2 16 | * 由于 2 是一位数,所以返回 2。 17 | * 18 | * 示例 1: 19 | * 输入: num = 0 20 | * 输出: 0 21 | * 22 | * 提示: 23 | * 0 <= num <= 231 - 1 24 | * 25 | * 进阶:你可以不使用循环或者递归,在 O(1) 时间复杂度内解决这个问题吗? 26 | * 通过次数 92,602 提交次数 133,116 27 | * 28 | * 来源:力扣(LeetCode) 29 | * 链接:https://leetcode-cn.com/problems/add-digits 30 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 31 | */ 32 | public class AddDigits { 33 | 34 | public static void main(String[] args) { 35 | AddDigits a = new AddDigits(); 36 | System.out.println(a.addDigits(36)); 37 | System.out.println(a.addDigits(38)); 38 | } 39 | 40 | public int addDigits(int num) { 41 | return (num - 1) % 9 + 1; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/com/hncboy/AddStrings.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2022/3/24 8:12 6 | * 415.字符串相加 7 | * 8 | * 给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和并同样以字符串形式返回。 9 | * 你不能使用任何內建的用于处理大整数的库(比如 BigInteger), 也不能直接将输入的字符串转换为整数形式。 10 | * 11 | * 示例 1: 12 | * 输入:num1 = "11", num2 = "123" 13 | * 输出:"134" 14 | * 15 | * 示例 2: 16 | * 输入:num1 = "456", num2 = "77" 17 | * 输出:"533" 18 | * 19 | * 示例 3: 20 | * 输入:num1 = "0", num2 = "0" 21 | * 输出:"0" 22 | * 23 | * 提示: 24 | * 1 <= num1.length, num2.length <= 104 25 | * num1 和num2 都只包含数字 0-9 26 | * num1 和num2 都不包含任何前导零 27 | * 通过次数187,148提交次数343,043 28 | * 29 | * 来源:力扣(LeetCode) 30 | * 链接:https://leetcode-cn.com/problems/add-strings 31 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 32 | */ 33 | public class AddStrings { 34 | 35 | public String addStrings(String num1, String num2) { 36 | StringBuilder result = new StringBuilder(""); 37 | int i = num1.length() - 1; 38 | int j = num2.length() - 1; 39 | int add = 0; 40 | while (i >= 0 || j >= 0) { 41 | int n1 = i >= 0 ? num1.charAt(i) - '0' : 0; 42 | int n2 = j >= 0 ? num2.charAt(j) - '0' : 0; 43 | int tmp = n1 + n2 + add; 44 | add = tmp / 10; 45 | result.append(tmp % 10); 46 | i--; 47 | j--; 48 | } 49 | if (add == 1) { 50 | result.append(1); 51 | } 52 | return result.reverse().toString(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/com/hncboy/AllElementsInTwoBinarySearchTrees.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hncboy/LeetCode/ab66f67d0a7a6667f1b21e8f0be503eb351863bd/src/com/hncboy/AllElementsInTwoBinarySearchTrees.java -------------------------------------------------------------------------------- /src/com/hncboy/ArrangingCoins.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2020/1/2 19:52 6 | * @description 441.排列硬币 7 | * 8 | * 你总共有 n 枚硬币,你需要将它们摆成一个阶梯形状,第 k 行就必须正好有 k 枚硬币。 9 | * 给定一个数字 n,找出可形成完整阶梯行的总行数。 10 | * n 是一个非负整数,并且在32位有符号整型的范围内。 11 | * 12 | * 示例 1: 13 | * n = 5 14 | * 硬币可排列成以下几行: 15 | * ¤ 16 | * ¤ ¤ 17 | * ¤ ¤ 18 | * 因为第三行不完整,所以返回2. 19 | * 20 | * 示例 2: 21 | * n = 8 22 | * 硬币可排列成以下几行: 23 | * ¤ 24 | * ¤ ¤ 25 | * ¤ ¤ ¤ 26 | * ¤ ¤ 27 | * 因为第四行不完整,所以返回3. 28 | */ 29 | public class ArrangingCoins { 30 | 31 | public static void main(String[] args) { 32 | ArrangingCoins a = new ArrangingCoins(); 33 | System.out.println(a.arrangeCoins(5)); 34 | System.out.println(a.arrangeCoins(8)); 35 | } 36 | 37 | private int arrangeCoins(int n) { 38 | long left = 0; 39 | long right = n; 40 | while (left < right) { 41 | long mid = left + (right - left + 1) / 2; 42 | long t = (1 + mid) * mid / 2; 43 | if (t > n) { 44 | right = mid - 1; 45 | } else { 46 | left = mid; 47 | } 48 | } 49 | return (int) left; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/com/hncboy/ArrayPartitionI.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author hncboy 7 | * @date 2019/11/22 11:50 8 | * @description 561.数组拆分 I 9 | * 10 | * 给定长度为 2n 的数组, 你的任务是将这些数分成 n 对, 例如 (a1, b1), (a2, b2), ..., (an, bn) ,使得从1 到 n 的 min(ai, bi) 总和最大。 11 | * 12 | * 示例 1: 13 | * 输入: [1,4,3,2] 14 | * 输出: 4 15 | * 解释: n 等于 2, 最大总和为 4 = min(1, 2) + min(3, 4). 16 | * 17 | * 提示: 18 | * n 是正整数,范围在 [1, 10000]. 19 | * 数组中的元素范围在 [-10000, 10000]. 20 | */ 21 | public class ArrayPartitionI { 22 | 23 | public static void main(String[] args) { 24 | ArrayPartitionI a = new ArrayPartitionI(); 25 | System.out.println(a.arrayPairSum(new int[]{1, 4, 3, 2})); 26 | } 27 | 28 | private int arrayPairSum(int[] nums) { 29 | Arrays.sort(nums); 30 | int sum = 0; 31 | for (int i = 0; i < nums.length; i += 2) { 32 | sum += nums[i]; 33 | } 34 | return sum; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/com/hncboy/Base7.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2022/3/7 8:17 6 | * 504.七进制数 7 | * 8 | * 给定一个整数 num,将其转化为 7 进制,并以字符串形式输出。 9 | * 10 | * 示例 1: 11 | * 输入: num = 100 12 | * 输出: "202" 13 | * 14 | * 示例 2: 15 | * 输入: num = -7 16 | * 输出: "-10" 17 | * 18 | * 提示: 19 | * -107 <= num <= 107 20 | * 通过次数38,659提交次数76,067 21 | * 22 | * 来源:力扣(LeetCode) 23 | * 链接:https://leetcode-cn.com/problems/base-7 24 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 25 | */ 26 | public class Base7 { 27 | 28 | public static void main(String[] args) { 29 | Base7 b = new Base7(); 30 | System.out.println(b.convertToBase7(100)); 31 | System.out.println(b.convertToBase7(-7)); 32 | } 33 | 34 | public String convertToBase7(int num) { 35 | if (num == 0) { 36 | return "0"; 37 | } 38 | 39 | // 是否是负数 40 | boolean negative = num < 0; 41 | if (negative) { 42 | num = -num; 43 | } 44 | StringBuilder digits = new StringBuilder(); 45 | do { 46 | digits.append(num % 7); 47 | num /= 7; 48 | } while (num > 0); 49 | 50 | if (negative) { 51 | digits.append('-'); 52 | } 53 | return digits.reverse().toString(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/com/hncboy/BestSightseeingPair.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/12/18 21:03 6 | * @description 1014.最佳观光组合 7 | * 8 | * 给定正整数数组 A,A[i] 表示第 i 个观光景点的评分,并且两个景点 i 和 j 之间的距离为 j - i。 9 | * 一对景点(i < j)组成的观光组合的得分为(A[i] + A[j] + i - j):景点的评分之和减去它们两者之间的距离。 10 | * 返回一对观光景点能取得的最高分。 11 | *   12 | * 示例: 13 | * 输入:[8,1,5,2,6] 14 | * 输出:11 15 | * 解释:i = 0, j = 2, A[i] + A[j] + i - j = 8 + 5 + 0 - 2 = 11 16 | * 17 | * 提示: 18 | * 2 <= A.length <= 50000 19 | * 1 <= A[i] <= 1000 20 | */ 21 | public class BestSightseeingPair { 22 | 23 | public static void main(String[] args) { 24 | BestSightseeingPair b = new BestSightseeingPair(); 25 | System.out.println(b.maxScoreSightseeingPair(new int[]{8, 1, 5, 2, 6})); 26 | } 27 | 28 | private int maxScoreSightseeingPair(int[] A) { 29 | // A[i] + A[j] + i - j (i < j) 30 | // A[i]+i + A[j]-j 31 | // A[j]-j 固定,求 A[i]+i 最大值 32 | int result = 0; 33 | int max = A[0]; 34 | for (int i = 1; i < A.length; i++) { 35 | result = Math.max(result, max + A[i] - i); 36 | max = Math.max(max, A[i] + i); 37 | } 38 | return result; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/com/hncboy/BestTimeToBuyAndSellStock.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/10/19 8:06 6 | * @description 121.买卖股票的最佳时机 7 | * 8 | * 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。 9 | * 如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。 10 | * 注意你不能在买入股票前卖出股票。 11 | * 12 | * 示例 1: 13 | * 输入: [7,1,5,3,6,4] 14 | * 输出: 5 15 | * 解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。 16 | * 注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。 17 | * 18 | * 示例 2: 19 | * 输入: [7,6,4,3,1] 20 | * 输出: 0 21 | * 解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。 22 | */ 23 | public class BestTimeToBuyAndSellStock { 24 | 25 | public static void main(String[] args) { 26 | BestTimeToBuyAndSellStock b = new BestTimeToBuyAndSellStock(); 27 | int[] prices1 = new int[]{7, 1, 5, 3, 6, 4}; 28 | int[] prices2 = new int[]{7, 6, 4, 3, 1}; 29 | System.out.println(b.maxProfit(prices1)); 30 | System.out.println(b.maxProfit(prices2)); 31 | } 32 | 33 | private int maxProfit(int[] prices) { 34 | int minPrice = Integer.MAX_VALUE; 35 | int maxProfit = 0; 36 | 37 | for (int price : prices) { 38 | minPrice = Math.min(minPrice, price); 39 | maxProfit = Math.max(maxProfit, price - minPrice); 40 | } 41 | 42 | return maxProfit; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/com/hncboy/BestTimeToBuyAndSellStockWithCooldown.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/10/19 9:01 6 | * @description 309.最佳买卖股票时机含冷冻期 7 | * 8 | * 给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。​ 9 | * 设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票): 10 | * 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。 11 | * 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。 12 | * 13 | * 示例: 14 | * 输入: [1,2,3,0,2] 15 | * 输出: 3 16 | * 解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出] 17 | */ 18 | public class BestTimeToBuyAndSellStockWithCooldown { 19 | 20 | public static void main(String[] args) { 21 | BestTimeToBuyAndSellStockWithCooldown b = new BestTimeToBuyAndSellStockWithCooldown(); 22 | System.out.println(b.maxProfit(new int[]{1, 2, 3, 0, 2})); 23 | } 24 | 25 | private int maxProfit(int[] prices) { 26 | int dp_i_0 = 0; 27 | int dp_i_1 = Integer.MIN_VALUE; 28 | int dp_pre = 0; 29 | for (int price : prices) { 30 | int temp = dp_i_0; 31 | dp_i_0 = Math.max(dp_i_0, dp_i_1 + price); 32 | // 买入的状态转移从上一天未持有股票的情况转移 33 | dp_i_1 = Math.max(dp_i_1, dp_pre - price); 34 | dp_pre = temp; 35 | } 36 | return dp_i_0; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/com/hncboy/BestTimeToBuyAndSellStockWithTransactionFee.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/12/19 17:37 6 | * @description 714.买卖股票的最佳时机含手续费 7 | * 8 | * 给定一个整数数组 prices,其中第 i 个元素代表了第 i 天的股票价格 ;非负整数 fee 代表了交易股票的手续费用。 9 | * 你可以无限次地完成交易,但是你每次交易都需要付手续费。 10 | * 如果你已经购买了一个股票,在卖出它之前你就不能再继续购买股票了。 11 | * 返回获得利润的最大值。 12 | * 13 | * 示例 1: 14 | * 输入: prices = [1, 3, 2, 8, 4, 9], fee = 2 15 | * 输出: 8 16 | * 解释: 能够达到的最大利润: 17 | * 在此处买入 prices[0] = 1 18 | * 在此处卖出 prices[3] = 8 19 | * 在此处买入 prices[4] = 4 20 | * 在此处卖出 prices[5] = 9 21 | * 总利润: ((8 - 1) - 2) + ((9 - 4) - 2) = 8. 22 | * 23 | * 注意: 24 | * 0 < prices.length <= 50000. 25 | * 0 < prices[i] < 50000. 26 | * 0 <= fee < 50000. 27 | */ 28 | public class BestTimeToBuyAndSellStockWithTransactionFee { 29 | 30 | public static void main(String[] args) { 31 | BestTimeToBuyAndSellStockWithTransactionFee b = new BestTimeToBuyAndSellStockWithTransactionFee(); 32 | System.out.println(b.maxProfit(new int[]{1, 3, 2, 8, 4, 9}, 2)); 33 | } 34 | 35 | private int maxProfit(int[] prices, int fee) { 36 | int dp_i_0 = 0; 37 | int dp_i_1 = Integer.MIN_VALUE; 38 | for (int price : prices) { 39 | int temp = dp_i_0; 40 | dp_i_0 = Math.max(dp_i_0, dp_i_1 + price); 41 | // 卖出的价格变少了 42 | dp_i_1 = Math.max(dp_i_1, temp - price - fee); 43 | } 44 | return dp_i_0; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/com/hncboy/BinaryNumberWithAlternatingBits.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/12/15 14:44 6 | * 693.交替位二进制数 7 | * 8 | * 给定一个正整数,检查它的二进制表示是否总是 0、1 交替出现:换句话说,就是二进制表示中相邻两位的数字永不相同。 9 | * 10 | * 示例 1: 11 | * 输入:n = 5 12 | * 输出:true 13 | * 解释:5 的二进制表示是:101 14 | * 15 | * 示例 2: 16 | * 输入:n = 7 17 | * 输出:false 18 | * 解释:7 的二进制表示是:111. 19 | * 20 | * 示例 3: 21 | * 输入:n = 11 22 | * 输出:false 23 | * 解释:11 的二进制表示是:1011. 24 | * 25 | * 提示: 26 | * 1 <= n <= 231 - 1 27 | * 通过次数34,018提交次数54,864 28 | * 29 | * 来源:力扣(LeetCode) 30 | * 链接:https://leetcode-cn.com/problems/binary-number-with-alternating-bits 31 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 32 | */ 33 | public class BinaryNumberWithAlternatingBits { 34 | 35 | public static void main(String[] args) { 36 | BinaryNumberWithAlternatingBits b = new BinaryNumberWithAlternatingBits(); 37 | System.out.println(b.hasAlternatingBits(5)); 38 | System.out.println(b.hasAlternatingBits(7)); 39 | System.out.println(b.hasAlternatingBits(11)); 40 | System.out.println(b.hasAlternatingBits(10)); 41 | } 42 | 43 | public boolean hasAlternatingBits(int n) { 44 | // 对 n 的二进制右移一位,得到的数字再与 n 按位异或运算; 45 | // 当前仅当 n 位交替位二进制数时,得到的结果的数字二进制位才都是 1 46 | n = n ^ (n >> 1); 47 | return (n & (n + 1)) == 0; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/com/hncboy/BinarySearch.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2020/1/3 22:05 6 | * @description 704.二分查找 7 | * 8 | * 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target, 9 | * 写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。 10 | * 11 | * 示例 1: 12 | * 输入: nums = [-1,0,3,5,9,12], target = 9 13 | * 输出: 4 14 | * 解释: 9 出现在 nums 中并且下标为 4 15 | * 16 | * 示例 2: 17 | * 输入: nums = [-1,0,3,5,9,12], target = 2 18 | * 输出: -1 19 | * 解释: 2 不存在 nums 中因此返回 -1 20 | * 21 | * 提示: 22 | * 你可以假设 nums 中的所有元素是不重复的。 23 | * n 将在 [1, 10000]之间。 24 | * nums 的每个元素都将在 [-9999, 9999]之间。 25 | */ 26 | public class BinarySearch { 27 | 28 | public static void main(String[] args) { 29 | BinarySearch b = new BinarySearch(); 30 | System.out.println(b.search(new int[]{-1, 0, 3, 5, 9, 12}, 9)); 31 | System.out.println(b.search(new int[]{-1, 0, 3, 5, 9, 12}, 2)); 32 | } 33 | 34 | private int search(int[] nums, int target) { 35 | int left = 0; 36 | int right = nums.length - 1; 37 | 38 | while (left <= right) { 39 | int mid = left + (right - left) / 2; 40 | if (nums[mid] == target) { 41 | return mid; 42 | } 43 | 44 | if (nums[mid] > target) { 45 | right = mid - 1; 46 | } else { 47 | left = mid + 1; 48 | } 49 | } 50 | 51 | return -1; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/com/hncboy/BulbSwitcher.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/11/15 8:51 6 | * @description 319.灯泡开关 7 | * 8 | * 初始时有 n 个灯泡处于关闭状态。第一轮,你将会打开所有灯泡。接下来的第二轮,你将会每两个灯泡关闭一个。 9 | * 第三轮,你每三个灯泡就切换一个灯泡的开关(即,打开变关闭,关闭变打开)。 10 | * 第 i 轮,你每 i 个灯泡就切换一个灯泡的开关。直到第 n 轮,你只需要切换最后一个灯泡的开关。 11 | * 找出并返回 n 轮后有多少个亮着的灯泡。 12 | * 13 | * 示例 1: 14 | * 输入:n = 3 15 | * 输出:1 16 | * 解释: 17 | * 初始时, 灯泡状态 [关闭, 关闭, 关闭]. 18 | * 第一轮后, 灯泡状态 [开启, 开启, 开启]. 19 | * 第二轮后, 灯泡状态 [开启, 关闭, 开启]. 20 | * 第三轮后, 灯泡状态 [开启, 关闭, 关闭]. 21 | * 你应该返回 1,因为只有一个灯泡还亮着。 22 | * 23 | * 示例 2: 24 | * 输入:n = 0 25 | * 输出:0 26 | * 27 | * 示例 3: 28 | * 输入:n = 1 29 | * 输出:1 30 | * 31 | * 提示: 32 | * 0 <= n <= 109 33 | * 34 | * 来源:力扣(LeetCode) 35 | * 链接:https://leetcode-cn.com/problems/bulb-switcher 36 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 37 | */ 38 | public class BulbSwitcher { 39 | 40 | public int bulbSwitch(int n) { 41 | return (int)Math.sqrt(n); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/com/hncboy/CheckIfItIsAStraightLine.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/10/20 10:30 6 | * @description 1232.缀点成线 7 | */ 8 | public class CheckIfItIsAStraightLine { 9 | 10 | public static void main(String[] args) { 11 | CheckIfItIsAStraightLine c = new CheckIfItIsAStraightLine(); 12 | int[][] coordinates1 = new int[][]{{1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 6}, {6, 7}}; 13 | int[][] coordinates2 = new int[][]{{1, 1}, {2, 2}, {3, 4}, {4, 5}, {5, 6}, {7, 7}}; 14 | int[][] coordinates3 = new int[][]{{-3, -2}, {-1, -2}, {2, -2}, {-2, -2}, {0, -2}}; 15 | System.out.println(c.checkStraightLine(coordinates1)); 16 | System.out.println(c.checkStraightLine(coordinates2)); 17 | System.out.println(c.checkStraightLine(coordinates3)); 18 | } 19 | 20 | private boolean checkStraightLine(int[][] coordinates) { 21 | int x1 = coordinates[1][0] - coordinates[0][0]; 22 | int y1 = coordinates[1][1] - coordinates[0][1]; 23 | 24 | for (int i = 2; i < coordinates.length; i++) { 25 | int x2 = coordinates[i][0] - coordinates[0][0]; 26 | int y2 = coordinates[i][1] - coordinates[0][1]; 27 | if (x1 * y2 != x2 * y1) { 28 | return false; 29 | } 30 | } 31 | return true; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/com/hncboy/ClimbingStairs.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/9/10 8:25 6 | * @description 70.爬楼梯 7 | *

8 | * 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 9 | * 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? 10 | * 注意:给定 n 是一个正整数。 11 | *

12 | * 示例 1: 13 | * 输入: 2 14 | * 输出: 2 15 | * 解释: 有两种方法可以爬到楼顶。 16 | * 1. 1 阶 + 1 阶 17 | * 2. 2 阶 18 | *

19 | * 示例 2: 20 | * 输入: 3 21 | * 输出: 3 22 | * 解释: 有三种方法可以爬到楼顶。 23 | * 1. 1 阶 + 1 阶 + 1 阶 24 | * 2. 1 阶 + 2 阶 25 | * 3. 2 阶 + 1 阶 26 | */ 27 | public class ClimbingStairs { 28 | 29 | public static void main(String[] args) { 30 | System.out.println(climbStairs(5)); 31 | } 32 | 33 | private static int climbStairs(int n) { 34 | // 迭代法 斐波那契 35 | if (n >= 1 && n <= 3) { 36 | return n; 37 | } 38 | int n1 = 2; 39 | int n2 = 3; 40 | while (n-- > 3) { 41 | n2 = n1 + n2; 42 | n1 = n2 - n1; 43 | } 44 | return n2; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/com/hncboy/CombinationSumIv.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2022/3/1 9:38 6 | * 377.组合总和 Ⅳ 7 | * 8 | * 给你一个由 不同 整数组成的数组 nums ,和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。 9 | * 题目数据保证答案符合 32 位整数范围。 10 | * 11 | * 示例 1: 12 | * 输入:nums = [1,2,3], target = 4 13 | * 输出:7 14 | * 解释: 15 | * 所有可能的组合为: 16 | * (1, 1, 1, 1) 17 | * (1, 1, 2) 18 | * (1, 2, 1) 19 | * (1, 3) 20 | * (2, 1, 1) 21 | * (2, 2) 22 | * (3, 1) 23 | * 请注意,顺序不同的序列被视作不同的组合。 24 | * 25 | * 示例 2: 26 | * 输入:nums = [9], target = 3 27 | * 输出:0 28 | * 29 | * 提示: 30 | * 1 <= nums.length <= 200 31 | * 1 <= nums[i] <= 1000 32 | * nums 中的所有元素 互不相同 33 | * 1 <= target <= 1000 34 | * 35 | * 进阶:如果给定的数组中含有负数会发生什么?问题会产生何种变化?如果允许负数出现,需要向题目中添加哪些限制条件? 36 | * 通过次数 78,362 提交次数 151,732 37 | * 38 | * 来源:力扣(LeetCode) 39 | * 链接:https://leetcode-cn.com/problems/combination-sum-iv 40 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 41 | */ 42 | public class CombinationSumIv { 43 | 44 | public int combinationSum4(int[] nums, int target) { 45 | // dp[x] 表示选取的元素之和等于 x 的方案数 46 | int[] dp = new int[target + 1]; 47 | dp[0] = 1; 48 | for (int i = 1; i <= target; i++) { 49 | for (int num : nums) { 50 | if (num <= i) { 51 | dp[i] += dp[i - num]; 52 | } 53 | } 54 | } 55 | return dp[target]; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/com/hncboy/ComplexNumberMultiplication.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2022/2/25 8:57 6 | * 537.复数乘法 7 | * 8 | * 复数 可以用字符串表示,遵循 "实部+虚部i" 的形式,并满足下述条件: 9 | * 实部 是一个整数,取值范围是 [-100, 100] 10 | * 虚部 也是一个整数,取值范围是 [-100, 100] 11 | * i2 == -1 12 | * 给你两个字符串表示的复数 num1 和 num2 ,请你遵循复数表示形式,返回表示它们乘积的字符串。 13 | * 14 | * 示例 1: 15 | * 输入:num1 = "1+1i", num2 = "1+1i" 16 | * 输出:"0+2i" 17 | * 解释:(1 + i) * (1 + i) = 1 + i2 + 2 * i = 2i ,你需要将它转换为 0+2i 的形式。 18 | * 19 | * 示例 2: 20 | * 输入:num1 = "1+-1i", num2 = "1+-1i" 21 | * 输出:"0+-2i" 22 | * 解释:(1 - i) * (1 - i) = 1 + i2 - 2 * i = -2i ,你需要将它转换为 0+-2i 的形式。 23 | * 24 | * 提示: 25 | * num1 和 num2 都是有效的复数表示。 26 | * 通过次数 15,575 提交次数 21,387 27 | * 28 | * 来源:力扣(LeetCode) 29 | * 链接:https://leetcode-cn.com/problems/complex-number-multiplication 30 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 31 | */ 32 | public class ComplexNumberMultiplication { 33 | 34 | public String complexNumberMultiply(String num1, String num2) { 35 | String[] complex1 = num1.split("\\+|i"); 36 | String[] complex2 = num2.split("\\+|i"); 37 | int real1 = Integer.parseInt(complex1[0]); 38 | int imag1 = Integer.parseInt(complex1[1]); 39 | int real2 = Integer.parseInt(complex2[0]); 40 | int imag2 = Integer.parseInt(complex2[1]); 41 | return String.format("%d+%di", real1 * real2 - imag1 * imag2, real1 * imag2 + imag1 * real2); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/com/hncboy/ConstructTheRectangle.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/10/23 10:18 6 | * @description 492.构造矩形 7 | * 8 | * 作为一位web开发者, 懂得怎样去规划一个页面的尺寸是很重要的。 现给定一个具体的矩形页面面积,你的任务是设计一个长度为 L 和宽度为 W 且满足以下要求的矩形的页面。要求: 9 | * 10 | * 1. 你设计的矩形页面必须等于给定的目标面积。 11 | * 2. 宽度 W 不应大于长度 L,换言之,要求 L >= W 。 12 | * 3. 长度 L 和宽度 W 之间的差距应当尽可能小。 13 | * 你需要按顺序输出你设计的页面的长度 L 和宽度 W。 14 | * 15 | * 示例: 16 | * 输入: 4 17 | * 输出: [2, 2] 18 | * 解释: 目标面积是 4, 所有可能的构造方案有 [1,4], [2,2], [4,1]。 19 | * 但是根据要求2,[1,4] 不符合要求; 根据要求3,[2,2] 比 [4,1] 更能符合要求. 所以输出长度 L 为 2, 宽度 W 为 2。 20 | * 21 | * 说明: 22 | * 给定的面积不大于 10,000,000 且为正整数。 23 | * 你设计的页面的长度和宽度必须都是正整数。 24 | * 25 | * 来源:力扣(LeetCode) 26 | * 链接:https://leetcode-cn.com/problems/construct-the-rectangle 27 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 28 | */ 29 | public class ConstructTheRectangle { 30 | 31 | public int[] constructRectangle(int area) { 32 | for (int w = (int) (Math.sqrt(area)); ; w--) { 33 | if (area % w == 0) { 34 | return new int[]{area / w, w}; 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/com/hncboy/ContainerWithMostWater.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/9/13 13:00 6 | * @description 11.盛最多水的容器 7 | * 8 | * 给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。 9 | * 在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。 10 | * 找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。 11 | * 说明:你不能倾斜容器,且 n 的值至少为 2。 12 | * 13 | * 示例: 14 | * 输入: [1,8,6,2,5,4,8,3,7] 15 | * 输出: 49 16 | */ 17 | public class ContainerWithMostWater { 18 | 19 | public static void main(String[] args) { 20 | int[] height = new int[]{1, 8, 6, 2, 5, 4, 8, 3, 7}; 21 | System.out.println(maxArea(height)); 22 | } 23 | 24 | private static int maxArea(int[] height) { 25 | int maxCapacity = 0; 26 | int i = 0; 27 | int j = height.length - 1; 28 | while (i < j) { 29 | maxCapacity = Math.max(maxCapacity, (j - i) * Math.min(height[i], height[j])); 30 | if (height[j] > height[i]) { 31 | i++; 32 | } else { 33 | j--; 34 | } 35 | } 36 | return maxCapacity; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/com/hncboy/CountAllValidPickupAndDeliveryOptions.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2020/2/22 23:39 6 | * @description 1359.有效的快递序列数目 7 | * 8 | * 给你 n 笔订单,每笔订单都需要快递服务。 9 | * 请你统计所有有效的 收件/配送 序列的数目,确保第 i 个物品的配送服务 delivery(i) 总是在其收件服务 pickup(i) 之后。 10 | * 由于答案可能很大,请返回答案对 10^9 + 7 取余的结果。 11 | * 12 | * 示例 1: 13 | * 输入:n = 1 14 | * 输出:1 15 | * 解释:只有一种序列 (P1, D1),物品 1 的配送服务(D1)在物品 1 的收件服务(P1)后。 16 | * 17 | * 示例 2: 18 | * 输入:n = 2 19 | * 输出:6 20 | * 解释:所有可能的序列包括: 21 | * (P1,P2,D1,D2),(P1,P2,D2,D1),(P1,D1,P2,D2),(P2,P1,D1,D2),(P2,P1,D2,D1) 和 (P2,D2,P1,D1)。 22 | * (P1,D2,P2,D1) 是一个无效的序列,因为物品 2 的收件服务(P2)不应在物品 2 的配送服务(D2)之后。 23 | * 24 | * 示例 3: 25 | * 输入:n = 3 26 | * 输出:90 27 | *   28 | * 提示: 29 | * 1 <= n <= 500 30 | */ 31 | public class CountAllValidPickupAndDeliveryOptions { 32 | 33 | public static void main(String[] args) { 34 | CountAllValidPickupAndDeliveryOptions c = new CountAllValidPickupAndDeliveryOptions(); 35 | System.out.println(c.countOrders(1)); 36 | System.out.println(c.countOrders(2)); 37 | System.out.println(c.countOrders(3)); 38 | System.out.println(c.countOrders(8)); 39 | } 40 | 41 | private int countOrders(int n) { 42 | long result = 1; 43 | for (int i = 2; i <= n; i++) { 44 | result = result * i * (2 * i - 1) % 1_000_000_007L; 45 | } 46 | return (int) result; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/com/hncboy/CountNumberOfPairsWithAbsoluteDifferenceK.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * @author hncboy 7 | * @date 2022/2/9 8:43 8 | * 2006.差的绝对值为 K 的数对数目 9 | * 10 | * 给你一个整数数组 nums 和一个整数 k ,请你返回数对 (i, j) 的数目,满足 i < j 且 |nums[i] - nums[j]| == k 。 11 | * |x| 的值定义为: 12 | * 如果 x >= 0 ,那么值为 x 。 13 | * 如果 x < 0 ,那么值为 -x 。 14 | * 15 | * 示例 1: 16 | * 输入:nums = [1,2,2,1], k = 1 17 | * 输出:4 18 | * 解释:差的绝对值为 1 的数对为: 19 | * - [1,2,2,1] 20 | * - [1,2,2,1] 21 | * - [1,2,2,1] 22 | * - [1,2,2,1] 23 | * 24 | * 示例 2: 25 | * 输入:nums = [1,3], k = 3 26 | * 输出:0 27 | * 解释:没有任何数对差的绝对值为 3 。 28 | * 29 | * 示例 3: 30 | * 输入:nums = [3,2,1,5,4], k = 2 31 | * 输出:3 32 | * 解释:差的绝对值为 2 的数对为: 33 | * - [3,2,1,5,4] 34 | * - [3,2,1,5,4] 35 | * - [3,2,1,5,4] 36 | * 37 | * 提示: 38 | * 1 <= nums.length <= 200 39 | * 1 <= nums[i] <= 100 40 | * 1 <= k <= 99 41 | * 通过次数 10,319 提交次数 12,004 42 | */ 43 | public class CountNumberOfPairsWithAbsoluteDifferenceK { 44 | 45 | public int countKDifference(int[] nums, int k) { 46 | int count = 0; 47 | Map map = new HashMap<>(); 48 | for (int num : nums) { 49 | count += map.getOrDefault(num - k, 0) + map.getOrDefault(num + k, 0); 50 | map.put(num, map.getOrDefault(num, 0) + 1); 51 | } 52 | return count; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/com/hncboy/CountNumbersWithUniqueDigits.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2022/4/11 8:39 6 | * 357.统计各位数字都不同的数字个数 7 | * 8 | * 给你一个整数 n ,统计并返回各位数字都不同的数字 x 的个数,其中 0 <= x < 10n 。 9 | * 10 | * 示例 1: 11 | * 输入:n = 2 12 | * 输出:91 13 | * 解释:答案应为除去 11、22、33、44、55、66、77、88、99 外,在 0 ≤ x < 100 范围内的所有数字。 14 | * 15 | * 示例 2: 16 | * 输入:n = 0 17 | * 输出:1 18 | * 19 | * 提示: 20 | * 0 <= n <= 8 21 | * 通过次数 30,970 提交次数 57,755 22 | * 23 | * 来源:力扣(LeetCode) 24 | * 链接:https://leetcode-cn.com/problems/count-numbers-with-unique-digits 25 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 26 | */ 27 | public class CountNumbersWithUniqueDigits { 28 | 29 | public int countNumbersWithUniqueDigits(int n) { 30 | if (n == 0) { 31 | return 1; 32 | } 33 | int result = 10; 34 | for (int i = 2, last = 9; i <= n; i++) { 35 | int cur = last * (10 - i + 1); 36 | last = cur; 37 | result += cur; 38 | } 39 | return result; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/com/hncboy/CountOfMatchesInTournament.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2022/1/25 8:45 6 | * 1688.比赛中的配对次数 7 | * 8 | * 给你一个整数 n ,表示比赛中的队伍数。比赛遵循一种独特的赛制: 9 | * 10 | * 如果当前队伍数是 偶数 ,那么每支队伍都会与另一支队伍配对。总共进行 n / 2 场比赛,且产生 n / 2 支队伍进入下一轮。 11 | * 如果当前队伍数为 奇数 ,那么将会随机轮空并晋级一支队伍,其余的队伍配对。总共进行 (n - 1) / 2 场比赛,且产生 (n - 1) / 2 + 1 支队伍进入下一轮。 12 | * 返回在比赛中进行的配对次数,直到决出获胜队伍为止。 13 | * 14 | * 示例 1: 15 | * 输入:n = 7 16 | * 输出:6 17 | * 解释:比赛详情: 18 | * - 第 1 轮:队伍数 = 7 ,配对次数 = 3 ,4 支队伍晋级。 19 | * - 第 2 轮:队伍数 = 4 ,配对次数 = 2 ,2 支队伍晋级。 20 | * - 第 3 轮:队伍数 = 2 ,配对次数 = 1 ,决出 1 支获胜队伍。 21 | * 总配对次数 = 3 + 2 + 1 = 6 22 | * 23 | * 示例 2: 24 | * 输入:n = 14 25 | * 输出:13 26 | * 解释:比赛详情: 27 | * - 第 1 轮:队伍数 = 14 ,配对次数 = 7 ,7 支队伍晋级。 28 | * - 第 2 轮:队伍数 = 7 ,配对次数 = 3 ,4 支队伍晋级。 29 | * - 第 3 轮:队伍数 = 4 ,配对次数 = 2 ,2 支队伍晋级。 30 | * - 第 4 轮:队伍数 = 2 ,配对次数 = 1 ,决出 1 支获胜队伍。 31 | * 总配对次数 = 7 + 3 + 2 + 1 = 13 32 | * 33 | * 提示: 34 | * 1 <= n <= 200 35 | * 通过次数 24,741 提交次数 30,151 36 | */ 37 | public class CountOfMatchesInTournament { 38 | 39 | public static void main(String[] args) { 40 | CountOfMatchesInTournament c = new CountOfMatchesInTournament(); 41 | System.out.println(c.numberOfMatches(7)); 42 | } 43 | 44 | public int numberOfMatches(int n) { 45 | return n - 1; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/com/hncboy/CountPrimes.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hncboy/LeetCode/ab66f67d0a7a6667f1b21e8f0be503eb351863bd/src/com/hncboy/CountPrimes.java -------------------------------------------------------------------------------- /src/com/hncboy/CountingBits.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/10/26 9:32 6 | * @description 338.比特位计数 7 | * 8 | * 给你一个整数 n ,对于 0 <= i <= n 中的每个 i ,计算其二进制表示中 1 的个数 ,返回一个长度为 n + 1 的数组 ans 作为答案。 9 | * 10 | * 示例 1: 11 | * 输入:n = 2 12 | * 输出:[0,1,1] 13 | * 解释: 14 | * 0 --> 0 15 | * 1 --> 1 16 | * 2 --> 10 17 | * 18 | * 示例 2: 19 | * 输入:n = 5 20 | * 输出:[0,1,1,2,1,2] 21 | * 解释: 22 | * 0 --> 0 23 | * 1 --> 1 24 | * 2 --> 10 25 | * 3 --> 11 26 | * 4 --> 100 27 | * 5 --> 101 28 | * 29 | * 提示: 30 | * 0 <= n <= 105 31 | * 32 | * 进阶: 33 | * 很容易就能实现时间复杂度为 O(n log n) 的解决方案,你可以在线性时间复杂度 O(n) 内用一趟扫描解决此问题吗? 34 | * 你能不使用任何内置函数解决此问题吗?(如,C++ 中的 __builtin_popcount ) 35 | * 36 | * 来源:力扣(LeetCode) 37 | * 链接:https://leetcode-cn.com/problems/counting-bits 38 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 39 | */ 40 | public class CountingBits { 41 | 42 | public int[] countBits(int n) { 43 | int[] bits = new int[n + 1]; 44 | for (int i = 1; i <= n; i++) { 45 | // i & (i-1) 用于去掉 i 最右边的 1,因此 i&(i-1) 比 i 小 46 | // i&(i-1) 中 1 的个数已经计算过了,此时只需要加 1 47 | bits[i] = bits[i & (i - 1)] + 1; 48 | } 49 | return bits; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/com/hncboy/DayOfTheWeek.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hncboy/LeetCode/ab66f67d0a7a6667f1b21e8f0be503eb351863bd/src/com/hncboy/DayOfTheWeek.java -------------------------------------------------------------------------------- /src/com/hncboy/DecompressRunLengthEncodedList.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | /** 8 | * @author hncboy 9 | * @date 2020/1/11 22:25 10 | * @description 1313.解压缩编码列表 11 | * 12 | * 给你一个以行程长度编码压缩的整数列表 nums 。 13 | * 考虑每相邻两个元素 [a, b] = [nums[2*i], nums[2*i+1]] (其中 i >= 0 ), 14 | * 每一对都表示解压后有 a 个值为 b 的元素。 15 | * 请你返回解压后的列表。 16 | * 17 | * 示例: 18 | * 输入:nums = [1,2,3,4] 19 | * 输出:[2,4,4,4] 20 | * 21 | * 提示: 22 | * 2 <= nums.length <= 100 23 | * nums.length % 2 == 0 24 | * 1 <= nums[i] <= 100 25 | */ 26 | public class DecompressRunLengthEncodedList { 27 | 28 | public static void main(String[] args) { 29 | DecompressRunLengthEncodedList d = new DecompressRunLengthEncodedList(); 30 | System.out.println(Arrays.toString(d.decompressRLElist(new int[]{1, 2, 3, 4, 5}))); 31 | } 32 | 33 | public int[] decompressRLElist(int[] nums) { 34 | List list = new ArrayList<>(); 35 | for (int i = 0; i * 2 + 1 < nums.length; i++) { 36 | for (int j = 0; j < nums[i * 2]; j++) { 37 | list.add(nums[i * 2 + 1]); 38 | } 39 | } 40 | 41 | int[] result = new int[list.size()]; 42 | for (int i = 0; i < list.size(); i++) { 43 | result[i] = list.get(i); 44 | } 45 | 46 | return result; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/com/hncboy/DecreaseElementsToMakeArrayZigzag.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hncboy/LeetCode/ab66f67d0a7a6667f1b21e8f0be503eb351863bd/src/com/hncboy/DecreaseElementsToMakeArrayZigzag.java -------------------------------------------------------------------------------- /src/com/hncboy/DeleteNodeInALinkedList.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/9/25 10:47 6 | * @description 237.删除链表中的节点 7 | * 8 | * 请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点。 9 | * 10 | * 示例 1: 11 | * 输入: head = [4,5,1,9], node = 5 12 | * 输出: [4,1,9] 13 | * 解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9. 14 | * 15 | * 示例 2: 16 | * 输入: head = [4,5,1,9], node = 1 17 | * 输出: [4,5,9] 18 | * 解释: 给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9. 19 | *   20 | * 21 | * 说明: 22 | * 链表至少包含两个节点。 23 | * 链表中所有节点的值都是唯一的。 24 | * 给定的节点为非末尾节点并且一定是链表中的一个有效节点。 25 | * 不要从你的函数中返回任何结果。 26 | */ 27 | public class DeleteNodeInALinkedList { 28 | 29 | public static void main(String[] args) { 30 | ListNode node = new ListNode(4); 31 | node.next = new ListNode(5); 32 | node.next.next = new ListNode(1); 33 | node.next.next.next = new ListNode(9); 34 | new DeleteNodeInALinkedList().deleteNode(node.next); 35 | } 36 | 37 | private void deleteNode(ListNode node) { 38 | // 无法知道 node 的上一个节点,则将下一个节点的值赋给 node 39 | // 将 node 的下一个节点指向下下个节点 40 | node.val = node.next.val; 41 | node.next = node.next.next; 42 | } 43 | } 44 | 45 | class ListNode { 46 | int val; 47 | ListNode next; 48 | 49 | ListNode(int x) { 50 | val = x; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/com/hncboy/DetectCapital.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2020/1/8 21:10 6 | * @description 520.检测大写字母 7 | * 8 | * 给定一个单词,你需要判断单词的大写使用是否正确。 9 | * 我们定义,在以下情况时,单词的大写用法是正确的: 10 | * 全部字母都是大写,比如"USA"。 11 | * 单词中所有字母都不是大写,比如"leetcode"。 12 | * 如果单词不只含有一个字母,只有首字母大写, 比如 "Google"。 13 | * 否则,我们定义这个单词没有正确使用大写字母。 14 | * 15 | * 示例 1: 16 | * 输入: "USA" 17 | * 输出: True 18 | * 19 | * 示例 2: 20 | * 输入: "FlaG" 21 | * 输出: False 22 | * 注意: 输入是由大写和小写拉丁字母组成的非空单词。 23 | */ 24 | public class DetectCapital { 25 | 26 | public static void main(String[] args) { 27 | DetectCapital d = new DetectCapital(); 28 | System.out.println(d.detectCapitalUse("USA")); 29 | System.out.println(d.detectCapitalUse("FlaG")); 30 | } 31 | 32 | private boolean detectCapitalUse(String word) { 33 | // 大写字母个数 34 | int upper = 0; 35 | // 小写字母个数 36 | int lower = 0; 37 | for (char ch : word.toCharArray()) { 38 | if (ch <= 'Z') { 39 | upper++; 40 | } else { 41 | lower++; 42 | } 43 | } 44 | 45 | // 1.全部字母都是大写,比如"USA"。 46 | // 2.单词中所有字母都不是大写,比如"leetcode"。 47 | // 3.如果单词不只含有一个字母,只有首字母大写, 比如 "Google"。 48 | return upper == word.length() || lower == word.length() || (upper == 1 && word.charAt(0) <= 'Z'); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/com/hncboy/DetermineColorOfAChessboardSquare.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2022/12/8 12:30 6 | * 1812.判断国际象棋棋盘中一个格子的颜色 7 | */ 8 | public class DetermineColorOfAChessboardSquare { 9 | 10 | public static void main(String[] args) { 11 | DetermineColorOfAChessboardSquare d = new DetermineColorOfAChessboardSquare(); 12 | System.out.println(d.squareIsWhite("a1")); 13 | System.out.println(d.squareIsWhite("h3")); 14 | System.out.println(d.squareIsWhite("c7")); 15 | } 16 | 17 | public boolean squareIsWhite(String coordinates) { 18 | // 下标统一从 1 开始,如果相加是奇数,则白色,否则黑色 19 | return ((coordinates.charAt(0) - 'a' + 1) + (coordinates.charAt(1) - '0')) % 2 == 1; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/com/hncboy/DiameterOfBinaryTree.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2020/3/10 18:11 6 | * @description 543.二叉树的直径 7 | * 8 | * 给定一棵二叉树,你需要计算它的直径长度。 9 | * 一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过根结点。 10 | * 11 | * 示例 : 12 | * 给定二叉树 13 | * 14 | * 1 15 | * / \ 16 | * 2 3 17 | * / \ 18 | * 4 5 19 | * 返回 3, 它的长度是路径 [4,2,1,3] 或者 [5,2,1,3]。 20 | * 注意:两结点之间的路径长度是以它们之间边的数目表示。 21 | */ 22 | public class DiameterOfBinaryTree { 23 | 24 | private int result; 25 | 26 | private int diameterOfBinaryTree(TreeNode root) { 27 | result = 1; 28 | depth(root); 29 | return result - 1; 30 | } 31 | 32 | private int depth(TreeNode node) { 33 | if (node == null) { 34 | return 0; 35 | } 36 | // 最大深度为,经过一个节点,该节点的左右节点深度之和 +1 37 | int left = depth(node.left); 38 | int right = depth(node.right); 39 | result = Math.max(result, left + right + 1); 40 | return Math.max(left, right) + 1; 41 | } 42 | 43 | private static class TreeNode { 44 | int val; 45 | TreeNode left; 46 | TreeNode right; 47 | 48 | TreeNode(int x) { 49 | val = x; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/com/hncboy/DistributeCandies.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2020/3/5 0:19 6 | * @description 575.分糖果 7 | * 8 | * 给定一个偶数长度的数组,其中不同的数字代表着不同种类的糖果,每一个数字代表一个糖果。 9 | * 你需要把这些糖果平均分给一个弟弟和一个妹妹。返回妹妹可以获得的最大糖果的种类数。 10 | * 11 | * 示例 1: 12 | * 输入: candies = [1,1,2,2,3,3] 13 | * 输出: 3 14 | * 解析: 一共有三种种类的糖果,每一种都有两个。 15 | * 最优分配方案:妹妹获得[1,2,3],弟弟也获得[1,2,3]。这样使妹妹获得糖果的种类数最多。 16 | * 17 | * 示例 2 : 18 | * 输入: candies = [1,1,2,3] 19 | * 输出: 2 20 | * 解析: 妹妹获得糖果[2,3],弟弟获得糖果[1,1],妹妹有两种不同的糖果,弟弟只有一种。 21 | * 这样使得妹妹可以获得的糖果种类数最多。 22 | * 23 | * 注意: 24 | * 数组的长度为[2, 10,000],并且确定为偶数。 25 | * 数组中数字的大小在范围[-100,000, 100,000]内。 26 | */ 27 | public class DistributeCandies { 28 | 29 | private int distributeCandies(int[] candies) { 30 | boolean[] check = new boolean[200001]; 31 | // 每人平均分得的糖果数量 32 | int average = candies.length / 2; 33 | int result = 0; 34 | for (int candy : candies) { 35 | // 数组的 [100000, 200000] 用于判断种类 36 | int i = candy + 100000; 37 | // 判断是否有该种糖果 38 | if (!check[i]) { 39 | check[i] = true; 40 | result++; 41 | if (result >= average) { 42 | return average; 43 | } 44 | } 45 | } 46 | return result; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/com/hncboy/DivisorGame.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/10/22 13:52 6 | * @description 1025.除数博弈 7 | * 8 | * 爱丽丝和鲍勃一起玩游戏,他们轮流行动。爱丽丝先手开局。 9 | * 最初,黑板上有一个数字 N 。在每个玩家的回合,玩家需要执行以下操作: 10 | * 11 | * 选出任一 x,满足 0 < x < N 且 N % x == 0 。 12 | * 用 N - x 替换黑板上的数字 N 。 13 | * 如果玩家无法执行这些操作,就会输掉游戏。 14 | * 只有在爱丽丝在游戏中取得胜利时才返回 True,否则返回 false。 15 | * 假设两个玩家都以最佳状态参与游戏。 16 | *   17 | * 18 | * 示例 1: 19 | * 输入:2 20 | * 输出:true 21 | * 解释:爱丽丝选择 1,鲍勃无法进行操作。 22 | * 23 | * 示例 2: 24 | * 输入:3 25 | * 输出:false 26 | * 解释:爱丽丝选择 1,鲍勃也选择 1,然后爱丽丝无法进行操作。 27 | *   28 | * 提示: 29 | * 1 <= N <= 1000 30 | */ 31 | public class DivisorGame { 32 | 33 | public static void main(String[] args) { 34 | DivisorGame d = new DivisorGame(); 35 | System.out.println(d.divisorGame(2)); 36 | System.out.println(d.divisorGame(3)); 37 | } 38 | 39 | private boolean divisorGame(int N) { 40 | return N % 2 ==0; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/com/hncboy/ElementAppearingMoreThan25InSortedArray.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/12/21 19:33 6 | * @description 1287.有序数组中出现次数超过25%的元素 7 | * 8 | * 给你一个非递减的 有序 整数数组,已知这个数组中恰好有一个整数,它的出现次数超过数组元素总数的 25%。 9 | * 请你找到并返回这个整数 10 | * 11 | * 示例: 12 | * 输入:arr = [1,2,2,6,6,6,6,7,10] 13 | * 输出:6 14 | *   15 | * 提示: 16 | * 1 <= arr.length <= 10^4 17 | * 0 <= arr[i] <= 10^5 18 | */ 19 | public class ElementAppearingMoreThan25InSortedArray { 20 | 21 | public static void main(String[] args) { 22 | ElementAppearingMoreThan25InSortedArray e = new ElementAppearingMoreThan25InSortedArray(); 23 | System.out.println(e.findSpecialInteger(new int[]{1, 2, 2, 6, 6, 6, 6, 7, 10})); 24 | } 25 | 26 | private int findSpecialInteger(int[] arr) { 27 | for (int i = 0, n = arr.length / 4; i < arr.length - n; i++) { 28 | if (arr[i] == arr[i + n]) { 29 | return arr[i]; 30 | } 31 | } 32 | return arr[0]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/com/hncboy/EliminationGame.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2022/1/3 13:07 6 | * 390.消除游戏 7 | * 8 | * 列表 arr 由在范围 [1, n] 中的所有整数组成,并按严格递增排序。请你对 arr 应用下述算法: 9 | * 从左到右,删除第一个数字,然后每隔一个数字删除一个,直到到达列表末尾。 10 | * 重复上面的步骤,但这次是从右到左。也就是,删除最右侧的数字,然后剩下的数字每隔一个删除一个。 11 | * 不断重复这两步,从左到右和从右到左交替进行,直到只剩下一个数字。 12 | * 给你整数 n ,返回 arr 最后剩下的数字。 13 | * 14 | * 示例 1: 15 | * 输入:n = 9 16 | * 输出:6 17 | * 解释: 18 | * arr = [1, 2, 3, 4, 5, 6, 7, 8, 9] 19 | * arr = [2, 4, 6, 8] 20 | * arr = [2, 6] 21 | * arr = [6] 22 | * 23 | * 示例 2: 24 | * 输入:n = 1 25 | * 输出:1 26 | * 27 | * 提示: 28 | * 1 <= n <= 109 29 | * 通过次数 26,392 提交次数 43,640 30 | * 31 | * 来源:力扣(LeetCode) 32 | * 链接:https://leetcode-cn.com/problems/elimination-game 33 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 34 | */ 35 | public class EliminationGame { 36 | 37 | public int lastRemaining(int n) { 38 | int head = 1; 39 | int step = 1; 40 | // true 表示从左边开始,false 表示从右边开始 41 | boolean direction = true; 42 | 43 | while (n > 1) { 44 | // 从左边开始移除 or(从右边开始移除,数列总数为奇数),将 head 移动到下一个位置 45 | if (direction || n % 2 == 1) { 46 | head += step; 47 | } 48 | 49 | // 步长 * 2 50 | step *= 2; 51 | // 总数 / 2 52 | n /= 2; 53 | // 取反移除方向 54 | direction = !direction; 55 | } 56 | 57 | return head; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/com/hncboy/ExcelSheetColumnNumber.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/12/10 10:47 6 | * @description 171.Excel表列序号 7 | * 8 | * 给定一个Excel表格中的列名称,返回其相应的列序号。 9 | * 10 | * 例如, 11 | * A -> 1 12 | * B -> 2 13 | * C -> 3 14 | * ... 15 | * Z -> 26 16 | * AA -> 27 17 | * AB -> 28 18 | * ... 19 | * 20 | * 示例 1: 21 | * 输入: "A" 22 | * 输出: 1 23 | * 24 | * 示例 2: 25 | * 输入: "AB" 26 | * 输出: 28 27 | * 28 | * 示例 3: 29 | * 输入: "ZY" 30 | * 输出: 701 31 | */ 32 | public class ExcelSheetColumnNumber { 33 | 34 | public static void main(String[] args) { 35 | ExcelSheetColumnNumber e = new ExcelSheetColumnNumber(); 36 | System.out.println(e.titleToNumber("A")); 37 | System.out.println(e.titleToNumber("AB")); 38 | System.out.println(e.titleToNumber("ZY")); 39 | System.out.println(e.titleToNumber("AAA")); 40 | } 41 | 42 | private int titleToNumber(String s) { 43 | int result = 0; 44 | for (int i = 0; i < s.length(); i++) { 45 | result = result * 26 + s.charAt(i) - 'A' + 1; 46 | } 47 | return result; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/com/hncboy/ExcelSheetColumnTitle.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2020/2/9 15:54 6 | * @description 168.Excel表列名称 7 | * 8 | * 给定一个正整数,返回它在 Excel 表中相对应的列名称。 9 | * 例如, 10 | * 1 -> A 11 | * 2 -> B 12 | * 3 -> C 13 | * ... 14 | * 26 -> Z 15 | * 27 -> AA 16 | * 28 -> AB 17 | * ... 18 | * 19 | * 示例 1: 20 | * 输入: 1 21 | * 输出: "A" 22 | * 23 | * 示例 2: 24 | * 输入: 28 25 | * 输出: "AB" 26 | * 27 | * 示例 3: 28 | * 输入: 701 29 | * 输出: "ZY" 30 | */ 31 | public class ExcelSheetColumnTitle { 32 | 33 | public static void main(String[] args) { 34 | ExcelSheetColumnTitle e = new ExcelSheetColumnTitle(); 35 | System.out.println(e.convertToTitle(1)); 36 | System.out.println(e.convertToTitle(28)); 37 | System.out.println(e.convertToTitle(701)); 38 | } 39 | 40 | private String convertToTitle(int n) { 41 | StringBuilder sb = new StringBuilder(); 42 | while (n > 0) { 43 | // 逆序取出字母 44 | int c = n % 26; 45 | if (c == 0) { 46 | c = 26; 47 | n -= 1; 48 | } 49 | sb.insert(0, (char) ('A' + c - 1)); 50 | n /= 26; 51 | } 52 | return sb.toString(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/com/hncboy/FactorialTrailingZeroes.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/12/10 11:04 6 | * 172.阶乘后的零 7 | * 8 | * 给定一个整数 n ,返回 n! 结果中尾随零的数量。 9 | * 提示 n! = n * (n - 1) * (n - 2) * ... * 3 * 2 * 1 10 | * 11 | * 示例 1: 12 | * 输入:n = 3 13 | * 输出:0 14 | * 解释:3! = 6 ,不含尾随 0 15 | * 16 | * 示例 2: 17 | * 输入:n = 5 18 | * 输出:1 19 | * 解释:5! = 120 ,有一个尾随 0 20 | * 21 | * 示例 3: 22 | * 输入:n = 0 23 | * 输出:0 24 | * 25 | * 提示: 26 | * 0 <= n <= 104 27 | * 28 | * 进阶:你可以设计并实现对数时间复杂度的算法来解决此问题吗? 29 | * 通过次数 111,957 提交次数 242,315 30 | * 31 | * 来源:力扣(LeetCode) 32 | * 链接:https://leetcode-cn.com/problems/factorial-trailing-zeroes 33 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 34 | */ 35 | public class FactorialTrailingZeroes { 36 | 37 | public static void main(String[] args) { 38 | FactorialTrailingZeroes f = new FactorialTrailingZeroes(); 39 | System.out.println(f.trailingZeroes(3)); 40 | System.out.println(f.trailingZeroes(5)); 41 | System.out.println(-1%5); 42 | } 43 | 44 | public int trailingZeroes(int n) { 45 | // 当前数乘以10就能得到一个0 46 | // 10 = 2*5,2出现的次数明显多余5的次数,所以统计 5 出现的次数 47 | // 每隔5个数,出现1个5,每个25个数出现2个5,每个125个数,出现3个5,依次类推 48 | int count = 0; 49 | while (n > 0) { 50 | count += n / 5; 51 | n /= 5; 52 | } 53 | return count; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/com/hncboy/FibonacciNumber.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/12/11 23:28 6 | * @description 509.斐波那契数 7 | * 8 | * 斐波那契数,通常用 F(n) 表示,形成的序列称为斐波那契数列。该数列由 0 和 1 开始, 9 | * 后面的每一项数字都是前面两项数字的和。也就是: 10 | * 11 | * F(0) = 0,   F(1) = 1 12 | * F(N) = F(N - 1) + F(N - 2), 其中 N > 1. 13 | * 给定 N,计算 F(N)。 14 | * 15 | * 示例 1: 16 | * 输入:2 17 | * 输出:1 18 | * 解释:F(2) = F(1) + F(0) = 1 + 0 = 1. 19 | * 20 | * 示例 2: 21 | * 输入:3 22 | * 输出:2 23 | * 解释:F(3) = F(2) + F(1) = 1 + 1 = 2. 24 | * 25 | * 示例 3: 26 | * 输入:4 27 | * 输出:3 28 | * 解释:F(4) = F(3) + F(2) = 2 + 1 = 3. 29 | *   30 | * 提示: 31 | * 0 ≤ N ≤ 30 32 | */ 33 | public class FibonacciNumber { 34 | 35 | public static void main(String[] args) { 36 | FibonacciNumber f = new FibonacciNumber(); 37 | System.out.println(f.fib2(2)); 38 | System.out.println(f.fib2(3)); 39 | System.out.println(f.fib2(4)); 40 | System.out.println(f.fib2(6)); 41 | } 42 | 43 | public int fib2(int N) { 44 | if (N == 0 || N == 1) { 45 | return N; 46 | } 47 | 48 | int a = 0; 49 | int b = 1; 50 | for (int i = 2; i <= N; i++) { 51 | int temp = b; 52 | b += a; 53 | a = temp; 54 | } 55 | return b; 56 | } 57 | 58 | 59 | public int fib(int N) { 60 | return N == 0 || N == 1 ? N : fib(N - 1) + fib(N - 2); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/com/hncboy/FindCenterOfStarGraph.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2022/2/18 9:01 6 | * 1791.找出星型图的中心节点 7 | * 8 | * 有一个无向的 星型 图,由 n 个编号从 1 到 n 的节点组成。星型图有一个 中心 节点, 9 | * 并且恰有 n - 1 条边将中心节点与其他每个节点连接起来。 10 | * 11 | * 给你一个二维整数数组 edges ,其中 edges[i] = [ui, vi] 表示在节点 ui 和 vi 之间存在一条边。请你找出并返回 edges 所表示星型图的中心节点。 12 | * 13 | * 示例 1: 14 | * 输入:edges = [[1,2],[2,3],[4,2]] 15 | * 输出:2 16 | * 解释:如上图所示,节点 2 与其他每个节点都相连,所以节点 2 是中心节点。 17 | * 18 | * 示例 2: 19 | * 输入:edges = [[1,2],[5,1],[1,3],[1,4]] 20 | * 输出:1 21 | * 22 | * 提示: 23 | * 3 <= n <= 105 24 | * edges.length == n - 1 25 | * edges[i].length == 2 26 | * 1 <= ui, vi <= n 27 | * ui != vi 28 | * 题目数据给出的 edges 表示一个有效的星型图 29 | * 通过次数 16,963 提交次数 20,483 30 | * 31 | * 来源:力扣(LeetCode) 32 | * 链接:https://leetcode-cn.com/problems/find-center-of-star-graph 33 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 34 | */ 35 | public class FindCenterOfStarGraph { 36 | 37 | public int findCenter(int[][] edges) { 38 | // 中心节点会在每条边中出现 39 | return edges[0][0] == edges[1][0] || edges[0][0] == edges[1][1] ? edges[0][0] : edges[0][1]; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/com/hncboy/FindNUniqueIntegersSumUpToZero.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hncboy/LeetCode/ab66f67d0a7a6667f1b21e8f0be503eb351863bd/src/com/hncboy/FindNUniqueIntegersSumUpToZero.java -------------------------------------------------------------------------------- /src/com/hncboy/FindNumbersWithEvenNumberOfDigits.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/12/22 10:10 6 | * @description 1295.统计位数为偶数的数字 7 | * 8 | * 给你一个整数数组 nums,请你返回其中位数为 偶数 的数字的个数。 9 | * 10 | * 示例 1: 11 | * 输入:nums = [12,345,2,6,7896] 12 | * 输出:2 13 | * 解释: 14 | * 12 是 2 位数字(位数为偶数)  15 | * 345 是 3 位数字(位数为奇数)   16 | * 2 是 1 位数字(位数为奇数)  17 | * 6 是 1 位数字 位数为奇数)  18 | * 7896 是 4 位数字(位数为偶数)   19 | * 因此只有 12 和 7896 是位数为偶数的数字 20 | * 21 | * 示例 2: 22 | * 输入:nums = [555,901,482,1771] 23 | * 输出:1 24 | * 解释: 25 | * 只有 1771 是位数为偶数的数字。 26 | * 27 | * 提示: 28 | * 1 <= nums.length <= 500 29 | * 1 <= nums[i] <= 10^5 30 | */ 31 | public class FindNumbersWithEvenNumberOfDigits { 32 | 33 | public static void main(String[] args) { 34 | FindNumbersWithEvenNumberOfDigits f = new FindNumbersWithEvenNumberOfDigits(); 35 | System.out.println(f.findNumbers(new int[]{12, 345, 2, 6, 7896})); 36 | System.out.println(f.findNumbers(new int[]{555, 901, 482, 1771})); 37 | } 38 | 39 | private int findNumbers(int[] nums) { 40 | int count = 0; 41 | for (int num : nums) { 42 | if (num > 10 && num < 100) { 43 | count++; 44 | } else if (num > 1000 && num < 10000) { 45 | count++; 46 | } 47 | } 48 | return count; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/com/hncboy/FindPositiveIntegerSolutionForAGivenEquation.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | /** 8 | * @author hncboy 9 | * @date 2019/10/27 10:30 10 | * @description 1237.找出给定方程的正整数解 11 | */ 12 | public class FindPositiveIntegerSolutionForAGivenEquation { 13 | 14 | public List> findSolution(CustomFunction customfunction, int z) { 15 | List> result = new ArrayList<>(); 16 | for (int i = 1; i <= z; i++) { 17 | for (int j = i; j <= z; j++) { 18 | if (customfunction.f(i, j) == z 19 | && customfunction.f(i, j) < customfunction.f(i, j + 1) 20 | && customfunction.f(i, j) < customfunction.f(i + 1, j)) { 21 | result.add(Arrays.asList(i, j)); 22 | } 23 | if (i != j && customfunction.f(j, i) == z 24 | && customfunction.f(j, i) < customfunction.f(j, i + 1) 25 | && customfunction.f(j, i) < customfunction.f(j + 1, i)) { 26 | result.add(Arrays.asList(j, i)); 27 | } 28 | } 29 | } 30 | return result; 31 | } 32 | 33 | interface CustomFunction { 34 | int f(int x, int y); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/com/hncboy/FindTheMinimumNumberOfFibonacciNumbersWhoseSumIsK.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2022/2/3 19:25 6 | * 1414.和为 K 的最少斐波那契数字数目 7 | * 8 | * 给你数字 k ,请你返回和为 k 的斐波那契数字的最少数目,其中,每个斐波那契数字都可以被使用多次。 9 | * 斐波那契数字定义为: 10 | * 11 | * F1 = 1 12 | * F2 = 1 13 | * Fn = Fn-1 + Fn-2 , 其中 n > 2 。 14 | * 数据保证对于给定的 k ,一定能找到可行解。 15 | * 16 | * 示例 1: 17 | * 输入:k = 7 18 | * 输出:2 19 | * 解释:斐波那契数字为:1,1,2,3,5,8,13,…… 20 | * 对于 k = 7 ,我们可以得到 2 + 5 = 7 。 21 | * 22 | * 示例 2: 23 | * 输入:k = 10 24 | * 输出:2 25 | * 解释:对于 k = 10 ,我们可以得到 2 + 8 = 10 。 26 | * 27 | * 示例 3: 28 | * 输入:k = 19 29 | * 输出:3 30 | * 解释:对于 k = 19 ,我们可以得到 1 + 5 + 13 = 19 。 31 | * 32 | * 提示: 33 | * 1 <= k <= 10^9 34 | * 通过次数 19,265 提交次数 28,190 35 | */ 36 | public class FindTheMinimumNumberOfFibonacciNumbersWhoseSumIsK { 37 | 38 | public int findMinFibonacciNumbers(int k) { 39 | int a = 1; 40 | int b = 1; 41 | // 找到不大于 k 的斐波那契数 42 | while (b <= k) { 43 | int c = a + b; 44 | a = b; 45 | b = c; 46 | } 47 | 48 | int result = 0; 49 | while (k != 0) { 50 | if (k >= b) { 51 | k -= b; 52 | result++; 53 | } 54 | int c = b - a; 55 | b = a; 56 | a = c; 57 | } 58 | return result; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/com/hncboy/FizzBuzz.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @author hncboy 8 | * @date 2019/10/17 8:28 9 | * @description 412.Fizz Buzz 10 | * 11 | * 写一个程序,输出从 1 到 n 数字的字符串表示。 12 | * 1. 如果 n 是3的倍数,输出“Fizz”; 13 | * 2. 如果 n 是5的倍数,输出“Buzz”; 14 | * 3.如果 n 同时是3和5的倍数,输出 “FizzBuzz”。 15 | * 16 | * 示例: 17 | * n = 15, 18 | * 返回: 19 | * [ 20 | * "1", 21 | * "2", 22 | * "Fizz", 23 | * "4", 24 | * "Buzz", 25 | * "Fizz", 26 | * "7", 27 | * "8", 28 | * "Fizz", 29 | * "Buzz", 30 | * "11", 31 | * "Fizz", 32 | * "13", 33 | * "14", 34 | * "FizzBuzz" 35 | * ] 36 | */ 37 | public class FizzBuzz { 38 | 39 | public static void main(String[] args) { 40 | FizzBuzz f = new FizzBuzz(); 41 | System.out.println(f.fizzBuzz(15)); 42 | } 43 | 44 | private List fizzBuzz(int n) { 45 | List result = new ArrayList<>(); 46 | for (int i = 1; i <= n; i++) { 47 | result.add(fizz(i)); 48 | } 49 | return result; 50 | } 51 | 52 | private String fizz(int n) { 53 | if (n%3 == 0 && n%5 == 0) { 54 | return "FizzBuzz"; 55 | } 56 | if (n%3 == 0) { 57 | return "Fizz"; 58 | } 59 | if (n%5 == 0) { 60 | return "Buzz"; 61 | } 62 | return String.valueOf(n); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/com/hncboy/GlobalAndLocalInversions.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/11/30 14:25 6 | * @description 775.全局倒置与局部倒置 7 | * 8 | * 数组 A 是 [0, 1, ..., N - 1] 的一种排列,N 是数组 A 的长度。 9 | * 全局倒置指的是 i,j 满足 0 <= i < j < N 并且 A[i] > A[j] , 10 | * 局部倒置指的是 i 满足 0 <= i < N 并且 A[i] > A[i+1] 。 11 | * 当数组 A 中全局倒置的数量等于局部倒置的数量时,返回 true 。 12 | *   13 | * 示例 1: 14 | * 输入: A = [1,0,2] 15 | * 输出: true 16 | * 解释: 有 1 个全局倒置,和 1 个局部倒置。 17 | * 18 | * 示例 2: 19 | * 输入: A = [1,2,0] 20 | * 输出: false 21 | * 解释: 有 2 个全局倒置,和 1 个局部倒置。 22 | * 23 | * 注意: 24 | * A 是 [0, 1, ..., A.length - 1] 的一种排列 25 | * A 的长度在 [1, 5000]之间 26 | * 这个问题的时间限制已经减少了。 27 | */ 28 | public class GlobalAndLocalInversions { 29 | 30 | public static void main(String[] args) { 31 | GlobalAndLocalInversions g = new GlobalAndLocalInversions(); 32 | System.out.println(g.isIdealPermutation(new int[]{1, 0, 2})); 33 | System.out.println(g.isIdealPermutation(new int[]{1, 2, 0})); 34 | } 35 | 36 | private boolean isIdealPermutation(int[] A) { 37 | // 局部倒置属于全局倒置,下标和对应的数的差不超过1 38 | for (int i = 0; i < A.length; i++) { 39 | if (Math.abs(A[i] - i) > 1) { 40 | return false; 41 | } 42 | } 43 | return true; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/com/hncboy/GreatestCommonDivisorOfStrings.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2020/3/12 1:34 6 | * @description 1071.字符串的最大公因子 7 | * 8 | * 对于字符串 S 和 T,只有在 S = T + ... + T(T 与自身连接 1 次或多次)时,我们才认定 “T 能除尽 S”。 9 | * 返回最长字符串 X,要求满足 X 能除尽 str1 且 X 能除尽 str2。 10 | * 11 | * 示例 1: 12 | * 输入:str1 = "ABCABC", str2 = "ABC" 13 | * 输出:"ABC" 14 | * 15 | * 示例 2: 16 | * 输入:str1 = "ABABAB", str2 = "ABAB" 17 | * 输出:"AB" 18 | * 19 | * 示例 3: 20 | * 输入:str1 = "LEET", str2 = "CODE" 21 | * 输出:"" 22 | *   23 | * 提示: 24 | * 1 <= str1.length <= 1000 25 | * 1 <= str2.length <= 1000 26 | * str1[i] 和 str2[i] 为大写英文字母 27 | */ 28 | public class GreatestCommonDivisorOfStrings { 29 | 30 | private String gcdOfStrings(String str1, String str2) { 31 | // str1=m*最大公约数,str2=n*最大公约数 32 | // str1+str2=(m+n)*最大公约数,所以满足拥有最大公约数的条件:str1+str2=str2+str1 33 | if (!(str1 + str2).equals(str2 + str1)) { 34 | return ""; 35 | } 36 | // 在确定有有解的情况下,最优解的长度为 gcd(str1.length(), str2.length()) 的字符串 37 | return str1.substring(0, gcd(str1.length(), str2.length())); 38 | } 39 | 40 | private int gcd(int a, int b) { 41 | return b == 0 ? a : gcd(b, a % b); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/com/hncboy/HIndexII.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2020/1/6 16:27 6 | * @description 275.H指数 II 7 | * 8 | * 给定一位研究者论文被引用次数的数组(被引用次数是非负整数),数组已经按照升序排列。 9 | * 编写一个方法,计算出研究者的 h 指数。 10 | * h 指数的定义: “h 代表“高引用次数”(high citations), 11 | * 一名科研人员的 h 指数是指他(她)的 (N 篇论文中)至多有 h 篇论文分别被引用了至少 h 次。 12 | * (其余的 N - h 篇论文每篇被引用次数不多于 h 次。)" 13 | * 14 | * 示例: 15 | * 输入: citations = [0,1,3,5,6] 16 | * 输出: 3 17 | * 解释: 给定数组表示研究者总共有 5 篇论文,每篇论文相应的被引用了 0, 1, 3, 5, 6 次。 18 | *   由于研究者有 3 篇论文每篇至少被引用了 3 次,其余两篇论文每篇被引用不多于 3 次,所以她的 h 指数是 3。 19 | * 20 | * 说明: 21 | * 如果 h 有多有种可能的值 ,h 指数是其中最大的那个。 22 | * 23 | * 进阶: 24 | * 这是 H指数 的延伸题目,本题中的 citations 数组是保证有序的。 25 | * 你可以优化你的算法到对数时间复杂度吗? 26 | */ 27 | public class HIndexII { 28 | 29 | public static void main(String[] args) { 30 | HIndexII h = new HIndexII(); 31 | System.out.println(h.hIndex(new int[]{0, 1, 3, 5, 6})); 32 | } 33 | 34 | private int hIndex(int[] citations) { 35 | int result = 0; 36 | int left = 0; 37 | int right = citations.length - 1; 38 | 39 | while (left <= right) { 40 | int mid = left + (right - left) / 2; 41 | int h = citations.length - mid; 42 | 43 | if (h <= citations[mid]) { 44 | result = h; 45 | right = mid - 1; 46 | } else { 47 | left = mid + 1; 48 | } 49 | } 50 | 51 | return result; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/com/hncboy/HappyNumber.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/12/11 18:54 6 | * @description 202.快乐数 7 | * 8 | * 编写一个算法来判断一个数是不是“快乐数”。 9 | * 10 | * 一个“快乐数”定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是无限循环但始终变不到 1。如果可以变为 1,那么这个数就是快乐数。 11 | * 12 | * 示例:  13 | * 输入: 19 14 | * 输出: true 15 | * 解释: 16 | * 12 + 92 = 82 17 | * 82 + 22 = 68 18 | * 62 + 82 = 100 19 | * 12 + 02 + 02 = 1 20 | */ 21 | public class HappyNumber { 22 | 23 | public static void main(String[] args) { 24 | HappyNumber h = new HappyNumber(); 25 | System.out.println(h.isHappy(19)); 26 | } 27 | 28 | public boolean isHappy(int n) { 29 | // 快慢指针,慢指针走1步,快指针走2步,当两个指针相遇时,判断是否是由1引起的 30 | int slow = n; 31 | int fast = n; 32 | do { 33 | slow = bitSquareSum(slow); 34 | fast = bitSquareSum(fast); 35 | fast = bitSquareSum(fast); 36 | } while (slow != fast); 37 | return slow == 1; 38 | } 39 | 40 | private int bitSquareSum(int n) { 41 | int sum = 0; 42 | while (n > 0) { 43 | sum += (n % 10) * (n % 10); 44 | n /= 10; 45 | } 46 | return sum; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/com/hncboy/HeightChecker.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/12/20 15:37 6 | * @description 1051.高度检查器 7 | * 8 | * 学校在拍年度纪念照时,一般要求学生按照 非递减 的高度顺序排列。 9 | * 请你返回至少有多少个学生没有站在正确位置数量。 10 | * 该人数指的是:能让所有学生以 非递减 高度排列的必要移动人数。 11 | * 12 | * 示例: 13 | * 输入:[1,1,4,2,1,3] 14 | * 输出:3 15 | * 解释: 16 | * 高度为 4、3 和最后一个 1 的学生,没有站在正确的位置。 17 | * 18 | * 提示: 19 | * 1 <= heights.length <= 100 20 | * 1 <= heights[i] <= 100 21 | */ 22 | public class HeightChecker { 23 | 24 | public static void main(String[] args) { 25 | HeightChecker h = new HeightChecker(); 26 | System.out.println(h.heightChecker(new int[]{1, 1, 4, 2, 1, 3})); 27 | } 28 | 29 | private int heightChecker(int[] heights) { 30 | // 1 <= heights[i] <= 100 31 | int[] nums = new int[101]; 32 | // 统计 heights 中每个元素的数量放入桶中,非递减的顺序放入 33 | for (int height : heights) { 34 | nums[height]++; 35 | } 36 | 37 | int count = 0; 38 | for (int i = 1, j = 0; i < nums.length; i++) { 39 | // 从桶中每次取出一个元素,直到成为空桶 40 | while (nums[i]-- > 0) { 41 | // 从桶中取出元素时就是非递减的方式,与 heights 中的元素比较,不一样的话 count++ 42 | if (heights[j++] != i) { 43 | count++; 44 | } 45 | } 46 | } 47 | 48 | return count; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/com/hncboy/ImplementStackUsingQueues.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | import java.util.Deque; 4 | import java.util.LinkedList; 5 | 6 | /** 7 | * @author hncboy 8 | * @date 2019/12/17 9:00 9 | * @description 225.用队列实现栈 10 | * 11 | * 使用队列实现栈的下列操作: 12 | * push(x) -- 元素 x 入栈 13 | * pop() -- 移除栈顶元素 14 | * top() -- 获取栈顶元素 15 | * empty() -- 返回栈是否为空 16 | * 17 | * 注意: 18 | * 你只能使用队列的基本操作-- 也就是 push to back, peek/pop from front, size, 和 is empty 这些操作是合法的。 19 | * 你所使用的语言也许不支持队列。 你可以使用 list 或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。 20 | * 你可以假设所有操作都是有效的(例如, 对一个空的栈不会调用 pop 或者 top 操作)。 21 | */ 22 | public class ImplementStackUsingQueues { 23 | 24 | private Deque deque; 25 | 26 | public static void main(String[] args) { 27 | ImplementStackUsingQueues i = new ImplementStackUsingQueues(); 28 | i.push(1); 29 | i.push(2); 30 | System.out.println(i.top()); 31 | System.out.println(i.pop()); 32 | System.out.println(i.empty()); 33 | } 34 | 35 | public ImplementStackUsingQueues() { 36 | deque = new LinkedList<>(); 37 | } 38 | 39 | public void push(int x) { 40 | deque.push(x); 41 | } 42 | 43 | public int pop() { 44 | return deque.pop(); 45 | } 46 | 47 | public int top() { 48 | return deque.peek(); 49 | } 50 | 51 | public boolean empty() { 52 | return deque.isEmpty(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/com/hncboy/IntegerBreak.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/9/23 11:37 6 | * @description 343.整数拆分 7 | * 8 | * 给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。 9 | * 10 | * 示例 1: 11 | * 输入: 2 12 | * 输出: 1 13 | * 解释: 2 = 1 + 1, 1 × 1 = 1。 14 | * 15 | * 示例 2: 16 | * 输入: 10 17 | * 输出: 36 18 | * 解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。 19 | * 说明: 你可以假设 n 不小于 2 且不大于 58。 20 | * 21 | * 来源:力扣(LeetCode) 22 | * 链接:https://leetcode-cn.com/problems/integer-break 23 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 24 | */ 25 | public class IntegerBreak { 26 | 27 | public static void main(String[] args) { 28 | IntegerBreak integerBreak = new IntegerBreak(); 29 | assert integerBreak.integerBreak(2) == 1; 30 | assert integerBreak.integerBreak(10) == 36; 31 | } 32 | 33 | private int integerBreak(int n) { 34 | int[] dp = new int[n + 1]; 35 | dp[2] = 1; 36 | for (int i = 3; i <= n; i++) { 37 | for (int j = 2; j < i; j++) { 38 | dp[i] = Math.max(dp[i], Math.max(j * (i - j), j * dp[i - j])); 39 | } 40 | } 41 | return dp[n]; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/com/hncboy/IntegerReplacement.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/11/19 9:08 6 | * @description 397.整数替换 7 | * 8 | * 给定一个正整数 n ,你可以做如下操作: 9 | * 如果 n 是偶数,则用 n / 2替换 n 。 10 | * 如果 n 是奇数,则可以用 n + 1或n - 1替换 n 。 11 | * n 变为 1 所需的最小替换次数是多少? 12 | * 13 | * 示例 1: 14 | * 输入:n = 8 15 | * 输出:3 16 | * 解释:8 -> 4 -> 2 -> 1 17 | * 18 | * 示例 2: 19 | * 输入:n = 7 20 | * 输出:4 21 | * 解释:7 -> 8 -> 4 -> 2 -> 1 22 | * 或 7 -> 6 -> 3 -> 2 -> 1 23 | * 24 | * 示例 3: 25 | * 输入:n = 4 26 | * 输出:2 27 | * 28 | * 提示: 29 | * 1 <= n <= 231 - 1 30 | * 31 | * 来源:力扣(LeetCode) 32 | * 链接:https://leetcode-cn.com/problems/integer-replacement 33 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 34 | */ 35 | public class IntegerReplacement { 36 | 37 | public int integerReplacement(int n) { 38 | int result = 0; 39 | while (n != 1) { 40 | // 如果 n 是偶数,则直接除 2 41 | if (n % 2 == 0) { 42 | result++; 43 | n /= 2; 44 | continue; 45 | } 46 | 47 | // n 为奇数的情况,result 直接加 2,包含了 +1 或 -1 和 /2 两个步骤 48 | result += 2; 49 | n /= 2; 50 | 51 | // 结果为 1 直接返回 52 | if (n == 1) { 53 | return result; 54 | } 55 | 56 | // 此时把奇数变为偶数 57 | if (n % 2 == 1) { 58 | n += 1; 59 | } 60 | } 61 | return result; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/com/hncboy/IntersectionOfTwoArrays.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * @author hncboy 7 | * @date 2020/1/1 16:27 8 | * @description 349.两个数组的交集 9 | * 10 | * 给定两个数组,编写一个函数来计算它们的交集。 11 | * 12 | * 示例 1: 13 | * 输入: nums1 = [1,2,2,1], nums2 = [2,2] 14 | * 输出: [2] 15 | * 16 | * 示例 2: 17 | * 输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4] 18 | * 输出: [9,4] 19 | * 20 | * 说明: 21 | * 输出结果中的每个元素一定是唯一的。 22 | * 我们可以不考虑输出结果的顺序。 23 | */ 24 | public class IntersectionOfTwoArrays { 25 | 26 | public static void main(String[] args) { 27 | IntersectionOfTwoArrays i = new IntersectionOfTwoArrays(); 28 | System.out.println(Arrays.toString(i.intersection(new int[]{1, 2, 2, 1}, new int[]{2, 2}))); 29 | System.out.println(Arrays.toString(i.intersection(new int[]{4, 9, 5}, new int[]{9, 4, 9, 8, 4}))); 30 | } 31 | 32 | private int[] intersection(int[] nums1, int[] nums2) { 33 | Set set1 = new HashSet<>(); 34 | for (int num : nums1) { 35 | set1.add(num); 36 | } 37 | Set set2 = new HashSet<>(); 38 | for (int num : nums2) { 39 | set2.add(num); 40 | } 41 | // 求两个集合的交集 42 | set1.retainAll(set2); 43 | 44 | int [] result = new int[set1.size()]; 45 | int i = 0; 46 | for (int num : set1) { 47 | result[i++] = num; 48 | } 49 | return result; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/com/hncboy/InvalidTransactions.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hncboy/LeetCode/ab66f67d0a7a6667f1b21e8f0be503eb351863bd/src/com/hncboy/InvalidTransactions.java -------------------------------------------------------------------------------- /src/com/hncboy/IsSubsequence.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/10/22 13:00 6 | * @description 392.判断子序列 7 | */ 8 | public class IsSubsequence { 9 | 10 | public static void main(String[] args) { 11 | IsSubsequence i = new IsSubsequence(); 12 | System.out.println(i.isSubsequence("abc", "ahbgdc")); 13 | System.out.println(i.isSubsequence("axc", "ahbgdc")); 14 | } 15 | 16 | private boolean isSubsequence(String s, String t) { 17 | int count = 0; 18 | for (char ch : t.toCharArray()) { 19 | if (count == s.length()) { 20 | return true; 21 | } 22 | if (s.charAt(count) == ch) { 23 | count++; 24 | } 25 | } 26 | return count == s.length(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/com/hncboy/IsomorphicStrings.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2020/2/9 16:06 6 | * @description 205.同构字符串 7 | * 8 | * 给定两个字符串 s 和 t,判断它们是否是同构的。 9 | * 如果 s 中的字符可以被替换得到 t ,那么这两个字符串是同构的。 10 | * 所有出现的字符都必须用另一个字符替换,同时保留字符的顺序。 11 | * 两个字符不能映射到同一个字符上,但字符可以映射自己本身。 12 | * 13 | * 示例 1: 14 | * 输入: s = "egg", t = "add" 15 | * 输出: true 16 | * 17 | * 示例 2: 18 | * 输入: s = "foo", t = "bar" 19 | * 输出: false 20 | * 21 | * 示例 3: 22 | * 输入: s = "paper", t = "title" 23 | * 输出: true 24 | * 25 | * 说明: 26 | * 你可以假设 s 和 t 具有相同的长度。 27 | */ 28 | public class IsomorphicStrings { 29 | 30 | public static void main(String[] args) { 31 | IsomorphicStrings i = new IsomorphicStrings(); 32 | System.out.println(i.isIsomorphic("ab", "aa")); 33 | System.out.println(i.isIsomorphic("egg", "add")); 34 | System.out.println(i.isIsomorphic("foo", "bar")); 35 | System.out.println(i.isIsomorphic("paper", "title")); 36 | } 37 | 38 | private boolean isIsomorphic(String s, String t) { 39 | char[] chars1 = s.toCharArray(); 40 | char[] chars2 = t.toCharArray(); 41 | 42 | for (int i = 0; i < s.length(); i++) { 43 | // 对比 s 和 t 中相同字符串最开始出现的位置是否相同 44 | if(s.indexOf(chars1[i]) != t.indexOf(chars2[i])){ 45 | return false; 46 | } 47 | } 48 | return true; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/com/hncboy/JewelsAndStones.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/12/31 12:35 6 | * @description 771.宝石与石头 7 | * 8 | * 给定字符串J 代表石头中宝石的类型,和字符串 S代表你拥有的石头。  9 | * S 中每个字符代表了一种你拥有的石头的类型,你想知道你拥有的石头中有多少是宝石。 10 | * J 中的字母不重复,J 和 S中的所有字符都是字母。字母区分大小写,因此"a"和"A"是不同类型的石头。 11 | * 12 | * 示例 1: 13 | * 输入: J = "aA", S = "aAAbbbb" 14 | * 输出: 3 15 | * 16 | * 示例 2: 17 | * 输入: J = "z", S = "ZZ" 18 | * 输出: 0 19 | * 20 | * 注意: 21 | * S 和 J 最多含有50个字母。 22 | * J 中的字符不重复。 23 | */ 24 | public class JewelsAndStones { 25 | 26 | public static void main(String[] args) { 27 | JewelsAndStones j = new JewelsAndStones(); 28 | System.out.println(j.numJewelsInStones("aA", "aAAbbbb")); 29 | System.out.println(j.numJewelsInStones("z", "ZZ")); 30 | } 31 | 32 | private int numJewelsInStones(String J, String S) { 33 | int result = 0; 34 | for (char ch : S.toCharArray()) { 35 | if (J.indexOf(ch) != -1) { 36 | result++; 37 | } 38 | } 39 | return result; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/com/hncboy/JumpGame.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/9/10 20:56 6 | * @description 55.跳跃游戏 7 | *

8 | * 给定一个非负整数数组,你最初位于数组的第一个位置。 9 | * 数组中的每个元素代表你在该位置可以跳跃的最大长度。 10 | * 判断你是否能够到达最后一个位置。 11 | *

12 | * 示例 1: 13 | * 输入: [2,3,1,1,4] 14 | * 输出: true 15 | * 解释: 从位置 0 到 1 跳 1 步, 然后跳 3 步到达最后一个位置。 16 | *

17 | * 示例 2: 18 | * 输入: [3,2,1,0,4] 19 | * 输出: false 20 | * 解释: 无论怎样,你总会到达索引为 3 的位置。但该位置的最大跳跃长度是 0 , 所以你永远不可能到达最后一个位置。 21 | */ 22 | public class JumpGame { 23 | 24 | public static void main(String[] args) { 25 | int[] nums = new int[]{2, 3, 1, 1, 3}; 26 | System.out.println(canJump(nums)); 27 | } 28 | 29 | private static boolean canJump(int[] nums) { 30 | // i = length - 2 的时候表示倒数第二个数与最后一个数的距离 31 | // i < length - 2 的时候,表示当前数与下一个能到达最后一个数的距离 32 | // distance = 1 表示当前数能到达最后一行,不能的话往前移动一位 33 | int distance = 1; 34 | int length = nums.length; 35 | // 从后前遍历数组 36 | for (int i = length - 2; i >= 0; i--) { 37 | // 如果当前数不能到达最后一个数,则增大distance 38 | // 否则截断后面的元素 39 | distance = nums[i] >= distance ? 1 : ++distance; 40 | } 41 | return distance <= 1; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/com/hncboy/JumpGameII.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/11/8 9:38 6 | * @description 45.跳跃游戏 II 7 | * 8 | * 给定一个非负整数数组,你最初位于数组的第一个位置。 9 | * 数组中的每个元素代表你在该位置可以跳跃的最大长度。 10 | * 你的目标是使用最少的跳跃次数到达数组的最后一个位置。 11 | * 12 | * 示例: 13 | * 输入: [2,3,1,1,4] 14 | * 输出: 2 15 | * 解释: 跳到最后一个位置的最小跳跃数是 2。 16 | *   从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。 17 | * 18 | * 说明: 19 | * 假设你总是可以到达数组的最后一个位置。 20 | */ 21 | public class JumpGameII { 22 | 23 | public static void main(String[] args) { 24 | int[] nums = new int[]{2, 3, 1, 1, 2, 1, 1}; 25 | System.out.println(new JumpGameII().jump(nums)); 26 | } 27 | 28 | private int jump(int[] nums) { 29 | int end = 0; 30 | int maxPosition = 0; 31 | int steps = 0; 32 | for (int i = 0; i < nums.length - 1; i++) { 33 | // 选出能跳的范围内跳的最远的位置 34 | maxPosition = Math.max(maxPosition, nums[i] + i); 35 | // 到达边界时更新边界 36 | if (i == end) { 37 | // 能跳得到的最远位置为边界 38 | end = maxPosition; 39 | steps++; 40 | } 41 | } 42 | return steps; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/com/hncboy/JumpGameIII.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hncboy/LeetCode/ab66f67d0a7a6667f1b21e8f0be503eb351863bd/src/com/hncboy/JumpGameIII.java -------------------------------------------------------------------------------- /src/com/hncboy/KthSmallestElementInABst.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/10/17 13:25 6 | * @description 230.二叉搜索树中第K小的元素 7 | * 8 | * 给定一个二叉搜索树的根节点 root ,和一个整数 k ,请你设计一个算法查找其中第 k 个最小元素(从 1 开始计数)。 9 | * 10 | * 示例 1: 11 | * 输入:root = [3,1,4,null,2], k = 1 12 | * 输出:1 13 | * 14 | * 示例 2: 15 | * 输入:root = [5,3,6,2,4,null,null,1], k = 3 16 | * 输出:3 17 | * 18 | * 提示: 19 | * 树中的节点数为 n 。 20 | * 1 <= k <= n <= 104 21 | * 0 <= Node.val <= 104 22 | * 23 | * 进阶:如果二叉搜索树经常被修改(插入/删除操作)并且你需要频繁地查找第 k 小的值,你将如何优化算法? 24 | * 25 | * 来源:力扣(LeetCode) 26 | * 链接:https://leetcode-cn.com/problems/kth-smallest-element-in-a-bst 27 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 28 | */ 29 | public class KthSmallestElementInABst { 30 | 31 | private int count; 32 | private int result; 33 | 34 | public int kthSmallest(TreeNode root, int _k) { 35 | count = _k; 36 | dfs(root); 37 | return result; 38 | } 39 | 40 | private void dfs(TreeNode root) { 41 | if (root == null) { 42 | return; 43 | } 44 | 45 | dfs(root.left); 46 | if (--count == 0) { 47 | result = root.val; 48 | return; 49 | } 50 | dfs(root.right); 51 | } 52 | 53 | private static class TreeNode { 54 | int val; 55 | TreeNode left; 56 | TreeNode right; 57 | 58 | TreeNode(int x) { 59 | val = x; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/com/hncboy/LargestNumber.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | /** 8 | * @author hncboy 9 | * @date 2019/10/16 9:08 10 | * @description 179.最大数 11 | * 12 | * 给定一组非负整数,重新排列它们的顺序使之组成一个最大的整数。 13 | * 14 | * 示例 1: 15 | * 输入: [10,2] 16 | * 输出: 210 17 | * 18 | * 示例 2: 19 | * 输入: [3,30,34,5,9] 20 | * 输出: 9534330 21 | * 说明: 输出结果可能非常大,所以你需要返回一个字符串而不是整数。 22 | */ 23 | public class LargestNumber { 24 | 25 | public static void main(String[] args) { 26 | LargestNumber ln = new LargestNumber(); 27 | int[] nums1 = new int[]{10, 2}; 28 | int[] nums2 = new int[]{9, 5, 34, 3, 30}; 29 | System.out.println(ln.largestNumber(nums1)); 30 | System.out.println(ln.largestNumber(nums2)); 31 | } 32 | 33 | private String largestNumber(int[] nums) { 34 | List list = new ArrayList<>(); 35 | Arrays.stream(nums).forEach((num) -> list.add(String.valueOf(num))); 36 | list.sort((o1, o2) -> (o2 + o1).compareTo(o1 + o2)); 37 | StringBuilder sb = new StringBuilder(); 38 | if (list.get(0).equals("0")) { 39 | return "0"; 40 | } 41 | list.forEach(sb::append); 42 | return sb.toString(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/com/hncboy/LargestPalindromeProduct.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2022/4/16 13:17 6 | * 479.最大回文数乘积 7 | * 8 | * 给定一个整数 n ,返回 可表示为两个 n 位整数乘积的 最大回文整数 。因为答案可能非常大,所以返回它对 1337 取余 。 9 | * 10 | * 示例 1: 11 | * 输入:n = 2 12 | * 输出:987 13 | * 解释:99 x 91 = 9009, 9009 % 1337 = 987 14 | * 15 | * 示例 2: 16 | * 输入: n = 1 17 | * 输出: 9 18 | * 19 | * 提示: 20 | * 1 <= n <= 8 21 | * 通过次数 11,273 提交次数 19,270 22 | * 23 | * 来源:力扣(LeetCode) 24 | * 链接:https://leetcode-cn.com/problems/largest-palindrome-product 25 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 26 | */ 27 | public class LargestPalindromeProduct { 28 | 29 | public int largestPalindrome(int n) { 30 | if (n == 1) { 31 | return 9; 32 | } 33 | int max = (int) Math.pow(10, n) - 1; 34 | for (int i = max; i >= 0; i--) { 35 | long num = i, t = i; 36 | while (t != 0) { 37 | num = num * 10 + (t % 10); 38 | t /= 10; 39 | } 40 | for (long j = max; j * j >= num; j--) { 41 | if (num % j == 0) { 42 | return (int)(num % 1337); 43 | } 44 | } 45 | } 46 | return -1; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/com/hncboy/LengthOfLastWord.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/10/30 16:53 6 | * @description 58.最后一个单词的长度 7 | * 8 | * 给定一个仅包含大小写字母和空格 ' ' 的字符串,返回其最后一个单词的长度。 9 | * 如果不存在最后一个单词,请返回 0 。 10 | * 说明:一个单词是指由字母组成,但不包含任何空格的字符串。 11 | * 12 | * 示例: 13 | * 输入: "Hello World" 14 | * 输出: 5 15 | */ 16 | public class LengthOfLastWord { 17 | 18 | public static void main(String[] args) { 19 | System.out.println(new LengthOfLastWord().lengthOfLastWord("Hello World")); 20 | System.out.println(new LengthOfLastWord().lengthOfLastWord("Hello")); 21 | System.out.println(new LengthOfLastWord().lengthOfLastWord("")); 22 | } 23 | 24 | private int lengthOfLastWord(String s) { 25 | int end = s.length() - 1; 26 | // 去掉最后的空格 27 | while (end >= 0 && s.charAt(end) == ' ') { 28 | end--; 29 | } 30 | if (end < 0) { 31 | return 0; 32 | } 33 | 34 | // 从最后非空格的位置开始统计,直到遇到空格 35 | int start = end; 36 | while (start >= 0 && s.charAt(start) != ' ') { 37 | start--; 38 | } 39 | // end-start 即为最后一个单词长度 40 | return end - start; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/com/hncboy/LexicographicalNumbers.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @author hncboy 8 | * @date 2022/4/18 9:50 9 | * 386.字典序排数 10 | * 11 | * 给你一个整数 n ,按字典序返回范围 [1, n] 内所有整数。 12 | * 你必须设计一个时间复杂度为 O(n) 且使用 O(1) 额外空间的算法。 13 | * 14 | * 示例 1: 15 | * 输入:n = 13 16 | * 输出:[1,10,11,12,13,2,3,4,5,6,7,8,9] 17 | * 18 | * 示例 2: 19 | * 输入:n = 2 20 | * 输出:[1,2] 21 | * 22 | * 提示: 23 | * 1 <= n <= 5 * 104 24 | * 通过次数 34,811 提交次数 45,774 25 | * 26 | * 来源:力扣(LeetCode) 27 | * 链接:https://leetcode-cn.com/problems/lexicographical-numbers 28 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 29 | */ 30 | public class LexicographicalNumbers { 31 | 32 | public List lexicalOrder(int n) { 33 | List result = new ArrayList<>(); 34 | int number = 1; 35 | for (int i = 0; i < n; i++) { 36 | result.add(number); 37 | if (number * 10 <= n) { 38 | number *= 10; 39 | } else { 40 | while (number % 10 == 9 || number + 1 > n) { 41 | number /= 10; 42 | } 43 | number++; 44 | } 45 | } 46 | return result; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/com/hncboy/LinkedListCycleII.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hncboy/LeetCode/ab66f67d0a7a6667f1b21e8f0be503eb351863bd/src/com/hncboy/LinkedListCycleII.java -------------------------------------------------------------------------------- /src/com/hncboy/LinkedListRandomNode.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hncboy/LeetCode/ab66f67d0a7a6667f1b21e8f0be503eb351863bd/src/com/hncboy/LinkedListRandomNode.java -------------------------------------------------------------------------------- /src/com/hncboy/LongestCommonPrefix.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | /** 9 | * @author hncboy 10 | * @date 2019/9/6 7:47 11 | * @description 最长公共前缀 12 | *

13 | * 编写一个函数来查找字符串数组中的最长公共前缀。 14 | * 如果不存在公共前缀,返回空字符串 ""。 15 | *

16 | * 示例 1: 17 | * 输入: ["flower","flow","flight"] 18 | * 输出: "fl" 19 | *

20 | * 示例 2: 21 | * 输入: ["dog","racecar","car"] 22 | * 输出: "" 23 | * 解释: 输入不存在公共前缀。 24 | *

25 | * 说明: 26 | * 所有输入只包含小写字母 a-z 。 27 | */ 28 | public class LongestCommonPrefix { 29 | 30 | public static void main(String[] args) { 31 | System.out.println(longestCommonPrefix(new String[]{"aa", "aa"})); 32 | } 33 | 34 | private static String longestCommonPrefix(String[] strs) { 35 | int length = strs.length; 36 | if (length == 0) { 37 | return ""; 38 | } 39 | 40 | String prefix = strs[0]; 41 | for (int i = 1; i < length; i++) { 42 | // 从整串字符串开始判断,逐一减小长度 43 | while (!strs[i].startsWith(prefix)) { 44 | prefix = prefix.substring(0, prefix.length() - 1); 45 | } 46 | 47 | if (prefix.length() == 0) { 48 | return ""; 49 | } 50 | } 51 | 52 | return prefix; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/com/hncboy/LongestContinuousIncreasingSubsequence.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/11/27 10:30 6 | * @description 674.最长连续递增序列 7 | * 8 | * 给定一个未经排序的整数数组,找到最长且连续的的递增序列。 9 | * 10 | * 示例 1: 11 | * 输入: [1,3,5,4,7] 12 | * 输出: 3 13 | * 解释: 最长连续递增序列是 [1,3,5], 长度为3。 14 | * 尽管 [1,3,5,7] 也是升序的子序列, 但它不是连续的,因为5和7在原数组里被4隔开。 15 | * 16 | * 示例 2: 17 | * 输入: [2,2,2,2,2] 18 | * 输出: 1 19 | * 解释: 最长连续递增序列是 [2], 长度为1。 20 | * 注意:数组长度不会超过10000。 21 | */ 22 | public class LongestContinuousIncreasingSubsequence { 23 | 24 | public static void main(String[] args) { 25 | LongestContinuousIncreasingSubsequence l = new LongestContinuousIncreasingSubsequence(); 26 | System.out.println(l.findLengthOfLCIS(new int[]{1, 3, 5, 7})); 27 | System.out.println(l.findLengthOfLCIS(new int[]{2, 2, 2, 2, 2})); 28 | System.out.println(l.findLengthOfLCIS(new int[]{1, 3, 5, 4, 2, 3, 4, 5})); 29 | } 30 | 31 | private int findLengthOfLCIS(int[] nums) { 32 | if (nums.length <= 1) { 33 | return nums.length; 34 | } 35 | int max = 1; 36 | int count = 1; 37 | for (int i = 1; i < nums.length; i++) { 38 | count = nums[i] > nums[i - 1] ? count + 1 : 1; 39 | max = Math.max(count, max); 40 | } 41 | return max; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/com/hncboy/LongestPalindrome.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2020/3/19 19:48 6 | * @description 409.最长回文串 7 | * 8 | * 给定一个包含大写字母和小写字母的字符串,找到通过这些字母构造成的最长的回文串。 9 | * 在构造过程中,请注意区分大小写。比如 "Aa" 不能当做一个回文字符串。 10 | * 注意: 11 | * 假设字符串的长度不会超过 1010。 12 | * 13 | * 示例 1: 14 | * 输入: 15 | * "abccccdd" 16 | * 输出: 17 | * 7 18 | */ 19 | public class LongestPalindrome { 20 | 21 | private int longestPalindrome(String s) { 22 | // 统计 Aa-Zz 出现的字符个数 23 | int[] count = new int[58]; 24 | for (char c : s.toCharArray()) { 25 | count[c - 'A'] += 1; 26 | } 27 | 28 | int result = 0; 29 | for (int x : count) { 30 | // 偶数的二进制末尾为 0,奇数的二进制末尾为 1 31 | // 当 x 为奇数时,x&1=1,减去 1 次,因为单独的一个数构不成会问 32 | result += x - (x & 1); 33 | } 34 | 35 | // 如果最终的长度小于原字符串的长度,说明里面某个字符出现了奇数次, 36 | // 那么那个字符可以放在回文串的中间,所以额外再加一。 37 | return result < s.length() ? result + 1 : result; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/com/hncboy/LongestUncommonSubsequenceI.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2022/3/5 13:12 6 | * 521.最长特殊序列Ⅰ 7 | * 8 | * 给你两个字符串 a 和 b,请返回 这两个字符串中 最长的特殊序列 的长度。如果不存在,则返回 -1 。 9 | * 「最长特殊序列」 定义如下:该序列为 某字符串独有的最长子序列(即不能是其他字符串的子序列) 。 10 | * 字符串 s 的子序列是在从 s 中删除任意数量的字符后可以获得的字符串。 11 | * 例如,"abc" 是 "aebdc" 的子序列,因为删除 "aebdc" 中斜体加粗的字符可以得到 "abc" 。 "aebdc" 的子序列还包括 "aebdc" 、 "aeb" 和 "" (空字符串)。 12 | * 13 | * 示例 1: 14 | * 输入: a = "aba", b = "cdc" 15 | * 输出: 3 16 | * 解释: 最长特殊序列可为 "aba" (或 "cdc"),两者均为自身的子序列且不是对方的子序列。 17 | * 18 | * 示例 2: 19 | * 输入:a = "aaa", b = "bbb" 20 | * 输出:3 21 | * 解释: 最长特殊序列是 "aaa" 和 "bbb" 。 22 | * 23 | * 示例 3: 24 | * 输入:a = "aaa", b = "aaa" 25 | * 输出:-1 26 | * 解释: 字符串 a 的每个子序列也是字符串 b 的每个子序列。同样,字符串 b 的每个子序列也是字符串 a 的子序列。 27 | * 28 | * 提示: 29 | * 1 <= a.length, b.length <= 100 30 | * a 和 b 由小写英文字母组成 31 | * 通过次数 40,721 提交次数 55,591 32 | * 33 | * 来源:力扣(LeetCode) 34 | * 链接:https://leetcode-cn.com/problems/longest-uncommon-subsequence-i 35 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 36 | */ 37 | public class LongestUncommonSubsequenceI { 38 | 39 | public int findLUSlength(String a, String b) { 40 | return a.equals(b) ? -1 : Math.max(a.length(), b.length()); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/com/hncboy/MaxChunksToMakeSorted.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/11/30 14:13 6 | * @description 769.最多能完成排序的块 7 | * 8 | * 数组arr是[0, 1, ..., arr.length - 1]的一种排列,我们将这个数组分割成几个“块”,并将这些块分别进行排序。 9 | * 之后再连接起来,使得连接的结果和按升序排序后的原数组相同。 10 | * 我们最多能将数组分成多少块? 11 | * 12 | * 示例 1: 13 | * 输入: arr = [4,3,2,1,0] 14 | * 输出: 1 15 | * 解释: 16 | * 将数组分成2块或者更多块,都无法得到所需的结果。 17 | * 例如,分成 [4, 3], [2, 1, 0] 的结果是 [3, 4, 0, 1, 2],这不是有序的数组。 18 | * 19 | * 示例 2: 20 | * 输入: arr = [1,0,2,3,4] 21 | * 输出: 4 22 | * 解释: 23 | * 我们可以把它分成两块,例如 [1, 0], [2, 3, 4]。 24 | * 然而,分成 [1, 0], [2], [3], [4] 可以得到最多的块数。 25 | * 26 | * 注意: 27 | * arr 的长度在 [1, 10] 之间。 28 | * arr[i]是 [0, 1, ..., arr.length - 1]的一种排列。 29 | */ 30 | public class MaxChunksToMakeSorted { 31 | 32 | public static void main(String[] args) { 33 | MaxChunksToMakeSorted m = new MaxChunksToMakeSorted(); 34 | System.out.println(m.maxChunksToSorted(new int[]{4, 3, 2, 1, 0})); 35 | System.out.println(m.maxChunksToSorted(new int[]{1, 0, 2, 3, 4})); 36 | } 37 | 38 | private int maxChunksToSorted(int[] arr) { 39 | int result = 0; 40 | int max = 0; 41 | // 只要该区间的最大值满足目前遍历到的i个数,即可自成排序区间 42 | for (int i = 0; i < arr.length; ++i) { 43 | max = Math.max(max, arr[i]); 44 | result = max == i ? result + 1 : result; 45 | } 46 | return result; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/com/hncboy/MaxConsecutiveOnes.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/11/21 10:48 6 | * @description 485.最大连续1的个数 7 | * 8 | * 给定一个二进制数组, 计算其中最大连续1的个数。 9 | * 10 | * 示例 1: 11 | * 输入: [1,1,0,1,1,1] 12 | * 输出: 3 13 | * 解释: 开头的两位和最后的三位都是连续1,所以最大连续1的个数是 3. 14 | * 15 | * 注意: 16 | * 输入的数组只包含 0 和1。 17 | * 输入数组的长度是正整数,且不超过 10,000。 18 | */ 19 | public class MaxConsecutiveOnes { 20 | 21 | public static void main(String[] args) { 22 | MaxConsecutiveOnes m = new MaxConsecutiveOnes(); 23 | System.out.println(m.findMaxConsecutiveOnes(new int[]{1, 1, 0, 1, 1, 1})); 24 | } 25 | 26 | private int findMaxConsecutiveOnes(int[] nums) { 27 | int result = 0; 28 | for (int i = 0, count = 0; i < nums.length; i++) { 29 | if (nums[i] == 1) { 30 | count++; 31 | result = Math.max(result, count); 32 | continue; 33 | } 34 | count = 0; 35 | } 36 | return result; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/com/hncboy/MaximumAverageSubarrayI.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/11/25 8:26 6 | * @description 643.子数组最大平均数 I 7 | * 8 | * 给定 n 个整数,找出平均数最大且长度为 k 的连续子数组,并输出该最大平均数。 9 | * 10 | * 示例 1: 11 | * 输入: [1,12,-5,-6,50,3], k = 4 12 | * 输出: 12.75 13 | * 解释: 最大平均数 (12-5-6+50)/4 = 51/4 = 12.75 14 | *   15 | * 注意: 16 | * 1 <= k <= n <= 30,000。 17 | * 所给数据范围 [-10,000,10,000]。 18 | */ 19 | public class MaximumAverageSubarrayI { 20 | 21 | public static void main(String[] args) { 22 | MaximumAverageSubarrayI m = new MaximumAverageSubarrayI(); 23 | System.out.println(m.findMaxAverage(new int[]{1, 12, -5, -6, 50, 3}, 4)); 24 | System.out.println(m.findMaxAverage(new int[]{5}, 1)); 25 | System.out.println(m.findMaxAverage(new int[]{0, 1, 1, 3, 3}, 4)); 26 | } 27 | 28 | private double findMaxAverage(int[] nums, int k) { 29 | double sum = 0; 30 | int left = 0; 31 | int right = 0; 32 | while (right < k) { 33 | sum += nums[right]; 34 | right++; 35 | } 36 | double average = sum / k; 37 | while (right < nums.length) { 38 | sum = sum - nums[left++] + nums[right++]; 39 | average = Math.max(average, sum / k); 40 | } 41 | return average; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/com/hncboy/MaximumDepthOfBinaryTree.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/10/5 10:46 6 | * @description 104.二叉树的最大深度 7 | * 8 | * 给定一个二叉树,找出其最大深度。 9 | * 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。 10 | * 说明: 叶子节点是指没有子节点的节点。 11 | * 12 | * 示例: 13 | * 给定二叉树 [3,9,20,null,null,15,7], 14 | * 15 | * 3 16 | * / \ 17 | * 9 20 18 | * / \ 19 | * 15 7 20 | * 返回它的最大深度 3 。 21 | */ 22 | public class MaximumDepthOfBinaryTree { 23 | 24 | public static void main(String[] args) { 25 | TreeNode node = new TreeNode(3); 26 | node.left = new TreeNode(9); 27 | node.right = new TreeNode(20); 28 | node.right.left = new TreeNode(15); 29 | node.right.right = new TreeNode(7); 30 | System.out.println(new MaximumDepthOfBinaryTree().maxDepth(node)); 31 | } 32 | 33 | private int maxDepth(TreeNode root) { 34 | return root == null ? 0 : Math.max(maxDepth(root.left), maxDepth(root.right)) + 1; 35 | } 36 | 37 | private static class TreeNode { 38 | int val; 39 | TreeNode left; 40 | TreeNode right; 41 | 42 | TreeNode(int x) { 43 | val = x; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/com/hncboy/MaximumLengthOfRepeatedSubarray.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/11/30 10:54 6 | * @description 718.最长重复子数组 7 | * 8 | * 给两个整数数组 A 和 B ,返回两个数组中公共的、长度最长的子数组的长度。 9 | * 10 | * 示例 1: 11 | * 输入: 12 | * A: [1,2,3,2,1] 13 | * B: [3,2,1,4,7] 14 | * 输出: 3 15 | * 解释: 16 | * 长度最长的公共子数组是 [3, 2, 1]。 17 | * 18 | * 说明: 19 | * 1 <= len(A), len(B) <= 1000 20 | * 0 <= A[i], B[i] < 100 21 | */ 22 | public class MaximumLengthOfRepeatedSubarray { 23 | 24 | public static void main(String[] args) { 25 | MaximumLengthOfRepeatedSubarray m = new MaximumLengthOfRepeatedSubarray(); 26 | System.out.println(m.findLength(new int[]{1, 2, 3, 2, 1}, new int[]{3, 2, 1, 4, 7})); 27 | } 28 | 29 | /** 30 | * 动态规划 31 | * 时间复杂度:O(M*N) 32 | * 空间复杂度:O(M) 33 | * @param A 34 | * @param B 35 | * @return 36 | */ 37 | private int findLength(int[] A, int[] B) { 38 | int result = 0; 39 | int[] dp = new int[B.length + 1]; 40 | for (int i = 0; i < A.length; i++) { 41 | for (int j = B.length - 1; j >= 0; j--) { 42 | if (A[i] == B[j]) { 43 | dp[j + 1] = dp[j] + 1; 44 | result = Math.max(dp[j + 1], result); 45 | } else { 46 | dp[j + 1] = 0; 47 | } 48 | } 49 | } 50 | return result; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/com/hncboy/MaximumProductSubarray.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/11/9 16:36 6 | * @description 152.乘积最大子序列 7 | * 8 | * 给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数)。 9 | * 10 | * 示例 1: 11 | * 输入: [2,3,-2,4] 12 | * 输出: 6 13 | * 解释: 子数组 [2,3] 有最大乘积 6。 14 | * 15 | * 示例 2: 16 | * 输入: [-2,0,-1] 17 | * 输出: 0 18 | * 解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。 19 | */ 20 | public class MaximumProductSubarray { 21 | 22 | public static void main(String[] args) { 23 | MaximumProductSubarray m = new MaximumProductSubarray(); 24 | int[] nums1 = new int[]{2, 3, -2, 4, -2}; 25 | int[] nums2 = new int[]{-2, 0, -1}; 26 | System.out.println(m.maxProduct(nums1)); 27 | System.out.println(m.maxProduct(nums2)); 28 | } 29 | 30 | private int maxProduct(int[] nums) { 31 | int result = Integer.MIN_VALUE; 32 | int max = 1; 33 | int min = 1; 34 | for (int num : nums) { 35 | if (num < 0) { 36 | int temp = max; 37 | max = min; 38 | min = temp; 39 | } 40 | 41 | max = Math.max(max * num, num); 42 | min = Math.min(min * num, num); 43 | result = Math.max(result, max); 44 | } 45 | return result; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/com/hncboy/MaximumSubarray.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/9/24 9:20 6 | * @description 53.最大子序和 7 | * 8 | * 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 9 | * 10 | * 示例: 11 | * 输入: [-2,1,-3,4,-1,2,1,-5,4], 12 | * 输出: 6 13 | * 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。 14 | */ 15 | public class MaximumSubarray { 16 | 17 | public static void main(String[] args) { 18 | int[] nums = new int[]{-2, 1, -3, 4, -1, 2, 1, -5, 4}; 19 | System.out.println(new MaximumSubarray().maxSubArray(nums)); 20 | assert new MaximumSubarray().maxSubArray(nums) == 6; 21 | } 22 | 23 | /** 24 | * 动态规划 25 | * @param nums 26 | * @return 27 | */ 28 | private int maxSubArray(int[] nums) { 29 | int max = nums[0]; 30 | int sum = 0; 31 | // 如果该数组有正数,那么最大子序列从头到尾都是正数 32 | for (int num : nums) { 33 | sum = sum > 0 ? sum + num : num; 34 | max = Math.max(max, sum); 35 | } 36 | return max; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/com/hncboy/MedianOfTwoSortedArrays.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author hncboy 7 | * @date 2019/8/30 14:03 8 | * @description 4.寻找两个有序数组的中位数 9 | * 10 | * 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。 11 | * 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。 12 | * 你可以假设 nums1 和 nums2 不会同时为空。 13 | * 14 | * 示例 1: 15 | * nums1 = [1, 3] 16 | * nums2 = [2] 17 | * 则中位数是 2.0 18 | * 19 | * 示例 2: 20 | * nums1 = [1, 2] 21 | * nums2 = [3, 4] 22 | * 则中位数是 (2 + 3)/2 = 2.5 23 | */ 24 | public class MedianOfTwoSortedArrays { 25 | 26 | public static void main(String[] args) { 27 | int[] nums1 = new int[]{1, 2}; 28 | int[] nums2 = new int[]{3, 4}; 29 | System.out.println(findMedianSortedArrays(nums1, nums2)); 30 | } 31 | 32 | public static double findMedianSortedArrays(int[] nums1, int[] nums2) { 33 | int[] nums3 = new int[nums1.length + nums2.length]; 34 | System.arraycopy(nums1, 0, nums3, 0, nums1.length); 35 | System.arraycopy(nums2, 0, nums3, nums1.length, nums2.length); 36 | Arrays.sort(nums3); 37 | 38 | if (nums3.length % 2 == 0) { 39 | return (nums3[nums3.length / 2 - 1] + nums3[nums3.length / 2]) / 2.0; 40 | } else { 41 | return nums3[nums3.length / 2]; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/com/hncboy/MergeSortedArray.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/10/11 8:03 6 | * @description 88.合并两个有序数组 7 | * 8 | * 给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。 9 | * 10 | * 说明: 11 | * 初始化 nums1 和 nums2 的元素数量分别为 m 和 n。 12 | * 你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。 13 | * 14 | * 示例: 15 | * 输入: 16 | * nums1 = [1,2,3,0,0,0], m = 3 17 | * nums2 = [2,5,6], n = 3 18 | * 输出: [1,2,2,3,5,6] 19 | */ 20 | public class MergeSortedArray { 21 | 22 | public static void main(String[] args) { 23 | int[] nums1 = new int[]{1, 2, 3, 0, 0, 0}; 24 | int[] nums2 = new int[]{2, 5, 6}; 25 | new MergeSortedArray().merge(nums1, 3, nums2, 3); 26 | } 27 | 28 | private void merge(int[] nums1, int m, int[] nums2, int n) { 29 | // 指针 i,从 nums1 数组最后开始 30 | int i = m - 1; 31 | // 指针 j,从 nums2 数组最后开始 32 | int j = n - 1; 33 | // 记录排序好的数下标 34 | int k = m + n - 1; 35 | while (i >= 0 && j >= 0) { 36 | nums1[k--] = nums1[i] > nums2[j] ? nums1[i--] : nums2[j--]; 37 | } 38 | // 将 nums2 剩下的数拷到 nums1 39 | System.arraycopy(nums2, 0, nums1, 0, j+1); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/com/hncboy/MinimumAbsoluteDifference.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hncboy/LeetCode/ab66f67d0a7a6667f1b21e8f0be503eb351863bd/src/com/hncboy/MinimumAbsoluteDifference.java -------------------------------------------------------------------------------- /src/com/hncboy/MinimumMovesToEqualArrayElements.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/10/20 8:11 6 | * @description 453.最小操作次数使数组元素相等 7 | * 8 | * 给你一个长度为 n 的整数数组,每次操作将会使 n - 1 个元素增加 1 。返回让数组所有元素相等的最小操作次数。 9 | * 10 | * 示例 1: 11 | * 输入:nums = [1,2,3] 12 | * 输出:3 13 | * 解释: 14 | * 只需要3次操作(注意每次操作会增加两个元素的值): 15 | * [1,2,3] => [2,3,3] => [3,4,3] => [4,4,4] 16 | * 17 | * 示例 2: 18 | * 输入:nums = [1,1,1] 19 | * 输出:0 20 | * 21 | * 提示: 22 | * n == nums.length 23 | * 1 <= nums.length <= 105 24 | * -109 <= nums[i] <= 109 25 | * 答案保证符合 32-bit 整数 26 | * 27 | * 来源:力扣(LeetCode) 28 | * 链接:https://leetcode-cn.com/problems/minimum-moves-to-equal-array-elements 29 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 30 | */ 31 | public class MinimumMovesToEqualArrayElements { 32 | 33 | public int minMoves(int[] nums) { 34 | int n = nums.length; 35 | int min = nums[0]; 36 | int sum = 0; 37 | // 求和并获取数组中最小数字 38 | for (int num : nums) { 39 | min = Math.min(min, num); 40 | sum += num; 41 | } 42 | return sum - min * n; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/com/hncboy/MinimumSwapsToMakeStringsEqual.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /**count-number-of-nice-subarrays 4 | * @author hncboy 5 | * @date 2019/11/3 10:30 6 | * @description 1247.交换字符使得字符串相同 7 | */ 8 | public class MinimumSwapsToMakeStringsEqual { 9 | 10 | public static void main(String[] args) { 11 | MinimumSwapsToMakeStringsEqual m = new MinimumSwapsToMakeStringsEqual(); 12 | System.out.println(m.minimumSwap("xx", "yy")); 13 | System.out.println(m.minimumSwap("xy", "yx")); 14 | System.out.println(m.minimumSwap("xx", "xy")); 15 | System.out.println(m.minimumSwap("xxyyxyxyxx", "xyyxyxxxyx")); 16 | } 17 | 18 | private int minimumSwap(String s1, String s2) { 19 | int xy = 0; 20 | int yx = 0; 21 | for (int i = 0; i < s1.length(); i++) { 22 | char ch1 = s1.charAt(i); 23 | char ch2 = s2.charAt(i); 24 | if (ch1 == 'x' && ch2 == 'y') { 25 | xy++; 26 | } else if (ch1 == 'y' && ch2 == 'x') { 27 | yx++; 28 | } 29 | } 30 | if (Math.abs(xy - yx) % 2 != 0) { 31 | return -1; 32 | } 33 | if (xy % 2 == 0 && yx % 2 == 0) { 34 | return xy / 2 + yx / 2; 35 | } 36 | return xy / 2 + yx / 2 + 2; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/com/hncboy/MissingNumber.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/10/14 9:47 6 | * @description 268.缺失数字 7 | * 8 | * 给定一个包含 0, 1, 2, ..., n 中 n 个数的序列,找出 0 .. n 中没有出现在序列中的那个数。 9 | * 10 | * 示例 1: 11 | * 输入: [3,0,1] 12 | * 输出: 2 13 | * 14 | * 示例 2: 15 | * 输入: [9,6,4,2,3,5,7,0,1] 16 | * 输出: 8 17 | * 说明: 18 | * 你的算法应具有线性时间复杂度。你能否仅使用额外常数空间来实现? 19 | */ 20 | public class MissingNumber { 21 | 22 | public static void main(String[] args) { 23 | MissingNumber m = new MissingNumber(); 24 | int[] nums1 = new int[]{3, 0, 1}; 25 | int[] nums2 = new int[]{9, 6, 4, 2, 3, 5, 7, 0, 1}; 26 | System.out.println(m.missingNumber2(nums1)); 27 | System.out.println(m.missingNumber2(nums2)); 28 | } 29 | 30 | private int missingNumber2(int[] nums) { 31 | int result = nums.length; 32 | for (int i = 0; i < nums.length; ++i){ 33 | result ^= nums[i]; 34 | result ^= i; 35 | } 36 | return result; 37 | } 38 | 39 | private int missingNumber1(int[] nums) { 40 | int result = 0; 41 | for (int i = 0; i < nums.length; i++) { 42 | nums[i] += i - nums[i]; 43 | } 44 | return result + nums.length; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/com/hncboy/MoveZeroes.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/10/8 8:02 6 | * @description 283.移动零 7 | * 8 | * 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 9 | * 10 | * 示例: 11 | * 输入: [0,1,0,3,12] 12 | * 输出: [1,3,12,0,0] 13 | * 14 | * 说明: 15 | * 必须在原数组上操作,不能拷贝额外的数组。 16 | * 尽量减少操作次数。 17 | */ 18 | public class MoveZeroes { 19 | 20 | public static void main(String[] args) { 21 | int[] nums = new int[]{0, 1, 0, 3, 12}; 22 | new MoveZeroes().moveZeroes(nums); 23 | } 24 | 25 | private void moveZeroes(int[] nums) { 26 | // 0 的数量 27 | int count = 0; 28 | for (int i = 0; i < nums.length; i++) { 29 | if (nums[i] != 0) { 30 | // 将不为 0 的数移动前面,0 移到后面 31 | // 将不为 0 的数与为 0 的数交换 32 | int temp = nums[i - count]; 33 | nums[i - count] = nums[i]; 34 | nums[i] = temp; 35 | } else { 36 | count++; 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/com/hncboy/NRepeatedElementInSize2nArray.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/12/6 9:35 6 | * @description 961.重复 N 次的元素 7 | * 8 | * 在大小为 2N 的数组 A 中有 N+1 个不同的元素,其中有一个元素重复了 N 次。 9 | * 返回重复了 N 次的那个元素。 10 | * 11 | * 示例 1: 12 | * 输入:[1,2,3,3] 13 | * 输出:3 14 | * 15 | * 示例 2: 16 | * 输入:[2,1,2,5,3,2] 17 | * 输出:2 18 | * 19 | * 示例 3: 20 | * 输入:[5,1,5,2,5,3,5,4] 21 | * 输出:5 22 | * 23 | * 提示: 24 | * 4 <= A.length <= 10000 25 | * 0 <= A[i] < 10000 26 | * A.length 为偶数 27 | */ 28 | public class NRepeatedElementInSize2nArray { 29 | 30 | public static void main(String[] args) { 31 | NRepeatedElementInSize2nArray n = new NRepeatedElementInSize2nArray(); 32 | System.out.println(n.repeatedNTimes(new int[]{1, 2, 3, 3})); 33 | System.out.println(n.repeatedNTimes(new int[]{2, 1, 2, 5, 3, 2})); 34 | System.out.println(n.repeatedNTimes(new int[]{5, 1, 5, 2, 5, 3, 5, 4})); 35 | } 36 | 37 | public int repeatedNTimes(int[] A) { 38 | // 一定会满足这三种情况 39 | for (int k = 1; k <= 3; k++) { 40 | for (int i = 0; i < A.length - k; i++) { 41 | if (A[i] == A[i + k]) { 42 | return A[i]; 43 | } 44 | } 45 | } 46 | return -1; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/com/hncboy/NThTribonacciNumber.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/11/7 9:28 6 | * @description 1137.第 N 个泰波那契数 7 | * 8 | * 泰波那契序列 Tn 定义如下:  9 | * T0 = 0, T1 = 1, T2 = 1, 且在 n >= 0 的条件下 Tn+3 = Tn + Tn+1 + Tn+2 10 | * 给你整数 n,请返回第 n 个泰波那契数 Tn 的值。 11 | *   12 | * 13 | * 示例 1: 14 | * 输入:n = 4 15 | * 输出:4 16 | * 解释: 17 | * T_3 = 0 + 1 + 1 = 2 18 | * T_4 = 1 + 1 + 2 = 4 19 | * 20 | * 示例 2: 21 | * 输入:n = 25 22 | * 输出:1389537 23 | * 24 | * 提示: 25 | * 0 <= n <= 37 26 | * 答案保证是一个 32 位整数,即 answer <= 2^31 - 1。 27 | */ 28 | public class NThTribonacciNumber { 29 | 30 | public static void main(String[] args) { 31 | System.out.println(tribonacci(4)); 32 | System.out.println(tribonacci(25)); 33 | } 34 | 35 | private static int tribonacci(int n) { 36 | int n0 = 0; 37 | int n1 = 1; 38 | int n2 = 1; 39 | while (n-- > 0) { 40 | n2 = n0 + n1 + n2; 41 | n1 = n2 - n1 - n0; 42 | n0 = n2 - n1 - n0; 43 | } 44 | return n0; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/com/hncboy/NimGame.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/9/8 14:48 6 | * @description Nim 游戏 7 | * 8 | * 你和你的朋友,两个人一起玩 Nim 游戏:桌子上有一堆石头,每次你们轮流拿掉 1 - 3 块石头。 9 | * 拿掉最后一块石头的人就是获胜者。你作为先手。你们是聪明人,每一步都是最优解。 10 | * 编写一个函数,来判断你是否可以在给定石头数量的情况下赢得游戏。 11 | * 12 | * 示例: 13 | * 输入: 4 14 | * 输出: false 15 | * 解释: 如果堆中有 4 块石头,那么你永远不会赢得比赛; 16 | *   因为无论你拿走 1 块、2 块 还是 3 块石头,最后一块石头总是会被你的朋友拿走。 17 | */ 18 | public class NimGame { 19 | 20 | public static void main(String[] args) { 21 | System.out.println(canWinNim(4)); 22 | } 23 | 24 | private static boolean canWinNim(int n) { 25 | // 巴什博奕,n%(m+1)!=0时,先手总是会赢的 26 | return n % 4 != 0; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/com/hncboy/NonDecreasingArray.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/11/25 9:08 6 | * @description 665.非递减数列 7 | * 8 | * 给定一个长度为 n 的整数数组,你的任务是判断在最多改变 1 个元素的情况下,该数组能否变成一个非递减数列。 9 | * 我们是这样定义一个非递减数列的: 对于数组中所有的 i (1 <= i < n),满足 array[i] <= array[i + 1]。 10 | * 11 | * 示例 1: 12 | * 输入: [4,2,3] 13 | * 输出: True 14 | * 解释: 你可以通过把第一个4变成1来使得它成为一个非递减数列。 15 | * 16 | * 示例 2: 17 | * 输入: [4,2,1] 18 | * 输出: False 19 | * 解释: 你不能在只改变一个元素的情况下将其变为非递减数列。 20 | * 说明:  n 的范围为 [1, 10,000]。 21 | */ 22 | public class NonDecreasingArray { 23 | 24 | public static void main(String[] args) { 25 | NonDecreasingArray n = new NonDecreasingArray(); 26 | System.out.println(n.checkPossibility(new int[]{4, 2, 3})); 27 | System.out.println(n.checkPossibility(new int[]{4, 2, 1})); 28 | System.out.println(n.checkPossibility(new int[]{3, 4, 2, 3})); 29 | } 30 | 31 | private boolean checkPossibility(int[] nums) { 32 | int count = 0; 33 | for (int i = 0; i < nums.length - 1 && count < 2; i++) { 34 | if (nums[i] > nums[i + 1]) { 35 | if (i == 0 || nums[i + 1] >= nums[i - 1]) { 36 | nums[i] = nums[i + 1]; 37 | } else { 38 | nums[i + 1] = nums[i]; 39 | } 40 | count++; 41 | } 42 | } 43 | return count <= 1; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/com/hncboy/NumberOfDigitOne.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/11/11 15:20 6 | * @description 233.数字 1 的个数 7 | * 8 | * 给定一个整数 n,计算所有小于等于 n 的非负整数中数字 1 出现的个数。 9 | * 10 | * 示例: 11 | * 输入: 13 12 | * 输出: 6 13 | * 解释: 数字 1 出现在以下数字中: 1, 10, 11, 12, 13 。 14 | */ 15 | public class NumberOfDigitOne { 16 | 17 | public static void main(String[] args) { 18 | NumberOfDigitOne n = new NumberOfDigitOne(); 19 | System.out.println(n.countDigitOne(1410065408)); 20 | System.out.println(n.countDigitOne(10)); 21 | System.out.println(n.countDigitOne(1)); 22 | } 23 | 24 | private int countDigitOne(int n) { 25 | long count = 0; 26 | // 分别计算个位、十位、百位上...出现 1 的个数 27 | for (long i = 1; i <= n; i *= 10) { 28 | // 高位 29 | long a = n / i; 30 | // 低位 31 | long b = n % i; 32 | /* 33 | 当该位上的数属于 [2,9],直接进 8 位将 a/10 的值 + 1,因为需要考虑该位为 1 的情况 34 | 当该位上的数为 1,进 8 位之后也不会将总数 +1,该位为 1 的情况会移到下面的式子计算 35 | 当改为上的数为 0,不用考虑该位为 1 的情况 36 | */ 37 | count += (a + 8) / 10 * i; 38 | count += a % 10 == 1 ? b + 1 : 0; 39 | } 40 | return (int) count; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/com/hncboy/NumberOfEquivalentDominoPairs.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author hncboy 7 | * @date 2019/12/23 22:33 8 | * @description 1128.等价多米诺骨牌对的数量 9 | * 10 | * 给你一个由一些多米诺骨牌组成的列表 dominoes。 11 | * 如果其中某一张多米诺骨牌可以通过旋转 0 度或 180 度得到另一张多米诺骨牌,我们就认为这两张牌是等价的。 12 | * 形式上,dominoes[i] = [a, b] 和 dominoes[j] = [c, d] 等价的前提是 a==c 且 b==d,或是 a==d 且 b==c。 13 | * 在 0 <= i < j < dominoes.length 的前提下,找出满足 dominoes[i] 和 dominoes[j] 等价的骨牌对 (i, j) 的数量。 14 | * 15 | * 示例: 16 | * 输入:dominoes = [[1,2],[2,1],[3,4],[5,6]] 17 | * 输出:1 18 | *   19 | * 提示: 20 | * 1 <= dominoes.length <= 40000 21 | * 1 <= dominoes[i][j] <= 9 22 | */ 23 | public class NumberOfEquivalentDominoPairs { 24 | 25 | public static void main(String[] args) { 26 | NumberOfEquivalentDominoPairs n = new NumberOfEquivalentDominoPairs(); 27 | int[][] dominoes1 = {{1, 2}, {2, 1}, {3, 4}, {5, 6}}; 28 | int[][] dominoes2 = {{1, 2}, {1, 2}, {1, 1}, {1, 2}, {2, 2}}; 29 | System.out.println(n.numEquivDominoPairs(dominoes1)); 30 | System.out.println(n.numEquivDominoPairs(dominoes2)); 31 | } 32 | 33 | private int numEquivDominoPairs(int[][] dominoes) { 34 | int result = 0; 35 | int[] count = new int[100]; 36 | for (int[] domino : dominoes) { 37 | Arrays.sort(domino); 38 | result += count[domino[0] * 10 + domino[1]]++; 39 | } 40 | return result; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/com/hncboy/NumberOfRectanglesThatCanFormTheLargestSquare.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2022/2/4 13:54 6 | * 1725.可以形成最大正方形的矩形数目 7 | * 8 | * 给你一个数组 rectangles ,其中 rectangles[i] = [li, wi] 表示第 i 个矩形的长度为 li 、宽度为 wi 。 9 | * 10 | * 如果存在 k 同时满足 k <= li 和 k <= wi ,就可以将第 i 个矩形切成边长为 k 的正方形。 11 | * 例如,矩形 [4,6] 可以切成边长最大为 4 的正方形。 12 | * 设 maxLen 为可以从矩形数组 rectangles 切分得到的 最大正方形 的边长。 13 | * 请你统计有多少个矩形能够切出边长为 maxLen 的正方形,并返回矩形 数目 。 14 | * 15 | * 示例 1: 16 | * 输入:rectangles = [[5,8],[3,9],[5,12],[16,5]] 17 | * 输出:3 18 | * 解释:能从每个矩形中切出的最大正方形边长分别是 [5,3,5,5] 。 19 | * 最大正方形的边长为 5 ,可以由 3 个矩形切分得到。 20 | * 21 | * 示例 2: 22 | * 输入:rectangles = [[2,3],[3,7],[4,3],[3,7]] 23 | * 输出:3 24 | * 25 | * 提示: 26 | * 1 <= rectangles.length <= 1000 27 | * rectangles[i].length == 2 28 | * 1 <= li, wi <= 109 29 | * li != wi 30 | * 通过次数 22,003 提交次数 26,730 31 | */ 32 | public class NumberOfRectanglesThatCanFormTheLargestSquare { 33 | 34 | public int countGoodRectangles(int[][] rectangles) { 35 | int max = 0; 36 | int result = 0; 37 | for (int[] rectangle : rectangles) { 38 | int curr = Math.min(rectangle[0], rectangle[1]); 39 | if (curr == max) { 40 | result++; 41 | } else if (curr > max) { 42 | max = curr; 43 | result = 1; 44 | } 45 | } 46 | return result; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/com/hncboy/NumberOfSegmentsInAString.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/10/7 9:38 6 | * @description 434.字符串中的单词数 7 | * 8 | * 统计字符串中的单词个数,这里的单词指的是连续的不是空格的字符。 9 | * 请注意,你可以假定字符串里不包括任何不可打印的字符。 10 | * 11 | * 示例: 12 | * 输入: "Hello, my name is John" 13 | * 输出: 5 14 | * 解释: 这里的单词是指连续的不是空格的字符,所以 "Hello," 算作 1 个单词。 15 | * 16 | * 来源:力扣(LeetCode) 17 | * 链接:https://leetcode-cn.com/problems/number-of-segments-in-a-string 18 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 19 | */ 20 | public class NumberOfSegmentsInAString { 21 | 22 | public static void main(String[] args) { 23 | NumberOfSegmentsInAString n = new NumberOfSegmentsInAString(); 24 | System.out.println(n.countSegments("Hello, my name is John") == 5); 25 | System.out.println(n.countSegments(", , , , a, eaefa") == 6); 26 | } 27 | 28 | private int countSegments(String s) { 29 | int n = s.length(); 30 | int result = 0; 31 | for (int i = 0; i < n; ) { 32 | // 跳过空格不计数 33 | if (s.charAt(i) == ' ') { 34 | i++; 35 | continue; 36 | } 37 | 38 | // 对于非空格的字符,遍历完一整个单词后进行一次统计 39 | while (i < n && s.charAt(i) != ' ') { 40 | i++; 41 | } 42 | result++; 43 | } 44 | return result; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/com/hncboy/PalindromeNumber.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/9/4 14:27 6 | * @description 9.回文数 7 | * 8 | * 判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。 9 | * 10 | * 示例 1: 11 | * 输入: 121 12 | * 输出: true 13 | * 14 | * 示例 2: 15 | * 输入: -121 16 | * 输出: false 17 | * 解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。 18 | * 19 | * 示例 3: 20 | * 输入: 10 21 | * 输出: false 22 | * 解释: 从右向左读, 为 01 。因此它不是一个回文数。 23 | * 24 | * 进阶: 25 | * 你能不将整数转为字符串来解决这个问题吗? 26 | */ 27 | public class PalindromeNumber { 28 | 29 | public static void main(String[] args) { 30 | System.out.println(isPalindrome(1341)); 31 | } 32 | 33 | private static boolean isPalindromeWithString(int x) { 34 | String num = String.valueOf(x); 35 | for (int i = 0, j = num.length() - 1; i < j; i++, j--) { 36 | if (num.charAt(i) != num.charAt(j)) { 37 | return false; 38 | } 39 | } 40 | return true; 41 | } 42 | 43 | private static boolean isPalindrome(int x) { 44 | if (x < 0 || (x > 0 && x % 10 == 0)) { 45 | return false; 46 | } 47 | int y = x; 48 | int result = 0; 49 | while (x != 0) { 50 | result = result * 10 + x % 10; 51 | x = x / 10; 52 | } 53 | return result == y; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/com/hncboy/PascalsTriangle.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @author hncboy 8 | * @date 2019/10/15 9:01 9 | * @description 118.杨辉三角 10 | * 11 | * 给定一个非负整数 numRows,生成杨辉三角的前 numRows 行。 12 | * 在杨辉三角中,每个数是它左上方和右上方的数的和。 13 | * 14 | * 示例: 15 | * 输入: 5 16 | * 输出: 17 | * [ 18 | * [1], 19 | * [1,1], 20 | * [1,2,1], 21 | * [1,3,3,1], 22 | * [1,4,6,4,1] 23 | * ] 24 | */ 25 | public class PascalsTriangle { 26 | 27 | public static void main(String[] args) { 28 | System.out.println(new PascalsTriangle().generate(5)); 29 | } 30 | 31 | private List> generate(int numRows) { 32 | List> result = new ArrayList<>(); 33 | // 遍历所需的行数 34 | for (int i = 0; i < numRows; i++) { 35 | List sub = new ArrayList<>(); 36 | // 计算每行中的每个数字 37 | for (int j = 0; j <= i; j++) { 38 | if (j == 0 || j == i) { 39 | sub.add(1); 40 | } else { 41 | List beforeRow = result.get(i - 1); 42 | sub.add(beforeRow.get(j - 1) + beforeRow.get(j)); 43 | } 44 | } 45 | result.add(sub); 46 | } 47 | return result; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/com/hncboy/PascalsTriangleII.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @author hncboy 8 | * @date 2019/10/15 9:21 9 | * @description 119.杨辉三角 II 10 | * 11 | * 给定一个非负索引 k,其中 k ≤ 33,返回杨辉三角的第 k 行。 12 | * 在杨辉三角中,每个数是它左上方和右上方的数的和。 13 | * 14 | * 示例: 15 | * 输入: 3 16 | * 输出: [1,3,3,1] 17 | * 进阶: 18 | * 你可以优化你的算法到 O(k) 空间复杂度吗? 19 | */ 20 | public class PascalsTriangleII { 21 | 22 | public static void main(String[] args) { 23 | System.out.println(new PascalsTriangleII().getRow(3)); 24 | } 25 | 26 | private List getRow(int rowIndex) { 27 | List currentRow = new ArrayList<>(); 28 | currentRow.add(1); 29 | for (int i = 1; i <= rowIndex; i++) { 30 | for (int j = i - 1; j > 0; j--) { 31 | currentRow.set(j, currentRow.get(j - 1) + currentRow.get(j)); 32 | } 33 | currentRow.add(1); 34 | } 35 | return currentRow; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/com/hncboy/PeakIndexInAMountainArray.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2020/2/9 14:55 6 | * @description 852.山脉数组的峰顶索引 7 | * 8 | * 我们把符合下列属性的数组 A 称作山脉: 9 | * A.length >= 3 10 | * 存在 0 < i < A.length - 1 使得A[0] < A[1] < ... A[i-1] < A[i] > A[i+1] > ... > A[A.length - 1] 11 | * 给定一个确定为山脉的数组,返回任何满足 A[0] < A[1] < ... A[i-1] < A[i] > A[i+1] > ... > A[A.length - 1] 的 i 的值。 12 | * 13 | * 示例 1: 14 | * 输入:[0,1,0] 15 | * 输出:1 16 | * 17 | * 示例 2: 18 | * 输入:[0,2,1,0] 19 | * 输出:1 20 | * 21 | * 提示: 22 | * 3 <= A.length <= 10000 23 | * 0 <= A[i] <= 10^6 24 | * A 是如上定义的山脉 25 | */ 26 | public class PeakIndexInAMountainArray { 27 | 28 | public static void main(String[] args) { 29 | PeakIndexInAMountainArray p = new PeakIndexInAMountainArray(); 30 | System.out.println(p.peakIndexInMountainArray(new int[]{0, 1, 0})); 31 | System.out.println(p.peakIndexInMountainArray(new int[]{0, 2, 1, 0})); 32 | } 33 | 34 | private int peakIndexInMountainArray(int[] A) { 35 | int left = 0; 36 | int right = A.length - 1; 37 | 38 | while (left < right) { 39 | int mid = left + (right - left) / 2; 40 | if (A[mid] < A[mid + 1]) { 41 | left = mid + 1; 42 | } else { 43 | right = mid; 44 | } 45 | } 46 | return left; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/com/hncboy/PerfectNumber.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/12/31 9:05 6 | * 507.完美数 7 | * 8 | * 对于一个 正整数,如果它和除了它自身以外的所有 正因子 之和相等,我们称它为 「完美数」。 9 | * 给定一个 整数 n, 如果是完美数,返回 true,否则返回 false 10 | * 11 | * 示例 1: 12 | * 输入:num = 28 13 | * 输出:true 14 | * 解释:28 = 1 + 2 + 4 + 7 + 14 15 | * 1, 2, 4, 7, 和 14 是 28 的所有正因子。 16 | * 17 | * 示例 2: 18 | * 输入:num = 6 19 | * 输出:true 20 | * 21 | * 示例 3: 22 | * 输入:num = 496 23 | * 输出:true 24 | * 25 | * 示例 4: 26 | * 输入:num = 8128 27 | * 输出:true 28 | * 29 | * 示例 5: 30 | * 输入:num = 2 31 | * 输出:false 32 | * 33 | * 提示: 34 | * 1 <= num <= 108 35 | * 通过次数 36,968 提交次数 84,680 36 | * 37 | * 来源:力扣(LeetCode) 38 | * 链接:https://leetcode-cn.com/problems/perfect-number 39 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 40 | */ 41 | public class PerfectNumber { 42 | 43 | public boolean checkPerfectNumber(int num) { 44 | if (num == 1) { 45 | return false; 46 | } 47 | int result = 1; 48 | for (int i = 2; i <= num / i; i++) { 49 | if (num % i == 0) { 50 | result += i + num / i; 51 | } 52 | } 53 | return result == num; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/com/hncboy/PlusOne.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author hncboy 7 | * @date 2019/9/18 7:59 8 | * @description 66.加一 9 | * 10 | * 给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。 11 | * 最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。 12 | * 你可以假设除了整数 0 之外,这个整数不会以零开头。 13 | * 14 | * 示例 1: 15 | * 输入: [1,2,3] 16 | * 输出: [1,2,4] 17 | * 解释: 输入数组表示数字 123。 18 | * 19 | * 示例 2: 20 | * 输入: [4,3,2,1] 21 | * 输出: [4,3,2,2] 22 | * 解释: 输入数组表示数字 4321。 23 | */ 24 | public class PlusOne { 25 | 26 | public static void main(String[] args) { 27 | int[] digits = new int[]{9, 9}; 28 | System.out.println(Arrays.toString(new PlusOne().plusOne(digits))); 29 | } 30 | 31 | private int[] plusOne(int[] digits) { 32 | int length = digits.length; 33 | for (int i = length - 1; i >= 0; i--) { 34 | digits[i]++; 35 | digits[i] %= 10; 36 | if (digits[i] != 0) { 37 | return digits; 38 | } 39 | } 40 | digits = new int[length + 1]; 41 | digits[0] = 1; 42 | return digits; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/com/hncboy/PoorPigs.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/11/25 13:19 6 | * @description 458.可怜的小猪 7 | * 8 | * 有 buckets 桶液体,其中 正好 有一桶含有毒药,其余装的都是水。它们从外观看起来都一样。为了弄清楚哪只水桶含有毒药,你可以喂一些猪喝,通过观察猪是否会死进行判断。不幸的是,你只有 minutesToTest 分钟时间来确定哪桶液体是有毒的。 9 | * 喂猪的规则如下: 10 | * 11 | * 选择若干活猪进行喂养 12 | * 可以允许小猪同时饮用任意数量的桶中的水,并且该过程不需要时间。 13 | * 小猪喝完水后,必须有 minutesToDie 分钟的冷却时间。在这段时间里,你只能观察,而不允许继续喂猪。 14 | * 过了 minutesToDie 分钟后,所有喝到毒药的猪都会死去,其他所有猪都会活下来。 15 | * 重复这一过程,直到时间用完。 16 | * 给你桶的数目 buckets ,minutesToDie 和 minutesToTest ,返回在规定时间内判断哪个桶有毒所需的 最小 猪数。 17 | * 18 | * 示例 1: 19 | * 输入:buckets = 1000, minutesToDie = 15, minutesToTest = 60 20 | * 输出:5 21 | * 22 | * 示例 2: 23 | * 输入:buckets = 4, minutesToDie = 15, minutesToTest = 15 24 | * 输出:2 25 | * 26 | * 示例 3: 27 | * 输入:buckets = 4, minutesToDie = 15, minutesToTest = 30 28 | * 输出:2 29 | * 30 | * 提示: 31 | * 1 <= buckets <= 1000 32 | * 1 <= minutesToDie <= minutesToTest <= 100 33 | * 34 | * 来源:力扣(LeetCode) 35 | * 链接:https://leetcode-cn.com/problems/poor-pigs 36 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 37 | */ 38 | public class PoorPigs { 39 | 40 | public int poorPigs(int buckets, int minutesToDie, int minutesToTest) { 41 | return (int) Math.ceil(Math.log(buckets) / Math.log(minutesToTest / minutesToDie + 1)); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/com/hncboy/PowerOfThree.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/10/9 8:20 6 | * @description 326. 3的幂 7 | * 8 | *给定一个整数,写一个函数来判断它是否是 3 的幂次方。 9 | * 10 | * 示例 1: 11 | * 输入: 27 12 | * 输出: true 13 | * 14 | * 示例 2: 15 | * 输入: 0 16 | * 输出: false 17 | * 18 | * 示例 3: 19 | * 输入: 9 20 | * 输出: true 21 | * 22 | * 示例 4: 23 | * 输入: 45 24 | * 输出: false 25 | * 进阶: 26 | * 你能不使用循环或者递归来完成本题吗? 27 | */ 28 | public class PowerOfThree { 29 | 30 | public static void main(String[] args) { 31 | PowerOfThree power = new PowerOfThree(); 32 | assert power.isPowerOfThree2(27); 33 | assert power.isPowerOfThree2(0); 34 | assert power.isPowerOfThree2(9); 35 | assert power.isPowerOfThree2(45); 36 | } 37 | 38 | /** 39 | * 迭代 40 | * @param n 41 | * @return 42 | */ 43 | private boolean isPowerOfThree2(int n) { 44 | while (n % 3 == 0 && n > 1) { 45 | n /= 3; 46 | } 47 | return n == 1; 48 | } 49 | 50 | private boolean isPowerOfThree1(int n) { 51 | return n > 0 && 1162261467 % n == 0; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/com/hncboy/PowerOfTwo.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/11/15 20:08 6 | * @description 231.2的幂 7 | * 8 | * 给定一个整数,编写一个函数来判断它是否是 2 的幂次方。 9 | * 10 | * 示例 1: 11 | * 输入: 1 12 | * 输出: true 13 | * 解释: 20 = 1 14 | * 15 | * 示例 2: 16 | * 输入: 16 17 | * 输出: true 18 | * 解释: 24 = 16 19 | * 20 | * 示例 3: 21 | * 输入: 218 22 | * 输出: false 23 | */ 24 | public class PowerOfTwo { 25 | 26 | public static void main(String[] args) { 27 | PowerOfTwo p = new PowerOfTwo(); 28 | System.out.println(p.isPowerOfTwo(1)); 29 | System.out.println(p.isPowerOfTwo(16)); 30 | System.out.println(p.isPowerOfTwo(218)); 31 | } 32 | 33 | private boolean isPowerOfTwo(int n) { 34 | return n > 0 && (n & (n - 1)) == 0; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/com/hncboy/PowxN.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/9/29 9:32 6 | * @description 50.Pow(x, n) 7 | * 8 | * 实现 pow(x, n) ,即计算 x 的 n 次幂函数。 9 | * 10 | * 示例 1: 11 | * 输入: 2.00000, 10 12 | * 输出: 1024.00000 13 | * 14 | * 示例 2: 15 | * 输入: 2.10000, 3 16 | * 输出: 9.26100 17 | * 18 | * 示例 3: 19 | * 输入: 2.00000, -2 20 | * 输出: 0.25000 21 | * 解释: 2-2 = 1/22 = 1/4 = 0.25 22 | * 23 | * 说明: 24 | * -100.0 < x < 100.0 25 | * n 是 32 位有符号整数,其数值范围是 [−231, 231 − 1] 。 26 | */ 27 | public class PowxN { 28 | 29 | public static void main(String[] args) { 30 | System.out.println(new PowxN().myPow(2.00000, 10)); 31 | System.out.println(new PowxN().myPow(2.10000, 3)); 32 | System.out.println(new PowxN().myPow(2.00000, -2)); 33 | } 34 | 35 | private double myPow(double x, int n) { 36 | double result = 1; 37 | // 折半计算 38 | for (int i = n; i != 0; i /= 2) { 39 | if (i % 2 != 0) { 40 | // i 为奇数的时候 result = result*x 41 | result *= x; 42 | } 43 | // 每次折半 x 都翻倍 44 | x *= x; 45 | } 46 | return n > 0 ? result : 1 / result; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/com/hncboy/ProductOfArrayExceptSelf.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author hncboy 7 | * @date 2019/10/18 8:47 8 | * @description 238.除自身以外数组的乘积 9 | * 10 | * 给定长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。 11 | * 12 | * 示例: 13 | * 输入: [1,2,3,4] 14 | * 输出: [24,12,8,6] 15 | * 说明: 请不要使用除法,且在 O(n) 时间复杂度内完成此题。 16 | * 17 | * 进阶: 18 | * 你可以在常数空间复杂度内完成这个题目吗? 19 | * ( 出于对空间复杂度分析的目的,输出数组不被视为额外空间。) 20 | */ 21 | public class ProductOfArrayExceptSelf { 22 | 23 | public static void main(String[] args) { 24 | ProductOfArrayExceptSelf p = new ProductOfArrayExceptSelf(); 25 | int[] nums = new int[]{1, 2, 3, 4}; 26 | System.out.println(Arrays.toString(p.productExceptSelf(nums))); 27 | } 28 | 29 | private int[] productExceptSelf(int[] nums) { 30 | int length = nums.length; 31 | int[] output = new int[length]; 32 | int result = 1; 33 | 34 | // 存储每个数对应左边数的乘积 35 | for (int i = 0; i < length; i++) { 36 | output[i] = result; 37 | result *= nums[i]; 38 | } 39 | 40 | result = 1; 41 | // 在上一步基础上,存储每个数对应右边数的乘积 42 | for (int i = length - 1; i >= 0; i--) { 43 | output[i] *= result; 44 | result *= nums[i]; 45 | } 46 | 47 | return output; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/com/hncboy/RangeAdditionII.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/11/7 12:30 6 | * @description 598.范围求和 II 7 | * 8 | * 给定一个初始元素全部为 0,大小为 m*n 的矩阵 M 以及在 M 上的一系列更新操作。 9 | * 操作用二维数组表示,其中的每个操作用一个含有两个正整数 a 和 b 的数组表示,含义是将所有符合 0 <= i < a 以及 0 <= j < b 的元素 M[i][j] 的值都增加 1。 10 | * 在执行给定的一系列操作后,你需要返回矩阵中含有最大整数的元素个数。 11 | * 12 | * 示例 1: 13 | * 输入: 14 | * m = 3, n = 3 15 | * operations = [[2,2],[3,3]] 16 | * 输出: 4 17 | * 解释: 18 | * 初始状态, M = 19 | * [[0, 0, 0], 20 | * [0, 0, 0], 21 | * [0, 0, 0]] 22 | * 23 | * 执行完操作 [2,2] 后, M = 24 | * [[1, 1, 0], 25 | * [1, 1, 0], 26 | * [0, 0, 0]] 27 | * 28 | * 执行完操作 [3,3] 后, M = 29 | * [[2, 2, 1], 30 | * [2, 2, 1], 31 | * [1, 1, 1]] 32 | * 33 | * M 中最大的整数是 2, 而且 M 中有4个值为2的元素。因此返回 4。 34 | * 注意: 35 | * 36 | * m 和 n 的范围是 [1,40000]。 37 | * a 的范围是 [1,m],b 的范围是 [1,n]。 38 | * 操作数目不超过 10000。 39 | * 40 | * 来源:力扣(LeetCode) 41 | * 链接:https://leetcode-cn.com/problems/range-addition-ii 42 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 43 | */ 44 | public class RangeAdditionII { 45 | 46 | public int maxCount(int m, int n, int[][] ops) { 47 | for (int[] op : ops) { 48 | m = Math.min(m, op[0]); 49 | n = Math.min(n, op[1]); 50 | } 51 | return m * n; 52 | } 53 | } -------------------------------------------------------------------------------- /src/com/hncboy/RangeSumQueryImmutable.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/10/25 13:02 6 | * @description 303.区域和检索 - 数组不可变 7 | * 8 | * 给定一个整数数组  nums,求出数组从索引 i 到 j  (i ≤ j) 范围内元素的总和,包含 i,  j 两点。 9 | * 10 | * 示例: 11 | * 给定 nums = [-2, 0, 3, -5, 2, -1],求和函数为 sumRange() 12 | * 13 | * sumRange(0, 2) -> 1 14 | * sumRange(2, 5) -> -1 15 | * sumRange(0, 5) -> -3 16 | * 说明: 17 | * 你可以假设数组不可变。 18 | * 会多次调用 sumRange 方法。 19 | */ 20 | public class RangeSumQueryImmutable { 21 | 22 | private int[] dp; 23 | 24 | public static void main(String[] args) { 25 | int[] nums = new int[]{-2, 0, 3, -5, 2, -1}; 26 | RangeSumQueryImmutable r = new RangeSumQueryImmutable(nums); 27 | System.out.println(r.sumRange(0, 2)); 28 | System.out.println(r.sumRange(2, 5)); 29 | System.out.println(r.sumRange(0, 5)); 30 | } 31 | 32 | private RangeSumQueryImmutable(int[] nums) { 33 | dp = new int[nums.length + 1]; 34 | dp[0] = 0; 35 | for (int i = 1; i <= nums.length; i++) { 36 | dp[i] = dp[i - 1] + nums[i - 1]; 37 | } 38 | } 39 | 40 | private int sumRange(int i, int j) { 41 | return dp[j + 1] - dp[i]; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/com/hncboy/RangeSumQueryMutable.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2022/4/4 14:35 6 | * 307.区域和检索 - 数组可修改 TODO 7 | */ 8 | public class RangeSumQueryMutable { 9 | 10 | private static class NumArray { 11 | 12 | private int[] tree; 13 | private int[] nums; 14 | 15 | public NumArray(int[] nums) { 16 | this.tree = new int[nums.length + 1]; 17 | this.nums = nums; 18 | for (int i = 0; i < nums.length; i++) { 19 | add(i + 1, nums[i]); 20 | } 21 | } 22 | 23 | public void update(int index, int val) { 24 | add(index + 1, val - nums[index]); 25 | nums[index] = val; 26 | } 27 | 28 | public int sumRange(int left, int right) { 29 | return prefixSum(right + 1) - prefixSum(left); 30 | } 31 | 32 | private int lowBit(int x) { 33 | return x & -x; 34 | } 35 | 36 | private void add(int index, int val) { 37 | while (index < tree.length) { 38 | tree[index] += val; 39 | index += lowBit(index); 40 | } 41 | } 42 | 43 | private int prefixSum(int index) { 44 | int sum = 0; 45 | while (index > 0) { 46 | sum += tree[index]; 47 | index -= lowBit(index); 48 | } 49 | return sum; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/com/hncboy/RectangleOverlap.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2020/3/18 21:42 6 | * @description 836.矩形重叠 7 | * 8 | * 矩形以列表 [x1, y1, x2, y2] 的形式表示,其中 (x1, y1) 为左下角的坐标,(x2, y2) 是右上角的坐标。 9 | * 如果相交的面积为正,则称两矩形重叠。需要明确的是,只在角或边接触的两个矩形不构成重叠。 10 | * 给出两个矩形,判断它们是否重叠并返回结果。 11 | * 12 | * 示例 1: 13 | * 输入:rec1 = [0,0,2,2], rec2 = [1,1,3,3] 14 | * 输出:true 15 | * 16 | * 示例 2: 17 | * 输入:rec1 = [0,0,1,1], rec2 = [1,0,2,1] 18 | * 输出:false 19 | * 20 | * 提示: 21 | * 两个矩形 rec1 和 rec2 都以含有四个整数的列表的形式给出。 22 | * 矩形中的所有坐标都处于 -10^9 和 10^9 之间。 23 | * x 轴默认指向右,y 轴默认指向上。 24 | * 你可以仅考虑矩形是正放的情况。 25 | */ 26 | public class RectangleOverlap { 27 | 28 | private boolean isRectangleOverlap(int[] rec1, int[] rec2) { 29 | return !(rec1[2] <= rec2[0] || rec2[2] <= rec1[0] || rec1[3] <= rec2[1] || rec2[3] <= rec1[1]); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/com/hncboy/RemoveDuplicatesFromSortedArray.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/9/23 16:22 6 | * @description 26.删除排序数组中的重复项 7 | * 8 | * 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。 9 | * 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。 10 | * 11 | * 示例 1: 12 | * 给定数组 nums = [1,1,2], 13 | * 函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。 14 | * 你不需要考虑数组中超出新长度后面的元素。 15 | * 16 | * 示例 2: 17 | * 给定 nums = [0,0,1,1,1,2,2,3,3,4], 18 | * 函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。 19 | * 你不需要考虑数组中超出新长度后面的元素。 20 | */ 21 | public class RemoveDuplicatesFromSortedArray { 22 | 23 | public static void main(String[] args) { 24 | int[] nums = new int[]{0, 0, 1, 1, 1, 2, 2, 3, 3, 4}; 25 | System.out.println(new RemoveDuplicatesFromSortedArray().removeDuplicates(nums)); 26 | } 27 | 28 | private int removeDuplicates(int[] nums) { 29 | int length = nums.length; 30 | int i = 0; 31 | for (int j = 1; j < length; j++) { 32 | if (nums[j] != nums[i]) { 33 | i++; 34 | nums[i] = nums[j]; 35 | } 36 | } 37 | return length == 0 ? 0 : i + 1; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/com/hncboy/RemoveElement.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/9/17 8:21 6 | * @description 27.移除元素 7 | * 8 | * 给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。 9 | * 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。 10 | * 元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。 11 | * 12 | * 示例 1: 13 | * 给定 nums = [3,2,2,3], val = 3, 14 | * 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 15 | * 你不需要考虑数组中超出新长度后面的元素。 16 | * 17 | * 示例 2: 18 | * 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 19 | * 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。 20 | * 注意这五个元素可为任意顺序。 21 | * 你不需要考虑数组中超出新长度后面的元素。 22 | */ 23 | public class RemoveElement { 24 | 25 | public static void main(String[] args) { 26 | int[] nums = new int[]{3, 2, 2, 3}; 27 | System.out.println(new RemoveElement().removeElement(nums, 3)); 28 | } 29 | 30 | private int removeElement(int[] nums, int val) { 31 | int length = nums.length; 32 | if (length == 0) { 33 | return 0; 34 | } 35 | int count = 0; 36 | for (int i = 0; i < length; i++) { 37 | // 不相等的话就把该元素赋值到对应的位置 38 | if (nums[i] != val) { 39 | nums[count] = nums[i]; 40 | count++; 41 | } 42 | } 43 | return count; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/com/hncboy/RemovePalindromicSubsequences.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2022/1/22 13:51 6 | * 1332.删除回文子序列 7 | * 8 | * 给你一个字符串 s,它仅由字母 'a' 和 'b' 组成。每一次删除操作都可以从 s 中删除一个回文 子序列。 9 | * 返回删除给定字符串中所有字符(字符串为空)的最小删除次数。 10 | * 「子序列」定义:如果一个字符串可以通过删除原字符串某些字符而不改变原字符顺序得到,那么这个字符串就是原字符串的一个子序列。 11 | * 「回文」定义:如果一个字符串向后和向前读是一致的,那么这个字符串就是一个回文。 12 | * 13 | * 示例 1: 14 | * 输入:s = "ababa" 15 | * 输出:1 16 | * 解释:字符串本身就是回文序列,只需要删除一次。 17 | * 18 | * 示例 2: 19 | * 输入:s = "abb" 20 | * 输出:2 21 | * 解释:"abb" -> "bb" -> "". 22 | * 先删除回文子序列 "a",然后再删除 "bb"。 23 | * 24 | * 示例 3: 25 | * 输入:s = "baabb" 26 | * 输出:2 27 | * 解释:"baabb" -> "b" -> "". 28 | * 先删除回文子序列 "baab",然后再删除 "b"。 29 | * 30 | * 提示: 31 | * 1 <= s.length <= 1000 32 | * s 仅包含字母 'a' 和 'b' 33 | * 通过次数 19,076 提交次数 25,376 34 | */ 35 | public class RemovePalindromicSubsequences { 36 | 37 | public int removePalindromeSub(String s) { 38 | int i = 0; 39 | int j = s.length() - 1; 40 | while (i < j) { 41 | if (s.charAt(i++) != s.charAt(j--)) { 42 | return 2; 43 | } 44 | } 45 | return 1; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/com/hncboy/ReorderedPowerOf2.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | /** 7 | * @author hncboy 8 | * @date 2021/10/28 8:26 9 | * @description 869.重新排序得到 2 的幂 10 | * 11 | * 给定正整数 N,我们按任何顺序(包括原始顺序)将数字重新排序,注意其前导数字不能为零。 12 | * 如果我们可以通过上述方式得到 2 的幂,返回 true;否则,返回 false。 13 | * 14 | * 示例 1: 15 | * 输入:1 16 | * 输出:true 17 | * 18 | * 示例 2: 19 | * 输入:10 20 | * 输出:false 21 | * 22 | * 示例 3: 23 | * 输入:16 24 | * 输出:true 25 | * 26 | * 示例 4: 27 | * 输入:24 28 | * 输出:false 29 | * 30 | * 示例 5: 31 | * 输入:46 32 | * 输出:true 33 | * 34 | * 提示: 35 | * 1 <= N <= 10^9 36 | * 37 | * 来源:力扣(LeetCode) 38 | * 链接:https://leetcode-cn.com/problems/reordered-power-of-2 39 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 40 | */ 41 | public class ReorderedPowerOf2 { 42 | 43 | public boolean reorderedPowerOf2(int n) { 44 | Set powerOf2Digits = new HashSet<>(); 45 | // 遍历所有 2 的幂的整数 46 | for (int i = 1; i <= 1e9; i *= 2) { 47 | powerOf2Digits.add(countDigits(i)); 48 | } 49 | return powerOf2Digits.contains(countDigits(n)); 50 | } 51 | 52 | /** 53 | * 将整数 n 的每位计数统计 54 | * 55 | * @param n 2 的幂的整数 56 | * @return 计数后的字符串 57 | */ 58 | private String countDigits(int n) { 59 | char[] count = new char[10]; 60 | while (n > 0) { 61 | count[n % 10]++; 62 | n /= 10; 63 | } 64 | return new String(count); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/com/hncboy/ReplaceElementsWithGreatestElementOnRightSide.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author hncboy 7 | * @date 2019/12/30 22:03 8 | * @description 1299.将每个元素替换为右侧最大元素 9 | * 10 | * 给你一个数组 arr ,请你将每个元素用它右边最大的元素替换,如果是最后一个元素,用 -1 替换。 11 | * 完成所有替换操作后,请你返回这个数组。 12 | * 13 | * 示例: 14 | * 输入:arr = [17,18,5,4,6,1] 15 | * 输出:[18,6,6,6,1,-1] 16 | * 17 | * 提示: 18 | * 1 <= arr.length <= 10^4 19 | * 1 <= arr[i] <= 10^5 20 | */ 21 | public class ReplaceElementsWithGreatestElementOnRightSide { 22 | 23 | public static void main(String[] args) { 24 | ReplaceElementsWithGreatestElementOnRightSide r = new ReplaceElementsWithGreatestElementOnRightSide(); 25 | System.out.println(Arrays.toString(r.replaceElements(new int[]{17, 18, 5, 4, 6, 1}))); 26 | } 27 | 28 | private int[] replaceElements(int[] arr) { 29 | int rightMax = arr[arr.length - 1]; 30 | arr[arr.length - 1] = -1; 31 | for (int i = arr.length - 2; i >= 0; i--) { 32 | int temp = arr[i]; 33 | arr[i] = rightMax; 34 | rightMax = Math.max(rightMax, temp); 35 | } 36 | return arr; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/com/hncboy/ReverseInteger.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/9/1 9:06 6 | * @description 7.整数反转 7 | * 8 | * 给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。 9 | * 10 | * 示例 1: 11 | * 输入: 123 12 | * 输出: 321 13 | * 14 | *  示例 2: 15 | * 输入: -123 16 | * 输出: -321 17 | * 18 | * 示例 3: 19 | * 输入: 120 20 | * 输出: 21 21 | * 22 | * 注意: 23 | * 假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231,  231 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。 24 | */ 25 | public class ReverseInteger { 26 | 27 | public static void main(String[] args) { 28 | System.out.println(reverse(1534236469)); 29 | } 30 | 31 | private static int reverse(int x) { 32 | if (x == 0 || x == Integer.MAX_VALUE || x == Integer.MIN_VALUE) { 33 | return 0; 34 | } else if (x > 0) { 35 | return plusReverse(x); 36 | } else { 37 | return -plusReverse(-x); 38 | } 39 | } 40 | 41 | private static int plusReverse(int x) { 42 | String s = String.valueOf(x); 43 | int length = s.length(); 44 | StringBuilder sb = new StringBuilder(); 45 | for (int i = 0; i < length; i++) { 46 | sb.append(s.charAt(length - i - 1)); 47 | } 48 | 49 | String maxValue = String.valueOf(Integer.MAX_VALUE); 50 | if (length == maxValue.length() && sb.toString().compareTo(maxValue) > 0) { 51 | return 0; 52 | } 53 | return Integer.parseInt(sb.toString()); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/com/hncboy/ReverseString.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/9/26 8:23 6 | * @description 344.反转字符串 7 | * 8 | * 写一个函数,其作用是将输入的字符串反转过来。 9 | * 输入字符串以字符数组 char[] 的形式给出。 10 | * 不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。 11 | * 你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。 12 | * 13 | * 示例 1: 14 | * 输入:["h","e","l","l","o"] 15 | * 输出:["o","l","l","e","h"] 16 | * 17 | * 示例 2: 18 | * 输入:["H","a","n","n","a","h"] 19 | * 输出:["h","a","n","n","a","H"] 20 | */ 21 | public class ReverseString { 22 | 23 | public static void main(String[] args) { 24 | char[] s1 = new char[]{'h', 'e', 'l', 'l', 'o'}; 25 | char[] s2 = new char[]{'H','a','n','n','a','h'}; 26 | new ReverseString().reverseString(s2); 27 | } 28 | 29 | private void reverseString(char[] s) { 30 | int length = s.length; 31 | char t; 32 | for (int i = 0; i < length / 2; i++) { 33 | t = s[i]; 34 | s[i] = s[length - i - 1]; 35 | s[length - i - 1] = t; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/com/hncboy/RotateString.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2022/4/7 12:44 6 | * 796.旋转字符串 7 | * 8 | * 给定两个字符串, s 和 goal。如果在若干次旋转操作之后,s 能变成 goal ,那么返回 true 。 9 | * s 的 旋转操作 就是将 s 最左边的字符移动到最右边。 10 | * 例如, 若 s = 'abcde',在旋转一次之后结果就是'bcdea' 。 11 | * 12 | * 示例 1: 13 | * 输入: s = "abcde", goal = "cdeab" 14 | * 输出: true 15 | * 16 | * 示例 2: 17 | * 输入: s = "abcde", goal = "abced" 18 | * 输出: false 19 | * 20 | * 提示: 21 | * 1 <= s.length, goal.length <= 100 22 | * s 和 goal 由小写英文字母组成 23 | * 通过次数 46,356 提交次数 76,721 24 | * 25 | * 来源:力扣(LeetCode) 26 | * 链接:https://leetcode-cn.com/problems/rotate-string 27 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 28 | */ 29 | public class RotateString { 30 | 31 | public boolean rotateString(String s, String goal) { 32 | return s.length() == goal.length() && (s + s).contains(goal); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/com/hncboy/SearchA2dMatrixII.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2020/2/16 14:30 6 | * @description 240.搜索二维矩阵 II 7 | * 8 | * 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target。该矩阵具有以下特性: 9 | * 每行的元素从左到右升序排列。 10 | * 每列的元素从上到下升序排列。 11 | * 12 | * 示例: 13 | * 现有矩阵 matrix 如下: 14 | * [ 15 | * [1, 4, 7, 11, 15], 16 | * [2, 5, 8, 12, 19], 17 | * [3, 6, 9, 16, 22], 18 | * [10, 13, 14, 17, 24], 19 | * [18, 21, 23, 26, 30] 20 | * ] 21 | * 给定 target = 5,返回 true。 22 | * 给定 target = 20,返回 false。 23 | */ 24 | public class SearchA2dMatrixII { 25 | 26 | private boolean findNumberIn2DArray(int[][] matrix, int target) { 27 | int i = matrix.length - 1; 28 | int j = 0; 29 | 30 | // 从矩阵的左下角开始遍历 31 | while (i >= 0 && j < matrix[0].length) { 32 | if (matrix[i][j] > target) { 33 | // 如果值大于 target,则往上移动 34 | i--; 35 | } else if (matrix[i][j] < target) { 36 | // 如果值小于 target,则往右移动 37 | j++; 38 | } else { 39 | return true; 40 | } 41 | } 42 | return false; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/com/hncboy/SearchInABinarySearchTree.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/11/26 9:59 6 | * @description 700.二叉搜索树中的搜索 7 | * 8 | * 给定二叉搜索树(BST)的根节点和一个值。 你需要在BST中找到节点值等于给定值的节点。 返回以该节点为根的子树。 9 | * 如果节点不存在,则返回 NULL。 10 | * 11 | * 例如, 12 | * 给定二叉搜索树: 13 | * 14 | * 4 15 | * / \ 16 | * 2 7 17 | * / \ 18 | * 1 3 19 | * 和值: 2 20 | * 你应该返回如下子树: 21 | * 2 22 | * / \ 23 | * 1 3 24 | * 在上述示例中,如果要找的值是 5,但因为没有节点值为 5,我们应该返回 NULL。 25 | * 26 | * 通过次数 98,849 提交次数 128,695 27 | * 28 | * 来源:力扣(LeetCode) 29 | * 链接:https://leetcode-cn.com/problems/search-in-a-binary-search-tree 30 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 31 | */ 32 | public class SearchInABinarySearchTree { 33 | 34 | public TreeNode searchBST(TreeNode root, int val) { 35 | while (root != null && root.val != val) { 36 | root = root.val < val ? root.right : root.left; 37 | } 38 | return root; 39 | } 40 | 41 | private static class TreeNode { 42 | int val; 43 | TreeNode left; 44 | TreeNode right; 45 | 46 | TreeNode() { 47 | } 48 | 49 | TreeNode(int val) { 50 | this.val = val; 51 | } 52 | 53 | TreeNode(int val, TreeNode left, TreeNode right) { 54 | this.val = val; 55 | this.left = left; 56 | this.right = right; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/com/hncboy/SimplifiedFractions.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @author hncboy 8 | * @date 2022/2/10 8:49 9 | * 1447.最简分数 10 | * 11 | * 给你一个整数 n ,请你返回所有 0 到 1 之间(不包括 0 和 1)满足分母小于等于 n 的 最简 分数 。分数可以以 任意 顺序返回。 12 | * 13 | * 示例 1: 14 | * 输入:n = 2 15 | * 输出:["1/2"] 16 | * 解释:"1/2" 是唯一一个分母小于等于 2 的最简分数。 17 | * 18 | * 示例 2: 19 | * 输入:n = 3 20 | * 输出:["1/2","1/3","2/3"] 21 | * 22 | * 示例 3: 23 | * 输入:n = 4 24 | * 输出:["1/2","1/3","1/4","2/3","3/4"] 25 | * 解释:"2/4" 不是最简分数,因为它可以化简为 "1/2" 。 26 | * 27 | * 示例 4: 28 | * 输入:n = 1 29 | * 输出:[] 30 | * 31 | * 提示: 32 | * 1 <= n <= 100 33 | * 通过次数 10,140 提交次数 15,519 34 | */ 35 | public class SimplifiedFractions { 36 | 37 | public List simplifiedFractions(int n) { 38 | List result = new ArrayList<>(); 39 | // 遍历分母,分母从 2 开始 40 | for (int denominator = 2; denominator <= n; denominator++) { 41 | // 遍历分子,分子从 1 开始,分子小于分母 42 | for (int numerator = 1; numerator < denominator; numerator++) { 43 | // 判断分子和分母的最大公约数是否为最简 44 | if (gcd(numerator, denominator) == 1) { 45 | result.add(numerator + "/" + denominator); 46 | } 47 | } 48 | } 49 | return result; 50 | } 51 | 52 | /** 53 | * 欧几里得算法求最大公约数 54 | */ 55 | private int gcd(int a, int b) { 56 | return b != 0 ? gcd(b, a % b) : a; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/com/hncboy/SingleNumber.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | import java.util.HashSet; 4 | import java.util.Iterator; 5 | import java.util.Set; 6 | 7 | /** 8 | * @author hncboy 9 | * @date 2019/9/9 17:09 10 | * @description 136.只出现一次的数字 11 | *

12 | * 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。 13 | * 找出那个只出现了一次的元素。 14 | * 说明: 15 | * 你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗? 16 | *

17 | * 示例 1: 18 | * 输入: [2,2,1] 19 | * 输出: 1 20 | *

21 | * 示例 2: 22 | * 输入: [4,1,2,1,2] 23 | * 输出: 4 24 | */ 25 | public class SingleNumber { 26 | 27 | public static void main(String[] args) { 28 | int[] nums = new int[]{4, 1, 2, 1, 2}; 29 | System.out.println(singleNumber2(nums)); 30 | } 31 | 32 | private static int singleNumber2(int[] nums) { 33 | /* 34 | 1.交换律:a ^ b ^ c <=> a ^ c ^ b 35 | 2.任何数于0异或为任何数 0 ^ n => n 36 | 3.相同的数异或为0: n ^ n => 0 37 | */ 38 | int result = 0; 39 | for (int num : nums) { 40 | result ^= num; 41 | } 42 | return result; 43 | } 44 | 45 | private static int singleNumber1(int[] nums) { 46 | Set set = new HashSet<>(); 47 | for (int num : nums) { 48 | if (set.contains(num)) { 49 | set.remove(num); 50 | continue; 51 | } 52 | set.add(num); 53 | } 54 | Iterator iterator = set.iterator(); 55 | return iterator.next(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/com/hncboy/SingleNumberII.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | import com.hncboy.swordreferstoofferspecial.Question004; 4 | 5 | /** 6 | * @author hncboy 7 | * @date 2021/10/27 9:41 8 | * @description 137.只出现一次的数字 II 9 | * 10 | * 给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。 11 | * 12 | * 示例 1: 13 | * 输入:nums = [2,2,3,2] 14 | * 输出:3 15 | * 16 | * 示例 2: 17 | * 输入:nums = [0,1,0,1,0,1,99] 18 | * 输出:99 19 | * 20 | * 提示: 21 | * 1 <= nums.length <= 3 * 104 22 | * -231 <= nums[i] <= 231 - 1 23 | * nums 中,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 24 | * 25 | * 进阶:你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗? 26 | * 27 | * 来源:力扣(LeetCode) 28 | * 链接:https://leetcode-cn.com/problems/single-number-ii 29 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 30 | */ 31 | public class SingleNumberII { 32 | 33 | public static void main(String[] args) { 34 | Question004 q = new Question004(); 35 | System.out.println(q.singleNumber(new int[]{2, 2, 3, 2})); 36 | } 37 | 38 | public int singleNumber(int[] nums) { 39 | // 用两位表示 3 种状态 40 | int ones = 0; 41 | int twos = 0; 42 | for (int num : nums) { 43 | ones = ones ^ num & ~twos; 44 | twos = twos ^ num & ~ones; 45 | } 46 | return ones; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/com/hncboy/SlowestKey.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2022/1/9 12:44 6 | * 1629.按键持续时间最长的键 7 | */ 8 | public class SlowestKey { 9 | 10 | public static void main(String[] args) { 11 | SlowestKey s = new SlowestKey(); 12 | System.out.println(s.slowestKey(new int[]{9, 29, 49, 50}, "cbcd")); 13 | System.out.println(s.slowestKey(new int[]{12,23,36,46,62}, "spuda")); 14 | } 15 | 16 | public char slowestKey(int[] releaseTimes, String keysPressed) { 17 | int maxTime = releaseTimes[0]; 18 | char result = keysPressed.charAt(0); 19 | for (int i = 1; i < releaseTimes.length; i++) { 20 | char key = keysPressed.charAt(i); 21 | int time = releaseTimes[i] - releaseTimes[i - 1]; 22 | if (time > maxTime || (time == maxTime && key > result)) { 23 | result = key; 24 | maxTime = time; 25 | } 26 | } 27 | return result; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/com/hncboy/SortArrayByParityII.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author hncboy 7 | * @date 2019/12/5 18:05 8 | * @description 922.按奇偶排序数组 II 9 | * 10 | * 给定一个非负整数数组 A, A 中一半整数是奇数,一半整数是偶数。 11 | * 对数组进行排序,以便当 A[i] 为奇数时,i 也是奇数;当 A[i] 为偶数时, i 也是偶数。 12 | * 你可以返回任何满足上述条件的数组作为答案。 13 | * 14 | * 示例: 15 | * 输入:[4,2,5,7] 16 | * 输出:[4,5,2,7] 17 | * 解释:[4,7,2,5],[2,5,4,7],[2,7,4,5] 也会被接受。 18 | *   19 | * 提示: 20 | * 2 <= A.length <= 20000 21 | * A.length % 2 == 0 22 | * 0 <= A[i] <= 1000 23 | */ 24 | public class SortArrayByParityII { 25 | 26 | public static void main(String[] args) { 27 | SortArrayByParityII s = new SortArrayByParityII(); 28 | System.out.println(Arrays.toString(s.sortArrayByParityII(new int[]{4, 2, 5, 7}))); 29 | } 30 | 31 | public int[] sortArrayByParityII(int[] A) { 32 | for (int i = 0, j = 1; i < A.length; i += 2) { 33 | if ((A[i] & 1) == 1) { 34 | while ((A[j] & 1) == 1) { 35 | j += 2; 36 | } 37 | A[i] = A[i] ^ A[j]; 38 | A[j] = A[i] ^ A[j]; 39 | A[i] = A[i] ^ A[j]; 40 | } 41 | } 42 | return A; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/com/hncboy/SubtractTheProductAndSumOfDigitsOfAnInteger.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/12/8 10:30 6 | * @description 1281.整数的各位积和之差 7 | * 8 | * 给你一个整数 n,请你帮忙计算并返回该整数「各位数字之积」与「各位数字之和」的差。 9 | * 10 | * 示例 1: 11 | * 输入:n = 234 12 | * 输出:15 13 | * 解释: 14 | * 各位数之积 = 2 * 3 * 4 = 24 15 | * 各位数之和 = 2 + 3 + 4 = 9 16 | * 结果 = 24 - 9 = 15 17 | * 18 | * 示例 2: 19 | * 输入:n = 4421 20 | * 输出:21 21 | * 解释: 22 | * 各位数之积 = 4 * 4 * 2 * 1 = 32 23 | * 各位数之和 = 4 + 4 + 2 + 1 = 11 24 | * 结果 = 32 - 11 = 21 25 | *   26 | * 提示: 27 | * 1 <= n <= 10^5 28 | */ 29 | public class SubtractTheProductAndSumOfDigitsOfAnInteger { 30 | 31 | public static void main(String[] args) { 32 | SubtractTheProductAndSumOfDigitsOfAnInteger s = new SubtractTheProductAndSumOfDigitsOfAnInteger(); 33 | System.out.println(s.subtractProductAndSum(234)); 34 | System.out.println(s.subtractProductAndSum(4421)); 35 | } 36 | 37 | private int subtractProductAndSum(int n) { 38 | int sum = 0; 39 | int product = 1; 40 | while (n > 0) { 41 | int num = n % 10; 42 | sum += num; 43 | product *= num; 44 | n /= 10; 45 | } 46 | return product - sum; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/com/hncboy/SumOfTwoIntegers.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/10/9 9:28 6 | * @description 371.两整数之和 7 | * 8 | * 不使用运算符 + 和 - ,计算两整数 a 、b 之和。 9 | * 10 | * 示例 1: 11 | * 输入: a = 1, b = 2 12 | * 输出: 3 13 | * 14 | * 示例 2: 15 | * 输入: a = -2, b = 3 16 | * 输出: 1 17 | */ 18 | public class SumOfTwoIntegers { 19 | 20 | public static void main(String[] args) { 21 | System.out.println(new SumOfTwoIntegers().getSum(1, 2)); 22 | System.out.println(new SumOfTwoIntegers().getSum(-2, 3)); 23 | } 24 | 25 | private int getSum(int a, int b) { 26 | // 循环,直到进位符为 0 27 | while (b != 0) { 28 | // & 操作符获取进位结果 29 | int c = (a & b) << 1; 30 | // ^ 操作符获取无进位结果 31 | // 当进位符为 0 时,异或运算的结果就是加法的结果,异或是无进位加法 32 | a = a ^ b; 33 | b = c; 34 | } 35 | return a; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/com/hncboy/SumOfUniqueElements.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2022/2/6 14:51 6 | * 1748.唯一元素的和 7 | * 8 | * 给你一个整数数组 nums 。数组中唯一元素是那些只出现 恰好一次 的元素。 9 | * 请你返回 nums 中唯一元素的 和 。 10 | * 11 | * 示例 1: 12 | * 输入:nums = [1,2,3,2] 13 | * 输出:4 14 | * 解释:唯一元素为 [1,3] ,和为 4 。 15 | * 16 | * 示例 2: 17 | * 输入:nums = [1,1,1,1,1] 18 | * 输出:0 19 | * 解释:没有唯一元素,和为 0 。 20 | * 21 | * 示例 3 : 22 | * 输入:nums = [1,2,3,4,5] 23 | * 输出:15 24 | * 解释:唯一元素为 [1,2,3,4,5] ,和为 15 。 25 | * 26 | * 提示: 27 | * 1 <= nums.length <= 100 28 | * 1 <= nums[i] <= 100 29 | * 通过次数 25,637 提交次数 32,451 30 | */ 31 | public class SumOfUniqueElements { 32 | 33 | public int sumOfUnique(int[] nums) { 34 | int[] temp = new int[101]; 35 | for (int num : nums) { 36 | temp[num]++; 37 | } 38 | 39 | int result = 0; 40 | for (int i = 0; i < temp.length; i++) { 41 | if (temp[i] == 1) { 42 | result += i; 43 | } 44 | } 45 | return result; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/com/hncboy/SummaryRanges.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @author hncboy 8 | * @date 2019/11/20 12:39 9 | * @description 228.汇总区间 10 | * 11 | * 给定一个无重复元素的有序整数数组,返回数组区间范围的汇总。 12 | * 13 | * 示例 1: 14 | * 输入: [0,1,2,4,5,7] 15 | * 输出: ["0->2","4->5","7"] 16 | * 解释: 0,1,2 可组成一个连续的区间; 4,5 可组成一个连续的区间。 17 | * 18 | * 示例 2: 19 | * 输入: [0,2,3,4,6,8,9] 20 | * 输出: ["0","2->4","6","8->9"] 21 | * 解释: 2,3,4 可组成一个连续的区间; 8,9 可组成一个连续的区间。 22 | */ 23 | public class SummaryRanges { 24 | 25 | public static void main(String[] args) { 26 | SummaryRanges s = new SummaryRanges(); 27 | int[] nums1 = {0, 1, 2, 4, 5, 7}; 28 | int[] nums2 = {0, 2, 3, 4, 6, 8, 9}; 29 | System.out.println(s.summaryRanges(nums1)); 30 | System.out.println(s.summaryRanges(nums2)); 31 | } 32 | 33 | private List summaryRanges(int[] nums) { 34 | List result = new ArrayList<>(); 35 | for (int i = 0, last = 0; i < nums.length; i++) { 36 | if (i < nums.length - 1 && nums[i + 1] - nums[i] == 1) { 37 | continue; 38 | } 39 | if (i == last) { 40 | result.add(nums[last] + ""); 41 | } else { 42 | result.add(nums[last] + "->" + nums[i]); 43 | } 44 | last = i + 1; 45 | } 46 | return result; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/com/hncboy/SuperUglyNumber.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hncboy/LeetCode/ab66f67d0a7a6667f1b21e8f0be503eb351863bd/src/com/hncboy/SuperUglyNumber.java -------------------------------------------------------------------------------- /src/com/hncboy/SurfaceAreaOf3dShapes.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2020/3/25 15:39 6 | * @description 892.三维形体的表面积 7 | * 8 | * 在 N * N 的网格上,我们放置一些 1 * 1 * 1  的立方体。 9 | * 每个值 v = grid[i][j] 表示 v 个正方体叠放在对应单元格 (i, j) 上。 10 | * 请你返回最终形体的表面积。 11 | * 12 | * 示例 1: 13 | * 输入:[[2]] 14 | * 输出:10 15 | * 16 | * 示例 2: 17 | * 输入:[[1,2],[3,4]] 18 | * 输出:34 19 | * 20 | * 示例 3: 21 | * 输入:[[1,0],[0,2]] 22 | * 输出:16 23 | * 24 | * 示例 4: 25 | * 输入:[[1,1,1],[1,0,1],[1,1,1]] 26 | * 输出:32 27 | * 28 | * 示例 5: 29 | * 输入:[[2,2,2],[2,1,2],[2,2,2]] 30 | * 输出:46 31 | * 32 | * 提示: 33 | * 1 <= N <= 50 34 | * 0 <= grid[i][j] <= 50 35 | */ 36 | public class SurfaceAreaOf3dShapes { 37 | 38 | private int surfaceArea(int[][] grid) { 39 | int n = grid.length; 40 | int area = 0; 41 | for (int i = 0; i < n; i++) { 42 | for (int j = 0; j < n; j++) { 43 | int level = grid[i][j]; 44 | if (level > 0) { 45 | // 4个侧面*个数+底面+顶面 46 | area += level * 4 + 2; 47 | // 减去与左边立方体相贴的两份表面积 48 | area -= i > 0 ? Math.min(level, grid[i - 1][j]) * 2 : 0; 49 | // 减去与上边立方体相贴的两份表面积 50 | area -= j > 0 ? Math.min(level, grid[i][j - 1]) * 2 : 0; 51 | } 52 | } 53 | } 54 | return area; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/com/hncboy/ToLowerCase.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/12/12 13:18 6 | * @description 709.转换成小写字母 7 | * 8 | * 给你一个字符串 s ,将该字符串中的大写字母转换成相同的小写字母,返回新的字符串。 9 | * 10 | * 示例 1: 11 | * 输入:s = "Hello" 12 | * 输出:"hello" 13 | * 14 | * 示例 2: 15 | * 输入:s = "here" 16 | * 输出:"here" 17 | * 18 | * 示例 3: 19 | * 输入:s = "LOVELY" 20 | * 输出:"lovely" 21 | * 22 | * 提示: 23 | * 1 <= s.length <= 100 24 | * s 由 ASCII 字符集中的可打印字符组成 25 | * 通过次数 84,191 提交次数 109,746 26 | * 27 | * 来源:力扣(LeetCode) 28 | * 链接:https://leetcode-cn.com/problems/to-lower-case 29 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 30 | */ 31 | public class ToLowerCase { 32 | 33 | public String toLowerCase(String s) { 34 | StringBuilder sb = new StringBuilder(); 35 | int diff = 'a' - 'A'; 36 | for (int i = 0; i < s.length(); ++i) { 37 | char ch = s.charAt(i); 38 | if (ch >= 'A' && ch <= 'Z') { 39 | ch |= diff; 40 | } 41 | sb.append(ch); 42 | } 43 | return sb.toString(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/com/hncboy/TransposeMatrix.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author hncboy 7 | * @date 2019/12/4 10:04 8 | * @description 867.转置矩阵 9 | * 10 | * 给定一个矩阵 A, 返回 A 的转置矩阵。 11 | * 矩阵的转置是指将矩阵的主对角线翻转,交换矩阵的行索引与列索引。 12 | * 13 | * 示例 1: 14 | * 输入:[[1,2,3],[4,5,6],[7,8,9]] 15 | * 输出:[[1,4,7],[2,5,8],[3,6,9]] 16 | * 17 | * 示例 2: 18 | * 输入:[[1,2,3],[4,5,6]] 19 | * 输出:[[1,4],[2,5],[3,6]] 20 | * 21 | * 提示: 22 | * 1 <= A.length <= 1000 23 | */ 24 | public class TransposeMatrix { 25 | 26 | public static void main(String[] args) { 27 | TransposeMatrix t = new TransposeMatrix(); 28 | int[][] A1 = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; 29 | int[][] A2 = {{1, 2, 3}, {4, 5, 6}}; 30 | System.out.println(Arrays.deepToString(t.transpose(A1))); 31 | System.out.println(Arrays.deepToString(t.transpose(A2))); 32 | } 33 | 34 | private int[][] transpose(int[][] A) { 35 | int row = A.length; 36 | int column = A[0].length; 37 | int[][] B = new int[column][row]; 38 | for (int i = 0; i < row; i++) { 39 | for (int j = 0; j < column; j++) { 40 | // 将行上的数替换到列 41 | B[j][i] = A[i][j]; 42 | } 43 | } 44 | return B; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/com/hncboy/TwoSum.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | import java.util.HashMap; 4 | 5 | /** 6 | * @author hncboy 7 | * @date 2019/8/30 9:43 8 | * @description 1.两数之和 9 | * 10 | * 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 11 | * 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。 12 | * 13 | * 示例: 14 | * 给定 nums = [2, 7, 11, 15], target = 9 15 | * 因为 nums[0] + nums[1] = 2 + 7 = 9 16 | * 所以返回 [0, 1] 17 | */ 18 | public class TwoSum { 19 | 20 | public int[] twoSum(int[] nums, int target) { 21 | int[] result = new int[2]; 22 | HashMap map = new HashMap<>(); 23 | for (int i = 0; i < nums.length; i++) { 24 | if (map.containsKey(target - nums[i])) { 25 | result[0] = map.get(target - nums[i]); 26 | result[1] = i; 27 | return result; 28 | } 29 | map.put(nums[i], i); 30 | } 31 | return result; 32 | } 33 | } 34 | 35 | -------------------------------------------------------------------------------- /src/com/hncboy/TwoSumIIInputArrayIsSorted.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author hncboy 7 | * @date 2019/11/3 18:15 8 | * @description 167.两数之和 II - 输入有序数组 9 | * 10 | * 给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。 11 | * 函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。 12 | * 13 | * 说明: 14 | * 返回的下标值(index1 和 index2)不是从零开始的。 15 | * 你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。 16 | * 17 | * 示例: 18 | * 输入: numbers = [2, 7, 11, 15], target = 9 19 | * 输出: [1,2] 20 | * 解释: 2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。 21 | */ 22 | public class TwoSumIIInputArrayIsSorted { 23 | 24 | public static void main(String[] args) { 25 | TwoSumIIInputArrayIsSorted t = new TwoSumIIInputArrayIsSorted(); 26 | int[] numbers = {2, 7, 11, 15}; 27 | System.out.println(Arrays.toString(t.twoSum(numbers, 9))); 28 | } 29 | 30 | private int[] twoSum(int[] numbers, int target) { 31 | int left = 0; 32 | int right = numbers.length - 1; 33 | while (left < right) { 34 | int sum = numbers[left] + numbers[right]; 35 | if (sum == target) { 36 | return new int[]{left + 1, right + 1}; 37 | } else if (sum < target) { 38 | left++; 39 | } else { 40 | right--; 41 | } 42 | } 43 | return null; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/com/hncboy/UglyNumber.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hncboy/LeetCode/ab66f67d0a7a6667f1b21e8f0be503eb351863bd/src/com/hncboy/UglyNumber.java -------------------------------------------------------------------------------- /src/com/hncboy/UglyNumberII.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hncboy/LeetCode/ab66f67d0a7a6667f1b21e8f0be503eb351863bd/src/com/hncboy/UglyNumberII.java -------------------------------------------------------------------------------- /src/com/hncboy/UniqueBinarySearchTrees.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/10/24 15:32 6 | * @description 96.不同的二叉搜索树 7 | * 8 | * 给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种? 9 | * 10 | * 示例: 11 | * 输入: 3 12 | * 输出: 5 13 | * 解释: 14 | * 给定 n = 3, 一共有 5 种不同结构的二叉搜索树: 15 | * 16 | * 1 3 3 2 1 17 | * \ / / / \ \ 18 | * 3 2 1 1 3 2 19 | * / / \ \ 20 | * 2 1 2 3 21 | */ 22 | public class UniqueBinarySearchTrees { 23 | 24 | public static void main(String[] args) { 25 | UniqueBinarySearchTrees u = new UniqueBinarySearchTrees(); 26 | System.out.println(u.numTrees(3)); 27 | } 28 | 29 | /** 30 | * 卡特兰数 31 | * @param n 32 | * @return 33 | */ 34 | private int numTrees(int n) { 35 | int[] dp = new int[n + 1]; 36 | dp[0] = 1; 37 | dp[1] = 1; 38 | 39 | for (int i = 2; i <= n; i++) { 40 | for (int j = 1; j < i + 1; j++) { 41 | dp[i] += dp[j - 1] * dp[i - j]; 42 | } 43 | } 44 | 45 | return dp[n]; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/com/hncboy/UniquePaths.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/9/29 10:38 6 | * @description 62.不同路径 7 | * 8 | * 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。 9 | * 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。 10 | * 问总共有多少条不同的路径? 11 | * 12 | * 说明:m 和 n 的值均不超过 100。 13 | * 14 | * 示例 1: 15 | * 输入: m = 3, n = 2 16 | * 输出: 3 17 | * 解释: 18 | * 从左上角开始,总共有 3 条路径可以到达右下角。 19 | * 1. 向右 -> 向右 -> 向下 20 | * 2. 向右 -> 向下 -> 向右 21 | * 3. 向下 -> 向右 -> 向右 22 | * 23 | * 示例 2: 24 | * 输入: m = 7, n = 3 25 | * 输出: 28 26 | */ 27 | public class UniquePaths { 28 | 29 | public static void main(String[] args) { 30 | System.out.println(new UniquePaths().uniquePaths(2, 3)); 31 | } 32 | 33 | private int uniquePaths(int m, int n) { 34 | int[][] dp = new int[m][n]; 35 | for (int i = 0; i < m; i++) { 36 | for (int j = 0; j < n; j++) { 37 | if (i == 0 || j == 0) { 38 | dp[i][j] = 1; 39 | } else { 40 | // 每条路径都是上方和左方两条路线的合计 41 | dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; 42 | } 43 | } 44 | } 45 | return dp[m - 1][n - 1]; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/com/hncboy/ValidAnagram.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/10/18 8:26 6 | * @description 242.有效的字母异位词 7 | * 8 | * 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。 9 | * 10 | * 示例 1: 11 | * 输入: s = "anagram", t = "nagaram" 12 | * 输出: true 13 | * 14 | * 示例 2: 15 | * 输入: s = "rat", t = "car" 16 | * 输出: false 17 | * 说明: 18 | * 你可以假设字符串只包含小写字母。 19 | * 进阶: 20 | * 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况? 21 | */ 22 | public class ValidAnagram { 23 | 24 | public static void main(String[] args) { 25 | ValidAnagram v = new ValidAnagram(); 26 | System.out.println(v.isAnagram("anagram", "nagaram")); 27 | } 28 | 29 | public boolean isAnagram(String s, String t) { 30 | if (s.length() != t.length() || s.equals(t)) { 31 | return false; 32 | } 33 | 34 | int[] hash = new int [26]; 35 | for (char ch : s.toCharArray()) { 36 | hash[ch - 'a']++; 37 | } 38 | 39 | for (char ch : t.toCharArray()) { 40 | if (--hash[ch - 'a'] < 0) { 41 | return false; 42 | } 43 | } 44 | 45 | return true; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/com/hncboy/ValidPalindromeII.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/10/31 10:43 6 | * @description 680.验证回文字符串 Ⅱ 7 | * 8 | * 给定一个非空字符串 s,最多删除一个字符。判断是否能成为回文字符串。 9 | * 10 | * 示例 1: 11 | * 输入: s = "aba" 12 | * 输出: true 13 | * 14 | * 示例 2: 15 | * 输入: s = "abca" 16 | * 输出: true 17 | * 解释: 你可以删除c字符。 18 | * 19 | * 示例 3: 20 | * 输入: s = "abc" 21 | * 输出: false 22 | * 23 | * 提示: 24 | * 1 <= s.length <= 105 25 | * s 由小写英文字母组成 26 | * 27 | * 来源:力扣(LeetCode) 28 | * 链接:https://leetcode-cn.com/problems/valid-palindrome-ii 29 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 30 | */ 31 | public class ValidPalindromeII { 32 | 33 | public boolean validPalindrome(String s) { 34 | int left = 0; 35 | int right = s.length() - 1; 36 | 37 | // 双指针 38 | while (left < right) { 39 | if (s.charAt(left) != s.charAt(right)) { 40 | return isValidPalindrome(s, left + 1, right) || isValidPalindrome(s, left, right - 1); 41 | } 42 | left++; 43 | right--; 44 | } 45 | return true; 46 | } 47 | 48 | private static boolean isValidPalindrome(String s, int left, int right) { 49 | while (left < right) { 50 | if (s.charAt(left++) != s.charAt(right--)) { 51 | return false; 52 | } 53 | } 54 | return true; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/com/hncboy/ValidTriangleNumber.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author hncboy 7 | * @date 2019/11/24 15:08 8 | * @description 611.有效三角形的个数 9 | * 10 | * 给定一个包含非负整数的数组,你的任务是统计其中可以组成三角形三条边的三元组个数。 11 | * 12 | * 示例 1: 13 | * 输入: [2,2,3,4] 14 | * 输出: 3 15 | * 解释: 16 | * 有效的组合是: 17 | * 2,3,4 (使用第一个 2) 18 | * 2,3,4 (使用第二个 2) 19 | * 2,2,3 20 | * 21 | * 注意: 22 | * 数组长度不超过1000。 23 | * 数组里整数的范围为 [0, 1000]。 24 | */ 25 | public class ValidTriangleNumber { 26 | 27 | public static void main(String[] args) { 28 | ValidTriangleNumber v = new ValidTriangleNumber(); 29 | System.out.println(v.triangleNumber(new int[]{2, 2, 3, 4})); 30 | } 31 | 32 | private int triangleNumber(int[] nums) { 33 | Arrays.sort(nums); 34 | int result = 0; 35 | for (int i = nums.length - 1; i >= 2; --i) { 36 | int left = 0; 37 | int right = i - 1; 38 | while (left < right) { 39 | if (nums[left] + nums[right] > nums[i]) { 40 | // 说明 nums[left + 1] + nums[right] > nums[i] 41 | // 说明 nums[left + 2] + nums[right] > nums[i] 42 | result += right - left; 43 | right--; 44 | } else { 45 | left++; 46 | } 47 | } 48 | } 49 | return result; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/com/hncboy/VerbalArithmeticPuzzle.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hncboy/LeetCode/ab66f67d0a7a6667f1b21e8f0be503eb351863bd/src/com/hncboy/VerbalArithmeticPuzzle.java -------------------------------------------------------------------------------- /src/com/hncboy/WaterAndJugProblem.java: -------------------------------------------------------------------------------- 1 | package com.hncboy; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/11/14 9:35 6 | * @description 365.水壶问题 7 | * 8 | * 有两个容量分别为 x升 和 y升 的水壶以及无限多的水。 9 | * 请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水? 10 | * 如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水。 11 | * 12 | * 你允许: 13 | * 装满任意一个水壶 14 | * 清空任意一个水壶 15 | * 从一个水壶向另外一个水壶倒水,直到装满或者倒空 16 | * 17 | * 示例 1: (From the famous "Die Hard" example) 18 | * 输入: x = 3, y = 5, z = 4 19 | * 输出: True 20 | * 21 | * 示例 2: 22 | * 输入: x = 2, y = 6, z = 5 23 | * 输出: False 24 | */ 25 | public class WaterAndJugProblem { 26 | 27 | public static void main(String[] args) { 28 | WaterAndJugProblem w = new WaterAndJugProblem(); 29 | System.out.println(w.canMeasureWater(3, 5, 4)); 30 | System.out.println(w.canMeasureWater(2, 6, 5)); 31 | } 32 | 33 | private boolean canMeasureWater(int x, int y, int z) { 34 | // z = a*x + b*y 35 | // x 和 y 的最大公约数为 g 36 | // z % g = 0 37 | return z == 0 || (x + y >= z && z % gcd(x, y) == 0); 38 | 39 | } 40 | 41 | /** 42 | * 辗转相除法求最大公约数 43 | * 44 | * @param x 45 | * @param y 46 | * @return 47 | */ 48 | private int gcd(int x, int y) { 49 | return y == 0 ? x : gcd(y, x % y); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/com/hncboy/lcci/SortedMergeLcci.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.lcci; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2020/3/3 0:13 6 | * @description 面试题 10.01.合并排序的数组 7 | * 8 | * 给定两个排序后的数组 A 和 B,其中 A 的末端有足够的缓冲空间容纳 B。 9 | * 编写一个方法,将 B 合并入 A 并排序。 10 | * 初始化 A 和 B 的元素数量分别为 m 和 n。 11 | * 12 | * 示例: 13 | * 输入: 14 | * A = [1,2,3,0,0,0], m = 3 15 | * B = [2,5,6], n = 3 16 | * 输出: [1,2,2,3,5,6] 17 | */ 18 | public class SortedMergeLcci { 19 | 20 | private void merge(int[] A, int m, int[] B, int n) { 21 | int a = m - 1; 22 | int b = n - 1; 23 | int i = A.length - 1; 24 | while (a >= 0 && b >= 0) { 25 | if (B[b] >= A[a]) { 26 | A[i--] = B[b--]; 27 | } else { 28 | A[i--] = A[a--]; 29 | } 30 | } 31 | 32 | while (b >= 0) { 33 | A[i--] = B[b--]; 34 | } 35 | while (a >= 0) { 36 | A[i--] = A[a--]; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/com/hncboy/lcci/TheMasseuseLcci.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.lcci; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2020/3/24 18:52 6 | * @description 面试题 17.16.按摩师 7 | * 8 | * 一个有名的按摩师会收到源源不断的预约请求,每个预约都可以选择接或不接。 9 | * 在每次预约服务之间要有休息时间,因此她不能接受相邻的预约。 10 | * 给定一个预约请求序列,替按摩师找到最优的预约集合(总预约时间最长),返回总的分钟数。 11 | * 注意:本题相对原题稍作改动 12 | * 13 | * 示例 1: 14 | * 输入: [1,2,3,1] 15 | * 输出: 4 16 | * 解释: 选择 1 号预约和 3 号预约,总时长 = 1 + 3 = 4。 17 | * 18 | * 示例 2: 19 | * 输入: [2,7,9,3,1] 20 | * 输出: 12 21 | * 解释: 选择 1 号预约、 3 号预约和 5 号预约,总时长 = 2 + 9 + 1 = 12。 22 | * 23 | * 示例 3: 24 | * 输入: [2,1,4,5,3,1,1,3] 25 | * 输出: 12 26 | * 解释: 选择 1 号预约、 3 号预约、 5 号预约和 8 号预约,总时长 = 2 + 4 + 3 + 3 = 12。 27 | */ 28 | public class TheMasseuseLcci { 29 | 30 | private int massage(int[] nums) { 31 | int a = 0, b = 0; 32 | for (int i = 0; i < nums.length; i++) { 33 | int c = Math.max(b, a + nums[i]); 34 | a = b; 35 | b = c; 36 | } 37 | return b; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstooffer/Question05.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstooffer; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2020/2/16 15:23 6 | * @description 剑指 Offer 05.替换空格 7 | * 8 | * 请实现一个函数,把字符串 s 中的每个空格替换成"%20"。 9 | * 10 | * 示例 1: 11 | * 输入:s = "We are happy." 12 | * 输出:"We%20are%20happy." 13 | * 14 | * 限制: 15 | * 0 <= s 的长度 <= 10000 16 | * 17 | * 来源:力扣(LeetCode) 18 | * 链接:https://leetcode-cn.com/problems/ti-huan-kong-ge-lcof 19 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 20 | */ 21 | public class Question05 { 22 | 23 | private String replaceSpace(String s) { 24 | // 申请最多3倍长度 25 | char[] result = new char[s.length() * 3]; 26 | int size = 0; 27 | for (char c : s.toCharArray()) { 28 | if (c == ' ') { 29 | result[size++] = '%'; 30 | result[size++] = '2'; 31 | result[size++] = '0'; 32 | } else { 33 | result[size++] = c; 34 | } 35 | } 36 | return new String(result, 0, size); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstooffer/Question10_I.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstooffer; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2020/2/16 17:10 6 | * @description 剑指 Offer 10-I.斐波那契数列 7 | * 8 | * 写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项(即 F(N))。斐波那契数列的定义如下: 9 | * F(0) = 0, F(1) = 1 10 | * F(N) = F(N - 1) + F(N - 2), 其中 N > 1. 11 | * 斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。 12 | * 13 | * 答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。 14 | * 15 | * 示例 1: 16 | * 输入:n = 2 17 | * 输出:1 18 | * 19 | * 示例 2: 20 | * 输入:n = 5 21 | * 输出:5 22 | * 23 | * 提示: 24 | * 0 <= n <= 100 25 | * 26 | * 来源:力扣(LeetCode) 27 | * 链接:https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof 28 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 29 | */ 30 | public class Question10_I { 31 | 32 | private int fib(int n) { 33 | if (n == 0 || n == 1) { 34 | return n; 35 | } 36 | 37 | int a = 0; 38 | int b = 1; 39 | 40 | for (int i = 2; i <= n; i++) { 41 | int c = a; 42 | a = b; 43 | b = (b + c) % 1000000007; 44 | } 45 | 46 | return b; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstooffer/Question10_II.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstooffer; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2020/2/16 17:10 6 | * @description 面试题10-II.青蛙跳台阶问题 7 | * 8 | * 一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。 9 | * 答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。 10 | * 11 | * 示例 1: 12 | * 输入:n = 2 13 | * 输出:2 14 | * 15 | * 示例 2: 16 | * 输入:n = 7 17 | * 输出:21 18 | * 19 | * 示例 3: 20 | * 输入:n = 0 21 | * 输出:1 22 | * 23 | * 提示: 24 | * 0 <= n <= 100 25 | * 注意:本题与主站 70 题 {@link com.hncboy.ClimbingStairs} 26 | * 相同:https://leetcode-cn.com/problems/climbing-stairs/ 27 | * 28 | * 来源:力扣(LeetCode) 29 | * 链接:https://leetcode-cn.com/problems/qing-wa-tiao-tai-jie-wen-ti-lcof 30 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 31 | */ 32 | public class Question10_II { 33 | 34 | private int numWays(int n) { 35 | if (n == 0) { 36 | return 1; 37 | } 38 | if (n == 1 || n == 2 || n == 3) { 39 | return n; 40 | } 41 | 42 | int a = 1; 43 | int b = 2; 44 | for (int i = 2; i < n; i++) { 45 | int c = a; 46 | a = b; 47 | b = (c + b) % 1000000007; 48 | } 49 | return b; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstooffer/Question14_I.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstooffer; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/9/23 11:31 6 | * @description 剑指 Offer 14-I.剪绳子 7 | * 和这题一样 {@link com.hncboy.IntegerBreak} 8 | * 给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]...k[m-1] 。 9 | * 请问 k[0]*k[1]*...*k[m-1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。 10 | * 11 | * 示例 1: 12 | * 输入: 2 13 | * 输出: 1 14 | * 解释: 2 = 1 + 1, 1 × 1 = 1 15 | * 16 | * 示例 2: 17 | * 输入: 10 18 | * 输出: 36 19 | * 解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36 20 | * 21 | * 提示: 22 | * 2 <= n <= 58 23 | * 24 | * 来源:力扣(LeetCode) 25 | * 链接:https://leetcode-cn.com/problems/jian-sheng-zi-lcof 26 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 27 | */ 28 | public class Question14_I { 29 | 30 | public int cuttingRope(int n) { 31 | int[] dp = new int[n + 1]; 32 | dp[2] = 1; 33 | for (int i = 3; i <= n; i++) { 34 | for (int j = 2; j < i; j++) { 35 | dp[i] = Math.max(dp[i], Math.max(j * (i - j), j * dp[i - j])); 36 | } 37 | } 38 | return dp[n]; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstooffer/Question14_II.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstooffer; 2 | 3 | import java.math.BigInteger; 4 | import java.util.Arrays; 5 | 6 | /** 7 | * @author hncboy 8 | * @date 2021/9/25 13:37 9 | * @description 剑指 Offer 14-II.剪绳子 II 10 | * 11 | * 给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]...k[m - 1] 。 12 | * 请问 k[0]*k[1]*...*k[m - 1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。 13 | * 14 | * 答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。 15 | * 16 | * 示例 1: 17 | * 输入: 2 18 | * 输出: 1 19 | * 解释: 2 = 1 + 1, 1 × 1 = 1 20 | * 21 | * 示例 2: 22 | * 输入: 10 23 | * 输出: 36 24 | * 解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36 25 | * 26 | * 提示: 27 | * 2 <= n <= 1000 28 | * 29 | * 来源:力扣(LeetCode) 30 | * 链接:https://leetcode-cn.com/problems/jian-sheng-zi-ii-lcof 31 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 32 | */ 33 | public class Question14_II { 34 | 35 | private int cuttingRope(int n) { 36 | BigInteger[] dp = new BigInteger[n + 1]; 37 | Arrays.fill(dp, BigInteger.valueOf(1)); 38 | for (int i = 3; i < n + 1; i++) { 39 | for (int j = 1; j < i; j++) { 40 | dp[i] = dp[i].max(BigInteger.valueOf((long) j * (i - j))).max(dp[i - j].multiply(BigInteger.valueOf(j))); 41 | } 42 | } 43 | return dp[n].mod(BigInteger.valueOf(1000000007)).intValue(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstooffer/Question18.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstooffer; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2020/3/1 18:33 6 | * @description 剑指 Offer 18.删除链表的节点 7 | * 8 | * 给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。 9 | * 返回删除后的链表的头节点。 10 | * 注意:此题对比原题有改动 11 | * 12 | * 示例 1: 13 | * 输入: head = [4,5,1,9], val = 5 14 | * 输出: [4,1,9] 15 | * 解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9. 16 | * 17 | * 示例 2: 18 | * 输入: head = [4,5,1,9], val = 1 19 | * 输出: [4,5,9] 20 | * 解释: 给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9. 21 | * 22 | * 说明: 23 | * 题目保证链表中节点的值互不相同 24 | * 若使用 C 或 C++ 语言,你不需要 free 或 delete 被删除的节点 25 | * 26 | * 来源:力扣(LeetCode) 27 | * 链接:https://leetcode-cn.com/problems/shan-chu-lian-biao-de-jie-dian-lcof 28 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 29 | */ 30 | public class Question18 { 31 | 32 | public ListNode deleteNode(ListNode head, int val) { 33 | if (head.val == val) { 34 | return head.next; 35 | } 36 | ListNode p = head; 37 | while (p.next != null) { 38 | if (p.next.val == val) { 39 | p.next = p.next.next; 40 | break; 41 | } 42 | p = p.next; 43 | } 44 | return head; 45 | } 46 | 47 | private static class ListNode { 48 | int val; 49 | ListNode next; 50 | 51 | ListNode(int x) { 52 | val = x; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstooffer/Question21.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstooffer; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2020/3/1 19:16 6 | * @description 剑指 Offer 21. 调整数组顺序使奇数位于偶数前面 7 | * 8 | * 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数在数组的前半部分,所有偶数在数组的后半部分。 9 | * 10 | * 示例: 11 | * 输入:nums = [1,2,3,4] 12 | * 输出:[1,3,2,4] 13 | * 注:[3,1,2,4] 也是正确的答案之一。 14 | * 15 | * 提示: 16 | * 0 <= nums.length <= 50000 17 | * 0 <= nums[i] <= 10000 18 | * 19 | * 来源:力扣(LeetCode) 20 | * 链接:https://leetcode-cn.com/problems/diao-zheng-shu-zu-shun-xu-shi-qi-shu-wei-yu-ou-shu-qian-mian-lcof 21 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 22 | */ 23 | public class Question21 { 24 | 25 | public int[] exchange(int[] nums) { 26 | int odd = 0; 27 | int even = nums.length - 1; 28 | while (odd < even) { 29 | // 如果发现了偶数 30 | if (nums[odd] % 2 == 0) { 31 | // 从最后的偶数位往前遍历找到奇数位 32 | while (even > odd && nums[even] % 2 == 0) { 33 | even--; 34 | } 35 | // 交换奇数位和偶数位 36 | int temp = nums[odd]; 37 | nums[odd] = nums[even]; 38 | nums[even] = temp; 39 | } 40 | odd++; 41 | } 42 | return nums; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstooffer/Question22.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstooffer; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2020/3/1 19:35 6 | * @description 剑指 Offer 22.链表中倒数第k个节点 7 | * 8 | * 输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。 9 | * 10 | * 例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。 11 | * 12 | * 来源:力扣(LeetCode) 13 | * 链接:https://leetcode-cn.com/problems/lian-biao-zhong-dao-shu-di-kge-jie-dian-lcof 14 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 15 | */ 16 | public class Question22 { 17 | 18 | public static void main(String[] args) { 19 | Question22 q = new Question22(); 20 | ListNode head = new ListNode(1); 21 | head.next = new ListNode(2); 22 | head.next.next = new ListNode(3); 23 | System.out.println(q.getKthFromEnd(head, 1)); 24 | } 25 | 26 | public ListNode getKthFromEnd(ListNode head, int k) { 27 | ListNode p = head; 28 | ListNode q = head; 29 | // p 指针先走 k 步 30 | for (int i = 0; i < k; i++) { 31 | p = p.next; 32 | } 33 | // p 指针一直走到底,这时 p 指针走的步数为 total-k 34 | // q 指针从头开始走,也走了 total-k 步 35 | while (p != null) { 36 | p = p.next; 37 | q = q.next; 38 | } 39 | return q; 40 | } 41 | 42 | private static class ListNode { 43 | int val; 44 | ListNode next; 45 | 46 | ListNode(int x) { 47 | val = x; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstooffer/Question39.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstooffer; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/9/30 13:31 6 | * @description 剑指 Offer 39.数组中出现次数超过一半的数字 7 | * 8 | * 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。 9 | * 你可以假设数组是非空的,并且给定的数组总是存在多数元素。 10 | * 11 | * 示例 1: 12 | * 输入: [1, 2, 3, 2, 2, 2, 5, 4, 2] 13 | * 输出: 2 14 | * 15 | * 限制: 16 | * 1 <= 数组长度 <= 50000 17 | * 注意:本题与主站 169 题 {@link com.hncboy.MajorityElement} 18 | * 相同:https://leetcode-cn.com/problems/majority-element/ 19 | * 20 | * 来源:力扣(LeetCode) 21 | * 链接:https://leetcode-cn.com/problems/shu-zu-zhong-chu-xian-ci-shu-chao-guo-yi-ban-de-shu-zi-lcof 22 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 23 | */ 24 | public class Question39 { 25 | 26 | public int majorityElement(int[] nums) { 27 | int votes = 0; 28 | int candidate = 0; 29 | 30 | // 根据众数出现的次数大于 n/2 的特性 31 | // 当选的数不是众数的时候,会被众数减到 0 32 | for (int num : nums) { 33 | if (votes == 0) { 34 | candidate = num; 35 | } 36 | votes += (num == candidate) ? 1 : -1; 37 | } 38 | 39 | return candidate; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstooffer/Question42.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstooffer; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/10/22 8:04 6 | * @description 剑指 Offer 42.连续子数组的最大和 7 | * 8 | * 输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。 9 | * 10 | * 要求时间复杂度为O(n)。 11 | * 12 | * 示例1: 13 | * 输入: nums = [-2,1,-3,4,-1,2,1,-5,4] 14 | * 输出: 6 15 | * 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。 16 | * 17 | * 18 | * 提示: 19 | * 1 <= arr.length <= 10^5 20 | * -100 <= arr[i] <= 100 21 | * 注意:本题与主站 53 题 {@link com.hncboy.MaximumSubarray} 22 | * 相同:https://leetcode-cn.com/problems/maximum-subarray/ 23 | * 24 | * 来源:力扣(LeetCode) 25 | * 链接:https://leetcode-cn.com/problems/lian-xu-zi-shu-zu-de-zui-da-he-lcof 26 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 27 | */ 28 | public class Question42 { 29 | 30 | public int maxSubArray(int[] nums) { 31 | int result = nums[0]; 32 | for (int i = 1; i < nums.length; i++) { 33 | nums[i] += Math.max(nums[i-1], 0); 34 | result = Math.max(result, nums[i]); 35 | } 36 | return result; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstooffer/Question47.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstooffer; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/10/15 15:41 6 | * @description 剑指 Offer 47.礼物的最大价值 7 | * 8 | * 在一个 m*n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。 9 | * 你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘的右下角。 10 | * 给定一个棋盘及其上面的礼物的价值,请计算你最多能拿到多少价值的礼物? 11 | * 12 | * 示例 1: 13 | * 输入: 14 | * [ 15 | * [1,3,1], 16 | * [1,5,1], 17 | * [4,2,1] 18 | * ] 19 | * 输出: 12 20 | * 解释: 路径 1→3→5→2→1 可以拿到最多价值的礼物 21 | * 22 | * 提示: 23 | * 0 < grid.length <= 200 24 | * 0 < grid[0].length <= 200 25 | * 26 | * 来源:力扣(LeetCode) 27 | * 链接:https://leetcode-cn.com/problems/li-wu-de-zui-da-jie-zhi-lcof 28 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 29 | */ 30 | public class Question47 { 31 | 32 | public int maxValue(int[][] grid) { 33 | int row = grid.length; 34 | int column = grid[0].length; 35 | 36 | // 初始化第一行 37 | for (int j = 1; j < column; j++) { 38 | grid[0][j] += grid[0][j - 1]; 39 | } 40 | 41 | // 初始化第一列 42 | for (int i = 1; i < row; i++) { 43 | grid[i][0] += grid[i - 1][0]; 44 | } 45 | 46 | for (int i = 1; i < row; i++) { 47 | for (int j = 1; j < column; j++) { 48 | grid[i][j] += Math.max(grid[i][j - 1], grid[i - 1][j]); 49 | } 50 | } 51 | return grid[row - 1][column - 1]; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstooffer/Question50.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstooffer; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/10/4 12:39 6 | * @description 剑指 Offer 50.第一个只出现一次的字符 7 | * 8 | * 在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。 9 | * 10 | * 示例 1: 11 | * 输入:s = "abaccdeff" 12 | * 输出:'b' 13 | * 14 | * 示例 2: 15 | * 输入:s = "" 16 | * 输出:' ' 17 | * 18 | * 限制: 19 | * 0 <= s 的长度 <= 50000 20 | * 21 | * 来源:力扣(LeetCode) 22 | * 链接:https://leetcode-cn.com/problems/di-yi-ge-zhi-chu-xian-yi-ci-de-zi-fu-lcof 23 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 24 | */ 25 | public class Question50 { 26 | 27 | public char firstUniqChar(String s) { 28 | int[] count = new int[26]; 29 | char[] chars = s.toCharArray(); 30 | 31 | for (char ch : chars) { 32 | count[ch - 'a']++; 33 | } 34 | 35 | for (char ch : chars) { 36 | if (count[ch - 'a'] == 1) { 37 | return ch; 38 | } 39 | } 40 | return ' '; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstooffer/Question53_II.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstooffer; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/10/11 9:09 6 | * @description 剑指 Offer 53-II.0~n-1中缺失的数字 7 | * 8 | * 一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。 9 | * 在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。 10 | * 11 | * 示例 1: 12 | * 输入: [0,1,3] 13 | * 输出: 2 14 | * 15 | * 示例 2: 16 | * 输入: [0,1,2,3,4,5,6,7,9] 17 | * 输出: 8 18 | * 19 | * 限制: 20 | * 1 <= 数组长度 <= 10000 21 | * 22 | * 来源:力扣(LeetCode) 23 | * 链接:https://leetcode-cn.com/problems/que-shi-de-shu-zi-lcof 24 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 25 | */ 26 | public class Question53_II { 27 | 28 | public int missingNumber(int[] nums) { 29 | int left = 0; 30 | int right = nums.length - 1; 31 | while (left <= right) { 32 | int mid = (left + right) / 2; 33 | if (nums[mid] == mid) { 34 | left = mid + 1; 35 | } else { 36 | right = mid - 1; 37 | } 38 | } 39 | return left; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstooffer/Question56_II.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstooffer; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/10/8 8:37 6 | * @description 剑指 Offer 56-II.数组中数字出现的次数 II 7 | * 8 | * 在一个数组 nums 中除一个数字只出现一次之外,其他数字都出现了三次。请找出那个只出现一次的数字。 9 | * 10 | * 示例 1: 11 | * 输入:nums = [3,4,3,3] 12 | * 输出:4 13 | * 14 | * 示例 2: 15 | * 输入:nums = [9,1,7,9,7,9,7] 16 | * 输出:1 17 | * 18 | * 限制: 19 | * 1 <= nums.length <= 10000 20 | * 1 <= nums[i] < 2^31 21 | * 22 | * 来源:力扣(LeetCode) 23 | * 链接:https://leetcode-cn.com/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-ii-lcof 24 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 25 | */ 26 | public class Question56_II { 27 | 28 | public int singleNumber(int[] nums) { 29 | // 定义长度为 32 的数组 30 | int[] counts = new int[32]; 31 | 32 | for (int num : nums) { 33 | // 统计 int 整数 32 位中各个二进制位出现的次数 34 | for (int i = 0; i < 32; i++) { 35 | // 对每位进行按位与运行 36 | counts[i] += num & 1; 37 | // num 无符号右移 38 | num >>>= 1; 39 | } 40 | } 41 | 42 | int result = 0; 43 | // 遍历所有数字各个二进制位出现的次数 44 | for (int i = 0; i < 32; i++) { 45 | // 左移一位 46 | result <<= 1; 47 | // 将对应二进制位与 3 取余,可以得到只出现一次数字二进制中第 31-i 位的值 48 | // 将二进制位与 result 进行按位或运算,可得到对应的十进制数值 49 | result |= counts[31 - i] % 3; 50 | } 51 | return result; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstooffer/Question57.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstooffer; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/10/9 9:03 6 | * @description 剑指 Offer 57.和为s的两个数字 7 | * 8 | * 输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。 9 | * 如果有多对数字的和等于s,则输出任意一对即可。 10 | * 11 | * 示例 1: 12 | * 输入:nums = [2,7,11,15], target = 9 13 | * 输出:[2,7] 或者 [7,2] 14 | * 15 | * 示例 2: 16 | * 输入:nums = [10,26,30,31,47,60], target = 40 17 | * 输出:[10,30] 或者 [30,10] 18 | * 19 | * 限制: 20 | * 1 <= nums.length <= 10^5 21 | * 1 <= nums[i]<= 10^6 22 | * 23 | * 来源:力扣(LeetCode) 24 | * 链接:https://leetcode-cn.com/problems/he-wei-sde-liang-ge-shu-zi-lcof 25 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 26 | */ 27 | public class Question57 { 28 | 29 | public int[] twoSum(int[] nums, int target) { 30 | int left = 0; 31 | int right = nums.length - 1; 32 | while (left < right) { 33 | int sum = nums[left] + nums[right]; 34 | if (sum < target) { 35 | left++; 36 | continue; 37 | } 38 | if (sum > target) { 39 | right--; 40 | } 41 | return new int[]{nums[left], nums[right]}; 42 | } 43 | return new int[0]; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstooffer/Question58_II.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstooffer; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/10/12 9:16 6 | * @description 剑指 Offer 58-II.左旋转字符串 7 | * 8 | * 字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。 9 | * 比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。 10 | * 11 | * 示例 1: 12 | * 输入: s = "abcdefg", k = 2 13 | * 输出: "cdefgab" 14 | * 15 | * 示例 2: 16 | * 输入: s = "lrloseumgh", k = 6 17 | * 输出: "umghlrlose" 18 | * 19 | * 限制: 20 | * 1 <= k < s.length <= 10000 21 | * 22 | * 来源:力扣(LeetCode) 23 | * 链接:https://leetcode-cn.com/problems/zuo-xuan-zhuan-zi-fu-chuan-lcof 24 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 25 | */ 26 | public class Question58_II { 27 | 28 | public String reverseLeftWords(String s, int n) { 29 | StringBuilder result = new StringBuilder(); 30 | // 遍历并通过取余的方式添加字符串 31 | for(int i = n; i < n + s.length(); i++) { 32 | result.append(s.charAt(i % s.length())); 33 | } 34 | return result.toString(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstooffer/Question61.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstooffer; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author hncboy 7 | * @date 2021/10/18 9:47 8 | * @description 剑指 Offer 61.扑克牌中的顺子 9 | * 10 | * 从若干副扑克牌中随机抽 5 张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身, 11 | * A为1,J为11,Q为12,K为13,而大、小王为 0 ,可以看成任意数字。A 不能视为 14。 12 | * 13 | * 示例 1: 14 | * 输入: [1,2,3,4,5] 15 | * 输出: True 16 | * 17 | * 示例 2: 18 | * 输入: [0,0,1,2,5] 19 | * 输出: True 20 | * 21 | * 限制: 22 | * 数组长度为 5 23 | * 数组的数取值为 [0, 13] . 24 | * 25 | * 来源:力扣(LeetCode) 26 | * 链接:https://leetcode-cn.com/problems/bu-ke-pai-zhong-de-shun-zi-lcof 27 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 28 | */ 29 | public class Question61 { 30 | 31 | public boolean isStraight(int[] nums) { 32 | int joker = 0; 33 | Arrays.sort(nums); 34 | 35 | for (int i = 0; i < 4; i++) { 36 | // 统计大小王数量 37 | if (nums[i] == 0) { 38 | joker++; 39 | } else if (nums[i] == nums[i + 1]) { 40 | // 不能重复 41 | return false; 42 | } 43 | } 44 | 45 | // 最大牌 - 最小牌 < 5 则可构成顺子 46 | return nums[4] - nums[joker] < 5; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstooffer/Question62.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstooffer; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2020/3/30 16:02 6 | * @description 面试题 62.圆圈中最后剩下的数字 7 | * 8 | * 0,1,,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字。 9 | * 求出这个圆圈里剩下的最后一个数字。 10 | * 例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字, 11 | * 则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。 12 | * 13 | * 示例 1: 14 | * 输入: n = 5, m = 3 15 | * 输出: 3 16 | * 17 | * 示例 2: 18 | * 输入: n = 10, m = 17 19 | * 输出: 2 20 | * 21 | * 限制: 22 | * 1 <= n <= 10^5 23 | * 1 <= m <= 10^6 24 | */ 25 | public class Question62 { 26 | 27 | private int lastRemaining(int n, int m) { 28 | int result = 0; 29 | for (int i = 2; i <= n; i++) { 30 | result = (result + m) % i; 31 | } 32 | return result; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstooffer/Question63.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstooffer; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/10/21 8:23 6 | * @description 剑指 Offer 63.股票的最大利润 7 | * 8 | * 假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖该股票一次可能获得的最大利润是多少? 9 | * 10 | * 示例 1: 11 | * 输入: [7,1,5,3,6,4] 12 | * 输出: 5 13 | * 解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。 14 | * 注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。 15 | * 16 | * 示例 2: 17 | * 输入: [7,6,4,3,1] 18 | * 输出: 0 19 | * 解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。 20 | * 21 | * 限制: 22 | * 0 <= 数组长度 <= 10^5 23 | * 24 | * 注意:本题与主站 121 题 {@link com.hncboy.BestTimeToBuyAndSellStock} 25 | * 相同:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/ 26 | * 27 | * 来源:力扣(LeetCode) 28 | * 链接:https://leetcode-cn.com/problems/gu-piao-de-zui-da-li-run-lcof 29 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 30 | */ 31 | public class Question63 { 32 | 33 | public int maxProfit(int[] prices) { 34 | int minPrice = Integer.MAX_VALUE; 35 | int maxProfit = 0; 36 | 37 | for (int price : prices) { 38 | minPrice = Math.min(minPrice, price); 39 | maxProfit = Math.max(maxProfit, price - minPrice); 40 | } 41 | 42 | return maxProfit; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstooffer/Question64.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstooffer; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/10/20 10:13 6 | * @description 剑指 Offer 64.求1+2+…+n 7 | * 8 | * 求 1+2+...+n ,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。 9 | * 10 | * 示例 1: 11 | * 输入: n = 3 12 | * 输出: 6 13 | * 14 | * 示例 2: 15 | * 输入: n = 9 16 | * 输出: 45 17 | * 18 | * 限制: 19 | * 1 <= n <= 10000 20 | * 21 | * 来源:力扣(LeetCode) 22 | * 链接:https://leetcode-cn.com/problems/qiu-12n-lcof 23 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 24 | */ 25 | public class Question64 { 26 | 27 | public int sumNums(int n) { 28 | boolean flag = n > 0 && (n += sumNums(n - 1)) > 0; 29 | return n; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstooffer/Question65.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstooffer; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/10/24 13:10 6 | * @description 剑指 Offer 65.不用加减乘除做加法 7 | * 8 | * 写一个函数,求两个整数之和,要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号。 9 | * 10 | * 示例: 11 | * 输入: a = 1, b = 1 12 | * 输出: 2 13 | * 14 | * 提示: 15 | * a, b 均可能是负数或 0 16 | * 结果不会溢出 32 位整数 17 | * 18 | * 来源:力扣(LeetCode) 19 | * 链接:https://leetcode-cn.com/problems/bu-yong-jia-jian-cheng-chu-zuo-jia-fa-lcof 20 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 21 | */ 22 | public class Question65 { 23 | 24 | public int add(int a, int b) { 25 | if (a == 0 || b == 0) { 26 | return a ^ b; 27 | } 28 | // a^b 表示 a+b 不进位的结果 29 | // (a&b)<<1 表示 a+b 只计算需要进位后的结果 30 | // 把这两个数相加,递归直到一方为 0,也就是不需要进位 31 | return add(a ^ b, (a & b) << 1); 32 | } 33 | 34 | public int add2(int a, int b) { 35 | while (b != 0) { 36 | int temp = a ^ b; 37 | b = (a & b) << 1; 38 | a = temp; 39 | } 40 | return a; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstooffer/Question66.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstooffer; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/10/22 9:33 6 | * @description 剑指 Offer 66.构建乘积数组 7 | * 8 | * 给定一个数组 A[0,1,…,n-1],请构建一个数组 B[0,1,…,n-1],其中 B[i] 的值是数组 A 中除了下标 i 以外的元素的积, 9 | * 即 B[i]=A[0]×A[1]×…×A[i-1]×A[i+1]×…×A[n-1]。不能使用除法。 10 | * 11 | * 示例: 12 | * 输入: [1,2,3,4,5] 13 | * 输出: [120,60,40,30,24] 14 | * 15 | * 提示: 16 | * 所有元素乘积之和不会溢出 32 位整数 17 | * a.length <= 100000 18 | * 19 | * 来源:力扣(LeetCode) 20 | * 链接:https://leetcode-cn.com/problems/gou-jian-cheng-ji-shu-zu-lcof 21 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 22 | */ 23 | public class Question66 { 24 | 25 | public int[] constructArr(int[] a) { 26 | int n = a.length; 27 | int[] b = new int[n]; 28 | 29 | // 从左往右累乘 30 | for (int i = 0, result = 1; i < n; result *= a[i], i++) { 31 | b[i] = result; 32 | } 33 | // 从右往左累乘 34 | for (int i = n - 1, result = 1; i >= 0; result *= a[i], i--) { 35 | b[i] *= result; 36 | } 37 | 38 | return b; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstoofferspecial/Question002.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstoofferspecial; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/10/25 8:54 6 | * @description 剑指 Offer II 002.二进制加法 7 | * 8 | * 给定两个 01 字符串 a 和 b ,请计算它们的和,并以二进制字符串的形式输出。 9 | * 输入为 非空 字符串且只包含数字 1 和 0。 10 | * 11 | * 示例 1: 12 | * 输入: a = "11", b = "10" 13 | * 输出: "101" 14 | * 15 | * 示例 2: 16 | * 输入: a = "1010", b = "1011" 17 | * 输出: "10101" 18 | * 19 | * 提示: 20 | * 每个字符串仅由字符 '0' 或 '1' 组成。 21 | * 1 <= a.length, b.length <= 10^4 22 | * 字符串如果不是 "0" ,就都不含前导零。 23 | * 24 | * 注意:本题与主站 67 题 {@link com.hncboy.AddBinary} 25 | * 相同:https://leetcode-cn.com/problems/add-binary/ 26 | * 27 | * 来源:力扣(LeetCode) 28 | * 链接:https://leetcode-cn.com/problems/JFETK5 29 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 30 | */ 31 | public class Question002 { 32 | 33 | public String addBinary(String a, String b) { 34 | StringBuilder result = new StringBuilder(); 35 | int sum = 0; 36 | for (int i = a.length() - 1, j = b.length() - 1; i >= 0 || j >= 0; i--, j--) { 37 | sum += i >= 0 ? a.charAt(i) - '0' : 0; 38 | sum += j >= 0 ? b.charAt(j) - '0' : 0; 39 | result.append(sum % 2); 40 | // 计算进位 41 | sum /= 2; 42 | } 43 | // 进位是1的话补1 44 | result.append(sum == 1 ? sum : ""); 45 | return result.reverse().toString(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstoofferspecial/Question003.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstoofferspecial; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/10/26 9:56 6 | * @description 剑指 Offer II 003.前 n 个数字二进制中 1 的个数 7 | * 8 | * 给定一个非负整数 n ,请计算 0 到 n 之间的每个数字的二进制表示中 1 的个数,并输出一个数组。 9 | * 10 | * 示例 1: 11 | * 输入: n = 2 12 | * 输出: [0,1,1] 13 | * 解释: 14 | * 0 --> 0 15 | * 1 --> 1 16 | * 2 --> 10 17 | * 示例 2: 18 | * 19 | * 输入: n = 5 20 | * 输出: [0,1,1,2,1,2] 21 | * 解释: 22 | * 0 --> 0 23 | * 1 --> 1 24 | * 2 --> 10 25 | * 3 --> 11 26 | * 4 --> 100 27 | * 5 --> 101 28 | * 29 | * 说明 : 30 | * 0 <= n <= 105 31 | * 32 | * 进阶: 33 | * 给出时间复杂度为 O(n*sizeof(integer)) 的解答非常容易。但你可以在线性时间 O(n) 内用一趟扫描做到吗? 34 | * 要求算法的空间复杂度为 O(n) 。 35 | * 你能进一步完善解法吗?要求在C++或任何其他语言中不使用任何内置函数(如 C++ 中的 __builtin_popcount )来执行此操作。 36 | * 37 | * 注意:本题与主站 338 题 {@link com.hncboy.CountingBits} 38 | * 相同:https://leetcode-cn.com/problems/counting-bits/ 39 | * 40 | * 来源:力扣(LeetCode) 41 | * 链接:https://leetcode-cn.com/problems/w3tCBm 42 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 43 | */ 44 | public class Question003 { 45 | 46 | public int[] countBits(int n) { 47 | int[] bits = new int[n + 1]; 48 | for (int i = 1; i <= n; i++) { 49 | // i & (i-1) 用于去掉 i 最右边的 1,因此 i&(i-1) 比 i 小 50 | // i&(i-1) 中 1 的个数已经计算过了,此时只需要加 1 51 | bits[i] = bits[i & (i - 1)] + 1; 52 | } 53 | return bits; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstoofferspecial/Question004.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstoofferspecial; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/10/27 9:06 6 | * @description 剑指 Offer II 004.只出现一次的数字 7 | * 8 | * 给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。 9 | * 10 | * 示例 1: 11 | * 输入:nums = [2,2,3,2] 12 | * 输出:3 13 | * 14 | * 示例 2: 15 | * 输入:nums = [0,1,0,1,0,1,100] 16 | * 输出:100 17 | * 18 | * 提示: 19 | * 1 <= nums.length <= 3 * 104 20 | * -231 <= nums[i] <= 231 - 1 21 | * nums 中,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 22 | * 23 | * 进阶:你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗? 24 | * 25 | * 注意:本题与主站 137 题 {@link com.hncboy.SingleNumberII} 相同:https://leetcode-cn.com/problems/single-number-ii/ 26 | * 27 | * 来源:力扣(LeetCode) 28 | * 链接:https://leetcode-cn.com/problems/WGki4K 29 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 30 | */ 31 | public class Question004 { 32 | 33 | public static void main(String[] args) { 34 | Question004 q = new Question004(); 35 | System.out.println(q.singleNumber(new int[]{2, 2, 3, 2})); 36 | } 37 | 38 | public int singleNumber(int[] nums) { 39 | // 用两位表示 3 种状态 40 | int ones = 0; 41 | int twos = 0; 42 | for (int num : nums) { 43 | ones = ones ^ num & ~twos; 44 | twos = twos ^ num & ~ones; 45 | } 46 | return ones; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstoofferspecial/Question010.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstoofferspecial; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * @author hncboy 8 | * @date 2021/11/8 9:55 9 | * @description 剑指 Offer II 010.和为 k 的子数组 10 | * 11 | * 给定一个整数数组和一个整数 k ,请找到该数组中和为 k 的连续子数组的个数。 12 | * 13 | * 示例 1 : 14 | * 输入:nums = [1,1,1], k = 2 15 | * 输出: 2 16 | * 解释: 此题 [1,1] 与 [1,1] 为两种不同的情况 17 | * 18 | * 示例 2 : 19 | * 输入:nums = [1,2,3], k = 3 20 | * 输出: 2 21 | * 22 | * 提示: 23 | * 1 <= nums.length <= 2 * 104 24 | * -1000 <= nums[i] <= 1000 25 | * -107 <= k <= 107 26 | * 27 | * 注意:本题与主站 560 题相同: https://leetcode-cn.com/problems/subarray-sum-equals-k/ 28 | * 29 | * 来源:力扣(LeetCode) 30 | * 链接:https://leetcode-cn.com/problems/QTMn0o 31 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 32 | */ 33 | public class Question010 { 34 | 35 | public int subarraySum(int[] nums, int k) { 36 | Map prevSumMap = new HashMap<>(); 37 | prevSumMap.put(0, 1); 38 | 39 | int result = 0; 40 | // 前缀和,将每个前缀和存入 prevSumMap 41 | int sum = 0; 42 | for (int num : nums) { 43 | sum += num; 44 | // 如果 prevSumMap 中存在 sum-k 的前缀和,则说明存在前缀和为 k 的 45 | if (prevSumMap.containsKey(sum - k)) { 46 | result += prevSumMap.get(sum - k); 47 | } 48 | prevSumMap.put(sum, prevSumMap.getOrDefault(sum, 0) + 1); 49 | } 50 | return result; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstoofferspecial/Question015.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstoofferspecial; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @author hncboy 8 | * @date 2021/11/13 14:25 9 | * @description 剑指 Offer II 015.字符串中的所有变位词 10 | */ 11 | public class Question015 { 12 | 13 | public List findAnagrams(String s, String p) { 14 | List result = new ArrayList<>(); 15 | char[] array1 = p.toCharArray(); 16 | char[] array2 = s.toCharArray(); 17 | 18 | // 遍历 s1 中的字符,统计每个字母的个数 19 | int[] needs = new int[26]; 20 | for (char ch : array1) { 21 | needs[ch - 'a']++; 22 | } 23 | 24 | for (int left = 0, right = 0; right < array2.length; right++) { 25 | // 滑动右指针 26 | needs[array2[right] - 'a']--; 27 | // 如果需要的字母小于 0,说明此时到这个字母的字符串都不符合要求 28 | while (needs[array2[right] - 'a'] < 0) { 29 | // 将做左指针不断往右移动,补充右指针留下的坑 30 | needs[array2[left++] - 'a']++; 31 | } 32 | // 满足条件 33 | if (right - left + 1 == array1.length) { 34 | result.add(left); 35 | } 36 | } 37 | return result; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstoofferspecial/Question018.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstoofferspecial; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/11/9 11:33 6 | * @description 剑指 Offer II 018.有效的回文 7 | * 8 | * 给定一个字符串 s ,验证 s 是否是 回文串 ,只考虑字母和数字字符,可以忽略字母的大小写。 9 | * 本题中,将空字符串定义为有效的 回文串 。 10 | * 11 | * 示例 1: 12 | * 输入: s = "A man, a plan, a canal: Panama" 13 | * 输出: true 14 | * 解释:"amanaplanacanalpanama" 是回文串 15 | * 16 | * 示例 2: 17 | * 输入: s = "race a car" 18 | * 输出: false 19 | * 解释:"raceacar" 不是回文串 20 | * 21 | * 提示: 22 | * 1 <= s.length <= 2 * 105 23 | * 字符串 s 由 ASCII 字符组成 24 | * 25 | * 注意:本题与主站 125 题 {@link com.hncboy.ValidPalindrome} 26 | * 相同: https://leetcode-cn.com/problems/valid-palindrome/ 27 | * 28 | * 来源:力扣(LeetCode) 29 | * 链接:https://leetcode-cn.com/problems/XltzEq 30 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 31 | */ 32 | public class Question018 { 33 | 34 | public boolean isPalindrome(String s) { 35 | int left = 0; 36 | int right = s.length() - 1; 37 | s = s.toLowerCase(); 38 | while (left <= right) { 39 | if (!Character.isLetterOrDigit(s.charAt(left))) { 40 | left++; 41 | } else if (!Character.isLetterOrDigit(s.charAt(right))) { 42 | right--; 43 | } else { 44 | if (s.charAt(left++) != s.charAt(right--)) { 45 | return false; 46 | } 47 | } 48 | } 49 | return true; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstoofferspecial/Question023.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstoofferspecial; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/10/30 11:45 6 | * @description 剑指 Offer II 023.两个链表的第一个重合节点 7 | * 8 | * 注意:本题与主站 160 题 {@link com.hncboy.IntersectionOfTwoLinkedLists } 9 | * 相同:https://leetcode-cn.com/problems/intersection-of-two-linked-lists/ 10 | * 11 | * 来源:力扣(LeetCode) 12 | * 链接:https://leetcode-cn.com/problems/3u1WK4 13 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 14 | */ 15 | public class Question023 { 16 | 17 | public ListNode getIntersectionNode(ListNode headA, ListNode headB) { 18 | if (headA == null || headB == null) { 19 | return null; 20 | } 21 | ListNode pA = headA, pB = headB; 22 | while (pA != pB) { 23 | pA = pA == null ? headB : pA.next; 24 | pB = pB == null ? headA : pB.next; 25 | } 26 | return pA; 27 | } 28 | 29 | private static class ListNode { 30 | int val; 31 | ListNode next; 32 | 33 | ListNode(int x) { 34 | val = x; 35 | next = null; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstoofferspecial/Question032.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstoofferspecial; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/10/30 11:27 6 | * @description 剑指 Offer II 032.有效的变位词 7 | * 8 | * 给定两个字符串 s 和 t ,编写一个函数来判断它们是不是一组变位词(字母异位词)。 9 | * 注意:若 s 和 t 中每个字符出现的次数都相同且字符顺序不完全相同,则称 s 和 t 互为变位词(字母异位词)。 10 | * 11 | * 示例 1: 12 | * 输入: s = "anagram", t = "nagaram" 13 | * 输出: true 14 | * 15 | * 示例 2: 16 | * 输入: s = "rat", t = "car" 17 | * 输出: false 18 | * 19 | * 示例 3: 20 | * 输入: s = "a", t = "a" 21 | * 输出: false 22 | * 23 | * 提示: 24 | * 1 <= s.length, t.length <= 5 * 104 25 | * s and t 仅包含小写字母 26 | * 27 | * 进阶: 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况? 28 | * 注意:本题与主站 242 题 {@link com.hncboy.ValidAnagram} 29 | * 相似(字母异位词定义不同):https://leetcode-cn.com/problems/valid-anagram/ 30 | * 31 | * 来源:力扣(LeetCode) 32 | * 链接:https://leetcode-cn.com/problems/dKk3P7 33 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 34 | */ 35 | public class Question032 { 36 | 37 | public boolean isAnagram(String s, String t) { 38 | if (s.length() != t.length() || s.equals(t)) { 39 | return false; 40 | } 41 | 42 | int[] hash = new int [26]; 43 | for (char ch : s.toCharArray()) { 44 | hash[ch - 'a']++; 45 | } 46 | 47 | for (char ch : t.toCharArray()) { 48 | if (--hash[ch - 'a'] < 0) { 49 | return false; 50 | } 51 | } 52 | 53 | return true; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstoofferspecial/Question088.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstoofferspecial; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/11/19 9:36 6 | * @description 剑指 Offer II 088.爬楼梯的最少成本 7 | * 8 | * 数组的每个下标作为一个阶梯,第 i 个阶梯对应着一个非负数的体力花费值 cost[i](下标从 0 开始)。 9 | * 每当爬上一个阶梯都要花费对应的体力值,一旦支付了相应的体力值,就可以选择向上爬一个阶梯或者爬两个阶梯。 10 | * 请找出达到楼层顶部的最低花费。在开始时,你可以选择从下标为 0 或 1 的元素作为初始阶梯。 11 | * 12 | * 示例 1: 13 | * 输入:cost = [10, 15, 20] 14 | * 输出:15 15 | * 解释:最低花费是从 cost[1] 开始,然后走两步即可到阶梯顶,一共花费 15 。 16 | * 17 | * 示例 2: 18 | * 输入:cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1] 19 | * 输出:6 20 | * 解释:最低花费方式是从 cost[0] 开始,逐个经过那些 1 ,跳过 cost[3] ,一共花费 6 。 21 | * 22 | * 提示: 23 | * 2 <= cost.length <= 1000 24 | * 0 <= cost[i] <= 999 25 | * 26 | * 注意:本题与主站 746 题相同: https://leetcode-cn.com/problems/min-cost-climbing-stairs/ 27 | * 28 | * 来源:力扣(LeetCode) 29 | * 链接:https://leetcode-cn.com/problems/GzCJIP 30 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 31 | */ 32 | public class Question088 { 33 | 34 | public int minCostClimbingStairs(int[] cost) { 35 | int lastOne = 0; 36 | int lastTwo = 0; 37 | for (int i = cost.length - 1; i >= 0; i--) { 38 | int current = cost[i] + Math.min(lastOne, lastTwo); 39 | lastTwo = lastOne; 40 | lastOne = current; 41 | } 42 | return Math.min(lastOne, lastTwo); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/com/hncboy/swordreferstoofferspecial/Question089.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.swordreferstoofferspecial; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2021/12/21 8:48 6 | * @description 剑指 Offer II 089.房屋偷盗 7 | * 8 | * 一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响小偷偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统, 9 | * 如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 10 | * 给定一个代表每个房屋存放金额的非负整数数组 nums ,请计算 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。 11 | * 12 | * 示例 1: 13 | * 输入:nums = [1,2,3,1] 14 | * 输出:4 15 | * 解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。 16 | * 偷窃到的最高金额 = 1 + 3 = 4 。 17 | * 18 | * 示例 2: 19 | * 输入:nums = [2,7,9,3,1] 20 | * 输出:12 21 | * 解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。 22 | * 偷窃到的最高金额 = 2 + 9 + 1 = 12 。 23 | * 24 | * 提示: 25 | * 1 <= nums.length <= 100 26 | * 0 <= nums[i] <= 400 27 | * 28 | * 注意:本题与主站 198 题 {@link com.hncboy.HouseRobber} 相同: https://leetcode-cn.com/problems/house-robber/ 29 | * 30 | * 通过次数 4,536 提交次数 7,371 31 | * 32 | * 来源:力扣(LeetCode) 33 | * 链接:https://leetcode-cn.com/problems/Gu0c2T 34 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 35 | */ 36 | public class Question089 { 37 | 38 | public int rob(int[] nums) { 39 | int prev = 0; 40 | int curr = 0; 41 | for (int num : nums) { 42 | int temp = Math.max(curr, prev + num); 43 | prev = curr; 44 | curr = temp; 45 | } 46 | return curr; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/com/hncboy/util/NamingConversionUtil.java: -------------------------------------------------------------------------------- 1 | package com.hncboy.util; 2 | 3 | /** 4 | * @author hncboy 5 | * @date 2019/12/8 12:16 6 | * @description 命名转换 7 | *

8 | * 类的命名时根据题目的英文名字来取的 9 | * 因为题目都是通过横杠连接,用一个工具类将题目转为驼峰命名 10 | */ 11 | public class NamingConversionUtil { 12 | 13 | /** 14 | * 横杠转大驼峰 15 | * 16 | * @param str 17 | * @return 18 | */ 19 | private static String lineToHump(String str) { 20 | String[] words = str.split("-"); 21 | StringBuilder sb = new StringBuilder(); 22 | for (String word : words) { 23 | sb.append(word.substring(0, 1).toUpperCase()) 24 | .append(word.substring(1).toLowerCase()); 25 | } 26 | return sb.toString(); 27 | } 28 | 29 | /** 30 | * 通过url获取题目的横杠命名 31 | * 32 | * @param str 33 | * @return 34 | */ 35 | private static String getUrlLine(String str) { 36 | String[] words = str.split("/"); 37 | return words[4]; 38 | } 39 | 40 | public static void main(String[] args) { 41 | System.out.println(lineToHump(getUrlLine("https://leetcode-cn.com/problems/distribute-candies-to-people/"))); 42 | } 43 | } 44 | --------------------------------------------------------------------------------