Repository: fluency03/leetcode-java Branch: master Commit: 81e5c1ab0ef5 Files: 596 Total size: 1.8 MB Directory structure: gitextract_ximp81dy/ ├── .gitignore ├── README.md └── src/ ├── .gitignore ├── AccountsMerge721.java ├── AddBinary67.java ├── AddBoldTagInString616.java ├── AddOneRowToTree623.java ├── AddStrings415.java ├── AddTwoNumbers2.java ├── AddTwoNumbersII445.java ├── AlienDictionary269.java ├── AllNodesDistanceKInBinaryTree863.java ├── AllOOneDataStructure432.java ├── AllPathsFromSourceToTarget797.java ├── AndroidUnlockPatterns351.java ├── AsyncJobMonitor.java ├── AverageOfLevelsInBinaryTree637.java ├── BackspaceStringCompare844.java ├── BalancedBinaryTree110.java ├── BaseballGame682.java ├── BasicCalculator224.java ├── BasicCalculatorII227.java ├── Bench.java ├── BestMeetingPoint296.java ├── BestTimeToBuyAndSellStock121.java ├── BestTimeToBuyAndSellStockII122.java ├── BestTimeToBuyAndSellStockIII123.java ├── BestTimeToBuyAndSellStockIV188.java ├── BestTimeToBuyAndSellStockWithCooldown309.java ├── BestTimeToBuyAndSellStockWithTransactionFee714.java ├── BinarySearchTreeIterator173.java ├── BinaryTreeInorderTraversal94.java ├── BinaryTreeLevelOrderTraversal102.java ├── BinaryTreeLevelOrderTraversalII107.java ├── BinaryTreeLongestConsecutiveSequence298.java ├── BinaryTreeMaximumPathSum124.java ├── BinaryTreePaths257.java ├── BinaryTreePreorderTraversal144.java ├── BinaryTreeRightSideView199.java ├── BinaryTreeVerticalOrderTraversal314.java ├── BinaryTreeZigzagLevelOrderTraversal103.java ├── BinaryTreesWithFactors823.java ├── BitwiseANDOfNumbersRange201.java ├── BoatsToSavePeople885.java ├── BombEnemy361.java ├── BoundaryOfBinaryTree545.java ├── BrickWall554.java ├── BricksFallingWhenHit803.java ├── BuddyStrings859.java ├── BullsAndCows299.java ├── BurstBalloons312.java ├── CanIWin464.java ├── CheapestFlightsWithinKStops787.java ├── ClimbingStairs70.java ├── CloneGraph133.java ├── ClosestBinarySearchTreeValue270.java ├── ClosestBinarySearchTreeValueII272.java ├── CoinChange322.java ├── CoinChangeII518.java ├── CollatzConjecture.java ├── CombinationSum39.java ├── CombinationSumIII216.java ├── CombinationSumIV377.java ├── CompareVersionNumbers165.java ├── ConcatenatedWords472.java ├── ConstructBinaryTreeFromInorderAndPostorderTraversal106.java ├── ConstructBinaryTreeFromPreorderAndInorderTraversal105.java ├── ConstructBinaryTreeFromString536.java ├── ConstructQuadTree427.java ├── ContainerWithMostWater11.java ├── ContainsDuplicate217.java ├── ContainsDuplicateIII220.java ├── ContainsDuplicatesII219.java ├── ContiguousArray525.java ├── ContinuousSubarraySum523.java ├── ConvertANumberToHexadecimal405.java ├── ConvertBSTToGreaterTree538.java ├── ConvertBinarySearchTreeToSortedDoublyLinkedList.java ├── ConvertSortedArrayToBinarySearchTree108.java ├── ConvertSortedListToBST109.java ├── CopyListWithRandomPointer138.java ├── CountNumbersWithUniqueDigits357.java ├── CountOfRangeSum327.java ├── CountOfSmallerNumbersAfterSelf315.java ├── CountPrimes204.java ├── CountingBits338.java ├── CouplesHoldingHands765.java ├── CourseSchedule207.java ├── CourseScheduleII210.java ├── CutOffTreesForGolfEvent675.java ├── DailyTemperatures739.java ├── DataStreamAsDisjointIntervals352.java ├── DecodeString394.java ├── DecodeWays91.java ├── DecodeWaysII639.java ├── DecodedStringAtIndex884.java ├── DeleteAndEarn740.java ├── DeleteNodeInABST450.java ├── DeleteNodeInALinkedList237.java ├── DesignCircularDeque641.java ├── DesignCircularQueue622.java ├── DesignCompressedStringIterator604.java ├── DesignHashMap706.java ├── DesignHashSet705.java ├── DesignHitCounter362.java ├── DesignInMemoryFileSystem588.java ├── DesignLinkedList707.java ├── DesignLogStorageSystem635.java ├── DesignSearchAutocompleteSystem642.java ├── DesignSnakeGame353.java ├── DesignTicTacToe348.java ├── DesignTwitter355.java ├── DiagonalTraverse498.java ├── DiameterOfBinaryTree543.java ├── DifferentWaysToAddParentheses241.java ├── DivideTwoIntegers29.java ├── DominoAndTrominoTiling790.java ├── EditDistance72.java ├── EmployeeFreeTime759.java ├── EncodeAndDecodeStrings271.java ├── EncodeAndDecodeTinyURL535.java ├── EqualTreePartition663.java ├── EvaluateDivision399.java ├── EvaluateReversePolishNotation150.java ├── ExamRoom855.java ├── ExclusiveTimeOfFunctions636.java ├── ExpressionAddOperators282.java ├── FindAllAnagramsInAString438.java ├── FindAllNumbersDisappearedInAnArray448.java ├── FindAnagramMappings760.java ├── FindAndReplacePattern890.java ├── FindBottomLeftTreeValue513.java ├── FindCenterOfMassInA2DArray.java ├── FindDuplicateSubtrees652.java ├── FindEventualSafeStates802.java ├── FindKClosestElements658.java ├── FindKPairsWithSmallestSums373.java ├── FindKthSmallestPairDistance719.java ├── FindLargestValueInEachTreeRow515.java ├── FindMedianFromDataStream295.java ├── FindMinimumInRotatedSortedArray153.java ├── FindMinimumInRotatedSortedArrayII154.java ├── FindModeInBinarySearchTree501.java ├── FindPeakElement162.java ├── FindTheCelebrity277.java ├── FindTheDuplicateNumber287.java ├── FirstBadVersion278.java ├── FirstMissingPositive41.java ├── FirstUniqueCharacterInAString387.java ├── FizzBuzz412.java ├── Flatten2DVector251.java ├── FlattenBinaryTreeToLinkedList114.java ├── FlipGame293.java ├── FlippingAnImage832.java ├── FourSum18.java ├── FourSumII454.java ├── FractionToRecurringDecimal166.java ├── FriendCircles547.java ├── FrogJump403.java ├── GameOfLife289.java ├── GeneralizedAbbreviation320.java ├── GenerateParentheses22.java ├── GraphValidTree261.java ├── GroupAnagrams49.java ├── GroupShiftedStrings249.java ├── GuessNumberHigherOrLowerII375.java ├── GuessTheWord843.java ├── HIndex274.java ├── HandOfStraights846.java ├── HappyNumber202.java ├── HighestPopulationYear.java ├── HouseRobber198.java ├── HouseRobberII213.java ├── HouseRobberIII337.java ├── ImageSmoother661.java ├── ImplementMagicDictionary676.java ├── ImplementQueueUsingStacks232.java ├── ImplementStackusingQueues225.java ├── ImplementStrStr28.java ├── ImplementTriePrefixTree208.java ├── IncreasingSubsequences491.java ├── IncreasingTripletSubsequence334.java ├── InorderSuccessorInBST285.java ├── InsertDeleteGetRandomOOne380.java ├── InsertInterval57.java ├── InsertIntoACyclicSortedList.java ├── InsertionSortList147.java ├── IntegerBreak343.java ├── IntegerToEnglishWords273.java ├── IntegerToRoman12.java ├── InterleavingString97.java ├── IntersectionOfTwoArrays349.java ├── IntersectionOfTwoArraysII350.java ├── IntersectionOfTwoLinkedLists160.java ├── Interval.java ├── InvertBinaryTree226.java ├── IsGraphBipartite785.java ├── IsSubsequence392.java ├── IslandPerimeter463.java ├── IsomorphicStrings205.java ├── JewelsAndStones771.java ├── JudgeRouteCircle657.java ├── JumpGame55.java ├── JumpGameII45.java ├── KEmptySlots683.java ├── KMP.java ├── KeysAndRooms841.java ├── KillProcess582.java ├── KokoEatingBananas875.java ├── KthLargestElementInAnArray215.java ├── KthSmallestElementInABST230.java ├── KthSmallestElementInASortedMatrix378.java ├── KthSmallestPrimeFraction786.java ├── KthSymbolInGrammar779.java ├── LFUCache460.java ├── LRUCache146.java ├── LargestBSTSubtree333.java ├── LargestDivisibleSubset368.java ├── LargestNumber179.java ├── LargestRectangleInHistogram84.java ├── LemonadeChange860.java ├── LengthOfLongestFibonacciSubsequence873.java ├── LetterCombinationsOfAPhoneNumber17.java ├── LexicographicalNumbers386.java ├── LicenseKeyFormatting482.java ├── LinkedListCycle141.java ├── LinkedListCycleII142.java ├── LinkedListRandomNode382.java ├── ListNode.java ├── LoggerRateLimiter359.java ├── LonelyPixelI531.java ├── LongestAbsoluteFilePath388.java ├── LongestCommonPrefix14.java ├── LongestConsecutiveSequence128.java ├── LongestContinuousIncreasingSubsequence674.java ├── LongestHarmoniousSubsequence594.java ├── LongestIncreasingSubsequence300.java ├── LongestMountainInArray845.java ├── LongestPalindrome409.java ├── LongestPalindromicSubsequence516.java ├── LongestPalindromicSubstring5.java ├── LongestRepeatingCharacterReplacement424.java ├── LongestSubstringWithAtMostKDistinctCharacters340.java ├── LongestSubstringWithAtMostTwoDistinctCharacters159.java ├── LongestSubstringWithoutRepeatingCharacters3.java ├── LongestUnivaluePath687.java ├── LongestValidParentheses32.java ├── LongestWordInDictionary720.java ├── LowestCommonAncestorOfABinarySearchTree235.java ├── LowestCommonAncestorOfABinaryTree236.java ├── MagicalString481.java ├── MajorityElement169.java ├── MapSumPairs677.java ├── MatchsticksToSquare473.java ├── MaxAreaOfIsland695.java ├── MaxChunksToMakeSorted769.java ├── MaxChunksToMakeSortedII768.java ├── MaxConsecutiveOnes485.java ├── MaxConsecutiveOnesII487.java ├── MaxIncreaseToKeepCitySkyline807.java ├── MaxPointsOnALine149.java ├── MaxStack716.java ├── MaxSumOfRectangleNoLargerThanK363.java ├── MaximalRectangle85.java ├── MaximalSquare221.java ├── MaximizeDistanceToClosestPerson849.java ├── MaximumAverageSubarrayI643.java ├── MaximumBinaryTree654.java ├── MaximumDepthOfBinaryTree104.java ├── MaximumFrequencyStack895.java ├── MaximumLengthOfPairChain646.java ├── MaximumLengthOfRepeatedSubarray718.java ├── MaximumProductOfThreeNumbers628.java ├── MaximumProductOfWordLengths318.java ├── MaximumProductSubarray152.java ├── MaximumSizeSubarraySumEqualsK325.java ├── MaximumSubarray53.java ├── MaximumSumOf3NonOverlappingSubarrays689.java ├── MaximumVacationDays568.java ├── MaximumWidthOfBinaryTree662.java ├── MaximumXOROfTwoNumbersInAnArray421.java ├── MedianOfTwoSortedArrays4.java ├── MeetingRooms252.java ├── MeetingRoomsII253.java ├── MergeIntervals56.java ├── MergeKSortedLists23.java ├── MergeSortedArray88.java ├── MergeTwoSortedLists21.java ├── MiddleOfTheLinkedList876.java ├── MinCostClimbingStairs746.java ├── MinStack.java ├── Minesweeper529.java ├── MinimumASCIIDeleteSumForTwoStrings712.java ├── MinimumAbsoluteDifferenceInBST530.java ├── MinimumDepthOfBinaryTree111.java ├── MinimumDistanceBetweenBSTNodes783.java ├── MinimumGeneticMutation433.java ├── MinimumHeightTrees310.java ├── MinimumMovesToEqualArrayElementsII462.java ├── MinimumPathSum64.java ├── MinimumSizeSubarraySum209.java ├── MinimumWindowSubsequence727.java ├── MinimumWindowSubstring76.java ├── MissingNumber268.java ├── MissingRanges163.java ├── MonotoneIncreasingDigits738.java ├── MonotonicArray896.java ├── MostCommonWord819.java ├── MostFrequentSubtreeSum508.java ├── MostProfitAssigningWork826.java ├── MoveZeroes283.java ├── MovingAverageFromDataStream346.java ├── MultiplyStrings43.java ├── MyCalendarI729.java ├── MyCalendarII731.java ├── NQueens51.java ├── NQueensII52.java ├── NaryTreeLevelOrderTraversal429.java ├── NaryTreePostorderTraversal590.java ├── NestedIterator.java ├── NestedListWeightSum339.java ├── NextClosestTime681.java ├── NextGreaterElementI496.java ├── NextGreaterElementII503.java ├── NextGreaterElementIII556.java ├── NextPermutation31.java ├── NonDecreasingArray665.java ├── NonOverlappingIntervals435.java ├── NumberOfConnectedComponentsInAnUndirectedGraph323.java ├── NumberOfCornerRectangles750.java ├── NumberOfDigitOne233.java ├── NumberOfIslands200.java ├── NumberOfIslandsII305.java ├── NumberOfLongestIncreasingSubsequence673.java ├── NumberOfMatchingSubsequences792.java ├── OddEvenLinkedList328.java ├── OneEditDistance.java ├── OneEditDistance161.java ├── OnesAndZeroes474.java ├── OpenTheLock752.java ├── OptimalAccountBalancing465.java ├── OutputContestMatches544.java ├── PacificAtlanticWaterFlow417.java ├── PaintFence276.java ├── PaintHouse256.java ├── PaintHouseII265.java ├── PalindromeLinkedList234.java ├── PalindromeNumber9.java ├── PalindromePairs336.java ├── PalindromePartitioning131.java ├── PalindromePermutationII267.java ├── PalindromicSubstrings647.java ├── PartitionEqualSubsetSum416.java ├── PartitionLabels763.java ├── PartitionList86.java ├── PartitionToKEqualSumSubsets698.java ├── PascalsTriangleII119.java ├── PatchingArray330.java ├── PathSum112.java ├── PathSumII113.java ├── PathSumIII437.java ├── PeekingIterator284.java ├── PerfectSquares279.java ├── PermutationInString567.java ├── PermutationSequence60.java ├── Permutations46.java ├── PermutationsII47.java ├── PlusOne66.java ├── PlusOneLinkedList369.java ├── Point.java ├── PopulatingNextRightPointersInEachNode116.java ├── PopulatingNextRightPointersInEachNodeII117.java ├── PossibleBipartition886.java ├── PowXN50.java ├── PowerOfTwo231.java ├── PredictTheWinner486.java ├── ProductOfArrayExceptSelf238.java ├── ProfitableSchemes879.java ├── ProjectionAreaOf3DShapes887.java ├── QuadTreeIntersection558.java ├── QueueReconstructionByHeight406.java ├── RandomFlipMatrix519.java ├── RandomListNode.java ├── RandomPickIndex398.java ├── RangeAddition370.java ├── RangeModule715.java ├── RangeSumQuery2DImmutable304.java ├── RangeSumQuery2DMutable308.java ├── RangeSumQueryImmutable303.java ├── RangeSumQueryMutable307.java ├── RansomNote383.java ├── ReadNCharactersGivenRead4IICallMultipleTimes158.java ├── ReadNCharactersGivenReadFour157.java ├── RearrangeStringKDistanceApart358.java ├── ReconstructItinerary332.java ├── ReconstructOriginalDigitsFromEnglish423.java ├── RectangleArea223.java ├── RectangleAreaII850.java ├── RectangleOverlap863.java ├── RedundantConnection684.java ├── RedundantConnectionII685.java ├── RegularExpressionMatching10.java ├── RemoveDuplicateLetters316.java ├── RemoveDuplicatesFromSortedArray26.java ├── RemoveDuplicatesFromSortedArrayII80.java ├── RemoveDuplicatesFromSortedList83.java ├── RemoveDuplicatesFromSortedListII82.java ├── RemoveInvalidParentheses301.java ├── RemoveLinkedListElements203.java ├── RemoveNthNodeFromEndOfList19.java ├── ReorderList143.java ├── ReorganizeString767.java ├── RepeatedDNASequences187.java ├── RepeatedStringMatch686.java ├── RepeatedSubstringPattern459.java ├── ReplaceWords648.java ├── RestoreIPAddresses93.java ├── ReverseLinkedList206.java ├── ReverseLinkedListII92.java ├── ReverseNodesInKGroup25.java ├── ReverseString344.java ├── ReverseStringII541.java ├── ReverseVowelsOfAString345.java ├── ReverseWordsInAString151.java ├── ReverseWordsInAStringII186.java ├── ReverseWordsInAStringIII557.java ├── RobotRoomCleaner.java ├── RomanToInteger13.java ├── RotateArray189.java ├── RotateFunction396.java ├── RotateImage48.java ├── RotateList61.java ├── RussianDollEnvelopes354.java ├── SameTree100.java ├── SearchA2DMatrix74.java ├── SearchA2DMatrixII240.java ├── SearchForARange34.java ├── SearchInASortedArrayOfUnknownSize702.java ├── SearchInRotatedSortedArray33.java ├── SearchInRotatedSortedArrayII81.java ├── SearchInsertPosition35.java ├── SecondMinimumNodeInABinaryTree671.java ├── SentenceScreenFitting418.java ├── SentenceSimilarity734.java ├── SentenceSimilarityII737.java ├── SerializeAndDeserializeBST449.java ├── SerializeAndDeserializeBinaryTree297.java ├── SetMatrixZeroes73.java ├── ShortestBridge934.java ├── ShortestCompletingWord748.java ├── ShortestDistanceFromAllBuildings317.java ├── ShortestPalindrome214.java ├── ShortestPathToGetAllKeys864.java ├── ShortestSubarrayWithSumAtLeastK862.java ├── ShortestWordDistance243.java ├── ShuffleAnArray384.java ├── SimplifyPath71.java ├── SingleElementInASortedArray540.java ├── SingleNumber136.java ├── SingleNumberII137.java ├── SlidingWindowMaximum239.java ├── SlidingWindowMedian480.java ├── SmallestRange632.java ├── SolveTheEquation640.java ├── SortArrayByParityII922.java ├── SortCharactersByFrequency451.java ├── SortColors75.java ├── SortList148.java ├── SortTransformedArray360.java ├── SparseMatrixMultiplication311.java ├── SpiralMatrix54.java ├── SpiralMatrixII59.java ├── SplitArrayIntoConsecutiveSubsequences659.java ├── SplitArrayIntoFibonacciSequence842.java ├── SplitArrayLargestSum410.java ├── SqrtX69.java ├── StoneGame877.java ├── StringCompression443.java ├── StringToInteger8.java ├── StrobogrammaticNumber246.java ├── StrobogrammaticNumberII247.java ├── SubarrayProductLessThanK713.java ├── SubarraySumEqualsK560.java ├── Subsequence.java ├── Subsets78.java ├── SubsetsII90.java ├── SubtreeOfAnotherTree572.java ├── SudokuSolver37.java ├── SumOfSquareNumbers633.java ├── SumRootToLeafNumbers129.java ├── SummaryRanges228.java ├── SuperUglyNumber313.java ├── SurroundedRegions130.java ├── SwapAdjacentInLRString777.java ├── SymmetricTree101.java ├── TargetSum494.java ├── TaskScheduler621.java ├── TextJustification68.java ├── TheMaze490.java ├── TheMazeII505.java ├── TheMazeIII499.java ├── TheSkylineProblem218.java ├── ThirdMaximumNumber414.java ├── ThreeSum15.java ├── ThreeSumClosest16.java ├── ThreeSumSmaller259.java ├── ToLowerCase709.java ├── TopKFrequentElements347.java ├── TopKFrequentWords692.java ├── TotalHammingDistance477.java ├── TrappingRainWater42.java ├── TrappingRainWaterII407.java ├── TreeLinkNode.java ├── TreeNode.java ├── TreeToForestByErasingNodes.java ├── Triangle120.java ├── TrimABinarySearchTree669.java ├── TwoSum1.java ├── TwoSumIIInputArrayIsSorted167.java ├── TwoSumIVInputIsABST653.java ├── UTF8Validation393.java ├── UglyNumber263.java ├── UglyNumberII264.java ├── UncommonWordsFromTwoSentences884.java ├── UndirectedGraphNode.java ├── UniqueBinarySearchTrees96.java ├── UniqueBinarySearchTreesII95.java ├── UniqueMorseCodeWords804.java ├── UniquePaths62.java ├── UniquePathsII63.java ├── UniqueWordAbbreviation288.java ├── ValidAnagram242.java ├── ValidNumber65.java ├── ValidPalindrome125.java ├── ValidPalindromeII680.java ├── ValidParentheses20.java ├── ValidParenthesisString678.java ├── ValidSudoku36.java ├── ValidTriangleNumber611.java ├── ValidWordAbbreviation408.java ├── ValidateBinarySearchTree98.java ├── ValidateStackSequences946.java ├── VerifyPreorderSequenceInBinarySearchTree255.java ├── WallsAndGates286.java ├── WaterAndJugProblem365.java ├── WiggleSort280.java ├── WiggleSortII324.java ├── WiggleSubsequence376.java ├── WildcardMatching44.java ├── WordAbbreviation527.java ├── WordBreak139.java ├── WordBreakII140.java ├── WordDictionary.java ├── WordLadder127.java ├── WordLadderII126.java ├── WordPattern290.java ├── WordPatternII291.java ├── WordSearch79.java ├── WordSearchII212.java ├── WordSquares425.java ├── ZeroOneMatrix542.java ├── ZigzagIterator281.java ├── data-structures/ │ ├── BinaryIndexedTree.java │ ├── BinarySearchTree.java │ ├── BinarySearchTreeWithParent.java │ ├── DisjointSet.java │ ├── LFUCache.java │ ├── LRUCache.java │ ├── MinHeap.java │ ├── Trie.java │ └── TrieNode.java ├── graph/ │ ├── Dijkstra.java │ ├── README.md │ ├── StrongConnectivity.java │ └── TopologicalSort.java ├── knapsack/ │ ├── CompleteKnapsack.java │ ├── MultipleKnapsack.java │ ├── README.md │ └── ZeroOneKnapsack.java ├── search/ │ ├── BinarySearch.java │ ├── ExponentialSearch.java │ ├── InterpolationSearch.java │ ├── JumpSearch.java │ ├── LinearSearch.java │ ├── README.md │ └── TernarySearch.java └── sort/ ├── BubbleSort.java ├── BucketSort.java ├── CountingSort.java ├── HeapSort.java ├── InsertionSort.java ├── MergeSort.java ├── QuickSort.java ├── README.md ├── RadixSort.java └── SelectionSort.java ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ *.class .DS_store .vscode .idea ================================================ FILE: README.md ================================================ # leetcode-java | Class Definition | |:----------------------------------------------------------------------------------:| | [ListNode](https://github.com/fluency03/leetcode-java/blob/master/src/ListNode.java) | | [TreeNode](https://github.com/fluency03/leetcode-java/blob/master/src/TreeNode.java) | | [Interval](https://github.com/fluency03/leetcode-java/blob/master/src/Interval.java) | | [TreeLinkNode](https://github.com/fluency03/leetcode-java/blob/master/src/TreeLinkNode.java) | | [UndirectedGraphNode](https://github.com/fluency03/leetcode-java/blob/master/src/UndirectedGraphNode.java) | | [Point](https://github.com/fluency03/leetcode-java/blob/master/src/Point.java) | # Search and Sort | Search ([*README*](https://github.com/fluency03/leetcode-java/tree/master/src/search)) | Sort ([*README*](https://github.com/fluency03/leetcode-java/tree/master/src/sort)) | |:-:|:-:| | [Linear Search](https://github.com/fluency03/leetcode-java/blob/master/src/search/LinearSearch.java) | [Selection Sort](https://github.com/fluency03/leetcode-java/blob/master/src/sort/SelectionSort.java) | | [Binary Search](https://github.com/fluency03/leetcode-java/blob/master/src/search/BinarySearch.java) | [Bubble Sort](https://github.com/fluency03/leetcode-java/blob/master/src/sort/BubbleSort.java) | | [Jump Search](https://github.com/fluency03/leetcode-java/blob/master/src/search/JumpSearch.java) | [Insertion Sort](https://github.com/fluency03/leetcode-java/blob/master/src/sort/InsertionSort.java) | | [Interpolation Search](https://github.com/fluency03/leetcode-java/blob/master/src/search/InterpolationSearch.java) | [Merge Sort ](https://github.com/fluency03/leetcode-java/blob/master/src/sort/MergeSort.java)| | [Exponential Search](https://github.com/fluency03/leetcode-java/blob/master/src/search/ExponentialSearch.java) | [Heap Sort](https://github.com/fluency03/leetcode-java/blob/master/src/sort/HeapSort.java) | | [Ternary Search](https://github.com/fluency03/leetcode-java/blob/master/src/search/TernarySearch.java) | [Quick Sort](https://github.com/fluency03/leetcode-java/blob/master/src/sort/QuickSort.java) | | [...](http://www.geeksforgeeks.org/fundamentals-of-algorithms/#SearchingandSorting) | [Radix Sort](https://github.com/fluency03/leetcode-java/blob/master/src/sort/RadixSort.java) | | | [Counting Sort](https://github.com/fluency03/leetcode-java/blob/master/src/sort/CountingSort.java) | | | [Bucket Sort](https://github.com/fluency03/leetcode-java/blob/master/src/sort/BucketSort.java) | | | Shell Sort | | | Comb Sort | | | [...](http://www.geeksforgeeks.org/fundamentals-of-algorithms/#SearchingandSorting) | # [Knapsack Problem](https://github.com/fluency03/leetcode-java/tree/master/src/knapsack) | Knapsack Problem | |:----------------------------------------------------------------------------------:| | [ZeroOneKnapsack](https://github.com/fluency03/leetcode-java/blob/master/src/knapsack/ZeroOneKnapsack.java) | | [CompleteKnapsack](https://github.com/fluency03/leetcode-java/blob/master/src/knapsack/CompleteKnapsack.java) | # [Data Structures](https://github.com/fluency03/leetcode-java/tree/master/src/data-structures) | Data Structures | |:----------------------------------------------------------------------------------:| | [TrieNode](https://github.com/fluency03/leetcode-java/blob/master/src/data-structures/TrieNode.java) | | [Trie](https://github.com/fluency03/leetcode-java/blob/master/src/data-structures/Trie.java) | | [LRUCache](https://github.com/fluency03/leetcode-java/blob/master/src/data-structures/LRUCache.java) | | [LFUCache](https://github.com/fluency03/leetcode-java/blob/master/src/data-structures/LFUCache.java) | | [BinarySearchTree](https://github.com/fluency03/leetcode-java/blob/master/src/data-structures/BinarySearchTree.java) | | [BinarySearchTreeWithParent](https://github.com/fluency03/leetcode-java/blob/master/src/data-structures/BinarySearchTreeWithParent.java) | | [BinaryIndexedTree](https://github.com/fluency03/leetcode-java/blob/master/src/data-structures/BinaryIndexedTree.java) | | [MinHeap](https://github.com/fluency03/leetcode-java/blob/master/src/data-structures/MinHeap.java) | | [DisjointSet (Union-Find)](https://github.com/fluency03/leetcode-java/blob/master/src/data-structures/DisjointSet.java) | | [Graph](https://github.com/fluency03/leetcode-java/blob/master/src/graph) | # Total: 538 | Easy | Medium | Hard | - | |:-------:|:-------:|:----:|:---:| | 142 | 292 | 92 | 12 | | Question | Solution | Difficulty | |------------------------------------------------------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------:|:----------:| | [1. Two Sum](https://leetcode.com/problems/two-sum/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/TwoSum1.java) | Easy | | [2. Add Two Numbers](https://leetcode.com/problems/add-two-numbers/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/AddTwoNumbers2.java) | Medium | | [3. Longest Substring Without Repeating Characters](https://leetcode.com/problems/longest-substring-without-repeating-characters/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LongestSubstringWithoutRepeatingCharacters3.java) | Medium | | [4. Median of Two Sorted Arrays](https://leetcode.com/problems/median-of-two-sorted-arrays/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MedianOfTwoSortedArrays4.java) | Hard | | [5. Longest Palindromic Substring](https://leetcode.com/problems/longest-palindromic-substring/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LongestPalindromicSubstring5.java) | Medium | | [9. Palindrome Number](https://leetcode.com/problems/palindrome-number/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PalindromeNumber9.java) | Easy | | [8. String to Integer (atoi)](https://leetcode.com/problems/string-to-integer-atoi/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/StringToInteger8.java) | Medium | | [10. Regular Expression Matching](https://leetcode.com/problems/regular-expression-matching/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RegularExpressionMatching10.java) | Hard | | [11. Container With Most Water](https://leetcode.com/problems/container-with-most-water/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ContainerWithMostWater11.java) | Medium | | [12. Integer to Roman](https://leetcode.com/problems/integer-to-roman/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/IntegerToRoman12.java) | Medium | | [13. Roman to Integer](https://leetcode.com/problems/roman-to-integer/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RomanToInteger13.java) | Easy | | [14. Longest Common Prefix](https://leetcode.com/problems/longest-common-prefix/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LongestCommonPrefix14.java) | Easy | | [15. 3Sum](https://leetcode.com/problems/3sum/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ThreeSum15.java) | Medium | | [16. 3Sum Closest](https://leetcode.com/problems/3sum-closest/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ThreeSumClosest16.java) | Medium | | [17. Letter Combinations of a Phone Number](https://leetcode.com/problems/letter-combinations-of-a-phone-number/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LetterCombinationsOfAPhoneNumber17.java) | Medium | | [18. 4Sum](https://leetcode.com/problems/4sum/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FourSum18.java) | Medium | | [19. Remove Nth Node From End of List](https://leetcode.com/problems/remove-nth-node-from-end-of-list/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LetterCombinationsOfAPhoneNumber17.java) | Medium | | [20. Valid Parentheses](https://leetcode.com/problems/valid-parentheses/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ValidParentheses20.java) | Easy | | [21. Merge Two Sorted Lists](https://leetcode.com/problems/merge-two-sorted-lists/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MergeTwoSortedLists21.java) | Easy | | [22. Generate Parentheses](https://leetcode.com/problems/generate-parentheses/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/GenerateParentheses22.java) | Medium | | [23. Merge k Sorted Lists](https://leetcode.com/problems/merge-k-sorted-lists/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MergeKSortedLists23.java) | Hard | | [25. Reverse Nodes in k-Group](https://leetcode.com/problems/reverse-nodes-in-k-group/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ReverseNodesInKGroup25.java) | Hard | | [26. Remove Duplicates from Sorted Array](https://leetcode.com/problems/remove-duplicates-from-sorted-array/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RemoveDuplicatesFromSortedArray26.java) | Easy | | [28. Implement strStr()](https://leetcode.com/problems/implement-strstr/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ImplementStrStr28.java) | Easy | | [29. Divide Two Integers](https://leetcode.com/problems/divide-two-integers/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/DivideTwoIntegers29.java) | Easy | | [31. Next Permutation](https://leetcode.com/problems/next-permutation/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/NextPermutation31.java) | Medium | | [32. Longest Valid Parentheses](https://leetcode.com/problems/longest-valid-parentheses/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LongestValidParentheses32.java) | Hard | | [33. Search in Rotated Sorted Array](https://leetcode.com/problems/search-in-rotated-sorted-array/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SearchInRotatedSortedArray33.java) | Medium | | [34. Search for a Range](https://leetcode.com/problems/search-for-a-range/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SearchForARange34.java) | Medium | | [35. Search Insert Position](https://leetcode.com/problems/search-insert-position/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SearchInsertPosition35.java) | Easy | | [36. Valid Sudoku](https://leetcode.com/problems/valid-sudoku/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ValidSudoku36.java) | Medium | | [37. Sudoku Solver](https://leetcode.com/problems/sudoku-solver/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SudokuSolver37.java) | Hard | | [39. Combination Sum](https://leetcode.com/problems/combination-sum/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/CombinationSum39.java) | Medium | | [41. First Missing Positive](https://leetcode.com/problems/first-missing-positive/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FirstMissingPositive41.java) | Hard | | [42. Trapping Rain Water](https://leetcode.com/problems/trapping-rain-water/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/TrappingRainWater42.java) | Hard | | [44. Wildcard Matching](https://leetcode.com/problems/wildcard-matching/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/WildcardMatching44.java) | Hard | | [45. Jump Game II](https://leetcode.com/problems/jump-game-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/JumpGameII45.java) | Hard | | [46. Permutations](https://leetcode.com/problems/permutations/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/Permutations46.java) | Medium | | [47. Permutations II](https://leetcode.com/problems/permutations-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PermutationsII47.java) | Medium | | [48. Rotate Image](https://leetcode.com/problems/rotate-image/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RotateImage48.java) | Medium | | [49. Group Anagrams](https://leetcode.com/problems/group-anagrams/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/GroupAnagrams49.java) | Medium | | [50. Pow(x, n)](https://leetcode.com/problems/powx-n/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PowXN50.java) | Medium | | [51. N-Queens](https://leetcode.com/problems/n-queens/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/NQueens51.java) | Hard | | [52. N-Queens II](https://leetcode.com/problems/n-queens-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/NQueensII52.java) | Hard | | [53. Maximum Subarray](https://leetcode.com/problems/maximum-subarray/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MaximumSubarray53.java) | Easy | | [54. Spiral Matrix](https://leetcode.com/problems/spiral-matrix/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SpiralMatrix54.java) | Medium | | [55. Jump Game](https://leetcode.com/problems/jump-game/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/JumpGame55.java) | Medium | | [56. Merge Intervals](https://leetcode.com/problems/merge-intervals/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MergeIntervals56.java) | Medium | | [57. Insert Interval](https://leetcode.com/problems/insert-interval/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/InsertInterval57.java) | Hard | | [59. Spiral Matrix II](https://leetcode.com/problems/spiral-matrix-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SpiralMatrixII59.java) | Medium | | [60. Permutation Sequence](https://leetcode.com/problems/permutation-sequence/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PermutationSequence60.java) | Medium | | [61. Rotate List](https://leetcode.com/problems/rotate-list/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RotateList61.java) | Medium | | [62. Unique Paths](https://leetcode.com/problems/unique-paths/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/UniquePaths62.java) | Medium | | [63. Unique Paths II](https://leetcode.com/problems/unique-paths-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/UniquePathsII63.java) | Medium | | [64. Minimum Path Sum](https://leetcode.com/problems/minimum-path-sum/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MinimumPathSum64.java) | Medium | | [65. Valid Number](https://leetcode.com/problems/valid-number/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ValidNumber65.java) | Hard | | [66. Plus One](https://leetcode.com/problems/plus-one/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PlusOne66.java) | Easy | | [67. Add Binary](https://leetcode.com/problems/add-binary/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/AddBinary67.java) | Easy | | [68. Text Justification](https://leetcode.com/problems/text-justification/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/TextJustification68.java) | Hard | | [69. Sqrt(x)](https://leetcode.com/problems/sqrtx/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SqrtX69.java) | Easy | | [70. Climbing Stairs](https://leetcode.com/problems/climbing-stairs/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ClimbingStairs70.java) | Easy | | [71. Simplify Path](https://leetcode.com/problems/simplify-path/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SimplifyPath71.java) | Medium | | [72. Edit Distance](https://leetcode.com/problems/edit-distance/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/EditDistance72.java) | Hard | | [73. Set Matrix Zeroes](https://leetcode.com/problems/set-matrix-zeroes/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SetMatrixZeroes73.java) | Medium | | [74. Search a 2D Matrix](https://leetcode.com/problems/search-a-2d-matrix/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SearchA2DMatrix74.java) | Medium | | [75. Sort Colors](https://leetcode.com/problems/sort-colors/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SortColors75.java) | Medium | | [76. Minimum Window Substring](https://leetcode.com/problems/minimum-window-substring/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MinimumWindowSubstring76.java) | Hard | | [78. Subsets](https://leetcode.com/problems/subsets/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/Subsets78.java) | Medium | | [79. Word Search](https://leetcode.com/problems/word-search/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/WordSearch79.java) | Medium | | [80. Remove Duplicates from Sorted Array II](https://leetcode.com/problems/remove-duplicates-from-sorted-array-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RemoveDuplicatesFromSortedArrayII80.java) | Medium | | [81. Search in Rotated Sorted Array II](https://leetcode.com/problems/search-in-rotated-sorted-array-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SearchInRotatedSortedArrayII81.java) | Medium | | [82. Remove Duplicates from Sorted List II](https://leetcode.com/problems/remove-duplicates-from-sorted-list-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RemoveDuplicatesFromSortedListII82.java) | Medium | | [83. Remove Duplicates from Sorted List](https://leetcode.com/problems/remove-duplicates-from-sorted-list/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RemoveDuplicatesFromSortedList83.java) | Easy | | [84. Largest Rectangle in Histogram](https://leetcode.com/problems/largest-rectangle-in-histogram/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LargestRectangleInHistogram84.java) | Hard | | [85. Maximal Rectangle](https://leetcode.com/problems/maximal-rectangle/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LargestRectangleInHistogram84.java) | Hard | | [86. Partition List](https://leetcode.com/problems/partition-list/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PartitionList86.java) | Medium | | [88. Merge Sorted Array](https://leetcode.com/problems/merge-sorted-array/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MergeSortedArray88.java) | Easy | | [90. Subsets II](https://leetcode.com/problems/subsets-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SubsetsII90.java) | Medium | | [91. Decode Ways](https://leetcode.com/problems/decode-ways/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/DecodeWays91.java) | Medium | | [92. Reverse Linked List II](https://leetcode.com/problems/reverse-linked-list-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ReverseLinkedListII92.java) | Medium | | [93. Restore IP Addresses](https://leetcode.com/problems/restore-ip-addresses/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RestoreIPAddresses93.java) | Medium | | [94. Binary Tree Inorder Traversal](https://leetcode.com/problems/binary-tree-inorder-traversal/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BinaryTreeInorderTraversal94.java) | Medium | | [95. Unique Binary Search Trees II](https://leetcode.com/problems/unique-binary-search-trees-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/UniqueBinarySearchTreesII95.java) | Medium | | [96. Unique Binary Search Trees](https://leetcode.com/problems/unique-binary-search-trees/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/UniqueBinarySearchTrees96.java) | Medium | | [97. Interleaving String](https://leetcode.com/problems/interleaving-string/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/InterleavingString97.java) | Hard | | [98. Validate Binary Search Tree](https://leetcode.com/problems/validate-binary-search-tree/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ValidateBinarySearchTree98.java) | Medium | | [100. Same Tree](https://leetcode.com/problems/same-tree/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SameTree100.java) | Easy | | [101. Symmetric Tree](https://leetcode.com/problems/symmetric-tree/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SymmetricTree101.java) | Easy | | [102. Binary Tree Level Order Traversal](https://leetcode.com/problems/binary-tree-level-order-traversal/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BinaryTreeLevelOrderTraversal102.java) | Medium | | [103. Binary Tree Zigzag Level Order Traversal](https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BinaryTreeZigzagLevelOrderTraversal103.java) | Medium | | [104. Maximum Depth of Binary Tree](https://leetcode.com/problems/maximum-depth-of-binary-tree/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MaximumDepthOfBinaryTree104.java) | Easy | | [105. Construct Binary Tree from Preorder and Inorder Traversal](https://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ConstructBinaryTreeFromPreorderAndInorderTraversal105.java) | Medium | | [106. Construct Binary Tree from Inorder and Postorder Traversal](https://leetcode.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ConstructBinaryTreeFromInorderAndPostorderTraversal106.java) | Medium | | [107. Binary Tree Level Order Traversal II](https://leetcode.com/problems/binary-tree-level-order-traversal-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BinaryTreeLevelOrderTraversalII107.java) | Easy | | [108. Convert Sorted Array to Binary Search Tree](https://leetcode.com/problems/convert-sorted-array-to-binary-search-tree/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ConvertSortedArrayToBinarySearchTree108.java) | Easy | | [109. Convert Sorted List to Binary Search Tree](https://leetcode.com/problems/convert-sorted-list-to-binary-search-tree/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ConvertSortedListToBST109.java) | Medium | | [110. Balanced Binary Tree](https://leetcode.com/problems/balanced-binary-tree/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BalancedBinaryTree110.java) | Easy | | [111. Minimum Depth of Binary Tree](https://leetcode.com/problems/minimum-depth-of-binary-tree/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MinimumDepthOfBinaryTree111.java) | Easy | | [112. Path Sum](https://leetcode.com/problems/path-sum/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PathSum112.java) | Easy | | [113. Path Sum II](https://leetcode.com/problems/path-sum-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PathSumII113.java) | Medium | | [114. Flatten Binary Tree to Linked List](https://leetcode.com/problems/flatten-binary-tree-to-linked-list/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FlattenBinaryTreeToLinkedList114.java) | Medium | | [116. Populating Next Right Pointers in Each Node](https://leetcode.com/problems/populating-next-right-pointers-in-each-node/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PopulatingNextRightPointersInEachNode116.java) | Medium | | [117. Populating Next Right Pointers in Each Node II](https://leetcode.com/problems/populating-next-right-pointers-in-each-node-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PopulatingNextRightPointersInEachNodeII117.java) | Medium | | [119. Pascal's Triangle II](https://leetcode.com/problems/pascals-triangle-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PascalsTriangleII119.java) | Easy | | [120. Triangle](https://leetcode.com/problems/triangle/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/Triangle120.java) | Medium | | [121. Best Time to Buy and Sell Stock](https://leetcode.com/problems/best-time-to-buy-and-sell-stock/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BestTimeToBuyAndSellStock121.java) | Easy | | [122. Best Time to Buy and Sell Stock II](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BestTimeToBuyAndSellStockII122.java) | Easy | | [123. Best Time to Buy and Sell Stock III](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BestTimeToBuyAndSellStockIII123.java) | Hard | | [124. Binary Tree Maximum Path Sum](https://leetcode.com/problems/binary-tree-maximum-path-sum/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BinaryTreeMaximumPathSum124.java) | Hard | | [125. Valid Palindrome](https://leetcode.com/problems/valid-palindrome/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ValidPalindrome125.java) | Easy | | [126. Word Ladder II](https://leetcode.com/problems/word-ladder-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/WordLadderII126.java) | Hard | | [127. Word Ladder](https://leetcode.com/problems/word-ladder/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/WordLadder127.java) | Medium | | [128. Longest Consecutive Sequence](https://leetcode.com/problems/longest-consecutive-sequence/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LongestConsecutiveSequence128.java) | Hard | | [129. Sum Root to Leaf Numbers](https://leetcode.com/problems/sum-root-to-leaf-numbers/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SumRootToLeafNumbers129.java) | Medium | | [130. Surrounded Regions](https://leetcode.com/problems/surrounded-regions/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SumRootToLeafNumbers129.java) | Medium | | [131. Palindrome Partitioning](https://leetcode.com/problems/palindrome-partitioning/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PalindromePartitioning131.java) | Medium | | [133. Clone Graph](https://leetcode.com/problems/clone-graph/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/CloneGraph133.java) | Medium | | [136. Single Number](https://leetcode.com/problems/single-number/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SingleNumber136.java) | Easy | | [137. Single Number II](https://leetcode.com/problems/single-number-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SingleNumberII137.java) | Medium | | [138. Copy List with Random Pointer](https://leetcode.com/problems/copy-list-with-random-pointer/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/CopyListWithRandomPointer138.java) | Medium | | [139. Word Break](https://leetcode.com/problems/word-break/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/WordBreak139.java) | Medium | | [140. Word Break II](https://leetcode.com/problems/word-break-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/WordBreakII140.java) | Hard | | [141. Linked List Cycle](https://leetcode.com/problems/linked-list-cycle/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LinkedListCycle141.java) | Easy | | [142. Linked List Cycle II](https://leetcode.com/problems/linked-list-cycle-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LinkedListCycleII142.java) | Easy | | [143. Reorder List](https://leetcode.com/problems/reorder-list/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ReorderList143.java) | Medium | | [144. Binary Tree Preorder Traversal](https://leetcode.com/problems/binary-tree-preorder-traversal/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BinaryTreePreorderTraversal144.java) | Medium | | [146. LRU Cache](https://leetcode.com/problems/lru-cache/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LRUCache146.java) | Hard | | [147. Insertion Sort List](https://leetcode.com/problems/insertion-sort-list/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/InsertionSortList147.java) | Medium | | [148. Sort List](https://leetcode.com/problems/sort-list/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SortList148.java) | Medium | | [149. Max Points on a Line](https://leetcode.com/problems/max-points-on-a-line/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/InsertionSortList147.java) | Hard | | [150. Evaluate Reverse Polish Notation](https://leetcode.com/problems/evaluate-reverse-polish-notation/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/EvaluateReversePolishNotation150.java) | Medium | | [151. Reverse Words in a String](https://leetcode.com/problems/reverse-words-in-a-string/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ReverseWordsInAString151.java) | Medium | | [152. Maximum Product Subarray](https://leetcode.com/problems/maximum-product-subarray/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MaximumProductSubarray152.java) | Medium | | [153. Find Minimum in Rotated Sorted Array](https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FindMinimumInRotatedSortedArray153.java) | Medium | | [154. Find Minimum in Rotated Sorted Array II](https://leetcode.com/problems/find-minimum-in-rotated-sorted-array-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FindMinimumInRotatedSortedArrayII154.java) | Hard | | [155. Min Stack](https://leetcode.com/problems/min-stack/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MinStack.java) | Easy | | [157. Read N Characters Given Read4](https://leetcode.com/problems/read-n-characters-given-read4/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ReadNCharactersGivenReadFour157.java) | Easy | | [158. Read N Characters Given Read4 II - Call multiple times](https://leetcode.com/problems/read-n-characters-given-read4-ii-call-multiple-times/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ReadNCharactersGivenRead4IICallMultipleTimes158.java) | Hard | | [159. Longest Substring with At Most Two Distinct Characters](https://leetcode.com/problems/longest-substring-with-at-most-two-distinct-characters/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LongestSubstringWithAtMostTwoDistinctCharacters159.java) | Hard | | [160. Intersection of Two Linked Lists](https://leetcode.com/problems/intersection-of-two-linked-lists/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/IntersectionOfTwoLinkedLists160.java) | Easy | | [161. One Edit Distance](https://leetcode.com/problems/one-edit-distance/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/OneEditDistance161.java) | Medium | | [162. Find Peak Element](https://leetcode.com/problems/find-peak-element/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FindPeakElement162.java) | Medium | | [163. Missing Ranges](https://leetcode.com/problems/missing-ranges/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MissingRanges163.java) | Medium | | [165. Compare Version Numbers](https://leetcode.com/problems/compare-version-numbers/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/CompareVersionNumbers165.java) | Medium | | [166. Fraction to Recurring Decimal](https://leetcode.com/problems/fraction-to-recurring-decimal/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FractionToRecurringDecimal166.java) | Medium | | [167. Two Sum II - Input array is sorted](https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/TwoSumIIInputArrayIsSorted167.java) | Easy | | [169. Majority Element](https://leetcode.com/problems/majority-element/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MajorityElement169.java) | Easy | | [173. Binary Search Tree Iterator](https://leetcode.com/problems/binary-search-tree-iterator/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BinarySearchTreeIterator173.java) | Medium | | [179. Largest Number](https://leetcode.com/problems/largest-number/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LargestNumber179.java) | Medium | | [186. Reverse Words in a String II](https://leetcode.com/problems/reverse-words-in-a-string-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ReverseWordsInAStringII186.java) | Easy | | [187. Repeated DNA Sequences](https://leetcode.com/problems/repeated-dna-sequences/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RepeatedDNASequences187.java) | Medium | | [188. Best Time to Buy and Sell Stock IV](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BestTimeToBuyAndSellStockIV188.java) | Hard | | [189. Rotate Array](https://leetcode.com/problems/rotate-array/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RotateArray189.java) | Easy | | [198. House Robber](https://leetcode.com/problems/house-robber/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/HouseRobber198.java) | Easy | | [199. Binary Tree Right Side View](https://leetcode.com/problems/binary-tree-right-side-view/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BinaryTreeRightSideView199.java) | Medium | | [200. Number of Islands](https://leetcode.com/problems/number-of-islands/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/NumberOfIslands200.java) | Medium | | [201. Bitwise AND of Numbers Range](https://leetcode.com/problems/bitwise-and-of-numbers-range/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BitwiseANDOfNumbersRange201.java) | Medium | | [202. Happy Number](https://leetcode.com/problems/happy-number/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/HappyNumber202.java) | Easy | | [203. Remove Linked List Elements](https://leetcode.com/problems/remove-linked-list-elements/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RemoveLinkedListElements203.java) | Easy | | [204. Count Primes](https://leetcode.com/problems/count-primes/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/CountPrimes204.java) | Easy | | [205. Isomorphic Strings](https://leetcode.com/problems/isomorphic-strings/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/IsomorphicStrings205.java) | Easy | | [206. Reverse Linked List](https://leetcode.com/problems/reverse-linked-list/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ReverseLinkedList206.java) | Easy | | [207. Course Schedule](https://leetcode.com/problems/course-schedule/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/CourseSchedule207.java) | Medium | | [208. Implement Trie (Prefix Tree)](https://leetcode.com/problems/implement-trie-prefix-tree/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ImplementTriePrefixTree208.java) | Medium | | [209. Minimum Size Subarray Sum](https://leetcode.com/problems/minimum-size-subarray-sum/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MinimumSizeSubarraySum209.java) | Medium | | [210. Course Schedule II](https://leetcode.com/problems/course-schedule-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/CourseScheduleII210.java) | Medium | | [211. Add and Search Word - Data structure design](https://leetcode.com/problems/add-and-search-word-data-structure-design/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/WordDictionary.java) | Medium | | [212. Word Search II](https://leetcode.com/problems/word-search-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/WordSearchII212.java) | Hard | | [213. House Robber II](https://leetcode.com/problems/house-robber-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/HouseRobberII213.java) | Medium | | [214. Shortest Palindrome](https://leetcode.com/problems/shortest-palindrome/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ShortestPalindrome214.java) | Medium | | [215. Kth Largest Element in an Array](https://leetcode.com/problems/kth-largest-element-in-an-array/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/KthLargestElementInAnArray215.java) | Medium | | [216. Combination Sum III](https://leetcode.com/problems/combination-sum-iii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/CombinationSumIII216.java) | Medium | | [217. Contains Duplicate](https://leetcode.com/problems/contains-duplicate/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ContainsDuplicate217.java) | Easy | | [218. The Skyline Problem](https://leetcode.com/problems/the-skyline-problem/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/TheSkylineProblem218.java) | Hard | | [219. Contains Duplicate II](https://leetcode.com/problems/contains-duplicate-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ContainsDuplicatesII219.java) | Easy | | [220. Contains Duplicate III](https://leetcode.com/problems/contains-duplicate-iii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ContainsDuplicateIII220.java) | Medium | | [221. Maximal Square](https://leetcode.com/problems/maximal-square/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MaximalSquare221.java) | Medium | | [223. Rectangle Area](https://leetcode.com/problems/rectangle-area/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MaximalSquare221.java) | Medium | | [224. Basic Calculator](https://leetcode.com/problems/basic-calculator/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BasicCalculator224.java) | Hard | | [225. Implement Stack using Queues](https://leetcode.com/problems/implement-stack-using-queues/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ImplementStackUsingQueues225.java) | Easy | | [226. Invert Binary Tree](https://leetcode.com/problems/invert-binary-tree/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/InvertBinaryTree226.java) | Easy | | [227. Basic Calculator II](https://leetcode.com/problems/basic-calculator-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BasicCalculatorII227.java) | Medium | | [228. Summary Ranges](https://leetcode.com/problems/summary-ranges/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SummaryRanges228.java) | Medium | | [230. Kth Smallest Element in a BST](https://leetcode.com/problems/kth-smallest-element-in-a-bst/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/KthSmallestElementInABST230.java) | Medium | | [231. Power of Two](https://leetcode.com/problems/power-of-two/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PowerOfTwo231.java) | Easy | | [232. Implement Queue using Stacks](https://leetcode.com/problems/implement-queue-using-stacks/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ImplementQueueUsingStacks232.java) | Easy | | [233. Number of Digit One](https://leetcode.com/problems/number-of-digit-one/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/NumberOfDigitOne233.java) | Hard | | [234. Palindrome Linked List](https://leetcode.com/problems/palindrome-linked-list/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PalindromeLinkedList234.java) | Easy | | [235. Lowest Common Ancestor of a Binary Search Tree](https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LowestCommonAncestorOfABinarySearchTree235.java) | Easy | | [236. Lowest Common Ancestor of a Binary Tree](https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LowestCommonAncestorOfABinaryTree236.java) | Medium | | [237. Delete Node in a Linked List](https://leetcode.com/problems/delete-node-in-a-linked-list/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/DeleteNodeInALinkedList237.java) | Easy | | [238. Product of Array Except Self](https://leetcode.com/problems/product-of-array-except-self/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ProductOfArrayExceptSelf238.java) | Medium | | [239. Sliding Window Maximum](https://leetcode.com/problems/sliding-window-maximum/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SlidingWindowMaximum239.java) | Hard | | [240. Search a 2D Matrix II](https://leetcode.com/problems/search-a-2d-matrix-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SearchA2DMatrixII240.java) | Medium | | [241. Different Ways to Add Parentheses](https://leetcode.com/problems/different-ways-to-add-parentheses/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/DifferentWaysToAddParentheses241.java) | Medium | | [242. Valid Anagram](https://leetcode.com/problems/valid-anagram/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ValidAnagram242.java) | Easy | | [243. Shortest Word Distance](https://leetcode.com/problems/shortest-word-distance/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ShortestWordDistance243.java) | Easy | | [246. Strobogrammatic Number](https://leetcode.com/problems/strobogrammatic-number/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/StrobogrammaticNumber246.java) | Easy | | [247. Strobogrammatic Number II](https://leetcode.com/problems/strobogrammatic-number-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/StrobogrammaticNumberII247.java) | Medium | | [249. Group Shifted Strings](https://leetcode.com/problems/group-shifted-strings/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/GroupShiftedStrings249.java) | Medium | | [251. Flatten 2D Vector](https://leetcode.com/problems/flatten-2d-vector/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/Flatten2DVector251.java) | Medium | | [252. Meeting Rooms](https://leetcode.com/problems/meeting-rooms/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MeetingRooms252.java) | Easy | | [253. Meeting Rooms II](https://leetcode.com/problems/meeting-rooms-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MeetingRoomsII253.java) | Medium | | [255. Verify Preorder Sequence in Binary Search Tree](https://leetcode.com/problems/verify-preorder-sequence-in-binary-search-tree/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/VerifyPreorderSequenceInBinarySearchTree255.java) | Medium | | [256. Paint House](https://leetcode.com/problems/paint-house/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PaintHouse256.java) | Easy | | [257. Binary Tree Paths](https://leetcode.com/problems/binary-tree-paths/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BinaryTreePaths257.java) | Easy | | [259. 3Sum Smaller](https://leetcode.com/problems/3sum-smaller/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ThreeSumSmaller259.java) | Medium | | [261. Graph Valid Tree](https://leetcode.com/problems/graph-valid-tree/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/GraphValidTree261.java) | Medium | | [263. Ugly Number](https://leetcode.com/problems/ugly-number/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/UglyNumber263.java) | Easy | | [264. Ugly Number II](https://leetcode.com/problems/ugly-number-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/UglyNumberII264.java) | Medium | | [265. Paint House II](https://leetcode.com/problems/paint-house-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PaintHouseII265.java) | Hard | | [267. Palindrome Permutation II](https://leetcode.com/problems/palindrome-permutation-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PalindromePermutationII267.java) | Medium | | [268. Missing Number](https://leetcode.com/problems/missing-number/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MissingNumber268.java) | Easy | | [269. Alien Dictionary](https://leetcode.com/problems/alien-dictionary/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/AlienDictionary269.java) | Hard | | [270. Closest Binary Search Tree Value](https://leetcode.com/problems/closest-binary-search-tree-value/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ClosestBinarySearchTreeValue270.java) | Easy | | [271. Encode and Decode Strings](https://leetcode.com/problems/encode-and-decode-strings/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/EncodeAndDecodeStrings271.java) | Medium | | [272. Closest Binary Search Tree Value II](https://leetcode.com/problems/closest-binary-search-tree-value-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ClosestBinarySearchTreeValueII272.java) | Medium | | [273. Integer to English Words](https://leetcode.com/problems/integer-to-english-words/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/IntegerToEnglishWords273.java) | Hard | | [274. H-Index](https://leetcode.com/problems/h-index/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/IntegerToEnglishWords273.java) | Medium | | [276. Paint Fence](https://leetcode.com/problems/paint-fence/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PaintFence276.java) | Easy | | [277. Find the Celebrity](https://leetcode.com/problems/find-the-celebrity/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FindTheCelebrity277.java) | Medium | | [278. First Bad Version](https://leetcode.com/problems/first-bad-version/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FirstBadVersion278.java) | Easy | | [279. Perfect Squares](https://leetcode.com/problems/perfect-squares/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PerfectSquares279.java) | Medium | | [280. Wiggle Sort](https://leetcode.com/problems/wiggle-sort/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/WiggleSort280.java) | Medium | | [281. Zigzag Iterator](https://leetcode.com/problems/zigzag-iterator/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ZigzagIterator281.java) | Medium | | [282. Expression Add Operators](https://leetcode.com/problems/expression-add-operators/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ExpressionAddOperators282.java) | Hard | | [283. Move Zeroes](https://leetcode.com/problems/move-zeroes/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MoveZeroes283.java) | Easy | | [284. Peeking Iterator](https://leetcode.com/problems/peeking-iterator/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PeekingIterator284.java) | Medium | | [285. Inorder Successor in BST](https://leetcode.com/problems/inorder-successor-in-bst/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/InorderSuccessorInBST285.java) | Medium | | [286. Walls and Gates](https://leetcode.com/problems/walls-and-gates/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/WallsAndGates286.java) | Medium | | [287. Find the Duplicate Number](https://leetcode.com/problems/find-the-duplicate-number/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FindTheDuplicateNumber287.java) | Medium | | [288. Unique Word Abbreviation](https://leetcode.com/problems/unique-word-abbreviation/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/UniqueWordAbbreviation288.java) | Medium | | [289. Game of Life](https://leetcode.com/problems/game-of-life/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/GameOfLife289.java) | Medium | | [290. Word Pattern](https://leetcode.com/problems/word-pattern/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/WordPattern290.java) | Easy | | [291. Word Pattern II](https://leetcode.com/problems/word-pattern-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/WordPatternII291.java) | Hard | | [293. Flip Game](https://leetcode.com/problems/flip-game/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FlipGame293.java) | Easy | | [295. Find Median from Data Stream](https://leetcode.com/problems/find-median-from-data-stream/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FindMedianFromDataStream295.java) | Hard | | [296. Best Meeting Point](https://leetcode.com/problems/best-meeting-point/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BestMeetingPoint296.java) | Hard | | [297. Serialize and Deserialize Binary Tree](https://leetcode.com/problems/serialize-and-deserialize-binary-tree/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SerializeAndDeserializeBinaryTree297.java) | Hard | | [298. Binary Tree Longest Consecutive Sequence](https://leetcode.com/problems/binary-tree-longest-consecutive-sequence/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BinaryTreeLongestConsecutiveSequence298.java) | Medium | | [299. Bulls and Cows](https://leetcode.com/problems/bulls-and-cows/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BullsAndCows299.java) | Medium | | [300. Longest Increasing Subsequence](https://leetcode.com/problems/longest-increasing-subsequence/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LongestIncreasingSubsequence300.java) | Medium | | [301. Remove Invalid Parentheses](https://leetcode.com/problems/remove-invalid-parentheses/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RemoveInvalidParentheses301.java) | Hard | | [303. Range Sum Query - Immutable](https://leetcode.com/problems/range-sum-query-immutable/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RangeSumQueryImmutable303.java) | Easy | | [304. Range Sum Query 2D - Immutable](https://leetcode.com/problems/range-sum-query-2d-immutable/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RangeSumQuery2DImmutable304.java) | Medium | | [305. Number of Islands II](https://leetcode.com/problems/number-of-islands-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/NumberOfIslandsII305.java) | Hard | | [307. Range Sum Query - Mutable](https://leetcode.com/problems/range-sum-query-mutable/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RangeSumQueryMutable307.java) | Medium | | [308. Range Sum Query 2D - Mutable](https://leetcode.com/problems/range-sum-query-2d-mutable/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RangeSumQuery2DMutable308.java) | Hard | | [309. Best Time to Buy and Sell Stock with Cooldown](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BestTimeToBuyAndSellStockWithCooldown309.java) | Medium | | [310. Minimum Height Trees](https://leetcode.com/problems/minimum-height-trees/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MinimumHeightTrees310.java) | Medium | | [311. Sparse Matrix Multiplication](https://leetcode.com/problems/sparse-matrix-multiplication/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SparseMatrixMultiplication311.java) | Medium | | [312. Burst Balloons](https://leetcode.com/problems/burst-balloons/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BurstBalloons312.java) | Hard | | [313. Super Ugly Number](https://leetcode.com/problems/super-ugly-number/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SuperUglyNumber313.java) | Medium | | [314. Binary Tree Vertical Order Traversal](https://leetcode.com/problems/binary-tree-vertical-order-traversal/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BinaryTreeVerticalOrderTraversal314.java) | Medium | | [315. Count of Smaller Numbers After Self](https://leetcode.com/problems/count-of-smaller-numbers-after-self/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/CountOfSmallerNumbersAfterSelf315.java) | Hard | | [317. Shortest Distance from All Buildings](https://leetcode.com/problems/shortest-distance-from-all-buildings/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ShortestDistanceFromAllBuildings317.java) | Hard | | [318. Maximum Product of Word Lengths](https://leetcode.com/problems/maximum-product-of-word-lengths/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MaximumProductOfWordLengths318.java) | Medium | | [320. Generalized Abbreviation](https://leetcode.com/problems/generalized-abbreviation/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/GeneralizedAbbreviation320.java) | Medium | | [322. Coin Change](https://leetcode.com/problems/coin-change/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/CountOfSmallerNumbersAfterSelf315.java) | Medium | | [323. Number of Connected Components in an Undirected Graph](https://leetcode.com/problems/number-of-connected-components-in-an-undirected-graph/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/NumberOfConnectedComponentsInAnUndirectedGraph323.java) | Medium | | [324. Wiggle Sort II](https://leetcode.com/problems/wiggle-sort-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/WiggleSortII324.java) | Medium | | [325. Maximum Size Subarray Sum Equals k](https://leetcode.com/problems/maximum-size-subarray-sum-equals-k/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MaximumSizeSubarraySumEqualsK325.java) | Medium | | [327. Count of Range Sum](https://leetcode.com/problems/count-of-range-sum/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/CountOfRangeSum327.java) | Hard | | [328. Odd Even Linked List](https://leetcode.com/problems/odd-even-linked-list/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/OddEvenLinkedList328.java) | Medium | | [332. Reconstruct Itinerary](https://leetcode.com/problems/reconstruct-itinerary/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ReconstructItinerary332.java) | Medium | | [333. Largest BST Subtree](https://leetcode.com/problems/largest-bst-subtree/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LargestBSTSubtree333.java) | Medium | | [334. Increasing Triplet Subsequence](https://leetcode.com/problems/increasing-triplet-subsequence/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/IncreasingTripletSubsequence334.java) | Medium | | [336. Palindrome Pairs](https://leetcode.com/problems/palindrome-pairs/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PalindromePairs336.java) | Hard | | [337. House Robber III](https://leetcode.com/problems/house-robber-iii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/HouseRobberIII337.java) | Medium | | [338. Counting Bits](https://leetcode.com/problems/counting-bits/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/CountingBits338.java) | Medium | | [339. Nested List Weight Sum](https://leetcode.com/problems/nested-list-weight-sum/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/NestedListWeightSum339.java) | Easy | | [340. Longest Substring with At Most K Distinct Characters](https://leetcode.com/problems/longest-substring-with-at-most-k-distinct-characters/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LongestSubstringWithAtMostKDistinctCharacters340.java) | Hard | | [341. Flatten Nested List Iterator](https://leetcode.com/problems/flatten-nested-list-iterator/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/NestedIterator.java) | Medium | | [343. Integer Break](https://leetcode.com/problems/integer-break/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/IntegerBreak343.java) | Medium | | [344. Reverse String](https://leetcode.com/problems/reverse-string/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ReverseString344.java) | Easy | | [345. Reverse Vowels of a String](https://leetcode.com/problems/reverse-vowels-of-a-string/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ReverseVowelsOfAString345.java) | Easy | | [346. Moving Average from Data Stream](https://leetcode.com/problems/moving-average-from-data-stream/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MovingAverageFromDataStream346.java) | Easy | | [347. Top K Frequent Elements](https://leetcode.com/problems/top-k-frequent-elements/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/TopKFrequentElements347.java) | Medium | | [348. Design Tic-Tac-Toe](https://leetcode.com/problems/design-tic-tac-toe/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/DesignTicTacToe348.java) | Medium | | [349. Intersection of Two Arrays](https://leetcode.com/problems/intersection-of-two-arrays/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/IntersectionOfTwoArrays349.java) | Easy | | [350. Intersection of Two Arrays II](https://leetcode.com/problems/intersection-of-two-arrays-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/IntersectionOfTwoArraysII350.java) | Easy | | [351. Android Unlock Patterns](https://leetcode.com/problems/android-unlock-patterns/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/AndroidUnlockPatterns351.java) | Medium | | [352. Data Stream as Disjoint Intervals](https://leetcode.com/problems/data-stream-as-disjoint-intervals/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/DataStreamAsDisjointIntervals352.java) | Hard | | [353. Design Snake Game](https://leetcode.com/problems/design-snake-game/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/DesignSnakeGame353.java) | Medium | | [354. Russian Doll Envelopes](https://leetcode.com/problems/russian-doll-envelopes/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RussianDollEnvelopes354.java) | Hard | | [355. Design Twitter](https://leetcode.com/problems/design-twitter/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/DesignTwitter355.java) | Medium | | [357. Count Numbers with Unique Digits](https://leetcode.com/problems/count-numbers-with-unique-digits/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/CountNumbersWithUniqueDigits357.java) | Medium | | [358. Rearrange String k Distance Apart](https://leetcode.com/problems/rearrange-string-k-distance-apart/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RearrangeStringKDistanceApart358.java) | Hard | | [359. Logger Rate Limiter](https://leetcode.com/problems/logger-rate-limiter/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LoggerRateLimiter359.java) | Easy | | [360. Sort Transformed Array](https://leetcode.com/problems/sort-transformed-array/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SortTransformedArray360.java) | Medium | | [361. Bomb Enemy](https://leetcode.com/problems/bomb-enemy/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BombEnemy361.java) | Medium | | [362. Design Hit Counter](https://leetcode.com/problems/design-hit-counter/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/DesignHitCounter362.java) | Medium | | [363. Max Sum of Rectangle No Larger Than K](https://leetcode.com/problems/max-sum-of-rectangle-no-larger-than-k/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MaxSumOfRectangleNoLargerThanK363.java) | Hard | | [365. Water and Jug Problem](https://leetcode.com/problems/water-and-jug-problem/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/WaterAndJugProblem365.java) | Medium | | [368. Largest Divisible Subset](https://leetcode.com/problems/largest-divisible-subset/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LargestDivisibleSubset368.java) | Medium | | [369. Plus One Linked List](https://leetcode.com/problems/plus-one-linked-list/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PlusOneLinkedList369.java) | Medium | | [370. Range Addition](https://leetcode.com/problems/range-addition/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RangeAddition370.java) | Medium | | [373. Find K Pairs with Smallest Sums](https://leetcode.com/problems/find-k-pairs-with-smallest-sums/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FindKPairsWithSmallestSums373.java) | Medium | | [375. Guess Number Higher or Lower II](https://leetcode.com/problems/guess-number-higher-or-lower-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/GuessNumberHigherOrLowerII375.java) | Medium | | [377. Combination Sum IV](https://leetcode.com/problems/combination-sum-iv/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/CombinationSumIV377.java) | Medium | | [378. Kth Smallest Element in a Sorted Matrix](https://leetcode.com/problems/kth-smallest-element-in-a-sorted-matrix/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/KthSmallestElementInASortedMatrix378.java) | Medium | | [380. Insert Delete GetRandom O(1)](https://leetcode.com/problems/insert-delete-getrandom-o1/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/InsertDeleteGetRandomOOne380.java) | Medium | | [382. Linked List Random Node](https://leetcode.com/problems/linked-list-random-node/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LinkedListRandomNode382.java) | Medium | | [383. Ransom Note](https://leetcode.com/problems/ransom-note/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RansomNote383.java) | Easy | | [384. Shuffle an Array](https://leetcode.com/problems/shuffle-an-array/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ShuffleAnArray384.java) | Medium | | [386. Lexicographical Numbers](https://leetcode.com/problems/lexicographical-numbers/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LexicographicalNumbers386.java) | Medium | | [387. First Unique Character in a String](https://leetcode.com/problems/first-unique-character-in-a-string/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FirstUniqueCharacterInAString387.java) | Easy | | [388. Longest Absolute File Path](https://leetcode.com/problems/longest-absolute-file-path/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LongestAbsoluteFilePath388.java) | Medium | | [392. Is Subsequence](https://leetcode.com/problems/is-subsequence/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/IsSubsequence392.java) | Medium | | [393. UTF-8 Validation](https://leetcode.com/problems/utf-8-validation/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/UTF8Validation393.java) | Medium | | [394. Decode String](https://leetcode.com/problems/decode-string/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/DecodeString394.java) | Medium | | [396. Rotate Function](https://leetcode.com/problems/rotate-function/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RotateFunction396.java) | Medium | | [399. Evaluate Division](https://leetcode.com/problems/evaluate-division/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/EvaluateDivision399.java) | Medium | | [403. Frog Jump](https://leetcode.com/problems/frog-jump/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FrogJump403.java) | Hard | | [405. Convert a Number to Hexadecimal](https://leetcode.com/problems/convert-a-number-to-hexadecimal/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ConvertANumberToHexadecimal405.java) | Easy | | [406. Queue Reconstruction by Height](https://leetcode.com/problems/queue-reconstruction-by-height/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/QueueReconstructionByHeight406.java) | Medium | | [407. Trapping Rain Water II](https://leetcode.com/problems/trapping-rain-water-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/TrappingRainWaterII407.java) | Medium | | [408. Valid Word Abbreviation](https://leetcode.com/problems/valid-word-abbreviation/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ValidWordAbbreviation408.java) | Easy | | [409. Longest Palindrome](https://leetcode.com/problems/longest-palindrome/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LongestPalindrome409.java) | Easy | | [410. Split Array Largest Sum](https://leetcode.com/problems/split-array-largest-sum/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SplitArrayLargestSum410.java) | Hard | | [412. Fizz Buzz](https://leetcode.com/problems/fizz-buzz/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FizzBuzz412.java) | Easy | | [414. Third Maximum Number](https://leetcode.com/problems/third-maximum-number/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ThirdMaximumNumber414.java) | Easy | | [415. Add Strings](https://leetcode.com/problems/add-strings/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/AddStrings415.java) | Easy | | [416. Partition Equal Subset Sum](https://leetcode.com/problems/partition-equal-subset-sum/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PartitionEqualSubsetSum416.java) | Medium | | [417. Pacific Atlantic Water Flow](https://leetcode.com/problems/pacific-atlantic-water-flow/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PacificAtlanticWaterFlow417.java) | Medium | | [418. Sentence Screen Fitting](https://leetcode.com/problems/sentence-screen-fitting/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SentenceScreenFitting418.java) | Medium | | [421. Maximum XOR of Two Numbers in an Array](https://leetcode.com/problems/maximum-xor-of-two-numbers-in-an-array/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MaximumXOROfTwoNumbersInAnArray421.java) | Medium | | [423. Reconstruct Original Digits from English](https://leetcode.com/problems/reconstruct-original-digits-from-english/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ReconstructOriginalDigitsFromEnglish423.java) | Medium | | [424. Longest Repeating Character Replacement](https://leetcode.com/problems/longest-repeating-character-replacement/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LongestRepeatingCharacterReplacement424.java) | Medium | | [425. Word Squares](https://leetcode.com/problems/word-squares/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/WordSquares425.java) | Hard | | [427. Construct Quad Tree](https://leetcode.com/problems/construct-quad-tree/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ConstructQuadTree427.java) | Easy | | [429. N-ary Tree Level Order Traversal](https://leetcode.com/problems/n-ary-tree-level-order-traversal/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/NaryTreeLevelOrderTraversal429.java) | Easy | | [432. All O`one Data Structure](https://leetcode.com/problems/all-oone-data-structure/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/AllOOneDataStructure432.java) | Hard | | [433. Minimum Genetic Mutation](https://leetcode.com/problems/minimum-genetic-mutation/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MinimumGeneticMutation433.java) | Medium | | [435. Non-overlapping Intervals](https://leetcode.com/problems/non-overlapping-intervals/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/NonOverlappingIntervals435.java) | Medium | | [437. Path Sum III](https://leetcode.com/problems/path-sum-iii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PathSumIII437.java) | Easy | | [438. Find All Anagrams in a String](https://leetcode.com/problems/find-all-anagrams-in-a-string/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FindAllAnagramsInAString438.java) | Easy | | [443. String Compression](https://leetcode.com/problems/string-compression/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/StringCompression443.java) | Easy | | [445. Add Two Numbers II](https://leetcode.com/problems/add-two-numbers-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/AddTwoNumbersII445.java) | Medium | | [448. Find All Numbers Disappeared in an Array](https://leetcode.com/problems/find-all-numbers-disappeared-in-an-array/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FindAllNumbersDisappearedInAnArray448.java) | Easy | | [449. Serialize and Deserialize BST](https://leetcode.com/problems/serialize-and-deserialize-bst/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SerializeAndDeserializeBST449.java) | Medium | | [450. Delete Node in a BST](https://leetcode.com/problems/delete-node-in-a-bst/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/DeleteNodeInABST450.java) | Medium | | [454. 4Sum II](https://leetcode.com/problems/4sum-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FourSumII454.java) | Medium | | [451. Sort Characters By Frequency](https://leetcode.com/problems/sort-characters-by-frequency/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SortCharactersByFrequency451.java) | Medium | | [459. Repeated Substring Pattern](https://leetcode.com/problems/repeated-substring-pattern/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RepeatedSubstringPattern459.java) | Easy | | [460. LFU Cache](https://leetcode.com/problems/lfu-cache/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LFUCache460.java) | Hard | | [462. Minimum Moves to Equal Array Elements II](https://leetcode.com/problems/minimum-moves-to-equal-array-elements-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MinimumMovesToEqualArrayElementsII462.java) | Medium | | [463. Island Perimeter](https://leetcode.com/problems/island-perimeter/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/IslandPerimeter463.java) | Easy | | [464. Can I Win](https://leetcode.com/problems/can-i-win/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/CanIWin464.java) | Medium | | [465. Optimal Account Balancing](https://leetcode.com/problems/optimal-account-balancing/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/OptimalAccountBalancing465.java) | Hard | | [472. Concatenated Words](https://leetcode.com/problems/concatenated-words/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ConcatenatedWords472.java) | Hard | | [473. Matchsticks to Square](https://leetcode.com/problems/matchsticks-to-square/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MatchsticksToSquare473.java) | Medium | | [474. Ones and Zeroes](https://leetcode.com/problems/ones-and-zeroes/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/OnesAndZeroes474.java) | Medium | | [477. Total Hamming Distance](https://leetcode.com/problems/total-hamming-distance) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/TotalHammingDistance477.java) | Medium | | [480. Sliding Window Median](https://leetcode.com/problems/sliding-window-median/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SlidingWindowMedian480.java) | Hard | | [481. Magical String](https://leetcode.com/problems/magical-string/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MagicalString481.java) | Medium | | [482. License Key Formatting](https://leetcode.com/problems/license-key-formatting/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LicenseKeyFormatting482.java) | Easy | | [485. Max Consecutive Ones](https://leetcode.com/problems/max-consecutive-ones/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MaxConsecutiveOnes485.java) | Easy | | [486. Predict the Winner](https://leetcode.com/problems/predict-the-winner/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PredictTheWinner486.java) | Medium | | [487. Max Consecutive Ones II](https://leetcode.com/problems/max-consecutive-ones-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MaxConsecutiveOnesII487.java) | Medium | | [490. The Maze](https://leetcode.com/problems/the-maze/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/TheMaze490.java) | Medium | | [491. Increasing Subsequences](https://leetcode.com/problems/increasing-subsequences/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/IncreasingSubsequences491.java) | Medium | | [494. Target Sum](https://leetcode.com/problems/target-sum/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/TargetSum494.java) | Medium | | [496. Next Greater Element I](https://leetcode.com/problems/next-greater-element-i/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/NextGreaterElementI496.java) | Easy | | [498. Diagonal Traverse](https://leetcode.com/problems/diagonal-traverse/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/DiagonalTraverse498.java) | Medium | | [499. The Maze III](https://leetcode.com/problems/the-maze-iii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/TheMazeIII499.java) | Hard | | [503. Next Greater Element II](https://leetcode.com/problems/next-greater-element-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/NextGreaterElementII503.java) | Medium | | [505. The Maze II](https://leetcode.com/problems/the-maze-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/TheMazeII505.java) | Hard | | [508. Most Frequent Subtree Sum](https://leetcode.com/problems/most-frequent-subtree-sum/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MostFrequentSubtreeSum508.java) | Medium | | [513. Find Bottom Left Tree Value](https://leetcode.com/problems/find-bottom-left-tree-value/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FindBottomLeftTreeValue513.java) | Medium | | [515. Find Largest Value in Each Tree Row](https://leetcode.com/problems/find-largest-value-in-each-tree-row/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FindLargestValueInEachTreeRow515.java) | Medium | | [516. Longest Palindromic Subsequence](https://leetcode.com/problems/longest-palindromic-subsequence/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LongestPalindromicSubsequence516.java) | Medium | | [518. Coin Change 2](https://leetcode.com/problems/coin-change-2/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/CoinChangeII518.java) | Medium | | [519. Random Flip Matrix](https://leetcode.com/problems/random-flip-matrix/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RandomFlipMatrix519.java) | Medium | | [523. Continuous Subarray Sum](https://leetcode.com/problems/continuous-subarray-sum/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ContinuousSubarraySum523.java) | Medium | | [525. Contiguous Array](https://leetcode.com/problems/contiguous-array/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ContiguousArray525.java) | Medium | | [527. Word Abbreviation](https://leetcode.com/problems/word-abbreviation/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/WordAbbreviation527.java) | Hard | | [529. Minesweeper](https://leetcode.com/problems/minesweeper/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/Minesweeper529.java) | Medium | | [530. Minimum Absolute Difference in BST](https://leetcode.com/problems/minimum-absolute-difference-in-bst/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MinimumAbsoluteDifferenceInBST530.java) | Easy | | [531. Lonely Pixel I](https://leetcode.com/problems/lonely-pixel-i/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LonelyPixelI531.java) | Medium | | [535. Encode and Decode TinyURL](https://leetcode.com/problems/encode-and-decode-tinyurl/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/EncodeAndDecodeTinyURL535.java) | Medium | | [536. Construct Binary Tree from String](https://leetcode.com/problems/construct-binary-tree-from-string/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ConstructBinaryTreeFromString536.java) | Medium | | [538. Convert BST to Greater Tree](https://leetcode.com/problems/convert-bst-to-greater-tree/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ConvertBSTToGreaterTree538.java) | Easy | | [540. Single Element in a Sorted Array](https://leetcode.com/problems/single-element-in-a-sorted-array/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SingleElementInASortedArray540.java) | Medium | | [541. Reverse String II](https://leetcode.com/problems/reverse-string-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ReverseStringII541.java) | Easy | | [542. 01 Matrix](https://leetcode.com/problems/01-matrix/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ZeroOneMatrix542.java) | Medium | | [543. Diameter of Binary Tree](https://leetcode.com/problems/diameter-of-binary-tree/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/DiameterOfBinaryTree543.java) | Easy | | [544. Output Contest Matches](https://leetcode.com/problems/output-contest-matches/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/OutputContestMatches544.java) | Medium | | [545. Boundary of Binary Tree](https://leetcode.com/problems/boundary-of-binary-tree/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BoundaryOfBinaryTree545.java) | Medium | | [547. Friend Circles](https://leetcode.com/problems/friend-circles/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FriendCircles547.java) | Medium | | [554. Brick Wall](https://leetcode.com/problems/brick-wall/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BrickWall554.java) | Medium | | [556. Next Greater Element III](https://leetcode.com/problems/next-greater-element-iii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/NextGreaterElementIII556.java) | Medium | | [557. Reverse Words in a String III](https://leetcode.com/problems/reverse-words-in-a-string-iii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ReverseWordsInAStringIII557.java) | Easy | | [558. Quad Tree Intersection](https://leetcode.com/problems/quad-tree-intersection/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/QuadTreeIntersection558.java) | Easy | | [560. Subarray Sum Equals K](https://leetcode.com/problems/subarray-sum-equals-k/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SubarraySumEqualsK560.java) | Medium | | [567. Permutation in String](https://leetcode.com/problems/permutation-in-string/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PermutationInString567.java) | Easy | | [568. Maximum Vacation Days](https://leetcode.com/problems/maximum-vacation-days/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MaximumVacationDays568.java) | Hard | | [572. Subtree of Another Tree](https://leetcode.com/problems/subtree-of-another-tree/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SubtreeOfAnotherTree572.java) | Easy | | [582. Kill Process](https://leetcode.com/problems/kill-process/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/KillProcess582.java) | Medium | | [588. Design In-Memory File System](https://leetcode.com/problems/design-in-memory-file-system/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/DesignInMemoryFileSystem588.java) | Hard | | [590. N-ary Tree Postorder Traversal](https://leetcode.com/problems/n-ary-tree-postorder-traversal/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/NaryTreePostorderTraversal590.java) | Easy | | [594. Longest Harmonious Subsequence](https://leetcode.com/problems/longest-harmonious-subsequence/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LongestHarmoniousSubsequence594.java) | Easy | | [604. Design Compressed String Iterator](https://leetcode.com/problems/design-compressed-string-iterator/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/DesignCompressedStringIterator604.java) | Easy | | [611. Valid Triangle Number](https://leetcode.com/problems/valid-triangle-number/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ValidTriangleNumber611.java) | Medium | | [616. Add Bold Tag in String](https://leetcode.com/problems/add-bold-tag-in-string/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/AddBoldTagInString616.java) | Medium | | [621. Task Scheduler](https://leetcode.com/problems/task-scheduler/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/TaskScheduler621.java) | Medium | | [622. Design Circular Queue](https://leetcode.com/problems/design-circular-queue/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/DesignCircularQueue622.java) | Medium | | [623. Add One Row to Tree](https://leetcode.com/problems/add-one-row-to-tree/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/AddOneRowToTree623.java) | Medium | | [628. Maximum Product of Three Numbers](https://leetcode.com/problems/maximum-product-of-three-numbers/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MaximumProductOfThreeNumbers628.java) | Easy | | [632. Smallest Range](https://leetcode.com/problems/smallest-range/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SmallestRange632.java) | Hard | | [633. Sum of Square Numbers](https://leetcode.com/problems/sum-of-square-numbers/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SumOfSquareNumbers633.java) | Easy | | [635. Design Log Storage System](https://leetcode.com/problems/design-log-storage-system/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/DesignLogStorageSystem635.java) | Hard | | [636. Exclusive Time of Functions](https://leetcode.com/problems/exclusive-time-of-functions/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ExclusiveTimeOfFunctions636.java) | Medium | | [637. Average of Levels in Binary Tree](https://leetcode.com/problems/average-of-levels-in-binary-tree/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/AverageOfLevelsInBinaryTree637.java) | Easy | | [639. Decode Ways II](https://leetcode.com/problems/decode-ways-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/DecodeWaysII639.java) | Hard | | [640. Solve the Equation](https://leetcode.com/problems/solve-the-equation/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SolveTheEquation640.java) | Medium | | [641. Design Circular Deque](https://leetcode.com/problems/design-circular-deque/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/DesignCircularDeque641.java) | Medium | | [642. Design Search Autocomplete System](https://leetcode.com/problems/design-search-autocomplete-system/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/DesignSearchAutocompleteSystem642.java) | Hard | | [643. Maximum Average Subarray I](https://leetcode.com/problems/maximum-average-subarray-i/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MaximumAverageSubarrayI643.java) | Easy | | [646. Maximum Length of Pair Chain](https://leetcode.com/problems/maximum-length-of-pair-chain/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MaximumLengthOfPairChain646.java) | Medium | | [647. Palindromic Substrings](https://leetcode.com/problems/palindromic-substrings/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PalindromicSubstrings647.java) | Medium | | [648. Replace Words](https://leetcode.com/problems/replace-words/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ReplaceWords648.java) | Medium | | [652. Find Duplicate Subtrees](https://leetcode.com/problems/find-duplicate-subtrees/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FindDuplicateSubtrees652.java) | Medium | | [653. Two Sum IV - Input is a BST](https://leetcode.com/problems/two-sum-iv-input-is-a-bst/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/TwoSumIVInputIsABST653.java) | Easy | | [654. Maximum Binary Tree](https://leetcode.com/problems/maximum-binary-tree/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MaximumBinaryTree654.java) | Medium | | [657. Judge Route Circle](https://leetcode.com/problems/judge-route-circle/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/JudgeRouteCircle657.java) | Easy | | [658. Find K Closest Elements](https://leetcode.com/problems/find-k-closest-elements//) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FindKClosestElements658.java) | Medium | | [659. Split Array into Consecutive Subsequences](https://leetcode.com/problems/split-array-into-consecutive-subsequences/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SplitArrayIntoConsecutiveSubsequences659.java) | Medium | | [661. Image Smoother](https://leetcode.com/problems/image-smoother/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ImageSmoother661.java) | Easy | | [662. Maximum Width of Binary Tree](https://leetcode.com/problems/maximum-width-of-binary-tree/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MaximumWidthOfBinaryTree662.java) | Medium | | [663. Equal Tree Partition](https://leetcode.com/problems/equal-tree-partition/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/EqualTreePartition663.java) | Medium | | [665. Non-decreasing Array](https://leetcode.com/problems/non-decreasing-array/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/NonDecreasingArray665.java) | Easy | | [669. Trim a Binary Search Tree](https://leetcode.com/problems/trim-a-binary-search-tree/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/TrimABinarySearchTree669.java) | Easy | | [671. Second Minimum Node In a Binary Tree](https://leetcode.com/problems/second-minimum-node-in-a-binary-tree/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SecondMinimumNodeInABinaryTree671.java) | Easy | | [673. Number of Longest Increasing Subsequence](https://leetcode.com/problems/number-of-longest-increasing-subsequence/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/NumberOfLongestIncreasingSubsequence673.java) | Medium | | [674. Longest Continuous Increasing Subsequence](https://leetcode.com/problems/longest-continuous-increasing-subsequence/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LongestContinuousIncreasingSubsequence674.java) | Easy | | [675. Cut Off Trees for Golf Event](https://leetcode.com/problems/cut-off-trees-for-golf-event/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/CutOffTreesForGolfEvent675.java) | Hard | | [676. Implement Magic Dictionary](https://leetcode.com/problems/implement-magic-dictionary/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ImplementMagicDictionary676.java) | Medium | | [677. Map Sum Pairs](https://leetcode.com/problems/map-sum-pairs/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MapSumPairs677.java) | Medium | | [678. Valid Parenthesis String](https://leetcode.com/problems/valid-parenthesis-string/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ValidParenthesisString678.java) | Medium | | [680. Valid Palindrome II](https://leetcode.com/problems/valid-palindrome-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ValidPalindromeII680.java) | Easy | | [681. Next Closest Time](https://leetcode.com/problems/next-closest-time/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/NextClosestTime681.java) | Medium | | [682. Baseball Game](https://leetcode.com/problems/baseball-game/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BaseballGame682.java) | Easy | | [683. K Empty Slots](https://leetcode.com/problems/k-empty-slots/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/KEmptySlots683.java) | Hard | | [684. Redundant Connection](https://leetcode.com/problems/redundant-connection/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RedundantConnection684.java) | Medium | | [685. Redundant Connection II](https://leetcode.com/problems/redundant-connection-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RedundantConnectionII685.java) | Hard | | [686. Repeated String Match](https://leetcode.com/problems/repeated-string-match/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RepeatedStringMatch686.java) | Easy | | [687. Longest Univalue Path](https://leetcode.com/problems/longest-univalue-path/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LongestUnivaluePath687.java) | Easy | | [689. Maximum Sum of 3 Non-Overlapping Subarrays](https://leetcode.com/problems/maximum-sum-of-3-non-overlapping-subarrays/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MaximumSumOf3NonOverlappingSubarrays689.java) | Hard | | [692. Top K Frequent Words](https://leetcode.com/problems/top-k-frequent-words/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/TopKFrequentWords692.java) | Medium | | [695. Max Area of Island](https://leetcode.com/problems/max-area-of-island/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MaxAreaOfIsland695.java) | Medium | | [698. Partition to K Equal Sum Subsets](https://leetcode.com/problems/partition-to-k-equal-sum-subsets/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PartitionToKEqualSumSubsets698.java) | Medium | | [702. Search in a Sorted Array of Unknown Size](https://leetcode.com/problems/search-in-a-sorted-array-of-unknown-size/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SearchInASortedArrayOfUnknownSize702.java) | Medium | | [705. Design HashSet](https://leetcode.com/problems/design-hashset/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/DesignHashSet705.java) | Easy | | [706. Design HashMap](https://leetcode.com/problems/design-hashmap/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/DesignHashMap706.java) | Easy | | [707. Design Linked List](https://leetcode.com/problems/design-linked-list/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/DesignLinkedList707.java) | Easy | | [709. To Lower Case](https://leetcode.com/problems/to-lower-case/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ToLowerCase709.java) | Easy | | [712. Minimum ASCII Delete Sum for Two Strings](https://leetcode.com/problems/minimum-ascii-delete-sum-for-two-strings/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MinimumASCIIDeleteSumForTwoStrings712.java) | Medium | | [713. Subarray Product Less Than K](https://leetcode.com/problems/subarray-product-less-than-k/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SubarrayProductLessThanK713.java) | Medium | | [714. Best Time to Buy and Sell Stock with Transaction Fee](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BestTimeToBuyAndSellStockWithTransactionFee714.java) | Medium | | [715. Range Module](https://leetcode.com/problems/range-module/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RangeModule715.java) | Hard | | [716. Max Stack](https://leetcode.com/problems/max-stack/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MaxStack716.java) | Hard | | [718. Maximum Length of Repeated Subarray](https://leetcode.com/problems/maximum-length-of-repeated-subarray/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MaximumLengthOfRepeatedSubarray718.java) | Medium | | [719. Find K-th Smallest Pair Distance](https://leetcode.com/problems/find-k-th-smallest-pair-distance/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FindKthSmallestPairDistance719.java) | Hard | | [720. Longest Word in Dictionary](https://leetcode.com/problems/longest-word-in-dictionary/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LongestWordInDictionary720.java) | Easy | | [721. Accounts Merge](https://leetcode.com/problems/accounts-merge/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/AccountsMerge721.java) | Medium | | [727. Minimum Window Subsequence](https://leetcode.com/problems/minimum-window-subsequence/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MinimumWindowSubsequence727.java) | Hard | | [729. My Calendar I](https://leetcode.com/problems/my-calendar-i/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MyCalendarI729.java) | Medium | | [731. My Calendar II](https://leetcode.com/problems/my-calendar-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MyCalendarII731.java) | Medium | | [734. Sentence Similarity](https://leetcode.com/problems/sentence-similarity/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SentenceSimilarity734.java) | Easy | | [737. Sentence Similarity II](https://leetcode.com/problems/sentence-similarity-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SentenceSimilarityII737.java) | Medium | | [738. Monotone Increasing Digits](https://leetcode.com/problems/monotone-increasing-digits/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MonotoneIncreasingDigits738.java) | Medium | | [739. Daily Temperatures](https://leetcode.com/problems/daily-temperatures/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/DailyTemperatures739.java) | Medium | | [740. Delete and Earn](https://leetcode.com/problems/delete-and-earn/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/DeleteAndEarn740.java) | Medium | | [746. Min Cost Climbing Stairs](https://leetcode.com/problems/min-cost-climbing-stairs/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MinCostClimbingStairs746.java) | Easy | | [748. Shortest Completing Word](https://leetcode.com/problems/shortest-completing-word/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ShortestCompletingWord748.java) | Medium | | [750. Number Of Corner Rectangles](https://leetcode.com/problems/number-of-corner-rectangles/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/NumberOfCornerRectangles750.java) | Medium | | [752. Open the Lock](https://leetcode.com/problems/open-the-lock/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/OpenTheLock752.java) | Medium | | [759. Employee Free Time](https://leetcode.com/problems/employee-free-time/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/EmployeeFreeTime759.java) | Hard | | [760. Find Anagram Mappings](https://leetcode.com/problems/find-anagram-mappings/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FindAnagramMappings760.java) | Easy | | [763. Partition Labels](https://leetcode.com/problems/partition-labels/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PartitionLabels763.java) | Medium | | [765. Couples Holding Hands](https://leetcode.com/problems/couples-holding-hands/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/CouplesHoldingHands765.java) | Hard | | [767. Reorganize String](https://leetcode.com/problems/reorganize-string/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ReorganizeString767.java) | Medium | | [768. Max Chunks To Make Sorted II](https://leetcode.com/problems/max-chunks-to-make-sorted-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MaxChunksToMakeSortedII768.java) | Hard | | [769. Max Chunks To Make Sorted](https://leetcode.com/problems/max-chunks-to-make-sorted/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MaxChunksToMakeSorted769.java) | Medium | | [771. Jewels and Stones](https://leetcode.com/problems/jewels-and-stones/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/JewelsAndStones771.java) | Easy | | [777. Swap Adjacent in LR String](https://leetcode.com/problems/swap-adjacent-in-lr-string/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SwapAdjacentInLRString777.java) | Medium | | [779. K-th Symbol in Grammar](https://leetcode.com/problems/k-th-symbol-in-grammar/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/KthSymbolInGrammar779.java) | Medium | | [785. Is Graph Bipartite?](https://leetcode.com/problems/is-graph-bipartite) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/IsGraphBipartite785.java) | Medium | | [787. Cheapest Flights Within K Stops](https://leetcode.com/problems/cheapest-flights-within-k-stops/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/CheapestFlightsWithinKStops787.java) | Medium | | [790. Domino and Tromino Tiling](https://leetcode.com/problems/domino-and-tromino-tiling/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/DominoAndTrominoTiling790.java) | Medium | | [792. Number of Matching Subsequences](https://leetcode.com/problems/number-of-matching-subsequences/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/NumberOfMatchingSubsequences792.java) | Medium | | [797. All Paths From Source to Target](https://leetcode.com/problems/all-paths-from-source-to-target/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/AllPathsFromSourceToTarget797.java) | Medium | | [783. Minimum Distance Between BST Nodes](https://leetcode.com/problems/minimum-distance-between-bst-nodes/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MinimumDistanceBetweenBSTNodes783.java) | Easy | | [802. Find Eventual Safe States](https://leetcode.com/problems/find-eventual-safe-states/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FindEventualSafeStates802.java) | Medium | | [803. Bricks Falling When Hit](https://leetcode.com/problems/bricks-falling-when-hit/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BricksFallingWhenHit803.java) | Hard | | [804. Unique Morse Code Words](https://leetcode.com/problems/unique-morse-code-words/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/UniqueMorseCodeWords804.java) | Easy | | [807. Max Increase to Keep City Skyline](https://leetcode.com/problems/max-increase-to-keep-city-skyline/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MaxIncreaseToKeepCitySkyline807.java) | Medium | | [819. Most Common Word](https://leetcode.com/problems/most-common-word/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MostCommonWord819.java) | Easy | | [826. Most Profit Assigning Work](https://leetcode.com/problems/most-profit-assigning-work/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MostProfitAssigningWork826.java) | Medium | | [832. Flipping an Image](https://leetcode.com/problems/flipping-an-image/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FlippingAnImage832.java) | Easy | | [836. Rectangle Overlap](https://leetcode.com/problems/rectangle-overlap/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RectangleOverlap863.java) | Easy | | [841. Keys and Rooms](https://leetcode.com/problems/keys-and-rooms/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/KeysAndRooms841.java) | Medium | | [842. Split Array into Fibonacci Sequence](https://leetcode.com/problems/split-array-into-fibonacci-sequence/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/SplitArrayIntoFibonacciSequence842.java) | Medium | | [843. Guess the Word](https://leetcode.com/problems/guess-the-word/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/GuessTheWord843.java) | Hard | | [844. Backspace String Compare](https://leetcode.com/problems/backspace-string-compare/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BackspaceStringCompare844.java) | Easy | | [845. Longest Mountain in Array](https://leetcode.com/problems/longest-mountain-in-array/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LongestMountainInArray845.java) | Medium | | [846. Hand of Straights](https://leetcode.com/problems/hand-of-straights/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/HandOfStraights846.java) | Medium | | [849. Maximize Distance to Closest Person](https://leetcode.com/problems/maximize-distance-to-closest-person/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MaximizeDistanceToClosestPerson849.java) | Easy | | [850. Rectangle Area II](https://leetcode.com/problems/rectangle-area-ii/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RectangleAreaII850.java) | Hard | | [855. Exam Room](https://leetcode.com/problems/exam-room/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ExamRoom855.java) | Medium | | [859. Buddy Strings](https://leetcode.com/problems/buddy-strings/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BuddyStrings859.java) | Easy | | [860. Lemonade Change](https://leetcode.com/problems/lemonade-change/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LemonadeChange860.java) | Easy | | [862. Shortest Subarray with Sum at Least K](https://leetcode.com/problems/shortest-subarray-with-sum-at-least-k/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ShortestSubarrayWithSumAtLeastK862.java) | Hard | | [863. All Nodes Distance K in Binary Tree](https://leetcode.com/problems/all-nodes-distance-k-in-binary-tree/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/AllNodesDistanceKInBinaryTree863.java) | Medium | | [864. Shortest Path to Get All Keys](https://leetcode.com/problems/shortest-path-to-get-all-keys/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ShortestPathToGetAllKeys864.java) | Hard | | [873. Length of Longest Fibonacci Subsequence](https://leetcode.com/problems/length-of-longest-fibonacci-subsequence/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/LengthOfLongestFibonacciSubsequence873.java) | Medium | | [875. Koko Eating Bananas](https://leetcode.com/problems/koko-eating-bananas/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/KokoEatingBananas875.java) | Easy | | [876. Middle of the Linked List](https://leetcode.com/problems/middle-of-the-linked-list/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MiddleOfTheLinkedList876.java) | Easy | | [877. Stone Game](https://leetcode.com/problems/stone-game/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/StoneGame877.java) | Medium | | [879. Profitable Schemes](https://leetcode.com/problems/profitable-schemes/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ProfitableSchemes879.java) | Hard | | [884. Decoded String at Index](https://leetcode.com/problems/decoded-string-at-index/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/DecodedStringAtIndex884.java) | Medium | | [885. Boats to Save People](https://leetcode.com/problems/boats-to-save-people/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/BoatsToSavePeople885.java) | Medium | | [886. Possible Bipartition](https://leetcode.com/problems/possible-bipartition) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/PossibleBipartition886.java) | Medium | | [887. Projection Area of 3D Shapes](https://leetcode.com/problems/projection-area-of-3d-shapes/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ProjectionAreaOf3DShapes887.java) | Easy | | [890. Find and Replace Pattern](https://leetcode.com/problems/find-and-replace-pattern/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FindAndReplacePattern890.java) | Medium | [895. Maximum Frequency Stack](https://leetcode.com/problems/maximum-frequency-stack/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/MaximumFrequencyStack895.java) | Hard | | [Convert Binary Search Tree to Sorted Doubly Linked List](https://leetcode.com/explore/interview/card/facebook/5/round-1-phone-interview/283/) | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/ConvertBinarySearchTreeToSortedDoublyLinkedList.java) | - | | HighestPopulationYear | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/HighestPopulationYear.java) | - | | Insert into a Cyclic Sorted List | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/InsertIntoACyclicSortedList.java) | - | | Robot Room Cleaner | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/RobotRoomCleaner.java) | - | | AsyncJobMonitor | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/AsyncJobMonitor.java) | - | | Bench | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/Bench.java) | - | | FindCenterOfMassInA2DArray | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/FindCenterOfMassInA2DArray.java) | - | | OneEditDistance | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/OneEditDistance.java) | - | | CollatzConjecture | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/CollatzConjecture.java) | - | | Subsequence | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/Subsequence.java) | - | | TreeToForestByErasingNodes | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/TreeToForestByErasingNodes.java) | - | | KMP | [Solution](https://github.com/fluency03/leetcode-java/blob/master/src/KMP.java) | - | ================================================ FILE: src/.gitignore ================================================ *.class .DS_store ================================================ FILE: src/AccountsMerge721.java ================================================ /** * Given a list accounts, each element accounts[i] is a list of strings, where * the first element accounts[i][0] is a name, and the rest of the elements are * emails representing emails of the account. * * Now, we would like to merge these accounts. Two accounts definitely belong * to the same person if there is some email that is common to both accounts. * Note that even if two accounts have the same name, they may belong to * different people as people could have the same name. A person can have any * number of accounts initially, but all of their accounts definitely have the * same name. * * After merging the accounts, return the accounts in the following format: * the first element of each account is the name, and the rest of the elements * are emails in sorted order. The accounts themselves can be returned in any * order. * * Example 1: * Input: * accounts = [["John", "johnsmith@mail.com", "john00@mail.com"], ["John", "johnnybravo@mail.com"], ["John", "johnsmith@mail.com", "john_newyork@mail.com"], ["Mary", "mary@mail.com"]] * Output: [["John", 'john00@mail.com', 'john_newyork@mail.com', 'johnsmith@mail.com'], ["John", "johnnybravo@mail.com"], ["Mary", "mary@mail.com"]] * * Explanation: * The first and third John's are the same person as they have the common email "johnsmith@mail.com". * The second John and Mary are different people as none of their email addresses are used by other accounts. * We could return these lists in any order, for example the answer [['Mary', 'mary@mail.com'], ['John', 'johnnybravo@mail.com'], * ['John', 'john00@mail.com', 'john_newyork@mail.com', 'johnsmith@mail.com']] would still be accepted. * * Note: * * The length of accounts will be in the range [1, 1000]. * The length of accounts[i] will be in the range [1, 10]. * The length of accounts[i][j] will be in the range [1, 30]. * */ public class AccountsMerge721 { public List> accountsMerge(List> accounts) { List> res = new ArrayList<>(); Map>> map = new HashMap<>(); for (List acc: accounts) { String name = acc.get(0); if (!map.containsKey(name)) { Set set = new HashSet<>(acc); set.remove(name); Set> setOfSet = new HashSet<>(); setOfSet.add(set); map.put(name, setOfSet); } else { Set> toBeMerged = new HashSet<>(); Set> setOfSet = map.get(name); Set curr = new HashSet<>(acc); curr.remove(name); for (String email: curr) { Set found = null; for (Set e: setOfSet) { if (e.contains(email)) { found = e; break; } } if (found != null) { setOfSet.remove(found); toBeMerged.add(found); } } for (Set s: toBeMerged) { curr.addAll(s); } setOfSet.add(curr); } } for (Map.Entry>> en: map.entrySet()) { for (Set es: en.getValue()) { List list = new ArrayList<>(es); java.util.Collections.sort(list); list.add(0, en.getKey()); res.add(list); } } return res; } /** * https://leetcode.com/problems/accounts-merge/solution/ */ int MAX_VAL = 10000; public List> accountsMerge(List> accounts) { Map emailToName = new HashMap<>(); Map emailToId = new HashMap<>(); DSU dsu = initDSU(accounts, emailToName, emailToId); Map> res = new HashMap(); for (String email: emailToName.keySet()) { int id = dsu.find(emailToId.get(email)); res.computeIfAbsent(id, x -> new ArrayList()).add(email); } for (List emails: res.values()) { Collections.sort(emails); emails.add(0, emailToName.get(emails.get(0))); } return new ArrayList(res.values()); } private DSU initDSU(List> accounts, Map emailToName, Map emailToId) { DSU dsu = new DSU(MAX_VAL+1); int id = 0; for (List acc: accounts) { String name = acc.get(0); for (int i=1; i> accountsMerge3(List> accounts) { Map emailToName = new HashMap<>(); Map> graph = initGraph(accounts, emailToName); Set visited = new HashSet<>(); List> res = new LinkedList<>(); for (String email: emailToName.keySet()) { List list = new LinkedList<>(); if (visited.add(email)) { dfs(graph, email, visited, list); Collections.sort(list); list.add(0, emailToName.get(email)); res.add(list); } } return res; } private Map> initGraph(List> accounts, Map emailToName) { Map> graph = new HashMap<>(); for (List acc : accounts) { String name = acc.get(0); for (int i = 1; i < acc.size(); i++) { String email = acc.get(i); if (!graph.containsKey(acc.get(i))) { graph.put(email, new HashSet<>()); } emailToName.put(email, name); if (i == 1) continue; graph.get(email).add(acc.get(i-1)); graph.get(acc.get(i-1)).add(email); } } return graph; } private void dfs(Map> graph, String email, Set visited, List list) { list.add(email); for (String l: graph.get(email)) { if (visited.add(l)) dfs(graph, l, visited, list); } } } ================================================ FILE: src/AddBinary67.java ================================================ /** * Given two binary strings, return their sum (also a binary string). * * For example, * a = "11" * b = "1" * Return "100". */ public class AddBinary67 { public String addBinary(String a, String b) { return addBinary(a, b, a.length()-1, b.length()-1, 0) ; } private String addBinary(String a, String b, int i, int j, int carry) { if (i < 0 && j < 0) return (carry == 0) ? "" : "1"; int sum = carry; if (i >= 0 && a.charAt(i) == '1') sum++; if (j >= 0 && b.charAt(j) == '1') sum++; return addBinary(a, b, i-1, j-1, (sum < 2) ? 0 : 1) + ((sum%2 == 0) ? "0" : "1"); } public String addBinary2(String a, String b) { StringBuilder sb = new StringBuilder(); addBinary(a, b, a.length()-1, b.length()-1, 0, sb) ; return sb.toString(); } private void addBinary(String a, String b, int i, int j, int carry, StringBuilder sb) { if (i < 0 && j < 0) { sb.append((carry == 0) ? "" : "1"); return; } int sum = carry; if (i >= 0 && a.charAt(i) == '1') sum++; if (j >= 0 && b.charAt(j) == '1') sum++; addBinary(a, b, i-1, j-1, (sum < 2) ? 0 : 1, sb); sb.append((sum%2 == 0) ? '0' : '1'); } public String addBinary3(String a, String b) { StringBuilder sb = new StringBuilder(); int carry = 0; int i = a.length()-1; int j = b.length()-1; while (i >= 0 && j >= 0) { int sum = carry; if (a.charAt(i) == '1') sum++; if (b.charAt(j) == '1') sum++; carry = (sum < 2) ? 0 : 1; sb.insert(0, (sum%2 == 0) ? '0' : '1'); i--; j--; } while (i >= 0) { int sum = carry; if (a.charAt(i) == '1') sum++; carry = (sum < 2) ? 0 : 1; sb.insert(0, (sum%2 == 0) ? '0' : '1'); i--; } while (j >= 0) { int sum = carry; if (b.charAt(j) == '1') sum++; carry = (sum < 2) ? 0 : 1; sb.insert(0, (sum%2 == 0) ? '0' : '1'); j--; } if (carry == 1) sb.insert(0, '1'); return sb.toString(); } public String addBinary4(String a, String b) { char[] intToChar = new char[]{'0', '1'}; int len = Math.max(a.length(), b.length()); char[] res = new char[len + 1]; int carry = 0; int s = len; int i = a.length() - 1; int j = b.length() - 1; while (i >= 0 && j >= 0) { int sum = charToInt(a.charAt(i--)) + charToInt(b.charAt(j--)) + carry; carry = sum >> 1; res[s--] = intToChar[sum & 1]; } while (i >= 0) { int sum = charToInt(a.charAt(i--)) + carry; carry = sum >> 1; res[s--] = intToChar[sum & 1]; } while (j >= 0) { int sum = charToInt(b.charAt(j--)) + carry; carry = sum >> 1; res[s--] = intToChar[sum & 1]; } res[0] = intToChar[carry]; return res[0] == '0' ? (new String(res)).substring(1) : new String(res); } private int charToInt(char c) { return c - '0'; } } ================================================ FILE: src/AddBoldTagInString616.java ================================================ /** * Given a string s and a list of strings dict, you need to add a closed pair * of bold tag and to wrap the substrings in s that exist in dict. If * two such substrings overlap, you need to wrap them together by only one pair * of closed bold tag. Also, if two substrings wrapped by bold tags are * consecutive, you need to combine them. * * Example 1: * * Input: * s = "abcxyz123" * dict = ["abc","123"] * Output: * "abcxyz123" * * Example 2: * Input: * s = "aaabbcc" * dict = ["aaa","aab","bc"] * Output: * "aaabbcc" * * Note: * The given dict won't contain duplicates, and its length won't exceed 100. * All the strings in input have length in range [1, 1000]. */ public class AddBoldTagInString616 { public String addBoldTag(String s, String[] dict) { Trie trie = constructTrie(dict); StringBuilder sb = new StringBuilder(); int l = 0; int r = 0; char[] chars = s.toCharArray(); for (int i=0; i= r) { if (r > l) { sb.append(""); sb.append(s.substring(l, r)); sb.append(""); } r = i + 1; l = r; sb.append(s.charAt(i)); } } else { r = Math.max(r, i+len); } } if (r > l) { sb.append(""); sb.append(s.substring(l, r)); sb.append(""); } return sb.toString(); } private Trie constructTrie(String[] dict) { Trie res = new Trie(); for (String word: dict) { res.addWord(word); } return res; } public String addBoldTag2(String s, String[] dict) { StringBuilder sb = new StringBuilder(); int l = 0; int r = 0; for (int i=0; i len) { len = word.length(); } } if (len == 0) { if (i >= r) { if (r > l) { sb.append(""); sb.append(s.substring(l, r)); sb.append(""); } r = i + 1; l = r; sb.append(s.charAt(i)); } } else { r = Math.max(r, i+len); } } if (r > l) { sb.append(""); sb.append(s.substring(l, r)); sb.append(""); } return sb.toString(); } /** * https://leetcode.com/problems/add-bold-tag-in-string/discuss/104262/short-java-solution */ public String addBoldTag3(String s, String[] dict) { int n = s.length(); int[] mark = new int[n+1]; for(String d : dict) { int i = -1; while((i = s.indexOf(d, i+1)) >= 0) { mark[i]++; mark[i + d.length()]--; } } StringBuilder sb = new StringBuilder(); int sum = 0; for(int i = 0; i <= n; i++) { int cur = sum + mark[i]; if (cur > 0 && sum == 0) sb.append(""); if (cur == 0 && sum > 0) sb.append(""); if (i == n) break; sb.append(s.charAt(i)); sum = cur; } return sb.toString(); } /** * https://leetcode.com/problems/add-bold-tag-in-string/discuss/104263/Java-solution-Same-as-Merge-Interval. */ public String addBoldTag4(String s, String[] dict) { List intervals = new ArrayList<>(); for (String str : dict) { int index = -1; index = s.indexOf(str, index); while (index != -1) { intervals.add(new Interval(index, index + str.length())); index +=1; index = s.indexOf(str, index); } } intervals = merge(intervals); int prev = 0; StringBuilder sb = new StringBuilder(); for (Interval interval : intervals) { sb.append(s.substring(prev, interval.start)); sb.append(""); sb.append(s.substring(interval.start, interval.end)); sb.append(""); prev = interval.end; } if (prev < s.length()) { sb.append(s.substring(prev)); } return sb.toString(); } class Interval { int start, end; public Interval(int s, int e) { start = s; end = e; } public String toString() { return "[" + start + ", " + end + "]" ; } } public List merge(List intervals) { if (intervals == null || intervals.size() <= 1) { return intervals; } Collections.sort(intervals, new Comparator(){ public int compare(Interval a, Interval b) { return a.start - b.start; } }); int start = intervals.get(0).start; int end = intervals.get(0).end; List res = new ArrayList<>(); for (Interval i : intervals) { if (i.start <= end) { end = Math.max(end, i.end); } else { res.add(new Interval(start, end)); start = i.start; end = i.end; } } res.add(new Interval(start, end)); return res; } /** * https://leetcode.com/problems/add-bold-tag-in-string/discuss/104262/short-java-solution */ public String addBoldTag5(String s, String[] dict) { int n = s.length(); int[] mark = new int[n+1]; for(String d : dict) { int i = -1; while((i = s.indexOf(d, i+1)) >= 0) { mark[i]++; mark[i + d.length()]--; } } StringBuilder sb = new StringBuilder(); int sum = 0; for(int i = 0; i <= n; i++) { int cur = sum + mark[i]; if (cur > 0 && sum == 0) sb.append(""); if (cur == 0 && sum > 0) sb.append(""); if (i == n) break; sb.append(s.charAt(i)); sum = cur; } return sb.toString(); } public String addBoldTag6(String s, String[] dict) { if (s == null || s.length() == 0) return s; StringBuilder sb = new StringBuilder(); int l = 0; int r = 0; int len = s.length(); for (int i=0; i").append(s.substring(l, r)).append(""); } sb.append(s.charAt(i)); l = i+1; r = i+1; } if (l != r) { sb.append("").append(s.substring(l, r)).append(""); } return sb.toString(); } } class Trie { Map children = new HashMap<>(); boolean end = false; public void addWord(String word) { addWord(word.toCharArray(), 0); } public void addWord(char[] chars, int i) { if (i == chars.length) { end = true; return; } char c = chars[i]; if (children.containsKey(c)) { children.get(c).addWord(chars, i+1); } else { Trie child = new Trie(); children.put(c, child); child.addWord(chars, i+1); } } public int search(char[] chars, int i) { return search(chars, i, i, 0); } private int search(char[] chars, int i, int x, int len) { if (x >= chars.length) return end ? x-i : len; char c = chars[x]; if (!children.containsKey(c)) return end ? x-i : len; return children.get(c).search(chars, i, x+1, len); } // public void print() { // for (char c: children.keySet()) { // System.out.println(c); // children.get(c).print(); // } // } } ================================================ FILE: src/AddOneRowToTree623.java ================================================ /** * Given the root of a binary tree, then value v and depth d, you need to add a * row of nodes with value v at the given depth d. The root node is at depth 1. * * The adding rule is: given a positive integer depth d, for each NOT null tree * nodes N in depth d-1, create two tree nodes with value v as N's left subtree * root and right subtree root. And N's original left subtree should be the left * subtree of the new left subtree root, its original right subtree should be * the right subtree of the new right subtree root. If depth d is 1 that means * there is no depth d-1 at all, then create a tree node with value v as the * new root of the whole original tree, and the original tree is the new root's * left subtree. * * Example 1: * Input: * A binary tree as following: * 4 * / \ * 2 6 * / \ / * 3 1 5 * * v = 1 * * d = 2 * * Output: * 4 * / \ * 1 1 * / \ * 2 6 * / \ / * 3 1 5 * * --------------------------------------------------- * * Example 2: * Input: * A binary tree as following: * 4 * / * 2 * / \ * 3 1 * * v = 1 * * d = 3 * * Output: * 4 * / * 2 * / \ * 1 1 * / \ * 3 1 * * * Note: * The given d is in range [1, maximum depth of the given tree + 1]. * The given binary tree has at least one tree node. */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class AddOneRowToTree623 { public TreeNode addOneRow(TreeNode root, int v, int d) { if (d == 1) { TreeNode newNode = new TreeNode(v); newNode.left = root; return newNode; } insert(root, v, d); return root; } private void insert(TreeNode root, int v, int d) { if (root == null) { return; } if (d == 2) { TreeNode t = root.left; root.left = new TreeNode(v); root.left.left = t; t = root.right; root.right = new TreeNode(v); root.right.right = t; } else { addOneRow(root.left, v, d-1); addOneRow(root.right, v, d-1); } } /** * https://discuss.leetcode.com/topic/92964/java-three-methods-one-bfs-and-two-dfs */ public TreeNode addOneRow3(TreeNode root, int v, int d) { if (d == 1) { TreeNode newroot = new TreeNode(v); newroot.left = root; return newroot; } LinkedList queue = new LinkedList<>(); queue.add(root); for (int i = 0; i < d-2; i++) { int size = queue.size(); for (int j = 0; j < size; j++) { TreeNode t = queue.poll(); if (t.left != null) queue.add(t.left); if (t.right != null) queue.add(t.right); } } while (!queue.isEmpty()) { TreeNode t = queue.poll(); TreeNode tmp = t.left; t.left = new TreeNode(v); t.left.left = tmp; tmp = t.right; t.right = new TreeNode(v); t.right.right = tmp; } return root; } } ================================================ FILE: src/AddStrings415.java ================================================ /** * Given two non-negative integers num1 and num2 represented as string, return * the sum of num1 and num2. * * Note: * The length of both num1 and num2 is < 5100. * Both num1 and num2 contains only digits 0-9. * Both num1 and num2 does not contain any leading zero. * You must not use any built-in BigInteger library or convert the inputs to * integer directly. */ public class AddStrings415 { public String addStrings(String num1, String num2) { int carry = 0; char[] chars1 = num1.toCharArray(); char[] chars2 = num2.toCharArray(); int len1 = num1.length(); int len2 = num2.length(); int len = Math.max(len1, len2); StringBuilder sb = new StringBuilder(); int i = 0; while (i < len) { int a = (len1 - i - 1 < 0) ? 0 : chars1[len1 - i - 1] - '0'; int b = (len2 - i - 1 < 0) ? 0 : chars2[len2 - i - 1] - '0'; int sum = a + b + carry; sb.insert(0, sum % 10); carry = sum / 10; i++; } if (carry > 0) sb.insert(0, Integer.toString(carry)); return sb.toString(); } /** * https://leetcode.com/problems/add-strings/ */ public String addStrings2(String num1, String num2) { char[] temp = new char[Math.max(num1.length(), num2.length())]; int i = num1.length() - 1, j = num2.length() - 1; int index = temp.length - 1; int carry = 0; while (i >= 0 || j >= 0) { int a = i >= 0 ? num1.charAt(i--) - '0' : 0; int b = j >= 0 ? num2.charAt(j--) - '0' : 0; int sum = a + b + carry; temp[index--] = (char)(sum % 10 + '0'); carry = sum / 10; } return carry == 0 ? new String(temp) : "1" + new String(temp); } } ================================================ FILE: src/AddTwoNumbers2.java ================================================ /** * You are given two non-empty linked lists representing two non-negative * integers. The digits are stored in reverse order and each of their nodes * contain a single digit. Add the two numbers and return it as a linked list. * * You may assume the two numbers do not contain any leading zero, except the * number 0 itself. * * Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) * Output: 7 -> 0 -> 8 */ public class AddTwoNumbers2 { public ListNode addTwoNumbers(ListNode l1, ListNode l2) { ListNode dummy = new ListNode(0); ListNode p = dummy; int carry = 0; while (l1 != null || l2 != null) { int a = l1 == null ? 0 : l1.val; int b = l2 == null ? 0 : l2.val; int sum = a + b + carry; ListNode n = new ListNode(sum%10); p.next = n; p = p.next; carry = sum/10; l1 = l1 == null ? null : l1.next; l2 = l2 == null ? null : l2.next; } if (carry != 0) p.next = new ListNode(carry); return dummy.next; } public ListNode addTwoNumbers2(ListNode l1, ListNode l2) { ListNode dummy = new ListNode(0); ListNode p = dummy; int carry = 0; while (l1 != null && l2 != null) { int sum = l1.val + l2.val + carry; p.next = new ListNode(sum % 10); p = p.next; carry = sum / 10; l1 = l1.next; l2 = l2.next; } while (l1 != null) { int sum = l1.val + carry; p.next = new ListNode(sum % 10); p = p.next; carry = sum / 10; l1 = l1.next; } while (l2 != null) { int sum = l2.val + carry; p.next = new ListNode(sum % 10); p = p.next; carry = sum / 10; l2 = l2.next; } if (carry != 0) p.next = new ListNode(carry); return dummy.next; } } ================================================ FILE: src/AddTwoNumbersII445.java ================================================ /** * You are given two non-empty linked lists representing two non-negative * integers. The most significant digit comes first and each of their nodes * contain a single digit. Add the two numbers and return it as a linked list. * * You may assume the two numbers do not contain any leading zero, except the * number 0 itself. * * Follow up: * What if you cannot modify the input lists? In other words, reversing the * lists is not allowed. * * Example: * * Input: (7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4) * Output: 7 -> 8 -> 0 -> 7 */ /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ public class AddTwoNumbersII445 { public ListNode addTwoNumbers(ListNode l1, ListNode l2) { Stack s1 = new Stack<>(); Stack s2 = new Stack<>(); while (l1 != null && l2 != null) { s1.push(l1.val); l1 = l1.next; s2.push(l2.val); l2 = l2.next; } while (l1 != null) { s1.push(l1.val); l1 = l1.next; } while (l2 != null) { s2.push(l2.val); l2 = l2.next; } ListNode dummy = new ListNode(0); ListNode p = dummy; int carry = 0; while (!s1.isEmpty() && !s2.isEmpty()) { int sum = s1.pop() + s2.pop() + carry; ListNode curr = new ListNode(sum % 10); curr.next = p.next; p.next = curr; carry = sum / 10; } while (!s1.isEmpty()) { int sum = s1.pop() + carry; ListNode curr = new ListNode(sum % 10); curr.next = p.next; p.next = curr; carry = sum / 10; } while (!s2.isEmpty()) { int sum = s2.pop() + carry; ListNode curr = new ListNode(sum % 10); curr.next = p.next; p.next = curr; carry = sum / 10; } if (carry != 0) { ListNode curr = new ListNode(carry); curr.next = p.next; p.next = curr; } return dummy.next; } public ListNode addTwoNumbers2(ListNode l1, ListNode l2) { ListNode ll1 = reverseList(l1); ListNode ll2 = reverseList(l2); return reverseList(addTwoNumbers0(ll1, ll2)); } public ListNode addTwoNumbers0(ListNode l1, ListNode l2) { ListNode dummy = new ListNode(0); ListNode p = dummy; int carry = 0; while (l1 != null || l2 != null) { int a = l1 == null ? 0 : l1.val; int b = l2 == null ? 0 : l2.val; int sum = a + b + carry; ListNode n = new ListNode(sum%10); p.next = n; p = p.next; carry = sum/10; l1 = l1 == null ? null : l1.next; l2 = l2 == null ? null : l2.next; } if (carry != 0) p.next = new ListNode(carry); return dummy.next; } public ListNode reverseList(ListNode head) { if (head == null || head.next == null) return head; ListNode dummy = new ListNode(0); ListNode tail = null; while (head != null) { ListNode t = head; head = head.next; tail = dummy.next; dummy.next = t; dummy.next.next = tail; } return dummy.next; } } ================================================ FILE: src/AlienDictionary269.java ================================================ /** * There is a new alien language which uses the latin alphabet. However, the * order among letters are unknown to you. You receive a list of non-empty words * from the dictionary, where words are sorted lexicographically by the rules of * this new language. Derive the order of letters in this language. * * Example 1: * * Input: * [ * "wrt", * "wrf", * "er", * "ett", * "rftt" * ] * * Output: "wertf" * Example 2: * * Input: * [ * "z", * "x" * ] * * Output: "zx" * Example 3: * * Input: * [ * "z", * "x", * "z" * ] * * Output: "" * * Explanation: The order is invalid, so return "". * * Note: * * You may assume all letters are in lowercase. * You may assume that if a is a prefix of b, then a must appear before b in * the given dictionary. * If the order is invalid, return an empty string. * There may be multiple valid order of letters, return any one of them is fine. */ public class AlienDictionary269 { private Set vertices = new HashSet<>(); private Set[] graph = new Set[26]; /** * DFS based topological sort */ public String alienOrder(String[] words) { initMap(words); updateOrderMap(words); StringBuilder sb = new StringBuilder(); boolean[] visited = new boolean[26]; for (char key: vertices) { if (!visited[key - 'a']) { if (!helper(key, new HashSet(), visited, sb)) return ""; } } return sb.reverse().toString(); } private boolean helper(Character key, Set path, boolean[] visited, StringBuilder sb) { visited[key - 'a'] = true; path.add(key); for (Character c: graph[key - 'a']) { if (path.contains(c)) return false; if (!visited[c - 'a']) { if (!helper(c, path, visited, sb)) return false; } } sb.append(key); path.remove(key); return true; } private void initMap(String[] words) { for (String word: words) { for (char c: word.toCharArray()) { if (!vertices.contains(c)) { vertices.add(c); graph[c - 'a'] = new HashSet(); } } } } private void updateOn(String word1, String word2) { int len = Math.min(word1.length(), word2.length()); for (int i=0; i adjs = graph[v - 'a']; if (adjs != null) { for (Character c: adjs) { incomming[c - 'a']++; } } } Queue q = new LinkedList<>(); for (Character c: vertices) { if (incomming[c - 'a'] == 0) { q.add(c); } } int visited = 0; StringBuilder sb = new StringBuilder(); while (!q.isEmpty()) { char c = q.remove(); sb.append(c); for (Character next: graph[c - 'a']) { incomming[next - 'a']--; if (incomming[next - 'a'] == 0) { q.add(next); } } visited++; } if (visited != vertices.size()) return ""; return sb.toString(); } /** * https://leetcode.com/problems/alien-dictionary/discuss/70115/3ms-Clean-Java-Solution-(DFS) */ private final int N = 26; public String alienOrder3(String[] words) { boolean[][] adj = new boolean[N][N]; int[] visited = new int[N]; buildGraph(words, adj, visited); StringBuilder sb = new StringBuilder(); for(int i = 0; i < N; i++) { if(visited[i] == 0) { // unvisited if(!dfs(adj, visited, sb, i)) return ""; } } return sb.reverse().toString(); } public boolean dfs(boolean[][] adj, int[] visited, StringBuilder sb, int i) { visited[i] = 1; // 1 = visiting for(int j = 0; j < N; j++) { if(adj[i][j]) { // connected if(visited[j] == 1) return false; // 1 => 1, cycle if(visited[j] == 0) { // 0 = unvisited if(!dfs(adj, visited, sb, j)) return false; } } } visited[i] = 2; // 2 = visited sb.append((char) (i + 'a')); return true; } public void buildGraph(String[] words, boolean[][] adj, int[] visited) { Arrays.fill(visited, -1); // -1 = not even existed for(int i = 0; i < words.length; i++) { for(char c : words[i].toCharArray()) visited[c - 'a'] = 0; if(i > 0) { String w1 = words[i - 1], w2 = words[i]; int len = Math.min(w1.length(), w2.length()); for(int j = 0; j < len; j++) { char c1 = w1.charAt(j), c2 = w2.charAt(j); if(c1 != c2) { adj[c1 - 'a'][c2 - 'a'] = true; break; } } } } } } ================================================ FILE: src/AllNodesDistanceKInBinaryTree863.java ================================================ /** * We are given a binary tree (with root node root), a target node, and an * integer value K. * * Return a list of the values of all nodes that have a distance K from the * target node. The answer can be returned in any order. * * Example 1: * Input: root = [3,5,1,6,2,0,8,null,null,7,4], target = 5, K = 2 * Output: [7,4,1] * * Explanation: * The nodes that are a distance 2 from the target node (with value 5) * have values 7, 4, and 1. * * https://s3-lc-upload.s3.amazonaws.com/uploads/2018/06/28/sketch0.png * * Note that the inputs "root" and "target" are actually TreeNodes. * The descriptions of the inputs above are just serializations of these objects. * * Note: * The given tree is non-empty. * Each node in the tree has unique values 0 <= node.val <= 500. * The target node is a node in the tree. * 0 <= K <= 1000. */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class AllNodesDistanceKInBinaryTree863 { public List distanceK(TreeNode root, TreeNode target, int K) { List res = new ArrayList<>(); if (root == null) return res; if (K == 0) { res.add(target.val); return res; } distanceToRoot(root, target, K, res, 0); return res; } private int distanceToRoot(TreeNode root, TreeNode target, int K, List res, int level) { if (root == null) return -1; if (root.val == target.val) { distanceKChildren(root, K, res); return level; } int leftFlag = distanceToRoot(root.left, target, K, res, level + 1); if (leftFlag != -1) { if (leftFlag - level == K) { res.add(root.val); } else if (leftFlag - level < K) { distanceKChildren(root.right, K - (leftFlag - level) - 1, res); } } int rightFlag = distanceToRoot(root.right, target, K, res, level + 1); if (rightFlag != -1) { if (rightFlag - level == K) { res.add(root.val); } else if (rightFlag - level < K) { distanceKChildren(root.left, K - (rightFlag - level) - 1, res); } } return leftFlag != -1 ? leftFlag : rightFlag; } private void distanceKChildren(TreeNode root, int K, List res) { if (root == null) return; Queue q = new LinkedList<>(); q.add(root); int i = 0; while (!q.isEmpty() && i < K) { int size = q.size(); for (int j=0; j parent; public List distanceK2(TreeNode root, TreeNode target, int K) { parent = new HashMap(); dfs(root, null); Queue queue = new LinkedList(); queue.add(null); queue.add(target); Set seen = new HashSet(); seen.add(target); seen.add(null); int dist = 0; while (!queue.isEmpty()) { TreeNode node = queue.poll(); if (node == null) { if (dist == K) { List ans = new ArrayList(); for (TreeNode n: queue) ans.add(n.val); return ans; } queue.offer(null); dist++; } else { if (!seen.contains(node.left)) { seen.add(node.left); queue.offer(node.left); } if (!seen.contains(node.right)) { seen.add(node.right); queue.offer(node.right); } TreeNode par = parent.get(node); if (!seen.contains(par)) { seen.add(par); queue.offer(par); } } } return new ArrayList(); } public void dfs(TreeNode node, TreeNode par) { if (node != null) { parent.put(node, par); dfs(node.left, node); dfs(node.right, node); } } /** * https://leetcode.com/problems/all-nodes-distance-k-in-binary-tree/solution/ */ List ans; TreeNode target; int K; public List distanceK3(TreeNode root, TreeNode target, int K) { ans = new LinkedList(); this.target = target; this.K = K; dfs(root); return ans; } // Return distance from node to target if exists, else -1 public int dfs(TreeNode node) { if (node == null) return -1; else if (node == target) { subtree_add(node, 0); return 1; } else { int L = dfs(node.left), R = dfs(node.right); if (L != -1) { if (L == K) ans.add(node.val); subtree_add(node.right, L + 1); return L + 1; } else if (R != -1) { if (R == K) ans.add(node.val); subtree_add(node.left, R + 1); return R + 1; } else { return -1; } } } // Add all nodes 'K - dist' from the node to answer. public void subtree_add(TreeNode node, int dist) { if (node == null) return; if (dist == K) ans.add(node.val); else { subtree_add(node.left, dist + 1); subtree_add(node.right, dist + 1); } } Map map = new HashMap<>(); public List distanceK4(TreeNode root, TreeNode target, int K) { List res = new LinkedList<>(); find(root, target, K); dfs(root, target, K, map.get(root), res); return res; } // find target node first and store the distance in that path that we could use it later directly private int find(TreeNode root, TreeNode target, int K) { if (root == null) return -1; if (root == target) { map.put(root, 0); return 0; } int left = find(root.left, target, K); if (left >= 0) { map.put(root, left + 1); return left + 1; } int right = find(root.right, target, K); if (right >= 0) { map.put(root, right + 1); return right + 1; } return -1; } private void dfs(TreeNode root, TreeNode target, int K, int length, List res) { if (root == null) return; if (map.containsKey(root)) length = map.get(root); if (length == K) res.add(root.val); dfs(root.left, target, K, length + 1, res); dfs(root.right, target, K, length + 1, res); } } ================================================ FILE: src/AllOOneDataStructure432.java ================================================ /** * Implement a data structure supporting the following operations: * * Inc(Key) - Inserts a new key with value 1. Or increments an existing key * by 1. Key is guaranteed to be a non-empty string. * Dec(Key) - If Key's value is 1, remove it from the data structure. Otherwise * decrements an existing key by 1. If the key does not exist, this function * does nothing. Key is guaranteed to be a non-empty string. * GetMaxKey() - Returns one of the keys with maximal value. If no element * exists, return an empty string "". * GetMinKey() - Returns one of the keys with minimal value. If no element * exists, return an empty string "". * * Challenge: Perform all these in O(1) time complexity. */ public class AllOOneDataStructure432 { class AllOne { private Map keyMap; private Map freqMap; private FreqNode head; /** Initialize your data structure here. */ public AllOne() { this.keyMap = new HashMap<>(); this.freqMap = new HashMap<>(); this.head = new FreqNode(); this.head.next = this.head; this.head.prev = this.head; } /** Inserts a new key with value 1. Or increments an existing key by 1. */ public void inc(String key) { KeyNode node = keyMap.get(key); if (node == null) { node = new KeyNode(key); FreqNode freqNode = freqMap.get(node.freq); if (freqNode == null) { freqNode = new FreqNode(node.freq); this.freqMap.put(freqNode.freq, freqNode); addAfter(this.head, freqNode); } addAfter(freqNode.keyHead, node); this.keyMap.put(node.key, node); } else { dislink(node); FreqNode preFreqNode = freqMap.get(node.freq); node.freq++; FreqNode nextFreqNode = freqMap.get(node.freq); if (nextFreqNode == null) { nextFreqNode = new FreqNode(node.freq); this.freqMap.put(nextFreqNode.freq, nextFreqNode); addAfter(preFreqNode, nextFreqNode); } addAfter(nextFreqNode.keyHead, node); if (isEmpty(preFreqNode.keyHead)) { dislink(preFreqNode); this.freqMap.remove(preFreqNode.freq); } } } private void dislink(KeyNode node) { node.next.prev = node.prev; node.prev.next = node.next; } private void dislink(FreqNode node) { node.next.prev = node.prev; node.prev.next = node.next; } private void addAfter(KeyNode node, KeyNode newNode) { newNode.next = node.next; newNode.prev = node; node.next.prev = newNode; node.next = newNode; } private void addAfter(FreqNode node, FreqNode newNode) { newNode.next = node.next; newNode.prev = node; node.next.prev = newNode; node.next = newNode; } /** Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. */ public void dec(String key) { KeyNode node = keyMap.get(key); if (node == null) return; dislink(node); FreqNode preFreqNode = freqMap.get(node.freq); node.freq--; if (node.freq > 0) { FreqNode nextFreqNode = freqMap.get(node.freq); if (nextFreqNode == null) { nextFreqNode = new FreqNode(node.freq); this.freqMap.put(nextFreqNode.freq, nextFreqNode); addBefore(preFreqNode, nextFreqNode); } addAfter(nextFreqNode.keyHead, node); } else { this.keyMap.remove(node.key); } if (isEmpty(preFreqNode.keyHead)) { dislink(preFreqNode); this.freqMap.remove(preFreqNode.freq); } } private void addBefore(FreqNode node, FreqNode newNode) { newNode.next = node; newNode.prev = node.prev; node.prev.next = newNode; node.prev = newNode; } /** Returns one of the keys with maximal value. */ public String getMaxKey() { if (isEmpty()) return ""; return this.head.prev.keyHead.next.key; } /** Returns one of the keys with Minimal value. */ public String getMinKey() { if (isEmpty()) return ""; return this.head.next.keyHead.next.key; } private boolean isEmpty() { return isEmpty(this.head); } private boolean isEmpty(KeyNode node) { return node.next == node; } private boolean isEmpty(FreqNode node) { return node.next == node; } class KeyNode { KeyNode prev; KeyNode next; String key; int freq; KeyNode() { } KeyNode(String key) { this.key = key; this.freq = 1; } KeyNode(String key, int freq) { this.key = key; this.freq = freq; } } class FreqNode { FreqNode prev; FreqNode next; int freq; KeyNode keyHead; FreqNode () { } FreqNode (int freq) { this.freq = freq; this.keyHead = new KeyNode(); this.keyHead.next = this.keyHead; this.keyHead.prev = this.keyHead; } } } /** * Your AllOne object will be instantiated and called as such: * AllOne obj = new AllOne(); * obj.inc(key); * obj.dec(key); * String param_3 = obj.getMaxKey(); * String param_4 = obj.getMinKey(); */ } ================================================ FILE: src/AllPathsFromSourceToTarget797.java ================================================ /** * Given a directed, acyclic graph of N nodes. Find all possible paths from * node 0 to node N-1, and return them in any order. * * The graph is given as follows: the nodes are0, 1, ..., graph.length - 1. * graph[i] is a list of all nodes j for which the edge (i, j) exists. * * Example: * Input: [[1,2], [3], [3], []] * Output: [[0,1,3],[0,2,3]] * Explanation: The graph looks like this: * 0--->1 * | | * v v * 2--->3 * There are two paths: 0 -> 1 -> 3 and 0 -> 2 -> 3. * * Note: * The number of nodes in the graph will be in the range [2, 15]. * You can print different paths in any order, but you should keep the order * of nodes inside one path. */ public class AllPathsFromSourceToTarget797 { public List> allPathsSourceTarget(int[][] graph) { List> res = new ArrayList<>(); if (graph == null || graph.length == 0) return res; int N = graph.length; backtrace(graph, 0, N-1, new ArrayList<>(), res, N); return res; } private void backtrace(int[][] graph, int current, int dest, List path, List> res, int N) { if (current == dest) { path.add(current); res.add(new ArrayList<>(path)); path.remove(path.size() - 1); return; } path.add(current); for (int child: graph[current]) { backtrace(graph, child, N-1, path, res, N); } path.remove(path.size() - 1); } public List> allPathsSourceTarget2(int[][] graph) { List> res = new ArrayList<>(); if (graph == null || graph.length == 0) return res; int N = graph.length; List path = new ArrayList<>(); path.add(0); backtrace2(graph, 0, N-1, path, res, N); return res; } private void backtrace2(int[][] graph, int current, int dest, List path, List> res, int N) { if (current == dest) { res.add(new ArrayList<>(path)); return; } for (int child: graph[current]) { path.add(child); backtrace2(graph, child, N-1, path, res, N); path.remove(path.size() - 1); } } } ================================================ FILE: src/AndroidUnlockPatterns351.java ================================================ /** * Given an Android 3x3 key lock screen and two integers m and n, where * 1 ≤ m ≤ n ≤ 9, count the total number of unlock patterns of the Android * lock screen, which consist of minimum of m keys and maximum n keys. * * Rules for a valid pattern: * - Each pattern must connect at least m keys and at most n keys. * - All the keys must be distinct. * - If the line connecting two consecutive keys in the pattern passes through * any other keys, the other keys must have previously selected in the pattern. * No jumps through non selected key is allowed. * - The order of keys used matters. * * Explanation: * | 1 | 2 | 3 | * | 4 | 5 | 6 | * | 7 | 8 | 9 | * Invalid move: 4 - 1 - 3 - 6 * Line 1 - 3 passes through key 2 which had not been selected in the pattern. * * Invalid move: 4 - 1 - 9 - 2 * Line 1 - 9 passes through key 5 which had not been selected in the pattern. * * Valid move: 2 - 4 - 1 - 3 - 6 * Line 1 - 3 is valid because it passes through key 2, which had been selected in the pattern * * Valid move: 6 - 5 - 4 - 1 - 9 - 2 * Line 1 - 9 is valid because it passes through key 5, which had been selected in the pattern. * * Example: * Given m = 1, n = 1, return 9. */ public class AndroidUnlockPatterns351 { private int[][] points = new int[][]{{0,0}, {0,1}, {0,2}, {1,0}, {1,1}, {1,2}, {2,0}, {2,1}, {2,2}}; public int numberOfPatterns(int m, int n) { boolean[][] visited = new boolean[3][3]; // corner int[] res0 = new int[1]; dfs(visited, 0, 0, m, n, 1, res0); // edge int[] res1 = new int[1]; dfs(visited, 0, 1, m, n, 1, res1); // center int[] res2 = new int[1]; dfs(visited, 1, 1, m, n, 1, res2); return res0[0] * 4 + res1[0] * 4 + res2[0]; } private void dfs(boolean[][] visited, int i, int j, int m, int n, int level, int[] res) { if (level > n) return; if (level >= m && level <=n) res[0]++; visited[i][j] = true; for (int[] p: points) { if (!visited[p[0]][p[1]] && canGo(i, j, p[0], p[1], visited)) { dfs(visited, p[0], p[1], m, n, level+1, res); } } visited[i][j] = false; } private boolean canGo(int i1, int j1, int i2, int j2, boolean[][] visited) { if (!isJumping(i1, j1, i2, j2)) return true; return visited[(i1+i2)/2][(j1+j2)/2]; } private boolean isJumping(int i1, int j1, int i2, int j2) { return (i1 == i2 && Math.abs(j1-j2) == 2) || (j1 == j2 && Math.abs(i1-i2) == 2) || (Math.abs(i1-i2) == 2 && Math.abs(j1-j2) == 2); } public int numberOfPatterns2(int m, int n) { // Skip array represents number to skip between two pairs int skip[][] = new int[10][10]; skip[1][3] = skip[3][1] = 2; skip[1][7] = skip[7][1] = 4; skip[3][9] = skip[9][3] = 6; skip[7][9] = skip[9][7] = 8; skip[1][9] = skip[9][1] = skip[2][8] = skip[8][2] = skip[3][7] = skip[7][3] = skip[4][6] = skip[6][4] = 5; boolean vis[] = new boolean[10]; int rst = 0; // DFS search each length from m to n for(int i = m; i <= n; ++i) { rst += DFS(vis, skip, 1, i - 1) * 4; // 1, 3, 7, 9 are symmetric rst += DFS(vis, skip, 2, i - 1) * 4; // 2, 4, 6, 8 are symmetric rst += DFS(vis, skip, 5, i - 1); // 5 } return rst; } // cur: the current position // remain: the steps remaining int DFS(boolean vis[], int[][] skip, int cur, int remain) { if(remain < 0) return 0; if(remain == 0) return 1; vis[cur] = true; int rst = 0; for(int i = 1; i <= 9; ++i) { // If vis[i] is not visited and (two numbers are adjacent or skip number is already visited) if(!vis[i] && (skip[cur][i] == 0 || (vis[skip[cur][i]]))) { rst += DFS(vis, skip, i, remain - 1); } } vis[cur] = false; return rst; } public int numberOfPatterns3(int m, int n) { boolean[][] visited = new boolean[3][3]; int[] res = new int[1]; for (int i=0; i<3; i++) { for (int j=0; j<3; j++) { dfs(i, j, visited, m, n, 1, res); } } return res[0]; } private void dfs(int i, int j, boolean[][] visited, int m, int n, int len, int[] res) { if (visited[i][j] || len > n) return; if (len >= m) res[0]++; visited[i][j] = true; for (int ii=0; ii<3; ii++) { int di = Math.abs(i - ii); for (int jj=0; jj<3; jj++) { int dj = Math.abs(j - jj); if (di == 0 && dj == 0) continue; if ((di == 2 && dj != 1) || (dj == 2 && di != 1)) { if (!visited[(i+ii)/2][(j+jj)/2]) continue; } dfs(ii, jj, visited, m, n, len+1, res); } } visited[i][j] = false; } } ================================================ FILE: src/AsyncJobMonitor.java ================================================ /** * */ import java.util.Map; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class AsyncJobMonitor { private static final long INIT_TIME = System.currentTimeMillis(); private Queue queue = new ConcurrentLinkedQueue<>(); private Map endMap = new ConcurrentHashMap<>(); public void start(Job job) { queue.add(job); } public void end(String id, long end) { endMap.put(id, end); cleanQueue(); } private void cleanQueue() { while (!queue.isEmpty() && endMap.containsKey(queue.peek().id)) { Job curr = queue.poll(); curr.end = endMap.get(curr.id); endMap.remove(curr.id); printJob(curr); } } private void printJob(Job job) { System.out.println(String.format("now: %s, job: %s, start: %s, end: %s", System.currentTimeMillis() - INIT_TIME, job.id, job.start - INIT_TIME, job.end - INIT_TIME)); } static class Job { String id; long start; long end; Job(String id, long start) { this.id = id; this.start = start; } } public static void main(String[] args) { AsyncJobMonitor monitor = new AsyncJobMonitor(); ExecutorService executorService = Executors.newFixedThreadPool(5); String[] ids = new String[]{"a", "b", "c", "d", "e"}; long[] times = new long[]{5, 2, 5, 4, 1}; for (int i=0; i<5; i++) { String id = ids[i]; long time = times[i]; executorService.execute(() -> { Job job = new Job(id, System.currentTimeMillis()); monitor.start(job); try { TimeUnit.SECONDS.sleep(time); } catch (InterruptedException ex) { ex.printStackTrace(); } monitor.end(id, System.currentTimeMillis()); }); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException ex) { ex.printStackTrace(); } } executorService.shutdown(); } } ================================================ FILE: src/AverageOfLevelsInBinaryTree637.java ================================================ /** * Given a non-empty binary tree, return the average value of the nodes on each * level in the form of an array. * * Example 1: * Input: * 3 * / \ * 9 20 * / \ * 15 7 * Output: [3, 14.5, 11] * Explanation: * The average value of nodes on level 0 is 3, on level 1 is 14.5, and on * level 2 is 11. Hence return [3, 14.5, 11]. * * Note: * The range of node's value is in the range of 32-bit signed integer. */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class AverageOfLevelsInBinaryTree637 { public List averageOfLevels(TreeNode root) { List res = new ArrayList<>(); Queue q = new LinkedList<>(); q.add(root); while (!q.isEmpty()) { int size = q.size(); long sum = 0L; for (int i=0; i= 0 && indexT >= 0) { char charS = S.charAt(indexS); char charT = T.charAt(indexT); if (charS != '#' && charT != '#' && countS == 0 && countT == 0) { if (charS != charT) return false; indexS--; indexT--; } else { if (charS == '#') { countS++; indexS--; } else { if (countS != 0) { countS--; indexS--; } } if (charT == '#') { countT++; indexT--; } else { if (countT != 0) { countT--; indexT--; } } } } while (indexS >= 0) { if (S.charAt(indexS) == '#') { countS++; } else { if (countS == 0) return false; countS--; } indexS--; } while (indexT >= 0) { if (T.charAt(indexT) == '#') { countT++; } else { if (countT == 0) return false; countT--; } indexT--; } return true; } /** * https://leetcode.com/problems/backspace-string-compare/solution/ */ public boolean backspaceCompare2(String S, String T) { return build(S).equals(build(T)); } public String build(String S) { Stack ans = new Stack(); for (char c: S.toCharArray()) { if (c != '#') ans.push(c); else if (!ans.empty()) ans.pop(); } return String.valueOf(ans); } /** * https://leetcode.com/problems/backspace-string-compare/solution/ */ public boolean backspaceCompare3(String S, String T) { int i = S.length() - 1, j = T.length() - 1; int skipS = 0, skipT = 0; while (i >= 0 || j >= 0) { // While there may be chars in build(S) or build (T) while (i >= 0) { // Find position of next possible char in build(S) if (S.charAt(i) == '#') {skipS++; i--;} else if (skipS > 0) {skipS--; i--;} else break; } while (j >= 0) { // Find position of next possible char in build(T) if (T.charAt(j) == '#') {skipT++; j--;} else if (skipT > 0) {skipT--; j--;} else break; } // If two actual characters are different if (i >= 0 && j >= 0 && S.charAt(i) != T.charAt(j)) return false; // If expecting to compare char vs nothing if ((i >= 0) != (j >= 0)) return false; i--; j--; } return true; } } ================================================ FILE: src/BalancedBinaryTree110.java ================================================ /** * Given a binary tree, determine if it is height-balanced. * * For this problem, a height-balanced binary tree is defined as a binary tree * in which the depth of the two subtrees of every node never differ by * more than 1. */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class BalancedBinaryTree110 { public boolean isBalanced(TreeNode root) { if (root == null) { return true; } int depthL = depth(root.left); int depthR = depth(root.right); return Math.abs(depthL - depthR) <= 1 && isBalanced(root.left) && isBalanced(root.right); } private int depth(TreeNode node) { if (node == null) { return 0; } int depthL = depth(node.left); int depthR = depth(node.right); return Math.max(depthL, depthR) + 1; } /** * https://discuss.leetcode.com/topic/11007/java-solution-based-on-height-check-left-and-right-node-in-every-recursion-to-avoid-further-useless-search */ public boolean isBalanced2(TreeNode root) { if (root == null) { return true; } return height(root) != -1; } public int height(TreeNode node){ if (node == null) { return 0; } int lH = height(node.left); if (lH == -1) { return -1; } int rH = height(node.right); if (rH == -1) { return -1; } if (lH-rH < -1 || lH-rH > 1) { return -1; } return Math.max(lH,rH) + 1; } public static void main(String[] args) { BalancedBinaryTree110 bbt = new BalancedBinaryTree110(); TreeNode root1 = new TreeNode(2); root1.left = new TreeNode(1); root1.right = new TreeNode(3); TreeNode root3 = new TreeNode(2); root3.left = new TreeNode(1); TreeNode root2 = new TreeNode(2); root2.left = root3; TreeNode n1 = new TreeNode(1); TreeNode n2 = new TreeNode(2); TreeNode n3 = new TreeNode(3); TreeNode n4 = new TreeNode(4); TreeNode n5 = new TreeNode(5); TreeNode n6 = new TreeNode(6); TreeNode n7 = new TreeNode(7); TreeNode n8 = new TreeNode(8); n4.left = n7; n2.left = n4; n2.right = n5; n1.left = n2; n6.right = n8; n3.right = n6; n1.right = n3; System.out.println("-------- 1"); System.out.println(bbt.isBalanced(root1)); System.out.println("-------- 2"); System.out.println(bbt.isBalanced(root2)); System.out.println("-------- 3"); System.out.println(bbt.isBalanced(root3)); System.out.println("-------- 4"); System.out.println(bbt.isBalanced(n1)); } } ================================================ FILE: src/BaseballGame682.java ================================================ /** * You're now a baseball game point recorder. * * Given a list of strings, each string can be one of the 4 following types: * * Integer (one round's score): Directly represents the number of points you get in this round. * "+" (one round's score): Represents that the points you get in this round are the sum of the last two valid round's points. * "D" (one round's score): Represents that the points you get in this round are the doubled data of the last valid round's points. * "C" (an operation, which isn't a round's score): Represents the last valid round's points you get were invalid and should be removed. * Each round's operation is permanent and could have an impact on the round before and the round after. * * You need to return the sum of the points you could get in all the rounds. * * Example 1: * Input: ["5","2","C","D","+"] * Output: 30 * Explanation: * Round 1: You could get 5 points. The sum is: 5. * Round 2: You could get 2 points. The sum is: 7. * Operation 1: The round 2's data was invalid. The sum is: 5. * Round 3: You could get 10 points (the round 2's data has been removed). The sum is: 15. * Round 4: You could get 5 + 10 = 15 points. The sum is: 30. * * Example 2: * Input: ["5","-2","4","C","D","9","+","+"] * Output: 27 * Explanation: * Round 1: You could get 5 points. The sum is: 5. * Round 2: You could get -2 points. The sum is: 3. * Round 3: You could get 4 points. The sum is: 7. * Operation 1: The round 3's data is invalid. The sum is: 3. * Round 4: You could get -4 points (the round 3's data has been removed). The sum is: -1. * Round 5: You could get 9 points. The sum is: 8. * Round 6: You could get -4 + 9 = 5 points. The sum is 13. * Round 7: You could get 9 + 5 = 14 points. The sum is 27. * * Note: * The size of the input list will be between 1 and 1000. * Every integer represented in the list will be between -30000 and 30000. */ public class BaseballGame682 { public int calPoints(String[] ops) { if (ops == null || ops.length == 0) return 0; Stack stack = new Stack<>(); int sum = 0; for (String op: ops) { if (op.equals("+")) { if (stack.size() >= 2) { int e1 = stack.pop(); int e2 = stack.peek(); int twoSum = e1 + e2; sum += twoSum; stack.push(e1); stack.push(twoSum); } } else if (op.equals("D")) { if (!stack.isEmpty()) { int doubledScore = stack.peek() * 2; sum += doubledScore; stack.push(doubledScore); } } else if (op.equals("C")) { if (!stack.isEmpty()) { int lastScore = stack.pop(); sum -= lastScore; } } else { int now = Integer.parseInt(op); sum += now; stack.push(now); } } return sum; } } ================================================ FILE: src/BasicCalculator224.java ================================================ /** * Implement a basic calculator to evaluate a simple expression string. * * The expression string may contain open ( and closing parentheses ), the * plus + or minus sign -, non-negative integers and empty spaces . * * You may assume that the given expression is always valid. * * Some examples: * "1 + 1" = 2 * " 2-1 + 2 " = 3 * "(1+(4+5+2)-3)+(6+8)" = 23 * Note: Do not use the eval built-in library function. * */ public class BasicCalculator224 { public int calculate(String s) { int L = s.length(); int result = 0; int start = 0; boolean isNum = false; boolean doPlus = true; for (int i=0; i l = calculate(s, i+1, L); result = doCal(result, l.get(0), doPlus); i = l.get(1); } } if (isNum) { return doCal(s, result, start, L, doPlus); } return result; } private List calculate(String s, int from, int L) { int result = 0; int start = from; int to = from; boolean isNum = false; boolean doPlus = true; for (int i=from; i l = calculate(s, i+1, L); result = doCal(result, l.get(0), doPlus); i = l.get(1); } else { to = i; break; } } if (isNum) { return Arrays.asList(doCal(s, result, start, to, doPlus), to); } return Arrays.asList(result, to); } private int doCal(String s, int previous, int start, int end, boolean doPlus) { int num = Integer.parseInt(s.substring(start, end)); return doCal(previous, num, doPlus); } private int doCal(int previous, int num, boolean doPlus) { if (doPlus) { return previous + num; } else { return previous - num; } } private boolean isPlus(char c) { return c == '+'; } private boolean isMunis(char c) { return c == '-'; } private boolean isOpen(char c) { return c == '('; } private boolean isClose(char c) { return c == ')'; } private boolean isDigit(char c) { return c >= '0' && c <= '9'; } private boolean isSpace(char c) { return c == ' '; } /** * https://discuss.leetcode.com/topic/15816/iterative-java-solution-with-stack */ public int calculate2(String s) { Stack stack = new Stack(); int result = 0; int number = 0; int sign = 1; for(int i = 0; i < s.length(); i++){ char c = s.charAt(i); if(Character.isDigit(c)){ number = 10 * number + (int)(c - '0'); }else if(c == '+'){ result += sign * number; number = 0; sign = 1; }else if(c == '-'){ result += sign * number; number = 0; sign = -1; }else if(c == '('){ //we push the result first, then sign; stack.push(result); stack.push(sign); //reset the sign and result for the value in the parenthesis sign = 1; result = 0; }else if(c == ')'){ result += sign * number; number = 0; result *= stack.pop(); //stack.pop() is the sign before the parenthesis result += stack.pop(); //stack.pop() now is the result calculated before the parenthesis } } if(number != 0) result += sign * number; return result; } public int calculate3(String s) { char[] chars = s.toCharArray(); int i = 0; int N = chars.length; int sign = 1; Stack stack = new Stack<>(); while (i < N) { char ch = chars[i]; if (ch == ' ') { i++; } else if (ch == '+') { sign = 1; i++; } else if (ch == '-') { sign = -1; i++; } else if (ch == '(') { stack.push((sign == 1 ? "+" : "-") + Character.toString(ch)); sign = 1; i++; } else if (ch == ')') { int local = 0; while (!stack.isEmpty() && !stack.peek().endsWith("(")) { local += Integer.valueOf(stack.pop()); } if (stack.isEmpty()) { stack.push(Integer.toString(local)); } else { String op = stack.pop(); if (op.startsWith("+")) { stack.push(Integer.toString(local)); } else { stack.push(Integer.toString(-local)); } } i++; } else { int j = getNum(chars, i); stack.push((sign == 1 ? "+" : "-") + s.substring(i, j)); i = j; } } int res = 0; while (!stack.isEmpty()) res += Integer.valueOf(stack.pop()); return res; } private int getNum(char[] chars, int i) { int j = i; while (j < chars.length && Character.isDigit(chars[j])) j++; return j; } /** * https://leetcode.com/problems/basic-calculator-ii/discuss/63088/Explanation-for-Java-O(n)-time-and-O(1)-space-solution */ public int calculate4(String s) { int pre = 0, curr = 0, sign = 1, op = 0, num = 0; for (int i = 0; i < s.length(); i++) { if (Character.isDigit(s.charAt(i))) { num = num * 10 + (s.charAt(i) - '0'); if (i == s.length() - 1 || !Character.isDigit(s.charAt(i + 1))) { curr = (op == 0 ? num : (op == 1 ? curr * num : curr / num)); } } else if (s.charAt(i) == '*' || s.charAt(i) == '/') { op = (s.charAt(i) == '*' ? 1 : -1); num = 0; } else if (s.charAt(i) == '+' || s.charAt(i) == '-') { pre += sign * curr; sign = (s.charAt(i) == '+' ? 1 : -1); op = 0; num = 0; } } return pre + sign * curr; } } ================================================ FILE: src/BasicCalculatorII227.java ================================================ /** * Implement a basic calculator to evaluate a simple expression string. * * The expression string contains only non-negative integers, +, -, *, / * operators and empty spaces . The integer division should truncate toward * zero. * * Example 1: * Input: "3+2*2" * Output: 7 * * Example 2: * Input: " 3/2 " * Output: 1 * * Example 3: * Input: " 3+5 / 2 " * Output: 5 * * Note: * You may assume that the given expression is always valid. * Do not use the eval built-in library function. */ public class BasicCalculatorII227 { public int calculate(String s) { char[] chars = s.toCharArray(); int N = s.length(); int res = 0; int i = 0; while (i < N && chars[i] == ' ') i++; int j = getNum(chars, i); int num = Integer.valueOf(s.substring(i, j)); i = j; while (i < N) { while (i < N && chars[i] == ' ') i++; if (i == N) break; char op = chars[i]; i++; while (i < N && chars[i] == ' ') i++; if (i == N) break; j = getNum(chars, i); int curr = Integer.valueOf(s.substring(i, j)); i = j; if (op == '+') { res += num; num = curr; } else if (op == '-') { res += num; num = -curr; } else if (op == '*') { num *= curr; } else { num /= curr; } } return res + num; } private int getNum(char[] chars, int i) { int j = i; while (j < chars.length && Character.isDigit(chars[j])) { j++; } return j; } } ================================================ FILE: src/Bench.java ================================================ /** * https://www.careercup.com/question?id=6204431937830912 */ import java.util.Arrays; import java.util.PriorityQueue; import java.util.Comparator; public class Bench { public static void sitFarestFromPeople(boolean[] bench, int k) { if (bench == null || bench.length == 0 || k <= 0) return; Comparator comp = (r1, r2) -> Integer.compare(r2.right - r2.left, r1.right - r1.left); PriorityQueue pq = new PriorityQueue<>(1, comp); int L = bench.length; int pre = -1; for (int i=0; i= 0 && curr.left + 1 < mid) { pq.add(new Range(curr.left, mid)); } if (curr.right < L && mid + 1 < curr.right) { pq.add(new Range(mid, curr.right)); } } } static class Range { int left; int right; Range (int l, int r) { this.left = l; this.right = r; } } public static void main(String[] args) { boolean[] bench1 = new boolean[]{true, false, false, false, true, false, true}; sitFarestFromPeople(bench1, 1); System.out.println(Arrays.toString(bench1)); boolean[] bench2 = new boolean[]{true, false, false, false, false, true, false, true}; sitFarestFromPeople(bench2, 2); System.out.println(Arrays.toString(bench2)); boolean[] bench3 = new boolean[]{false, false, false, true, false, true}; sitFarestFromPeople(bench3, 2); System.out.println(Arrays.toString(bench3)); } } ================================================ FILE: src/BestMeetingPoint296.java ================================================ /** * A group of two or more people wants to meet and minimize the total travel * distance. You are given a 2D grid of values 0 or 1, where each 1 marks the * home of someone in the group. The distance is calculated using * Manhattan Distance (http://en.wikipedia.org/wiki/Taxicab_geometry), where * distance(p1, p2) = |p2.x - p1.x| + |p2.y - p1.y|. * * Example: * * Input: * 1 - 0 - 0 - 0 - 1 * | | | | | * 0 - 0 - 0 - 0 - 0 * | | | | | * 0 - 0 - 1 - 0 - 0 * * Output: 6 * * Explanation: Given three people living at (0,0), (0,4), and (2,2): * The point (0,2) is an ideal meeting point, as the total travel distance * of 2+2+2=6 is minimal. So return 6. */ public class BestMeetingPoint296 { /** * https://leetcode.com/problems/best-meeting-point/discuss/74186/14ms-java-solution */ public int minTotalDistance(int[][] grid) { int m = grid.length; int n = grid[0].length; List I = new ArrayList<>(m); List J = new ArrayList<>(n); for(int i = 0; i < m; i++){ for(int j = 0; j < n; j++){ if(grid[i][j] == 1){ I.add(i); J.add(j); } } } return getMin(I) + getMin(J); } private int getMin(List list){ int ret = 0; Collections.sort(list); int i = 0; int j = list.size() - 1; while(i < j){ ret += list.get(j--) - list.get(i++); } return ret; } } ================================================ FILE: src/BestTimeToBuyAndSellStock121.java ================================================ /** * Say you have an array for which the ith element is the price of a given * stock on day i. * * If you were only permitted to complete at most one transaction (ie, buy one * and sell one share of the stock), design an algorithm to find the maximum * profit. * * Example 1: * Input: [7, 1, 5, 3, 6, 4] * Output: 5 * * max. difference = 6-1 = 5 (not 7-1 = 6, as selling price needs to be larger than buying price) * * Example 2: * Input: [7, 6, 4, 3, 1] * Output: 0 * * In this case, no transaction is done, i.e. max profit = 0. * */ public class BestTimeToBuyAndSellStock121 { public int maxProfit(int[] prices) { if (prices == null || prices.length <= 1) return 0; int minSoFar = Integer.MAX_VALUE; int res = 0; for (int p: prices) { if (p > minSoFar) { res = Math.max(res, p - minSoFar); } else { minSoFar = p; } } return res; } public int maxProfit2(int[] prices) { int buy = Integer.MIN_VALUE; int sell = 0; for (int p: prices) { int oldBuy = buy; buy = Math.max(buy, - p); sell = Math.max(sell, oldBuy + p); } return sell; } } ================================================ FILE: src/BestTimeToBuyAndSellStockII122.java ================================================ /** * Say you have an array for which the ith element is the price of a given stock * on day i. * * Design an algorithm to find the maximum profit. You may complete as many * transactions as you like (ie, buy one and sell one share of the stock * multiple times). However, you may not engage in multiple transactions at * the same time (ie, you must sell the stock before you buy again). * */ public class BestTimeToBuyAndSellStockII122 { public int maxProfit(int[] prices) { if (prices == null || prices.length <= 1) return 0; int[] buy = new int[prices.length]; int[] sell = new int[prices.length]; buy[0] = -prices[0]; for (int i=1; iprices[i-1]){ profit+= prices[i]-prices[i-1]; } } return profit; } } ================================================ FILE: src/BestTimeToBuyAndSellStockIII123.java ================================================ /** * Say you have an array for which the ith element is the price of a given * stock on day i. * * Design an algorithm to find the maximum profit. You may complete at most * two transactions. * * Note: * You may not engage in multiple transactions at the same time (ie, you must * sell the stock before you buy again). * */ public class BestTimeToBuyAndSellStockIII123 { public int maxProfit(int[] prices) { if (prices == null || prices.length <= 1) return 0; int buy = Integer.MIN_VALUE; int preBuy = Integer.MIN_VALUE; int sell = 0; int preSell = 0; for (int p: prices) { sell = Math.max(sell, buy + p); buy = Math.max(buy, preSell - p); preSell = Math.max(preSell, preBuy + p); preBuy = Math.max(preBuy, - p); } return sell; } public int maxProfit2(int[] prices) { return maxProfit(2, prices); } public int maxProfit(int k, int[] prices) { if (prices == null || prices.length <= 1 || k <= 0) return 0; if (k >= prices.length >>> 1) { int profit = 0; for(int i=1; i prices[i-1]){ profit += prices[i] - prices[i-1]; } } return profit; } int[] buy = new int[k+1]; int[] sell = new int[k+1]; for (int j=0; j<=k; j++) { buy[j] = Integer.MIN_VALUE; } for (int price : prices) { for (int j=1; j<=k; j++) { buy[j] = Math.max(buy[j], sell[j-1] - price); sell[j] = Math.max(sell[j], buy[j] + price); } } return sell[k]; } } ================================================ FILE: src/BestTimeToBuyAndSellStockIV188.java ================================================ /** * Say you have an array for which the ith element is the price of a given * stock on day i. * * Design an algorithm to find the maximum profit. You may complete at most * k transactions. * * Note: * You may not engage in multiple transactions at the same time (ie, you must * sell the stock before you buy again). * * Example 1: * * Input: [2,4,1], k = 2 * Output: 2 * Explanation: * Buy on day 1 (price = 2) and sell on day 2 (price = 4), profit = 4-2 = 2. * * Example 2: * * Input: [3,2,6,5,0,3], k = 2 * Output: 7 * Explanation: * Buy on day 2 (price = 2) and sell on day 3 (price = 6), profit = 6-2 = 4. * Then buy on day 5 (price = 0) and sell on day 6 (price = 3), profit = 3-0 = 3. * */ public class BestTimeToBuyAndSellStockIV188 { public int maxProfit(int k, int[] prices) { if (prices == null || prices.length <= 1 || k <= 0) return 0; if (k >= prices.length >>> 1) { int profit = 0; for(int i=1; i prices[i-1]){ profit += prices[i] - prices[i-1]; } } return profit; } int[] buy = new int[k]; int[] sell = new int[k]; for (int j=0; j= len / 2) return quickSolve(prices); int[][] t = new int[k + 1][len]; for (int i = 1; i <= k; i++) { int tmpMax = -prices[0]; for (int j = 1; j < len; j++) { t[i][j] = Math.max(t[i][j - 1], prices[j] + tmpMax); tmpMax = Math.max(tmpMax, t[i - 1][j - 1] - prices[j]); } } return t[k][len - 1]; } private int quickSolve(int[] prices) { int len = prices.length, profit = 0; for (int i = 1; i < len; i++) // as long as there is a price gap, we gain a profit. if (prices[i] > prices[i - 1]) profit += prices[i] - prices[i - 1]; return profit; } } ================================================ FILE: src/BestTimeToBuyAndSellStockWithCooldown309.java ================================================ /** * Say you have an array for which the ith element is the price of a given * stock on day i. * * Design an algorithm to find the maximum profit. You may complete as many * transactions as you like (ie, buy one and sell one share of the stock * multiple times) with the following restrictions: * * You may not engage in multiple transactions at the same time (ie, you * must sell the stock before you buy again). * * After you sell your stock, you cannot buy stock on next day. * (ie, cooldown 1 day) * * Example: * * prices = [1, 2, 3, 0, 2] * maxProfit = 3 * transactions = [buy, sell, cooldown, buy, sell] * */ public class BestTimeToBuyAndSellStockWithCooldown309 { /** * https://discuss.leetcode.com/topic/30421/share-my-thinking-process */ public int maxProfit(int[] prices) { int sell = 0, prev_sell = 0, buy = Integer.MIN_VALUE, prev_buy; for (int price : prices) { prev_buy = buy; buy = Math.max(prev_sell - price, prev_buy); prev_sell = sell; sell = Math.max(prev_buy + price, prev_sell); } return sell; } /** * https://discuss.leetcode.com/topic/30431/easiest-java-solution-with-explanations/35 */ public int maxProfit2(int[] prices) { if(prices == null || prices.length <= 1) return 0; int b0 = -prices[0], b1 = b0; int s0 = 0, s1 = 0, s2 = 0; for(int i = 1; i < prices.length; i++) { b0 = Math.max(b1, s2 - prices[i]); s0 = Math.max(s1, b1 + prices[i]); b1 = b0; s2 = s1; s1 = s0; } return s0; } } ================================================ FILE: src/BestTimeToBuyAndSellStockWithTransactionFee714.java ================================================ /** * Your are given an array of integers prices, for which the i-th element is * the price of a given stock on day i; and a non-negative integer fee * representing a transaction fee. * * You may complete as many transactions as you like, but you need to pay the * transaction fee for each transaction. You may not buy more than 1 share of * a stock at a time (ie. you must sell the stock share before you buy again.) * * Return the maximum profit you can make. * * Example 1: * Input: prices = [1, 3, 2, 8, 4, 9], fee = 2 * Output: 8 * Explanation: The maximum profit can be achieved by: * Buying at prices[0] = 1 * Selling at prices[3] = 8 * Buying at prices[4] = 4 * Selling at prices[5] = 9 * The total profit is ((8 - 1) - 2) + ((9 - 4) - 2) = 8. * * Note: * 0 < prices.length <= 50000. * 0 < prices[i] < 50000. * 0 <= fee < 50000. * */ public class BestTimeToBuyAndSellStockWithTransactionFee714 { public int maxProfit(int[] prices, int fee) { if (prices == null || prices.length < 2) return 0; int[] buy = new int[prices.length]; int sell = 0; buy[0] = -prices[0] - fee; for (int i=1; i stack = new Stack(); public BSTIterator(TreeNode root) { if (root != null) { addAllLeft(root); } } private void addAllLeft(TreeNode node) { while (true) { this.stack.push(node); node = node.left; if (node == null) return; } } /** @return whether we have a next smallest number */ public boolean hasNext() { return !this.stack.isEmpty(); } /** @return the next smallest number */ public int next() { TreeNode tmp = this.stack.pop(); int returned = tmp.val; if (tmp.right != null) { addAllLeft(tmp.right); } return returned; } } /** * Your BSTIterator will be called like this: * BSTIterator i = new BSTIterator(root); * while (i.hasNext()) v[f()] = i.next(); */ } ================================================ FILE: src/BinaryTreeInorderTraversal94.java ================================================ /** * Given a binary tree, return the inorder traversal of its nodes' values. * * For example: * Given binary tree [1,null,2,3], * 1 * \ * 2 * / * 3 * return [1,3,2]. * * Note: Recursive solution is trivial, could you do it iteratively? */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ import java.util.ArrayList; import java.util.List; import java.util.Stack; public class BinaryTreeInorderTraversal94 { public List inorderTraversal(TreeNode root) { if (node == null) { return new ArrayList(); } List result = new ArrayList<>(); if (root.left == null && root.right == null) { result.add(root.val); return result; } result.addAll(inorderTraversal(root.left)); result.add(root.val); result.addAll(inorderTraversal(root.right)); return result; } /** * https://discuss.leetcode.com/topic/6478/iterative-solution-in-java-simple-and-readable */ public List inorderTraversal2(TreeNode root) { List list = new ArrayList(); Stack stack = new Stack(); TreeNode cur = root; while (cur != null || !stack.empty()){ while (cur != null){ stack.add(cur); cur = cur.left; } cur = stack.pop(); list.add(cur.val); cur = cur.right; } return list; } public List inorderTraversal3(TreeNode root) { List res = new ArrayList<>(); inorderTraversal(root, res); return res; } private void inorderTraversal(TreeNode root, List res) { if (root == null) return; inorderTraversal(root.left, res); res.add(root.val); inorderTraversal(root.right, res); } } ================================================ FILE: src/BinaryTreeLevelOrderTraversal102.java ================================================ /** * Given a binary tree, return the level order traversal of its nodes' values. * (ie, from left to right, level by level). * * For example: * Given binary tree [3,9,20,null,null,15,7], * 3 * / \ * 9 20 * / \ * 15 7 * return its level order traversal as: * [ * [3], * [9,20], * [15,7] * ] */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ import java.util.LinkedList; import java.util.Queue; import java.util.ArrayList; import java.util.List; public class BinaryTreeLevelOrderTraversal102 { public List> levelOrder(TreeNode root) { Queue q = new LinkedList<>(); List> result = new ArrayList<>(); int level = 0; if (root == null) { return result; } else { q.add(root); } helper(q, result, 0); return result; } private void helper(Queue q, List> result, int level) { int s = q.size(); if (s == 0) { return; } addLevel(result, level); int i = 0; while (i < s) { TreeNode now = q.poll(); result.get(level).add(now.val); if (now.left != null) { q.add(now.left); } if (now.right != null) { q.add(now.right); } i++; } helper(q, result, level + 1); } private void addLevel(List> result, int level) { while (result.size() <= level) { result.add(new ArrayList()); } } /** * https://discuss.leetcode.com/topic/7647/java-solution-with-a-queue-used */ public List> levelOrder2(TreeNode root) { Queue queue = new LinkedList(); List> wrapList = new LinkedList>(); if(root == null) return wrapList; queue.offer(root); while(!queue.isEmpty()){ int levelNum = queue.size(); List subList = new LinkedList(); for(int i=0; i> levelOrder3(TreeNode root) { List> res = new ArrayList<>(); if (root == null) return res; Queue queue = new LinkedList<>(); queue.add(root); while (!queue.isEmpty()) { List level = new ArrayList<>(); int cnt = queue.size(); for (int i = 0; i < cnt; i++) { TreeNode node = queue.poll(); level.add(node.val); if (node.left != null) { queue.add(node.left); } if (node.right != null) { queue.add(node.right); } } res.add(level); } return res; } /** * https://discuss.leetcode.com/topic/7332/java-solution-using-dfs */ public List> levelOrder(TreeNode root) { List> res = new ArrayList>(); levelHelper(res, root, 0); return res; } public void levelHelper(List> res, TreeNode root, int height) { if (root == null) return; if (height >= res.size()) { res.add(new LinkedList()); } res.get(height).add(root.val); levelHelper(res, root.left, height+1); levelHelper(res, root.right, height+1); } } ================================================ FILE: src/BinaryTreeLevelOrderTraversalII107.java ================================================ /** * Given a binary tree, return the bottom-up level order traversal of its * nodes' values. (ie, from left to right, level by level from leaf to root). * * For example: * Given binary tree [3,9,20,null,null,15,7], * 3 * / \ * 9 20 * / \ * 15 7 * return its bottom-up level order traversal as: * [ * [15,7], * [9,20], * [3] * ] */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class BinaryTreeLevelOrderTraversalII107 { public List> levelOrderBottom(TreeNode root) { LinkedList> res = new LinkedList<>(); if (root == null) return res; Queue q = new LinkedList<>(); q.add(root); while (!q.isEmpty()) { int size = q.size(); List level = new ArrayList<>(); for (int i=0; i> levelOrderBottom2(TreeNode root) { LinkedList> res = new LinkedList<>(); if (root == null) return res; levelOrder(root, 0, res); return res; } private void levelOrder(TreeNode root, int level, LinkedList> res) { if (root == null) return; if (res.size() <= level) res.addFirst(new ArrayList<>()); levelOrder(root.left, level+1, res); levelOrder(root.right, level+1, res); res.get(res.size()-level-1).add(root.val); } } ================================================ FILE: src/BinaryTreeLongestConsecutiveSequence298.java ================================================ /** * Given a binary tree, find the length of the longest consecutive sequence path. * * The path refers to any sequence of nodes from some starting node to any node * in the tree along the parent-child connections. The longest consecutive path * need to be from parent to child (cannot be the reverse). * * Example 1: * * Input: * * 1 * \ * 3 * / \ * 2 4 * \ * 5 * * Output: 3 * Explanation: Longest consecutive sequence path is 3-4-5, so return 3. * * Example 2: * * Input: * * 2 * \ * 3 * / * 2 * / * 1 * * Output: 2 * Explanation: Longest consecutive sequence path is 2-3, not 3-2-1, so return 2. */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class BinaryTreeLongestConsecutiveSequence298 { public int longestConsecutive(TreeNode root) { if (root == null) return 0; return helper(root, 0); } public int helper(TreeNode root, int i) { if (root == null) return i; int l = i + 1; if (root.left != null) { if (root.val + 1 == root.left.val) { l = helper(root.left, i+1); } else { l = helper(root.left, 0); } } int r = i + 1; if (root.right != null) { if (root.val + 1 == root.right.val) { r = helper(root.right, i+1); } else { r = helper(root.right, 0); } } return Math.max(Math.max(l, r), i+1); } /** * Bottom-up * https://leetcode.com/problems/binary-tree-longest-consecutive-sequence/solution/ */ private int maxLength = 0; public int longestConsecutive2(TreeNode root) { dfs(root); return maxLength; } private int dfs(TreeNode p) { if (p == null) return 0; int L = dfs(p.left) + 1; int R = dfs(p.right) + 1; if (p.left != null && p.val + 1 != p.left.val) { L = 1; } if (p.right != null && p.val + 1 != p.right.val) { R = 1; } int length = Math.max(L, R); maxLength = Math.max(maxLength, length); return length; } } ================================================ FILE: src/BinaryTreeMaximumPathSum124.java ================================================ /** * Given a binary tree, find the maximum path sum. * * For this problem, a path is defined as any sequence of nodes from some starting node to any node in the tree along the parent-child connections. * The path must contain at least one node and does not need to go through the root. * * For example: * Given the below binary tree, * * 1 * / \ * 2 3 * * Return 6. */ public class BinaryTreeMaximumPathSum124 { private int maxSum; public int maxPathSum(TreeNode root) { maxSum = Integer.MIN_VALUE; maxBranch(root); return maxSum; } private int maxBranch(TreeNode root) { if (root == null) return 0; int valueLeft = Math.max(0, maxBranch(root.left)); int valueRight = Math.max(0, maxBranch(root.right)); maxSum = Math.max(maxSum, root.val + valueLeft + valueRight); return Math.max(valueLeft, valueRight) + root.val; } public static void main(String[] args) { BinaryTreeMaximumPathSum124 btmps = new BinaryTreeMaximumPathSum124(); TreeNode root1 = new TreeNode(2); root1.left = new TreeNode(1); root1.right = new TreeNode(3); TreeNode root2 = new TreeNode(-3); System.out.println(btmps.maxPathSum(root1)); System.out.println(btmps.maxPathSum(root2)); } } ================================================ FILE: src/BinaryTreePaths257.java ================================================ /** * Given a binary tree, return all root-to-leaf paths. * * For example, given the following binary tree: * * 1 * / \ * 2 3 * \ * 5 * All root-to-leaf paths are: * * ["1->2->5", "1->3"] * */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class BinaryTreePaths257 { public List binaryTreePaths(TreeNode root) { List res = new ArrayList<>(); binaryTreePaths(root, new StringBuilder(), res); return res; } public void binaryTreePaths(TreeNode root, StringBuilder path, List res) { if (root == null) return; path.append(root.val); if (root.left == null && root.right == null) { res.add(path.toString()); return; } path.append("->"); int l = path.length(); binaryTreePaths(root.left, path, res); path.delete(l, path.length()); binaryTreePaths(root.right, path, res); path.delete(l, path.length()); } /** * https://leetcode.com/problems/binary-tree-paths/discuss/68278/My-Java-solution-in-DFS-BFS-recursion */ public List binaryTreePaths2(TreeNode root) { List sList=new LinkedList(); if (root==null) return sList; if (root.left==null && root.right==null) { sList.add(Integer.toString(root.val)); return sList; } for (String s: binaryTreePaths(root.left)) { sList.add(Integer.toString(root.val)+"->"+s); } for (String s: binaryTreePaths(root.right)) { sList.add(Integer.toString(root.val)+"->"+s); } return sList; } } ================================================ FILE: src/BinaryTreePreorderTraversal144.java ================================================ /** * Given a binary tree, return the preorder traversal of its nodes' values. * * Example: * * Input: [1,null,2,3] * 1 * \ * 2 * / * 3 * Output: [1,2,3] * * Follow up: Recursive solution is trivial, could you do it iteratively? */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class BinaryTreePreorderTraversal144 { public List preorderTraversal(TreeNode root) { List res = new ArrayList<>(); helper(root, res); return res; } private void helper(TreeNode root, List res) { if (root == null) return; res.add(root.val); helper(root.left, res); helper(root.right, res); } public List preorderTraversal2(TreeNode root) { List res = new ArrayList<>(); if (root == null) return res; Stack stack = new Stack<>(); stack.add(root); while (!stack.isEmpty()) { TreeNode curr = stack.pop(); res.add(curr.val); if (curr.right != null) stack.add(curr.right); if (curr.left != null) stack.add(curr.left); } return res; } } ================================================ FILE: src/BinaryTreeRightSideView199.java ================================================ /** * Given a binary tree, imagine yourself standing on the right side of it, * return the values of the nodes you can see ordered from top to bottom. * * Example: * * Input: [1,2,3,null,5,null,4] * Output: [1, 3, 4] * * Explanation: * * 1 <--- * / \ * 2 3 <--- * \ \ * 5 4 <--- */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class BinaryTreeRightSideView199 { public List rightSideView(TreeNode root) { List res = new ArrayList<>(); rightSideView(root, res, 0); return res; } public void rightSideView(TreeNode root, List res, int level) { if (root == null) return; if (level >= res.size()) res.add(root.val); if (root.right != null) rightSideView(root.right, res, level+1); if (root.left != null) rightSideView(root.left, res, level+1); } } ================================================ FILE: src/BinaryTreeVerticalOrderTraversal314.java ================================================ /** * Given a binary tree, return the vertical order traversal of its nodes' values. * (ie, from top to bottom, column by column). * * If two nodes are in the same row and column, the order should be from left to right. * * Examples: * * 1. Given binary tree [3,9,20,null,null,15,7], * 3 * /\ * / \ * 9 20 * /\ * / \ * 15 7 * return its vertical order traversal as: * [ * [9], * [3,15], * [20], * [7] * ] * * * 2. Given binary tree [3,9,8,4,0,1,7], * 3 * /\ * / \ * 9 8 * /\ /\ * / \/ \ * 4 01 7 * return its vertical order traversal as: * [ * [4], * [9], * [3,0,1], * [8], * [7] * ] * * * 3. Given binary tree [3,9,8,4,0,1,7,null,null,null,2,5] (0's right child is 2 and 1's left child is 5), * 3 * /\ * / \ * 9 8 * /\ /\ * / \/ \ * 4 01 7 * /\ * / \ * 5 2 * return its vertical order traversal as: * [ * [4], * [9,5], * [3,0,1], * [8,2], * [7] * ] * */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class BinaryTreeVerticalOrderTraversal314 { public List> verticalOrder(TreeNode root) { if (root == null) return new ArrayList>(); Map> map = new HashMap<>(); Queue q = new LinkedList<>(); Map vs = new HashMap<>(); q.offer(root); vs.put(root, 0); int min = 0; while (!q.isEmpty()) { TreeNode curr = q.poll(); int i = vs.get(curr); if (curr.left != null) { vs.put(curr.left, i-1); q.offer(curr.left); } if (curr.right != null) { vs.put(curr.right, i+1); q.offer(curr.right); } map.computeIfAbsent(i, p -> new ArrayList()).add(curr.val); min = Math.min(min, i); } List> res = new ArrayList<>(); while (map.containsKey(min)) { res.add(map.get(min++)); } return res; } public List> verticalOrder2(TreeNode root) { if (root == null) return new ArrayList>(); Map> map = new HashMap<>(); Queue q = new LinkedList<>(); Queue qi = new LinkedList<>(); q.add(root); qi.add(0); int min = 0; while (!q.isEmpty()) { TreeNode curr = q.remove(); Integer i = qi.remove(); if (curr.left != null) { qi.add(i-1); q.add(curr.left); } if (curr.right != null) { qi.add(i+1); q.add(curr.right); } if (!map.containsKey(i)) { map.put(i, new ArrayList()); } map.get(i).add(curr.val); // map.computeIfAbsent(i, p -> new ArrayList()).add(curr.val); min = Math.min(min, i); } List> res = new ArrayList<>(); while (map.containsKey(min)) { res.add(map.get(min++)); } return res; } /** * https://leetcode.com/problems/binary-tree-vertical-order-traversal/discuss/76401/5ms-Java-Clean-Solution */ public List> verticalOrder3(TreeNode root) { List> cols = new ArrayList<>(); if (root == null) { return cols; } int[] range = new int[] {0, 0}; getRange(root, range, 0); for (int i = range[0]; i <= range[1]; i++) { cols.add(new ArrayList()); } Queue queue = new LinkedList<>(); Queue colQueue = new LinkedList<>(); queue.add(root); colQueue.add(-range[0]); while (!queue.isEmpty()) { TreeNode node = queue.poll(); int col = colQueue.poll(); cols.get(col).add(node.val); if (node.left != null) { queue.add(node.left); colQueue.add(col - 1); } if (node.right != null) { queue.add(node.right); colQueue.add(col + 1); } } return cols; } public void getRange(TreeNode root, int[] range, int col) { if (root == null) { return; } range[0] = Math.min(range[0], col); range[1] = Math.max(range[1], col); getRange(root.left, range, col - 1); getRange(root.right, range, col + 1); } } ================================================ FILE: src/BinaryTreeZigzagLevelOrderTraversal103.java ================================================ /** * Given a binary tree, return the zigzag level order traversal of its nodes' * values. (ie, from left to right, then right to left for the next level and * alternate between). * * For example: * Given binary tree [3,9,20,null,null,15,7], * 3 * / \ * 9 20 * / \ * 15 7 * return its zigzag level order traversal as: * [ * [3], * [20,9], * [15,7] * ] */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class BinaryTreeZigzagLevelOrderTraversal103 { public List> zigzagLevelOrder(TreeNode root) { List> res = new ArrayList<>(); if (root == null) return res; LinkedList level = new LinkedList<>(); level.add(root); zigzagLevelOrder(level, true, res); return res; } private void zigzagLevelOrder(LinkedList level, boolean left, List> res) { if (level.isEmpty()) return; LinkedList one = new LinkedList<>(); LinkedList newLevel = new LinkedList<>(); while (!level.isEmpty()) { TreeNode t = level.removeFirst(); if (t == null) continue; if (left) one.add(t.val); else one.addFirst(t.val); newLevel.add(t.left); newLevel.add(t.right); } if (!one.isEmpty()) res.add(one); zigzagLevelOrder(newLevel, !left, res); } } ================================================ FILE: src/BinaryTreesWithFactors823.java ================================================ /** * Given an array of unique integers, each integer is strictly greater than 1. * * We make a binary tree using these integers and each number may be used for * any number of times. * * Each non-leaf node's value should be equal to the product of the values of * it's children. * * How many binary trees can we make? Return the answer modulo 10 ** 9 + 7. * * Example 1: * Input: A = [2, 4] * Output: 3 * Explanation: We can make these trees: [2], [4], [4, 2, 2] * * Example 2: * Input: A = [2, 4, 5, 10] * Output: 7 * Explanation: We can make these trees: * [2], [4], [5], [10], [4, 2, 2], [10, 2, 5], [10, 5, 2]. * * Note: * 1 <= A.length <= 1000. * 2 <= A[i] <= 10 ^ 9. */ public class BinaryTreesWithFactors823 { private static long MOD = (long) Math.pow(10, 9) + 7; public int numFactoredBinaryTrees(int[] A) { Arrays.sort(A); int N = A.length; int max = A[N-1]; Map map = new HashMap<>(); long res = 0; for (int i=0; i index = new HashMap(); for (int i = 0; i < N; ++i) index.put(A[i], i); for (int i = 0; i < N; ++i) for (int j = 0; j < i; ++j) { if (A[i] % A[j] == 0) { // A[j] is left child int right = A[i] / A[j]; if (index.containsKey(right)) { dp[i] = (dp[i] + dp[j] * dp[index.get(right)]) % MOD; } } } long ans = 0; for (long x: dp) ans += x; return (int) (ans % MOD); } } ================================================ FILE: src/BitwiseANDOfNumbersRange201.java ================================================ /** * Given a range [m, n] where 0 <= m <= n <= 2147483647, return the bitwise AND * of all numbers in this range, inclusive. * * Example 1: * Input: [5,7] * Output: 4 * * Example 2: * Input: [0,1] * Output: 0 */ public class BitwiseANDOfNumbersRange201 { public int rangeBitwiseAnd(int m, int n) { if (m == 0) return 0; int res = 0; int range = n - m + 1; int b = 1; for (int i=0; i<=31; i++) { if (range <= b && (getBit(m, i) == 1 && getBit(n, i) == 1)) { res = setBit(res, i); } b <<= 1; } return res; } private int setBit(int num, int pos) { return num | (1 << pos); } private int getBit(int num, int pos) { return (num & (1 << pos)) >> pos; } /** * https://leetcode.com/problems/bitwise-and-of-numbers-range/discuss/56729/Bit-operation-solution(JAVA) */ public int rangeBitwiseAnd2(int m, int n) { if(m == 0){ return 0; } int moveFactor = 1; while(m != n){ m >>= 1; n >>= 1; moveFactor <<= 1; } return m * moveFactor; } /** * https://leetcode.com/problems/bitwise-and-of-numbers-range/discuss/56721/2-line-Solution-with-detailed-explanation */ public int rangeBitwiseAnd3(int m, int n) { while(m limit) { j--; } else { i++; j--; } res++; } if (i == j) res++; return res; } } ================================================ FILE: src/BombEnemy361.java ================================================ /** * Given a 2D grid, each cell is either a wall 'W', an enemy 'E' or empty '0' * (the number zero), return the maximum enemies you can kill using one bomb. * The bomb kills all the enemies in the same row and column from the planted * point until it hits the wall since the wall is too strong to be destroyed. * Note that you can only put the bomb at an empty cell. * * Example: * For the given grid * * 0 E 0 0 * E 0 W E * 0 E 0 0 * * return 3. (Placing a bomb at (1,1) kills 3 enemies) */ public class BombEnemy361 { public int maxKilledEnemies(char[][] grid) { if (grid == null || grid.length <= 0 || grid[0].length <= 0) return 0; int n = grid.length; int m = grid[0].length; int res = 0; for (int i=0; i=0 && grid[i][k] != 'W'; k--) { if (grid[i][k] == 'E') res++; } // top for (int k=i-1; k>=0 && grid[k][j] != 'W'; k--) { if (grid[k][j] == 'E') res++; } // bottom for (int k=i+1; k=0 && grid[i][k] != 'W'; k--) { if (grid[i][k] == 'E') h++; else if (grid[i][k] == '0') { h = hori[i][k]; hf = true; break; } else { break; } } if (!hf) { // right for (int k=j+1; k=0 && grid[k][j] != 'W'; k--) { if (grid[k][j] == 'E') v++; else if (grid[k][j] == '0') { v = vert[k][j]; vf = true; break; } else { break; } } if (!vf) { // bottom for (int k=i+1; k 0 ? left[i][j-1] : 0) + add; top[i][j] = (i > 0 ? top[i-1][j] : 0) + add; } if (grid[i][n-j-1] != 'W') { right[i][n-j-1] = (j > 0 ? right[i][n-j] : 0) + (grid[i][n-j-1] == 'E' ? 1 : 0); } if (grid[m-i-1][j] != 'W') { bottom[m-i-1][j] = (i > 0 ? bottom[m-i][j] : 0) + (grid[m-i-1][j] == 'E' ? 1 : 0); } } } int res = 0; for (int i=0; i res) { res = local; } } } } return res; } public int maxKilledEnemies4(char[][] grid) { if (grid == null || grid.length == 0 || grid[0].length == 0) return 0; int m = grid.length; int n = grid[0].length; int rowKills = 0; int[] colKills = new int[n]; int res = 0; for (int i=0; i res) { res = rowKills + colKills[j]; } } } return res; } } ================================================ FILE: src/BoundaryOfBinaryTree545.java ================================================ /** * Given a binary tree, return the values of its boundary in anti-clockwise * direction starting from root. Boundary includes left boundary, leaves, and * right boundary in order without duplicate nodes. * * Left boundary is defined as the path from root to the left-most node. Right * boundary is defined as the path from root to the right-most node. If the * root doesn't have left subtree or right subtree, then the root itself is * left boundary or right boundary. Note this definition only applies to the * input binary tree, and not applies to any subtrees. * * The left-most node is defined as a leaf node you could reach when you always * firstly travel to the left subtree if exists. If not, travel to the right * subtree. Repeat until you reach a leaf node. * * The right-most node is also defined by the same way with left and right exchanged. * * Example 1 * Input: * 1 * \ * 2 * / \ * 3 4 * * Ouput: * [1, 3, 4, 2] * * Explanation: * The root doesn't have left subtree, so the root itself is left boundary. * The leaves are node 3 and 4. * The right boundary are node 1,2,4. Note the anti-clockwise direction means * you should output reversed right boundary. * So order them in anti-clockwise without duplicates and we have [1,3,4,2]. * * Example 2 * Input: * ____1_____ * / \ * 2 3 * / \ / * 4 5 6 * / \ / \ * 7 8 9 10 * * Ouput: * [1,2,4,7,8,9,10,6,3] * * Explanation: * The left boundary are node 1,2,4. (4 is the left-most node according to definition) * The leaves are node 4,7,8,9,10. * The right boundary are node 1,3,6,10. (10 is the right-most node). * So order them in anti-clockwise without duplicate nodes we have [1,2,4,7,8,9,10,6,3]. */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class BoundaryOfBinaryTree545 { public List boundaryOfBinaryTree(TreeNode root) { List res = new ArrayList<>(); if (root == null) return res; res.add(root.val); if (root.left != null) dfsLeft(root.left, new boolean[1], res); List rightRes = new ArrayList<>(); if (root.right != null) dfsRight(root.right, new boolean[1], rightRes); for (int i=rightRes.size()-1; i>=0; i--) { res.add(rightRes.get(i)); } return res; } private void dfsLeft(TreeNode root, boolean[] flag, List res) { if (root.left == null && root.right == null) { res.add(root.val); flag[0] = true; return; } if (!flag[0]) res.add(root.val); if (root.left != null) dfsLeft(root.left, flag, res); if (root.right != null) dfsLeft(root.right, flag, res); } private void dfsRight(TreeNode root, boolean[] flag, List res) { if (root.left == null && root.right == null) { res.add(root.val); flag[0] = true; return; } if (!flag[0]) res.add(root.val); if (root.right != null) dfsRight(root.right, flag, res); if (root.left != null) dfsRight(root.left, flag, res); } } ================================================ FILE: src/BrickWall554.java ================================================ /** * There is a brick wall in front of you. The wall is rectangular and has * several rows of bricks. The bricks have the same height but different width. * You want to draw a vertical line from the top to the bottom and cross the * least bricks. * * The brick wall is represented by a list of rows. Each row is a list of * integers representing the width of each brick in this row from left to right. * * If your line go through the edge of a brick, then the brick is not considered * as crossed. You need to find out how to draw the line to cross the least * bricks and return the number of crossed bricks. * * You cannot draw a line just along one of the two vertical edges of the wall, * in which case the line will obviously cross no bricks. * * Example: * Input: * [[1,2,2,1], * [3,1,2], * [1,3,2], * [2,4], * [3,1,2], * [1,3,1,1]] * Output: 2 * * Explanation: * https://leetcode.com/static/images/problemset/brick_wall.png * * Note: * The width sum of bricks in different rows are the same and won't exceed INT_MAX. * The number of bricks in each row is in range [1,10,000]. The height of * wall is in range [1,10,000]. Total number of bricks of the wall won't * exceed 20,000. * */ public class BrickWall554 { public int leastBricks(List> wall) { Map map = new HashMap<>(); for (int i = 0; i row = wall.get(i); int sum = 0; for (int j = 0; j 0 && A[r-1][c] == 1) dsu.union(i, (r-1) *C + c); if (c > 0 && A[r][c-1] == 1) dsu.union(i, r * C + c-1); } } } int t = hits.length; int[] ans = new int[t--]; while (t >= 0) { int r = hits[t][0]; int c = hits[t][1]; int preRoof = dsu.top(); if (grid[r][c] == 0) { t--; } else { int i = r * C + c; for (int k = 0; k < 4; ++k) { int nr = r + dr[k]; int nc = c + dc[k]; if (0 <= nr && nr < R && 0 <= nc && nc < C && A[nr][nc] == 1) dsu.union(i, nr * C + nc); } if (r == 0) dsu.union(i, R*C); A[r][c] = 1; ans[t--] = Math.max(0, dsu.top() - preRoof - 1); } } return ans; } class DSU { int[] parent; int[] rank; int[] sz; public DSU(int N) { parent = new int[N]; for (int i = 0; i < N; ++i) parent[i] = i; rank = new int[N]; sz = new int[N]; Arrays.fill(sz, 1); } public int find(int x) { if (parent[x] != x) parent[x] = find(parent[x]); return parent[x]; } public void union(int x, int y) { int xr = find(x), yr = find(y); if (xr == yr) return; if (rank[xr] < rank[yr]) { parent[xr] = yr; sz[yr] += sz[xr]; } else if (rank[xr] > rank[yr]) { parent[yr] = xr; sz[xr] += sz[yr]; } else { rank[xr]++; parent[yr] = xr; sz[xr] += sz[yr]; } } public int size(int x) { return sz[find(x)]; } public int top() { return sz[find(sz.length - 1)] - 1; } } /** * https://leetcode.com/problems/bricks-falling-when-hit/discuss/121072/Java-Solution */ public int[] hitBricks2(int[][] grid, int[][] hits) { if (hits.length == 0 || hits[0].length == 0) return null; removeHitBrick(grid, hits); markRemainBricks(grid); return searchFallingBrick(grid, hits); } private void markRemainBricks(int[][] grid) { for (int i = 0; i < grid[0].length; i++) { deepSearch(grid, 0, i); } } private void removeHitBrick(int[][] grid, int[][] hits) { for (int i = 0; i < hits.length; i++) { grid[hits[i][0]][hits[i][1]] = grid[hits[i][0]][hits[i][1]] - 1; } } private int[] searchFallingBrick(int[][] grid, int[][] hits) { int[] result = new int[hits.length]; for (int i = hits.length - 1; i >= 0; i--) { if (grid[hits[i][0]][hits[i][1]] == 0) { grid[hits[i][0]][hits[i][1]] = 1; if (isConnectToTop(grid, hits[i][0], hits[i][1])) { result[i] = deepSearch(grid, hits[i][0], hits[i][1]) - 1; } else { result[i] = 0; } } } return result; } private boolean isConnectToTop(int[][] grid, int i, int j) { if(i == 0) return true; if (i - 1 >= 0 && grid[i - 1][j] == 2) { return true; } if (i + 1 < grid.length && grid[i + 1][j] == 2) { return true; } if (j - 1 >= 0 && grid[i][j - 1] == 2) { return true; } if (j + 1 < grid[0].length && grid[i][j + 1] == 2) { return true; } return false; } private int deepSearch(int[][] data, int row, int column) { int arrayRow = data.length; int arrayLine = data[0].length; int effectBricks = 0; if (row < 0 || row >= arrayRow) return effectBricks; if (column < 0 || column >= arrayLine) return effectBricks; if (data[row][column] == 1) { data[row][column] = 2; effectBricks = 1; effectBricks += deepSearch(data, row + 1, column); effectBricks += deepSearch(data, row - 1, column); effectBricks += deepSearch(data, row, column + 1); effectBricks += deepSearch(data, row, column - 1); } return effectBricks; } } ================================================ FILE: src/BuddyStrings859.java ================================================ /** * Given two strings A and B of lowercase letters, return true if and only if * we can swap two letters in A so that the result equals B. * * Example 1: * Input: A = "ab", B = "ba" * Output: true * * Example 2: * Input: A = "ab", B = "ab" * Output: false * * Example 3: * Input: A = "aa", B = "aa" * Output: true * * Example 4: * Input: A = "aaaaaaabc", B = "aaaaaaacb" * Output: true * * Example 5: * Input: A = "", B = "aa" * Output: false * * Note: * 0 <= A.length <= 20000 * 0 <= B.length <= 20000 * A and B consist only of lowercase letters. */ public class BuddyStrings859 { public boolean buddyStrings(String A, String B) { if (A == null || B == null || A.length() < 2 || B.length() < 2 || A.length() != B.length()) return false; char[] aa = A.toCharArray(); char[] bb = B.toCharArray(); int len = A.length(); int first = -1; int second = -1; int[] map = new int[26]; boolean same = false; for (int i=0; i= 2) same = true; continue; } if (first == -1) { first = i; } else { if (second != -1 || (aa[first] != bb[i] || aa[i] != bb[first])) return false; second = i; } } return first != -1 || same; } } ================================================ FILE: src/BullsAndCows299.java ================================================ /** * You are playing the following Bulls and Cows game with your friend: * You write down a number and ask your friend to guess what the number is. * Each time your friend makes a guess, you provide a hint that indicates * how many digits in said guess match your secret number exactly in both digit * and position (called "bulls") and how many digits match the secret number * but locate in the wrong position (called "cows"). Your friend will use * successive guesses and hints to eventually derive the secret number. * * Bulls and Cows https://en.wikipedia.org/wiki/Bulls_and_Cows * * For example: * * Secret number: "1807" * Friend's guess: "7810" * * Hint: 1 bull and 3 cows. (The bull is 8, the cows are 0, 1 and 7.) * Write a function to return a hint according to the secret number and * friend's guess, use A to indicate the bulls and B to indicate the cows. * In the above example, your function should return "1A3B". * * Please note that both secret number and friend's guess may contain duplicate digits, for example: * * Secret number: "1123" * Friend's guess: "0111" * * In this case, the 1st 1 in friend's guess is a bull, the 2nd or 3rd 1 is a * cow, and your function should return "1A1B". * * You may assume that the secret number and your friend's guess only contain * digits, and their lengths are always equal. */ public class BullsAndCows299 { public String getHint(String secret, String guess) { Map secrets = new HashMap<>(); Map guesses = new HashMap<>(); Map counts = new HashMap<>(); counts.put("bull", 0); counts.put("cows", 0); List left = new ArrayList<>(); for (int i=0; i e: guesses.entrySet()) { if (secrets.containsKey(e.getKey())) { counts.put("cows", counts.get("cows") + Math.min(secrets.get(e.getKey()), e.getValue())); } } return String.format("%dA%dB", counts.get("bull"), counts.get("cows")); } public String getHint2(String secret, String guess) { Map secrets = new HashMap<>(); Map guesses = new HashMap<>(); Map counts = new HashMap<>(); counts.put("bull", 0); counts.put("cows", 0); for (int i=0; i 0) { secrets.put(c2, secrets.get(c2)-1); counts.put("cows", counts.get("cows")+1); } else { guesses.put(c2, guesses.getOrDefault(c2, 0)+1); } if (guesses.containsKey(c1) && guesses.get(c1) > 0) { guesses.put(c1, guesses.get(c1)-1); counts.put("cows", counts.get("cows")+1); } else { secrets.put(c1, secrets.getOrDefault(c1, 0)+1); } } } return String.format("%dA%dB", counts.get("bull"), counts.get("cows")); } /** * https://discuss.leetcode.com/topic/28463/one-pass-java-solution */ public String getHint3(String secret, String guess) { int bulls = 0; int cows = 0; int[] numbers = new int[10]; for (int i = 0; i 0) cows++; } } return bulls + "A" + cows + "B"; } } ================================================ FILE: src/BurstBalloons312.java ================================================ /** * Given n balloons, indexed from 0 to n-1. Each balloon is painted with a * number on it represented by array nums. You are asked to burst all the * balloons. If the you burst balloon i you will get * * nums[left] * nums[i] * nums[right] * * coins. Here left and right are adjacent indices of i. After the burst, * the left and right then becomes adjacent. * * Find the maximum coins you can collect by bursting the balloons wisely. * * Note: * (1) You may imagine nums[-1] = nums[n] = 1. They are not real therefore you can not burst them. * (2) 0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100 * * Example: * * Given [3, 1, 5, 8] * * Return 167 * * nums = [3,1,5,8] --> [3,5,8] --> [3,8] --> [8] --> [] * coins = 3*1*5 + 3*5*8 + 1*3*8 + 1*8*1 = 167 * */ public class BurstBalloons312 { public int maxCoins(int[] nums) { if (nums.length == 0) return 0; if (nums.length == 1) return nums[0]; int res = Integer.MIN_VALUE; for (int i=0; i key = new HashSet<>(); for (int i=0; i, Integer>()); } private int dp(int[] nums, Set key, Map, Integer> caches) { if (key.size() == 0) return 0; if (key.size() == 1) return nums[key.iterator().next()]; if (caches.containsKey(key)) return caches.get(key); int res = Integer.MIN_VALUE; for (Integer pos: key) { int posL = pos-1; int posR = pos+1; while(posL >= 0 && !key.contains(posL)) posL--; while(posR < nums.length && !key.contains(posR)) posR++; int l = (posL < 0) ? 1 : nums[posL]; int r = (posR >= nums.length) ? 1 : nums[posR]; int curr = l * nums[pos] * r; Set newKey = new HashSet<>(key); newKey.remove(pos); if (caches.containsKey(newKey)) { res = Math.max(res, curr + caches.get(newKey)); } else { Integer rem = dp(nums, newKey, caches); caches.put(newKey, rem); res = Math.max(res, curr + rem); } } return res; } public int maxCoins2(int[] nums) { if (nums == null || nums.length == 0) return 0; if (nums.length == 1) return nums[0]; int[][] dp = new int[nums.length][nums.length]; for (int len=0; len<=nums.length; len++) { for (int s=0; s<=nums.length-len; s++) { int e = s + len - 1; for (int i=s; i<=e; i++) { int l = (s <= 0) ? 1 : nums[s-1]; int r = (e >= nums.length-1) ? 1 : nums[e+1]; int curr = l * nums[i] * r; curr += i != s ? dp[s][i - 1] : 0; curr += i != e ? dp[i + 1][e] : 0; dp[s][e] = Math.max(dp[s][e], curr); } } } return dp[0][nums.length-1]; } /** * https://discuss.leetcode.com/topic/30746/share-some-analysis-and-explanations */ public int maxCoins3(int[] iNums) { int[] nums = new int[iNums.length + 2]; int n = 1; for (int x : iNums) if (x > 0) nums[n++] = x; nums[0] = nums[n++] = 1; int[][] dp = new int[n][n]; for (int k = 2; k < n; ++k) for (int left = 0; left < n - k; ++left) { int right = left + k; for (int i = left + 1; i < right; ++i) dp[left][right] = Math.max(dp[left][right], nums[left] * nums[i] * nums[right] + dp[left][i] + dp[i][right]); } return dp[0][n - 1]; } /** * https://discuss.leetcode.com/topic/30746/share-some-analysis-and-explanations */ public int maxCoins4(int[] iNums) { int[] nums = new int[iNums.length + 2]; int n = 1; for (int x : iNums) if (x > 0) nums[n++] = x; nums[0] = nums[n++] = 1; int[][] memo = new int[n][n]; return burst(memo, nums, 0, n - 1); } public int burst(int[][] memo, int[] nums, int left, int right) { if (left + 1 == right) return 0; if (memo[left][right] > 0) return memo[left][right]; int ans = 0; for (int i = left + 1; i < right; ++i) ans = Math.max(ans, nums[left] * nums[i] * nums[right] + burst(memo, nums, left, i) + burst(memo, nums, i, right)); memo[left][right] = ans; return ans; } } ================================================ FILE: src/CanIWin464.java ================================================ /** * In the "100 game," two players take turns adding, to a running total, any * integer from 1..10. The player who first causes the running total to reach * or exceed 100 wins. * * What if we change the game so that players cannot re-use integers? * * For example, two players might take turns drawing from a common pool of * numbers of 1..15 without replacement until they reach a total >= 100. * * Given an integer maxChoosableInteger and another integer desiredTotal, * determine if the first player to move can force a win, assuming both players * play optimally. * * You can always assume that maxChoosableInteger will not be larger than 20 * and desiredTotal will not be larger than 300. * * Example * Input: * maxChoosableInteger = 10 * desiredTotal = 11 * Output: * false * * Explanation: * No matter which integer the first player choose, the first player will lose. * The first player can choose an integer from 1 up to 10. * If the first player choose 1, the second player can only choose integers from 2 up to 10. * The second player will win by choosing 10 and get a total = 11, which is >= desiredTotal. * Same with other integers chosen by the first player, the second player will always win. */ public class CanIWin464 { public boolean canIWin(int maxChoosableInteger, int desiredTotal) { if (desiredTotal == 0) return true; if (((1 + maxChoosableInteger) / 2 * maxChoosableInteger) < desiredTotal) { return false; } return helper(new boolean[maxChoosableInteger], desiredTotal, new HashMap<>()); } private boolean helper(boolean[] set, int desiredTotal, Map memo) { if (desiredTotal <= 0) return false; String k = setKey(set); if (memo.containsKey(k)) return memo.get(k); for (int i=set.length-1; i>=0; i--) { if (!set[i]) { set[i] = true; if (!helper(set, desiredTotal-i-1, memo)) { set[i] = false; memo.put(k, true); return true; } set[i] = false; } } memo.put(k, false); return false; } private String setKey(boolean[] set) { StringBuilder sb = new StringBuilder(); for (boolean b: set) { sb.append(b ? 't' : 'f'); } return sb.toString(); } public boolean canIWin2(int maxChoosableInteger, int desiredTotal) { if (desiredTotal == 0) return true; if (((1 + maxChoosableInteger) / 2 * maxChoosableInteger) < desiredTotal) { return false; } return helper(0, desiredTotal, new Boolean[1 << maxChoosableInteger], maxChoosableInteger); } private boolean helper(int state, int desiredTotal, Boolean[] memo, int M) { if (desiredTotal <= 0) return false; if (memo[state] != null) return memo[state]; for (int i=M-1; i>=0; i--) { if ((state & (1 << i)) == 0) { state |= 1 << i; if (!helper(state, desiredTotal-i-1, memo, M)) { state &= ~(1 << i); memo[state] = true; return true; } state &= ~(1 << i); } } memo[state] = false; return false; } } ================================================ FILE: src/CheapestFlightsWithinKStops787.java ================================================ /** * There are n cities connected by m flights. Each fight starts from city u and * arrives at v with a price w. * * Now given all the cities and flights, together with starting city src and * the destination dst, your task is to find the cheapest price from src to dst * with up to k stops. If there is no such route, output -1. * * Example 1: * Input: * n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]] * src = 0, dst = 2, k = 1 * Output: 200 * * Explanation: * The graph looks like this: * https://s3-lc-upload.s3.amazonaws.com/uploads/2018/02/16/995.png * * The cheapest price from city 0 to city 2 with at most 1 stop costs 200, as * marked red in the picture. * * Example 2: * Input: * n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]] * src = 0, dst = 2, k = 0 * Output: 500 * * Explanation: * The graph looks like this: * https://s3-lc-upload.s3.amazonaws.com/uploads/2018/02/16/995.png * * The cheapest price from city 0 to city 2 with at most 0 stop costs 500, as * marked blue in the picture. * * Note: * The number of nodes n will be in range [1, 100], with nodes labeled from 0 * to n - 1. * The size of flights will be in range [0, n * (n - 1) / 2]. * The format of each flight will be (src, dst, price). * The price of each flight will be in the range [1, 10000]. * k is in the range of [0, n - 1]. * There will not be any duplicated flights or self cycles. */ public class CheapestFlightsWithinKStops787 { public int findCheapestPrice(int n, int[][] flights, int src, int dst, int K) { int[][] graph = constructGraph(n, flights); Queue q = new LinkedList<>(); q.add(new int[]{src, 0}); int[][] dist = new int[n][K+2]; for (int[] row: dist) Arrays.fill(row, Integer.MAX_VALUE); dist[src][0] = 0; while (!q.isEmpty()) { int[] cur = q.poll(); int[] nei = graph[cur[0]]; for (int next=0; next best = new HashMap(); Comparator comp = (a, b) -> a[0] - b[0]; PriorityQueue pq = new PriorityQueue(comp); pq.offer(new int[]{0, 0, src}); while (!pq.isEmpty()) { int[] info = pq.poll(); int cost = info[0], k = info[1], place = info[2]; if (k > K+1 || cost > best.getOrDefault(k * 1000 + place, Integer.MAX_VALUE)) continue; if (place == dst) return cost; for (int nei = 0; nei < n; ++nei) if (graph[place][nei] > 0) { int newcost = cost + graph[place][nei]; if (newcost < best.getOrDefault((k+1) * 1000 + nei, Integer.MAX_VALUE)) { pq.offer(new int[]{newcost, k+1, nei}); best.put((k+1) * 1000 + nei, newcost); } } } return -1; } /** * https://leetcode.com/problems/cheapest-flights-within-k-stops/discuss/128776/5-ms-AC-Java-Solution-based-on-Dijkstra's-Algorithm */ private class City implements Comparable{ int id; int costFromSrc; int stopFromSrc; public City(int id, int costFromSrc, int stopFromSrc){ this.id = id; this.costFromSrc = costFromSrc; this.stopFromSrc = stopFromSrc; } public boolean equals(City c){ if(c instanceof City) return this.id == c.id; return false; } public int compareTo(City c){ return this.costFromSrc - c.costFromSrc; } } public int findCheapestPrice4(int n, int[][] flights, int src, int dst, int K) { int[][] srcToDst = new int[n][n]; for(int i = 0; i < flights.length; i++) srcToDst[flights[i][0]][flights[i][1]] = flights[i][2]; PriorityQueue minHeap = new PriorityQueue(); minHeap.offer(new City(src,0,0)); int[] cost = new int[n]; Arrays.fill(cost, Integer.MAX_VALUE); cost[src] = 0; int[] stop = new int[n]; Arrays.fill(stop, Integer.MAX_VALUE); stop[src] = 0; while(!minHeap.isEmpty()){ City curCity = minHeap.poll(); if(curCity.id == dst) return curCity.costFromSrc; if(curCity.stopFromSrc == K + 1) continue; int[] nexts = srcToDst[curCity.id]; for(int i = 0; i < n; i++){ if(nexts[i] != 0){ int newCost = curCity.costFromSrc + nexts[i]; int newStop = curCity.stopFromSrc + 1; if(newCost < cost[i]){ minHeap.offer(new City(i, newCost, newStop)); cost[i] = newCost; } else if(newStop < stop[i]){ minHeap.offer(new City(i, newCost, newStop)); stop[i] = newStop; } } } } return cost[dst] == Integer.MAX_VALUE? -1:cost[dst]; } /** * https://leetcode.com/problems/cheapest-flights-within-k-stops/discuss/163698/easy-java-Bellman-Ford */ public int findCheapestPrice5(int n, int[][] flights, int src, int dst, int k) { int INF = 0x3F3F3F3F; int[] cost = new int[n]; Arrays.fill(cost, INF); cost[src] = 0; int ans = cost[dst]; for(int i = k; i >= 0; i--){ int[] cur = new int[n]; Arrays.fill(cur, INF); for(int[] flight : flights){ cur[flight[1]] = Math.min(cur[flight[1]], cost[flight[0]] + flight[2]); } cost = cur; ans = Math.min(ans, cost[dst]); } return ans == INF ? -1 : ans; } private static int MAX = Integer.MAX_VALUE / 2; public int findCheapestPrice6(int n, int[][] flights, int src, int dst, int K) { int[][] dp = new int[K+2][n]; for (int[] row: dp) Arrays.fill(row, MAX); dp[0][src] = 0; for (int i=1; i<=K+1; i++) { for (int[] f: flights) { dp[i][f[1]] = Math.min(dp[i][f[1]], Math.min(dp[i-1][f[1]], dp[i-1][f[0]] + f[2])); } } return dp[K+1][dst] >= MAX ? -1 : dp[K+1][dst]; } public int findCheapestPrice7(int n, int[][] flights, int src, int dst, int K) { int[][] dp = new int[2][n]; Arrays.fill(dp[0], MAX); Arrays.fill(dp[1], MAX); dp[0][src] = 0; int k = 1; while (k <= K+1) { for (int[] f: flights) { dp[k%2][f[1]] = Math.min(dp[k%2][f[1]], Math.min(dp[(k-1)%2][f[1]], dp[(k-1)%2][f[0]] + f[2])); } k++; } k--; return dp[k%2][dst] >= MAX ? -1 : dp[k%2][dst]; } } ================================================ FILE: src/ClimbingStairs70.java ================================================ /** * You are climbing a stair case. It takes n steps to reach to the top. * * Each time you can either climb 1 or 2 steps. In how many distinct ways can * you climb to the top? * * Note: Given n will be a positive integer. * * Example 1: * * Input: 2 * Output: 2 * Explanation: There are two ways to climb to the top. * * 1. 1 step + 1 step * 2. 2 steps * * * Example 2: * * Input: 3 * Output: 3 * Explanation: There are three ways to climb to the top. * * 1. 1 step + 1 step + 1 step * 2. 1 step + 2 steps * 3. 2 steps + 1 step * */ public class ClimbingStairs70 { public int climbStairs(int n) { if (n == 1) return 1; int[] dp = new int[n+1]; dp[0] = 1; dp[1] = 1; for (int i=2; i<=n; i++) { dp[i] = dp[i-1] + dp[i-2]; } return dp[n]; } public int climbStairs2(int n) { if (n == 1) return 1; int pre = 1; int now = 1; for (int i=2; i<=n; i++) { int newVal = pre + now; pre = now; now = newVal; } return now; } } ================================================ FILE: src/CloneGraph133.java ================================================ /** * Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors. * * * OJ's undirected graph serialization: * Nodes are labeled uniquely. * * We use # as a separator for each node, and , as a separator for node label and each neighbor of the node. * As an example, consider the serialized graph {0,1,2#1,2#2,2}. * * The graph has a total of three nodes, and therefore contains three parts as separated by #. * * First node is labeled as 0. Connect node 0 to both nodes 1 and 2. * Second node is labeled as 1. Connect node 1 to node 2. * Third node is labeled as 2. Connect node 2 to node 2 (itself), thus forming a self-cycle. * Visually, the graph looks like the following: * * 1 * / \ * / \ * 0 --- 2 * / \ * \_/ * */ /** * Definition for undirected graph. * class UndirectedGraphNode { * int label; * List neighbors; * UndirectedGraphNode(int x) { label = x; neighbors = new ArrayList(); } * }; */ public class CloneGraph133 { public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) { HashMap map = new HashMap<>(); return clone(node, map); } private UndirectedGraphNode clone(UndirectedGraphNode node, HashMap map) { if (node == null) return null; if (map.containsKey(node.label)) { return map.get(node.label); } UndirectedGraphNode clone = new UndirectedGraphNode(node.label); map.put(clone.label, clone); for (UndirectedGraphNode neighbor : node.neighbors) { clone.neighbors.add(clone(neighbor, map)); } return clone; } } ================================================ FILE: src/ClosestBinarySearchTreeValue270.java ================================================ /** * Given a non-empty binary search tree and a target value, find the value in * the BST that is closest to the target. * * Note: * * Given target value is a floating point. * You are guaranteed to have only one unique value in the BST that is closest * to the target. * * Example: * * Input: root = [4,2,5,1,3], target = 3.714286 * * 4 * / \ * 2 5 * / \ * 1 3 * * Output: 4 */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class ClosestBinarySearchTreeValue270 { public int closestValue(TreeNode root, double target) { return closestValue(root, target, null, null); } private int closestValue(TreeNode root, double target, Integer mi, Integer ma) { if (root == null) { if (mi == null) return ma; else if (ma == null) return mi; else return (ma - target > target - mi) ? mi : ma; } double val = root.val * 1.0; if (val == target) { return root.val; } else if (val > target) { return closestValue(root.left, target, mi, root.val); } else { return closestValue(root.right, target, root.val, ma); } } public int closestValue2(TreeNode root, double target) { Integer mi = null; Integer ma = null; while (root != null) { double val = root.val * 1.0; if (val == target) { return root.val; } else if (val > target) { ma = root.val; root = root.left; } else { mi = root.val; root = root.right; } } if (mi == null) return ma; else if (ma == null) return mi; else return (ma - target > target - mi) ? mi : ma; } /** * https://leetcode.com/problems/closest-binary-search-tree-value/discuss/70327/4-7-lines-recursiveiterative-RubyC++JavaPython */ public int closestValue3(TreeNode root, double target) { int a = root.val; TreeNode kid = target < a ? root.left : root.right; if (kid == null) return a; int b = closestValue(kid, target); return Math.abs(a - target) < Math.abs(b - target) ? a : b; } /** * https://leetcode.com/problems/closest-binary-search-tree-value/discuss/70331/Clean-and-concise-java-solution */ public int closestValue4(TreeNode root, double target) { int ret = root.val; while(root != null){ if(Math.abs(target - root.val) < Math.abs(target - ret)){ ret = root.val; } root = root.val > target? root.left: root.right; } return ret; } } ================================================ FILE: src/ClosestBinarySearchTreeValueII272.java ================================================ /** * Given a non-empty binary search tree and a target value, find k values in * the BST that are closest to the target. * * Note: * Given target value is a floating point. * You may assume k is always valid, that is: k ≤ total nodes. * You are guaranteed to have only one unique set of k values in the BST that * are closest to the target. * * Example: * * Input: root = [4,2,5,1,3], target = 3.714286, and k = 2 * * 4 * / \ * 2 5 * / \ * 1 3 * * Output: [4,3] * * Follow up: * Assume that the BST is balanced, could you solve it in less than O(n) * runtime (where n = total nodes)? */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class ClosestBinarySearchTreeValueII272 { public List closestKValues(TreeNode root, double target, int k) { LinkedList res = new LinkedList<>(); helper(root, target, k, res); return res; } private void helper(TreeNode root, double target, int k, LinkedList res) { if (root == null) return; helper(root.left, target, k, res); res.addLast(root.val); helper(root.right, target, k, res); cut(target, k, res); } private void cut(double target, int k, LinkedList res) { if (res.size() > k) { if (Math.abs(res.getFirst() * 1.0 - target) >= Math.abs(res.getLast() * 1.0 - target)) { res.removeFirst(); } else { res.removeLast(); } } } } ================================================ FILE: src/CoinChange322.java ================================================ /** * You are given coins of different denominations and a total amount of money * amount. Write a function to compute the fewest number of coins that you * need to make up that amount. If that amount of money cannot be made up by * any combination of the coins, return -1. * * Example 1: * coins = [1, 2, 5], amount = 11 * return 3 (11 = 5 + 5 + 1) * * Example 2: * coins = [2], amount = 3 * return -1. * * Note: * You may assume that you have an infinite number of each kind of coin. * */ public class CoinChange322 { public int coinChange(int[] coins, int amount) { Arrays.sort(coins); return helper(coins.length-1, coins, amount); } private int helper(int idx, int[] coins, int left) { if (idx < 0) return -1; int curr = coins[idx]; int multi = left / curr; int currLeft = left % curr; if (currLeft == 0) return multi; int res = Integer.MAX_VALUE; int reduce = multi; int newLeft = currLeft; while(reduce >= 0) { int temp = helper(idx-1, coins, newLeft); if (temp != -1) res = Math.min(res, temp+reduce); reduce--; newLeft = newLeft + curr; } return (res == Integer.MAX_VALUE) ? -1 : res; } /** * https://leetcode.com/problems/coin-change/solution/ */ public int coinChange2(int[] coins, int amount) { if (amount < 1) return 0; return dp(coins, amount, new int[amount]); } private int dp(int[] coins, int left, int[] amounts) { if (left < 0) return -1; if (left == 0) return 0; if (amounts[left - 1] != 0) return amounts[left - 1]; int res = Integer.MAX_VALUE; for (int i=0; i= 0 && next < res) res = next +1; } amounts[left - 1] = (res == Integer.MAX_VALUE) ? -1 : res; return amounts[left - 1]; } /** * https://leetcode.com/problems/coin-change/solution/ */ public int coinChange3(int[] coins, int amount) { int[] dp = new int[amount + 1]; Arrays.fill(dp, amount + 1); dp[0] = 0; for (int i=1; i<=amount; i++) { for (int j=0; j amount ? -1 : dp[amount]; } public int coinChange4(int[] coins, int amount) { int[] dp = new int[amount + 1]; for (int i=1; i<=amount; i++) { int t = Integer.MAX_VALUE; for (int c: coins) { if (i >= c && dp[i - c] != -1) { t = Math.min(t, dp[i - c] + 1); } } dp[i] = t == Integer.MAX_VALUE ? -1 : t; } return dp[amount]; } public int coinChange5(int[] coins, int amount) { int[] dp = new int[amount + 1]; Arrays.fill(dp, amount + 1); dp[0] = 0; for (int c: coins) { for (int i=c; i<=amount; i++) { dp[i] = Math.min(dp[i], dp[i - c] + 1); } } return (dp[amount] == amount + 1) ? -1 : dp[amount]; } public int coinChange6(int[] coins, int amount) { Arrays.sort(coins); int[] res = new int[]{amount + 1}; coinChange(coins, amount, coins.length - 1, res, 0); return (res[0] == amount + 1) ? -1 : res[0]; } public void coinChange(int[] coins, int amount, int idx, int[] res, int num) { if (amount == 0) { res[0] = Math.min(res[0], num); return; } if (idx < 0) return; int k = amount / coins[idx]; for (int j=k; j>=0 && num + j < res[0]; j--) { coinChange(coins, amount - j * coins[idx], idx-1, res, num + j); } } } ================================================ FILE: src/CoinChangeII518.java ================================================ /** * You are given coins of different denominations and a total amount of money. * Write a function to compute the number of combinations that make up that * amount. You may assume that you have infinite number of each kind of coin. * * Note: You can assume that * * 0 <= amount <= 5000 * 1 <= coin <= 5000 * the number of coins is less than 500 * the answer is guaranteed to fit into signed 32-bit integer * * * Example 1: * * Input: amount = 5, coins = [1, 2, 5] * Output: 4 * Explanation: there are four ways to make up the amount: * 5=5 * 5=2+2+1 * 5=2+1+1+1 * 5=1+1+1+1+1 * * * Example 2: * * Input: amount = 3, coins = [2] * Output: 0 * Explanation: the amount of 3 cannot be made up just with coins of 2. * * * Example 3: * * Input: amount = 10, coins = [10] * Output: 1 */ public class CoinChangeII518 { public int change(int amount, int[] coins) { int[][] dp = new int[coins.length+1][amount + 1]; dp[0][0] = 1; for (int i=1; i<=coins.length; i++) { dp[i][0] = 1; int c = coins[i-1]; for (int j=1; j<=amount; j++) { dp[i][j] = dp[i-1][j] + (j < c ? 0 : dp[i][j-c]); } } return dp[coins.length][amount]; } public int change2(int amount, int[] coins) { int[] dp = new int[amount + 1]; dp[0] = 1; for (int coin : coins) { for (int i = coin; i <= amount; i++) { dp[i] += dp[i-coin]; } } return dp[amount]; } public int change3(int amount, int[] coins) { int[][] dp = new int[coins.length+1][amount + 1]; for (int i=0; i<=coins.length; i++) dp[i][0] = 1; for (int j=1; j<=amount; j++) { for (int i=1; i<=coins.length; i++) { int c = coins[i - 1]; dp[i][j] = dp[i-1][j] + (j < c ? 0 : dp[i][j-c]); } } return dp[coins.length][amount]; } } ================================================ FILE: src/CollatzConjecture.java ================================================ /** * */ public class CollatzConjecture { // public int maxSteps(int n) { // if (n < 1) return -1; // int res = -1; // for (int i=1; i<=n; i++) { // res = Math.max(res, steps(i)); // } // return res; // } // public int steps(int i) { // int res = 0; // while (i != 1) { // if (i % 2 == 0) { // i = i / 2; // } else { // i = i * 3 + 1; // } // } // return res; // } public int maxSteps(int n) { if (n < 1) return -1; int res = -1; int[] memo = new int[n+1]; for (int i=1; i<=n; i++) { res = Math.max(res, steps(i, memo)); } return res; } public int steps(int i, int[] memo) { int res = 0; int p = i; while (p != 1) { if (memo[p] > 0) { memo[i] = res = memo[p]; return memo[i]; } if (p % 2 == 0) { p = p / 2; } else { p = p * 3 + 1; } } memo[i] = res; return res; } } ================================================ FILE: src/CombinationSum39.java ================================================ /** * Given a set of candidate numbers (candidates) (without duplicates) and a * target number (target), find all unique combinations in candidates where * the candidate numbers sums to target. * * The same repeated number may be chosen from candidates unlimited number of times. * * Note: * All numbers (including target) will be positive integers. * The solution set must not contain duplicate combinations. * * Example 1: * Input: candidates = [2,3,6,7], target = 7, * A solution set is: * [ * [7], * [2,2,3] * ] * * Example 2: * Input: candidates = [2,3,5], target = 8, * A solution set is: * [ * [2,2,2,2], * [2,3,3], * [3,5] * ] */ public class CombinationSum39 { public List> combinationSum(int[] candidates, int target) { List> res = new ArrayList<>(); helper(candidates, target, 0, new ArrayList(), res); return res; } private void helper(int[] candidates, int target, int start, List path, List> res) { if (target < 0) return; if (target == 0) { List newPath = new ArrayList(); for (Integer i: path) newPath.add(i); res.add(newPath); } for (int i = start; i= 1) { for (int j=1; j<= count; j++) {path.add(c);} while (count >= 1) { helper(candidates, target - c * count, i+1, path, res); path.remove(path.size() - 1); count--; } } } } } ================================================ FILE: src/CombinationSumIII216.java ================================================ /** * Find all possible combinations of k numbers that add up to a number n, given * that only numbers from 1 to 9 can be used and each combination should be a * unique set of numbers. * * Note: * All numbers will be positive integers. * The solution set must not contain duplicate combinations. * * Example 1: * Input: k = 3, n = 7 * Output: [[1,2,4]] * * Example 2: * Input: k = 3, n = 9 * Output: [[1,2,6], [1,3,5], [2,3,4]] */ public class CombinationSumIII216 { public List> combinationSum3(int k, int n) { List> res = new ArrayList<>(); combinationSum3(k, n, new boolean[9], new ArrayList<>(), 0, 1, res); return res; } private void combinationSum3(int k, int n, List path, int sum, int start, List> res) { if (path.size() == k) { if (sum == n) res.add(new ArrayList<>(path)); return; } for (int i=start; i<=9; i++) { path.add(i); combinationSum3(k, n, visited, path, sum + i, i+1, res); path.remove(path.size()-1); } } } ================================================ FILE: src/CombinationSumIV377.java ================================================ /** * Given an integer array with all positive numbers and no duplicates, find the * number of possible combinations that add up to a positive integer target. * * Example: * * nums = [1, 2, 3] * target = 4 * * The possible combination ways are: * (1, 1, 1, 1) * (1, 1, 2) * (1, 2, 1) * (1, 3) * (2, 1, 1) * (2, 2) * (3, 1) * * Note that different sequences are counted as different combinations. * Therefore the output is 7. * * Follow up: * What if negative numbers are allowed in the given array? * How does it change the problem? * What limitation we need to add to the question to allow negative numbers? */ public class CombinationSumIV377 { public int combinationSum4(int[] nums, int target) { if (nums == null || target < 0) return 0; int N = nums.length; int[][] dp = new int[N + 1][target + 1]; for (int i=0; i<=N; i++) { dp[i][0] = 1; } for (int i=1; i<=N; i++) { int n = nums[i-1]; for (int j=1; j<=target; j++) { int local = 0; for (int k=1; k= nums[i]) { res += helper(nums, target - nums[i]); } } dp[target] = res; return res; } public int combinationSum43(int[] nums, int target) { int[] comb = new int[target + 1]; comb[0] = 1; for (int i = 1; i <= target; i++) { for (int n: nums) { if (i - n >= 0) { comb[i] += comb[i - n]; } } } return comb[target]; } } ================================================ FILE: src/CompareVersionNumbers165.java ================================================ /** * Compare two version numbers version1 and version2. * If version1 > version2 return 1; if version1 < version2 return -1; * otherwise return 0. * * You may assume that the version strings are non-empty and contain only * digits and the . character. * * The . character does not represent a decimal point and is used to separate * number sequences. * * For instance, 2.5 is not "two and a half" or "half way to version three", * it is the fifth second-level revision of the second first-level revision. * * Example 1: * Input: version1 = "0.1", version2 = "1.1" * Output: -1 * * Example 2: * Input: version1 = "1.0.1", version2 = "1" * Output: 1 * * Example 3: * Input: version1 = "7.5.2.4", version2 = "7.5.3" * Output: -1 */ public class CompareVersionNumbers165 { public int compareVersion(String version1, String version2) { String[] v1 = version1.split("\\."); String[] v2 = version2.split("\\."); int len = Math.min(v1.length, v2.length); for (int i=0; i 0) return 1; l++; } l = len; while (l < v2.length) { if (Integer.valueOf(v2[l]) > 0) return -1; l++; } return 0; } public int compareVersion2(String version1, String version2) { String[] v1 = version1.split("\\."); String[] v2 = version2.split("\\."); int len = Math.max(v1.length, v2.length); for (int i=0; i findAllConcatenatedWordsInADict(String[] words) { Trie trie = constructTrie(words); List res = new ArrayList<>(); for (String word: words) { if (count(trie, word.toCharArray(), 0, trie, 1) >= 2) { res.add(word); } } return res; } private int count(Trie trie, char[] chars, int i, Trie root, int cnt) { if (i == chars.length) return -1; int idx = chars[i] - 'a'; if (trie.children[idx] == null) return -1; if (trie.children[idx].isWord) { if (i == chars.length - 1) return cnt; int tmp = count(root, chars, i+1, root, cnt+1); if (tmp >= 2) { return tmp; } } return count(trie.children[idx], chars, i+1, root, cnt); } private Trie constructTrie(String[] words) { Trie trie = new Trie(); for (String word: words) trie.add(word); return trie; } class Trie { Trie[] children = new Trie[26]; boolean isWord; void add(String word) { add(word.toCharArray(), 0); } void add(char[] chars, int i) { if (i == chars.length) { isWord = true; return; } int idx = chars[i] - 'a'; if (children[idx] == null) { children[idx] = new Trie(); } children[idx].add(chars, i+1); } } } ================================================ FILE: src/ConstructBinaryTreeFromInorderAndPostorderTraversal106.java ================================================ /** * Given inorder and postorder traversal of a tree, construct the binary tree. * * Note: * You may assume that duplicates do not exist in the tree. * * For example, given * * inorder = [9,3,15,20,7] * postorder = [9,15,7,20,3] * Return the following binary tree: * * 3 * / \ * 9 20 * / \ * 15 7 */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class ConstructBinaryTreeFromInorderAndPostorderTraversal106 { public TreeNode buildTree(int[] inorder, int[] postorder) { if (inorder == null || postorder == null || inorder.length == 0 || postorder.length == 0 || inorder.length != postorder.length) return null; int len = inorder.length; return buildTree(inorder, 0, len-1, postorder, 0, len-1); } private TreeNode buildTree(int[] inorder, int ii, int ij, int[] postorder, int pi, int pj) { if (ii > ij) return null; int midVal = postorder[pj]; TreeNode curr = new TreeNode(midVal); if (pi == pj) return curr; int mid = ii; while (inorder[mid] != midVal) mid++; curr.left = buildTree(inorder, ii, mid-1, postorder, pi, pi+(mid-1-ii)); curr.right = buildTree(inorder, mid+1, ij, postorder, pi+(mid-ii), pj-1); return curr; } } ================================================ FILE: src/ConstructBinaryTreeFromPreorderAndInorderTraversal105.java ================================================ /** * Given preorder and inorder traversal of a tree, construct the binary tree. * * Note: * You may assume that duplicates do not exist in the tree. * */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class ConstructBinaryTreeFromPreorderAndInorderTraversal105 { public TreeNode buildTree(int[] preorder, int[] inorder) { if (inorder == null || inorder.length == 0) return null; if (inorder.length == 1) return new TreeNode(inorder[0]); int val = preorder[0]; int index = search(inorder, val); TreeNode root = new TreeNode(val); root.left = buildTree(Arrays.copyOfRange(preorder, 1, index+1), Arrays.copyOfRange(inorder, 0, index)); root.right = buildTree(Arrays.copyOfRange(preorder, index+1, preorder.length), Arrays.copyOfRange(inorder, index+1, inorder.length)); return root; } private int search(int[] order, int val) { for (int i=0; i e1 || s2 > e2) return null; if (s1 == e1 || s2 == e2) return new TreeNode(preorder[s1]); int val = preorder[s1]; int index = search(inorder, val, s2, e2); int len = index-s2; TreeNode root = new TreeNode(val); root.left = buildTree(preorder, s1+1, len+s1, inorder, s2, index-1); root.right = buildTree(preorder, len+s1+1, e1, inorder, index+1, e2); return root; } private int search(int[] order, int val, int start, int end) { for (int i=start; i<=end; i++) { if (order[i] == val) return i; } return -1; } public TreeNode buildTree3(int[] preorder, int[] inorder) { if (preorder.length == 0) return null; return buildTree(preorder, 0, inorder, 0, inorder.length); } private TreeNode buildTree(int[] preorder, int p, int[] inorder, int i, int j) { if (p >= inorder.length || i > j) return null; int curr = preorder[p]; TreeNode res = new TreeNode(curr); int mid = i; while (inorder[mid] != curr) mid++; res.left = buildTree(preorder, p+1, inorder, i, mid-1); res.right = buildTree(preorder, p+(mid-i)+1, inorder, mid+1, j); return res; } /** * https://discuss.leetcode.com/topic/29838/5ms-java-clean-solution-with-caching */ public TreeNode buildTree4(int[] preorder, int[] inorder) { Map inMap = new HashMap(); for(int i = 0; i < inorder.length; i++) { inMap.put(inorder[i], i); } TreeNode root = buildTree(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1, inMap); return root; } public TreeNode buildTree(int[] preorder, int preStart, int preEnd, int[] inorder, int inStart, int inEnd, Map inMap) { if(preStart > preEnd || inStart > inEnd) return null; TreeNode root = new TreeNode(preorder[preStart]); int inRoot = inMap.get(root.val); int numsLeft = inRoot - inStart; root.left = buildTree(preorder, preStart + 1, preStart + numsLeft, inorder, inStart, inRoot - 1, inMap); root.right = buildTree(preorder, preStart + numsLeft + 1, preEnd, inorder, inRoot + 1, inEnd, inMap); return root; } } ================================================ FILE: src/ConstructBinaryTreeFromString536.java ================================================ /** * You need to construct a binary tree from a string consisting of parenthesis * and integers. * * The whole input represents a binary tree. It contains an integer followed * by zero, one or two pairs of parenthesis. The integer represents the root's * value and a pair of parenthesis contains a child binary tree with the same * structure. * * You always start to construct the left child node of the parent first if * it exists. * * Example: * Input: "4(2(3)(1))(6(5))" * Output: return the tree root node representing the following tree: * * 4 * / \ * 2 6 * / \ / * 3 1 5 * * Note: * There will only be '(', ')', '-' and '0' ~ '9' in the input string. * An empty tree is represented by "" instead of "()". */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class ConstructBinaryTreeFromString536 { public TreeNode str2tree(String s) { if (s == null || s.length() == 0) return null; return str2tree(s.toCharArray(), 0, s.length()-1); } public TreeNode str2tree(char[] chars, int i, int j) { if (i > j) return null; int len = 0; while (i+len <= j && chars[i+len] != '(' && chars[i+len] != ')') { len++; } TreeNode root = new TreeNode(Integer.parseInt(new String(chars, i, len))); if (i + len - 1 == j) return root; int m = i + len; int count = 0; while (m <= j) { if (chars[m] == '(') { count++; } else if (chars[m] == ')') { count--; } m++; if (count == 0) break; } root.left = str2tree(chars, i+len+1, m-2); root.right = str2tree(chars, m+1, j-1); return root; } } ================================================ FILE: src/ConstructQuadTree427.java ================================================ /** * We want to use quad trees to store an N x N boolean grid. Each cell in the * grid can only be true or false. The root node represents the whole grid. For * each node, it will be subdivided into four children nodes until the values * in the region it represents are all the same. * * Each node has another two boolean attributes : isLeaf and val. isLeaf is * true if and only if the node is a leaf node. The val attribute for a leaf * node contains the value of the region it represents. * * Your task is to use a quad tree to represent a given grid. The following * example may help you understand the problem better: * * Given the 8 x 8 grid below, we want to construct the corresponding quad tree: * https://s3-lc-upload.s3.amazonaws.com/uploads/2018/02/01/962_grid.png * * It can be divided according to the definition above: * https://s3-lc-upload.s3.amazonaws.com/uploads/2018/02/01/962_grid_divided.png * * The corresponding quad tree should be as following, where each node is * represented as a (isLeaf, val) pair. * * For the non-leaf nodes, val can be arbitrary, so it is represented as *. * https://s3-lc-upload.s3.amazonaws.com/uploads/2018/02/01/962_quad_tree.png * * Note: * N is less than 1000 and guaranteened to be a power of 2. * If you want to know more about the quad tree, you can refer to its wiki. */ /* // Definition for a QuadTree node. class Node { public boolean val; public boolean isLeaf; public Node topLeft; public Node topRight; public Node bottomLeft; public Node bottomRight; public Node() {} public Node(boolean _val,boolean _isLeaf,Node _topLeft,Node _topRight,Node _bottomLeft,Node _bottomRight) { val = _val; isLeaf = _isLeaf; topLeft = _topLeft; topRight = _topRight; bottomLeft = _bottomLeft; bottomRight = _bottomRight; } }; */ public class ConstructQuadTree427 { public Node construct(int[][] grid) { if (grid == null) return null; int N = grid.length; return construct(grid, 0, N-1, 0, N-1); } public Node construct(int[][] grid, int xi, int xj, int yi, int yj) { if (xi > xj) return null; Node res = new Node(); if (xi == xj) { res.isLeaf = true; res.val = grid[xi][yi] == 1; return res; } int xm = (xi + xj) / 2; int ym = (yi + yj) / 2; res.topLeft = construct(grid, xi, xm, yi, ym); res.topRight = construct(grid, xi, xm, ym+1, yj); res.bottomLeft = construct(grid, xm+1, xj, yi, ym); res.bottomRight = construct(grid, xm+1, xj, ym+1, yj); if (allLeaves(res) && allSame(res)) { res.isLeaf = true; res.val = res.topLeft.val; res.topLeft = null; res.topRight = null; res.bottomLeft = null; res.bottomRight = null; } return res; } private boolean allLeaves(Node n) { return n.topLeft.isLeaf && n.topRight.isLeaf && n.bottomLeft.isLeaf && n.bottomRight.isLeaf; } private boolean allSame(Node n) { return (n.topLeft.val == n.topRight.val) && (n.bottomLeft.val == n.bottomRight.val) && (n.topLeft.val == n.bottomLeft.val); } } ================================================ FILE: src/ContainerWithMostWater11.java ================================================ /** * Given n non-negative integers a1, a2, ..., an, where each represents a point * at coordinate (i, ai). n vertical lines are drawn such that the two endpoints * of line i is at (i, ai) and (i, 0). Find two lines, which together with * x-axis forms a container, such that the container contains the most water. * * Note: You may not slant the container and n is at least 2. */ public class ContainerWithMostWater11 { /** * https://leetcode.com/problems/container-with-most-water/discuss/6089/Anyone-who-has-a-O(N)-algorithm/7268 * Here is the proof. * Proved by contradiction: * * Suppose the returned result is not the optimal solution. Then there must * exist an optimal solution, say a container with a_ol and a_or (left and * right respectively), such that it has a greater volume than the one we got. * Since our algorithm stops only if the two pointers meet. So, we must have * visited one of them but not the other. WLOG, let's say we visited a_ol but * not a_or. When a pointer stops at a_ol, it won't move until * * The other pointer also points to a_ol. * In this case, iteration ends. But the other pointer must have visited a_or * on its way from right end to a_ol. Contradiction to our assumption that we * didn't visit a_or. * * The other pointer arrives at a value, say a_rr, that is greater than a_ol * before it reaches a_or. * * In this case, we does move a_ol. But notice that the volume of a_ol and * a_rr is already greater than a_ol and a_or (as it is wider and heigher), * which means that a_ol and a_or is not the optimal solution -- * Contradiction! * * Both cases arrive at a contradiction. */ public int maxArea(int[] height) { int res = 0; int n = height.length; int left = 0; int right = n-1; while (left < right) { res = Math.max(res, Math.min(height[left], height[right]) * (right - left)); if (height[left] < height[right]) { left++; } else { right--; } } return res; } } ================================================ FILE: src/ContainsDuplicate217.java ================================================ /** * Given an array of integers, find if the array contains any duplicates. Your * function should return true if any value appears at least twice in the array, * and it should return false if every element is distinct. */ public class ContainsDuplicate217 { public boolean containsDuplicate(int[] nums) { Set set = new HashSet<>(); for (int n: nums) { if (set.contains(n)) { return true; } else { set.add(n); } } return false; } public boolean containsDuplicate2(int[] nums) { Arrays.sort(nums); for (int i = 0; i < nums.length - 1; ++i) { if (nums[i] == nums[i + 1]) return true; } return false; } } ================================================ FILE: src/ContainsDuplicateIII220.java ================================================ /** * Given an array of integers, find out whether there are two distinct indices * i and j in the array such that the absolute difference between nums[i] and * nums[j] is at most t and the absolute difference between i and j is at * most k. */ public class ContainsDuplicateIII220 { // // TLE // public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) { // for (int i=0; i set = new TreeSet<>(); for (int i = 0; i < nums.length; ++i) { // Find the successor of current element Integer s = set.ceiling(nums[i]); if (s != null && s <= nums[i] + t) return true; // Find the predecessor of current element Integer g = set.floor(nums[i]); if (g != null && nums[i] <= g + t) return true; set.add(nums[i]); if (set.size() > k) { set.remove(nums[i - k]); } } return false; } /** * https://leetcode.com/problems/contains-duplicate-iii/solution/ */ // Get the ID of the bucket from element value x and bucket width w // In Java, `-3 / 5 = 0` and but we need `-3 / 5 = -1`. private long getID(long x, long w) { return x < 0 ? (x + 1) / w - 1 : x / w; } public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) { if (t < 0) return false; Map d = new HashMap<>(); long w = (long)t + 1; for (int i = 0; i < nums.length; ++i) { long m = getID(nums[i], w); // check if bucket m is empty, each bucket may contain at most one element if (d.containsKey(m)) return true; // check the neighbor buckets for almost duplicate if (d.containsKey(m - 1) && Math.abs(nums[i] - d.get(m - 1)) < w) return true; if (d.containsKey(m + 1) && Math.abs(nums[i] - d.get(m + 1)) < w) return true; // now bucket m is empty and no almost duplicate in neighbor buckets d.put(m, (long)nums[i]); if (i >= k) d.remove(getID(nums[i - k], w)); } return false; } } ================================================ FILE: src/ContainsDuplicatesII219.java ================================================ /** * Given an array of integers and an integer k, find out whether there are * two distinct indices i and j in the array such that nums[i] = nums[j] and * the absolute difference between i and j is at most k. */ import java.util.HashSet; import java.util.Set; import java.util.HashMap; import java.util.Map; public class ContainsDuplicatesII219 { // too slow public boolean containsNearbyDuplicate(int[] nums, int k) { if (nums.length < 2) { return false; } for (int i = 0; i < nums.length; i++) { int numI = nums[i]; for (int j = i + 1; j < nums.length && j - i <= k; j++) { int numJ = nums[j]; if (numI == numJ) { return true; } } } return false; } public boolean containsNearbyDuplicate2(int[] nums, int k) { if (nums.length < 2) { return false; } Map map = new HashMap<>(); for (int i = 0; i < nums.length; i++) { Integer key = nums[i]; if (map.containsKey(key)) { if (i - map.get(key) <= k) { return true; } } map.put(key, i); } return false; } /** * https://discuss.leetcode.com/topic/15305/simple-java-solution */ public boolean containsNearbyDuplicate3(int[] nums, int k) { Set set = new HashSet(); for(int i = 0; i < nums.length; i++) { if(i > k) { set.remove(nums[i-k-1]); } if(!set.add(nums[i])) { return true; } } return false; } public static void main(String[] args) { ContainsDuplicatesII219 cd2 = new ContainsDuplicatesII219(); System.out.println(cd2.containsNearbyDuplicate2(new int[]{5, 8, 2, 10, 5}, 4)); System.out.println(cd2.containsNearbyDuplicate2(new int[]{5, 8, 2, 10}, 1)); } } ================================================ FILE: src/ContiguousArray525.java ================================================ /** * Given a binary array, find the maximum length of a contiguous subarray with * equal number of 0 and 1. * * Example 1: * Input: [0,1] * Output: 2 * * Explanation: [0, 1] is the longest contiguous subarray with equal number of 0 and 1. * * Example 2: * Input: [0,1,0] * Output: 2 * * Explanation: [0, 1] (or [1, 0]) is a longest contiguous subarray with equal number of 0 and 1. * * Note: The length of the given binary array will not exceed 50,000. * */ public class ContiguousArray525 { /** * https://leetcode.com/problems/contiguous-array/solution/ */ public int findMaxLength(int[] nums) { int maxlen = 0; for (int start = 0; start < nums.length; start++) { int zeroes = 0, ones = 0; for (int end = start; end < nums.length; end++) { if (nums[end] == 0) { zeroes++; } else { ones++; } if (zeroes == ones) { maxlen = Math.max(maxlen, end - start + 1); } } } return maxlen; } public int findMaxLength2(int[] nums) { int[] arr = new int[2 * nums.length + 1]; Arrays.fill(arr, -2); arr[nums.length] = -1; int maxlen = 0, count = 0; for (int i = 0; i < nums.length; i++) { count = count + (nums[i] == 0 ? -1 : 1); if (arr[count + nums.length] >= -1) { maxlen = Math.max(maxlen, i - arr[count + nums.length]); } else { arr[count + nums.length] = i; } } return maxlen; } public int findMaxLength3(int[] nums) { Map map = new HashMap<>(); map.put(0, -1); int maxlen = 0, count = 0; for (int i = 0; i < nums.length; i++) { count = count + (nums[i] == 1 ? 1 : -1); if (map.containsKey(count)) { maxlen = Math.max(maxlen, i - map.get(count)); } else { map.put(count, i); } } return maxlen; } } ================================================ FILE: src/ContinuousSubarraySum523.java ================================================ /** * Given a list of non-negative numbers and a target integer k, write a * function to check if the array has a continuous subarray of size at least 2 * that sums up to the multiple of k, that is, sums up to n*k where n is also * an integer. * * Example 1: * Input: [23, 2, 4, 6, 7], k=6 * Output: True * Explanation: Because [2, 4] is a continuous subarray of size 2 and sums up * to 6. * * Example 2: * Input: [23, 2, 6, 4, 7], k=6 * Output: True * Explanation: Because [23, 2, 6, 4, 7] is an continuous subarray of size 5 * and sums up to 42. * * Note: * The length of the array won't exceed 10,000. * You may assume the sum of all the numbers is in the range of a signed * 32-bit integer. * */ public class ContinuousSubarraySum523 { public boolean checkSubarraySum(int[] nums, int k) { if (k == 0) return kIsZero(nums); return kIsNotZero(nums, k); } public boolean kIsNotZero(int[] nums, int k) { Map map = new HashMap<>(); map.put(0, -1); int sum = 0; for (int i=0; i= 2) return true; } else { map.put(mod, i); } } return false; } public boolean kIsZero(int[] nums) { int count = 0; for (int i=0; i= 2) return true; } else { count = 0; } } return false; } /** * https://leetcode.com/problems/continuous-subarray-sum/solution/ */ public boolean checkSubarraySum2(int[] nums, int k) { int sum = 0; HashMap < Integer, Integer > map = new HashMap < > (); map.put(0, -1); for (int i = 0; i < nums.length; i++) { sum += nums[i]; if (k != 0) sum = sum % k; if (map.containsKey(sum)) { if (i - map.get(sum) > 1) return true; } else map.put(sum, i); } return false; } } ================================================ FILE: src/ConvertANumberToHexadecimal405.java ================================================ /** * Given an integer, write an algorithm to convert it to hexadecimal. For * negative integer, two’s complement method is used. * * Note: * * All letters in hexadecimal (a-f) must be in lowercase. * The hexadecimal string must not contain extra leading 0s. If the number is * zero, it is represented by a single zero character '0'; otherwise, the first * character in the hexadecimal string will not be the zero character. * The given number is guaranteed to fit within the range of a 32-bit signed integer. * You must not use any method provided by the library which converts/formats * the number to hex directly. * * Example 1: * Input: * 26 * Output: * "1a" * * Example 2: * Input: * -1 * Output: * "ffffffff" */ public class ConvertANumberToHexadecimal405 { public String toHex(int num) { if (num == 0) return "0"; char[] map = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; StringBuilder sb = new StringBuilder(); long n = num & 0x00000000ffffffffL; while (n > 0) { sb.insert(0, map[(int) (n % 16)]); n /= 16; } return sb.toString(); } /** * https://leetcode.com/problems/convert-a-number-to-hexadecimal/discuss/89253/Simple-Java-solution-with-comment */ public String toHex2(int num) { if(num == 0) return "0"; char[] map = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; String result = ""; while(num != 0){ result = map[(num & 15)] + result; num = (num >>> 4); } return result; } } ================================================ FILE: src/ConvertBSTToGreaterTree538.java ================================================ /** * Given a Binary Search Tree (BST), convert it to a Greater Tree such that * every key of the original BST is changed to the original key plus sum of * all keys greater than the original key in BST. * * Example: * * Input: The root of a Binary Search Tree like this: * 5 * / \ * 2 13 * * Output: The root of a Greater Tree like this: * 18 * / \ * 20 13 * */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class ConvertBSTToGreaterTree538 { public TreeNode convertBST(TreeNode root) { return convertBST(root, new int[1]); } private TreeNode convertBST(TreeNode root, int[] sum) { if (root == null) return null; convertBST(root.right, sum); sum[0] += root.val; root.val = sum[0]; convertBST(root.left, sum); return root; } public TreeNode convertBST2(TreeNode root) { if (root == null) return null; TreeNode curr = root; Stack stack = new Stack<>(); int sum = 0; while (!stack.isEmpty() || curr != null) { while (curr != null) { stack.push(curr); curr = curr.right; } curr = stack.pop(); sum += curr.val; curr.val = sum; curr = curr.left; } return root; } } ================================================ FILE: src/ConvertBinarySearchTreeToSortedDoublyLinkedList.java ================================================ /** * Convert a BST to a sorted circular doubly-linked list in-place. Think of the * left and right pointers as synonymous to the previous and next pointers in a * doubly-linked list. * * Let's take the following BST as an example, it may help you understand the problem better: * * https://leetcode.com/static/images/problemset/BSTDLLOriginalBST.png * * We want to transform this BST into a circular doubly linked list. Each node * in a doubly linked list has a predecessor and successor. For a circular * doubly linked list, the predecessor of the first element is the last element, * and the successor of the last element is the first element. * * The figure below shows the circular doubly linked list for the BST above. * The "head" symbol means the node it points to is the smallest element of * the linked list. * * https://leetcode.com/static/images/problemset/BSTDLLReturnDLL.png * * Specifically, we want to do the transformation in place. After the * transformation, the left pointer of the tree node should point to its * predecessor, and the right pointer should point to its successor. We should * return the pointer to the first element of the linked list. * * The figure below shows the transformed BST. The solid line indicates the * successor relationship, while the dashed line means the predecessor relationship. * * https://leetcode.com/static/images/problemset/BSTDLLReturnBST.png * */ /* // Definition for a Node. class Node { public int val; public Node left; public Node right; public Node() {} public Node(int _val,Node _left,Node _right) { val = _val; left = _left; right = _right; } }; */ public class ConvertBinarySearchTreeToSortedDoublyLinkedList { public Node treeToDoublyList(Node root) { if (root == null) return null; Node[] edges = dfs(root); edges[0].left = edges[1]; edges[1].right = edges[0]; return edges[0]; } private Node[] dfs(Node n) { if (n.left == null && n.right == null) return new Node[]{n, n}; Node head; Node tail; if (n.left == null) { head = n; head.left = null; } else { Node[] left = dfs(n.left); head = left[0]; head.left = null; Node leftTail = left[1]; leftTail.right = n; n.left = leftTail; } if (n.right == null) { tail = n; tail.right = null; } else { Node[] right = dfs(n.right); tail = right[1]; tail.right = null; Node rightHead = right[0]; rightHead.left = n; n.right = rightHead; } return new Node[]{head, tail}; } } ================================================ FILE: src/ConvertSortedArrayToBinarySearchTree108.java ================================================ /** * Given an array where elements are sorted in ascending order, convert it to a * height balanced BST. * * For this problem, a height-balanced binary tree is defined as a binary tree * in which the depth of the two subtrees of every node never differ by more * than 1. * * * Example: * * Given the sorted array: [-10,-3,0,5,9], * * One possible answer is: [0,-3,9,-10,null,5], which represents the following * height balanced BST: * * 0 * / \ * -3 9 * / / * -10 5 * */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ class ConvertSortedArrayToBinarySearchTree108 { public TreeNode sortedArrayToBST(int[] nums) { return sortedArrayToBST(nums, 0, nums.length-1); } public TreeNode sortedArrayToBST(int[] nums, int i, int j) { if (i > j) return null; int mid = (i + j) / 2; TreeNode res = new TreeNode(nums[mid]); if (i == j) return res; res.left = sortedArrayToBST(nums, i, mid-1); res.right = sortedArrayToBST(nums, mid+1, j); return res; } } ================================================ FILE: src/ConvertSortedListToBST109.java ================================================ /** * Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST. */ import java.util.ArrayList; import java.util.List; /* The following classes are defined in seperate files. */ /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class ConvertSortedListToBST109 { public TreeNode sortedListToBST(ListNode head) { List nodes = new ArrayList(); storeBSTNodes(head, nodes); int n = nodes.size(); return buildBST(nodes, 0, n-1); } private void storeBSTNodes(ListNode head, List nodes) { while (head != null) { nodes.add(new TreeNode(head.val)); head = head.next; } } private TreeNode buildBST(List nodes, int start, int end) { if (start > end) return null; int mid = (start + end) / 2; TreeNode node = nodes.get(mid); node.left = buildBST(nodes, start, mid - 1); node.right = buildBST(nodes, mid + 1, end); return node; } /** ------------------------------------------------------------------- * Top Solution: O(n logn) * https://discuss.leetcode.com/topic/35997/share-my-java-solution-1ms-very-short-and-concise * -------------------------------------------------------------------- */ public TreeNode sortedListToBST2(ListNode head) { if (head == null) return null; return toBST(head, null); } public TreeNode toBST(ListNode head, ListNode tail){ ListNode slow = head; ListNode fast = head; if(head == tail) return null; while(fast != tail && fast.next != tail){ fast = fast.next.next; slow = slow.next; } TreeNode thead = new TreeNode(slow.val); thead.left = toBST(head, slow); thead.right = toBST(slow.next, tail); return thead; } /** ------------------------------------------------------------------- * Top Solution: O(n) * https://discuss.leetcode.com/topic/35997/share-my-java-solution-1ms-very-short-and-concise * -------------------------------------------------------------------- */ private ListNode node; public TreeNode sortedListToBST3(ListNode head) { if(head == null){ return null; } int size = 0; ListNode runner = head; node = head; while(runner != null){ runner = runner.next; size ++; } return inorderHelper(0, size - 1); } public TreeNode inorderHelper(int start, int end){ if(start > end){ return null; } int mid = start + (end - start) / 2; TreeNode left = inorderHelper(start, mid - 1); TreeNode treenode = new TreeNode(node.val); treenode.left = left; node = node.next; TreeNode right = inorderHelper(mid + 1, end); treenode.right = right; return treenode; } public TreeNode sortedListToBST4(ListNode head) { if (head == null) return null; if (head.next == null) return new TreeNode(head.val); ListNode fast = head; ListNode slow = head; ListNode beforeSlow = null; while (slow != null && fast != null && fast.next != null) { fast = fast.next.next; beforeSlow = slow; slow = slow.next; } beforeSlow.next = null; TreeNode res = new TreeNode(slow.val); res.left = sortedListToBST(head); res.right = sortedListToBST(slow.next); return res; } public TreeNode sortedListToBST5(ListNode head) { if (head == null) return null; ListNode fast = head; ListNode slow = head; ListNode pre = null; while (fast != null && fast.next != null) { fast = fast.next.next; pre = slow; slow = slow.next; } if (pre == null) { return new TreeNode(head.val); } pre.next = null; TreeNode root = new TreeNode(slow.val); root.left = sortedListToBST(head); root.right = sortedListToBST(slow.next); return root; } } ================================================ FILE: src/CopyListWithRandomPointer138.java ================================================ /** * A linked list is given such that each node contains an additional random * pointer which could point to any node in the list or null. * * Return a deep copy of the list. * */ /** * Definition for singly-linked list with a random pointer. * class RandomListNode { * int label; * RandomListNode next, random; * RandomListNode(int x) { this.label = x; } * }; */ public class CopyListWithRandomPointer138 { public RandomListNode copyRandomList(RandomListNode head) { return deepCopy(head, new HashMap()); } public RandomListNode deepCopy(RandomListNode node, Map map) { if (node == null) return null; if (map.containsKey(node)) return map.get(node); RandomListNode copy = new RandomListNode(node.label); map.put(node, copy); copy.next = deepCopy(node.next, map); copy.random = deepCopy(node.random, map); return copy; } /** * https://leetcode.com/problems/copy-list-with-random-pointer/discuss/43488/Java-O(n)-solution */ public RandomListNode copyRandomList2(RandomListNode head) { if (head == null) return null; Map map = new HashMap(); // loop 1. copy all the nodes RandomListNode node = head; while (node != null) { map.put(node, new RandomListNode(node.label)); node = node.next; } // loop 2. assign next and random pointers node = head; while (node != null) { map.get(node).next = map.get(node.next); map.get(node).random = map.get(node.random); node = node.next; } return map.get(head); } /** * https://leetcode.com/problems/copy-list-with-random-pointer/discuss/43491/A-solution-with-constant-space-complexity-O(1)-and-linear-time-complexity-O(N) */ public RandomListNode copyRandomList3(RandomListNode head) { RandomListNode iter = head, next; // First round: make copy of each node, // and link them together side-by-side in a single list. while (iter != null) { next = iter.next; RandomListNode copy = new RandomListNode(iter.label); iter.next = copy; copy.next = next; iter = next; } // Second round: assign random pointers for the copy nodes. iter = head; while (iter != null) { if (iter.random != null) { iter.next.random = iter.random.next; } iter = iter.next.next; } // Third round: restore the original list, and extract the copy list. iter = head; RandomListNode pseudoHead = new RandomListNode(0); RandomListNode copy, copyIter = pseudoHead; while (iter != null) { next = iter.next.next; // extract the copy copy = iter.next; copyIter.next = copy; copyIter = copy; // restore the original list iter.next = next; iter = next; } return pseudoHead.next; } } ================================================ FILE: src/CountNumbersWithUniqueDigits357.java ================================================ /** * Given a non-negative integer n, count all numbers with unique digits, x, * where 0 ≤ x < 10n. * * Example: * Given n = 2, return 91. (The answer should be the total numbers in the * range of 0 ≤ x < 100, excluding [11,22,33,44,55,66,77,88,99]) */ public class CountNumbersWithUniqueDigits357 { public int countNumbersWithUniqueDigits(int n) { n = Math.min(n, 10); int res = 1; for (int i=1; i<=n; i++) { res += count(i); } return res; } private int count(int i) { int res = 9; int k = 1; while (k < i) { res *= (10-k); k++; } return res; } /** * https://leetcode.com/problems/count-numbers-with-unique-digits/discuss/83037/Very-simple-15-line-backtrack-solution */ public int countNumbersWithUniqueDigits2(int n) { return count(n, new boolean[10], 0); } private int count(int n, boolean[] used, int l) { if (l == n) return 1; int res = 0; for (int i = (l == 0 ? 1 : 0); i<=9; i++) { if (!used[i]) { used[i] = true; res += count(n, used, l+1); used[i] = false; } } return res; } public int countNumbersWithUniqueDigits3(int n) { int[] res = new int[1]; count(n, new boolean[10], 0, res); return res[0]; } private void count(int n, boolean[] used, int l, int[] res) { res[0]++; if (l == n) return; for (int i = (l == 0 ? 1 : 0); i<=9; i++) { if (!used[i]) { used[i] = true; count(n, used, l+1, res); used[i] = false; } } } } ================================================ FILE: src/CountOfRangeSum327.java ================================================ /** * Given an integer array nums, return the number of range sums that lie in * [lower, upper] inclusive. * * Range sum S(i, j) is defined as the sum of the elements in nums between * indices i and j (i ≤ j), inclusive. * * Note: * A naive algorithm of O(n2) is trivial. You MUST do better than that. * * Example: * Given nums = [-2, 5, -1], lower = -2, upper = 2, * Return 3. * * The three ranges are : [0, 0], [2, 2], [0, 2] and their respective sums * are: -2, -1, 2. * */ public class CountOfRangeSum327 { public int countRangeSum(int[] nums, int lower, int upper) { int len = nums.length; if (nums == null || len == 0) return 0; int[][] dp = new int[len][len]; int res = 0; for (int i=0; i= lower && nums[i] <= upper) res++; } for (int j=1; j= '0' && c <= '9') { num.append(c); i++; continue; } if (c == '[') { Res res = decodeString(s, i); int next = res.next; String in = res.in; for (int j = 0; j= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { sb.append(c); i++; continue; } } return sb.toString(); } public Res decodeString(String s, int start) { StringBuilder sb = new StringBuilder(""); int i = start+1; StringBuilder num = new StringBuilder(""); while (i < s.length()) { char c = s.charAt(i); if (c >= '0' && c <= '9') { num.append(c); i++; continue; } if (c == '[') { Res res = decodeString(s, i); int next = res.next; String in = res.in; for (int j = 0; j= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { sb.append(c); i++; continue; } } return new Res(i+1, sb.toString()); } class Res { int next; String in; Res (int next, String in) { this.next = next; this.in = in; } } /** * https://discuss.leetcode.com/topic/57318/java-simple-recursive-solution */ public String decodeString2(String s) { if (s.length() == 0) return ""; StringBuilder sb = new StringBuilder(); for (int i = 0; i < s.length(); i ++) { char c = s.charAt(i); if (Character.isDigit(c)) { int digit_begin = i; while (s.charAt(i) != '[') i++; int num = Integer.valueOf(s.substring(digit_begin, i)); int count = 1; int str_begin = i+1; i ++; while (count != 0) { if (s.charAt(i) == '[') count ++; else if (s.charAt(i) == ']') count --; i ++; } i--; String str = decodeString(s.substring(str_begin, i)); for (int j = 0; j < num; j ++) { sb.append(str); } } else { sb.append(c); } } return sb.toString(); } /** * https://discuss.leetcode.com/topic/57159/simple-java-solution-using-stack */ public String decodeString3(String s) { String res = ""; Stack countStack = new Stack<>(); Stack resStack = new Stack<>(); int idx = 0; while (idx < s.length()) { if (Character.isDigit(s.charAt(idx))) { int count = 0; while (Character.isDigit(s.charAt(idx))) { count = 10 * count + (s.charAt(idx) - '0'); idx++; } countStack.push(count); } else if (s.charAt(idx) == '[') { resStack.push(res); res = ""; idx++; } else if (s.charAt(idx) == ']') { StringBuilder temp = new StringBuilder (resStack.pop()); int repeatTimes = countStack.pop(); for (int i = 0; i < repeatTimes; i++) { temp.append(res); } res = temp.toString(); idx++; } else { res += s.charAt(idx++); } } return res; } } ================================================ FILE: src/DecodeWays91.java ================================================ /** * A message containing letters from A-Z is being encoded to numbers using the * following mapping: * * 'A' -> 1 * 'B' -> 2 * ... * 'Z' -> 26 * Given an encoded message containing digits, determine the total number of * ways to decode it. * * For example, * Given encoded message "12", it could be decoded as "AB" (1 2) or "L" (12). * * The number of ways decoding "12" is 2. */ import java.util.Map; import java.util.HashMap; public class DecodeWays91 { public int numDecodings(String s) { int length = s.length(); length = s.length(); if (length == 0) { return 0; } if (s.charAt(0) == '0') { return 0; } int[] dp = new int[length + 1]; dp[0] = 1; dp[1] = 1; boolean isZero = false; for (int i = 2; i <= length; i++) { int n = Integer.valueOf(s.substring(i-2, i)); if (s.charAt(i - 1) == '0' && (n > 26 || n == 0)) { return 0; } else if (s.charAt(i - 1) == '0') { isZero = true; dp[i] = dp[i - 2]; } else if (isZero) { isZero = false; dp[i] = dp[i - 1]; } else { isZero = false; dp[i] = dp[i - 1] + ((n > 0 && n <= 26) ? dp[i - 2] : 0); } } return dp[length]; } /** * https://discuss.leetcode.com/topic/2562/dp-solution-java-for-reference */ public int numDecodings2(String s) { int n = s.length(); if (n == 0) return 0; int[] memo = new int[n+1]; memo[n] = 1; memo[n-1] = s.charAt(n-1) != '0' ? 1 : 0; for (int i = n - 2; i >= 0; i--) if (s.charAt(i) == '0') continue; else memo[i] = (Integer.parseInt(s.substring(i,i+2))<=26) ? memo[i+1]+memo[i+2] : memo[i+1]; return memo[0]; } /** * https://discuss.leetcode.com/topic/35840/java-clean-dp-solution-with-explanation */ public int numDecodings3(String s) { if (s == null || s.length() == 0) { return 0; } int[] ways = new int[s.length() + 1]; ways[0] = 1; ways[1] = s.charAt(0) == '0' ? 0 : 1; for (int i = 2; i <= s.length(); i++) { int one = s.charAt(i - 1) - '0'; int two = (s.charAt(i - 2) - '0') * 10 + one; if (one != 0) { ways[i] += ways[i - 1]; } if (two >= 10 && two <= 26) { ways[i] += ways[i - 2]; } } return ways[s.length()]; } public int numDecodings4(String s) { if (s == null || s.length() == 0) return 0; if (s.charAt(0) == '0') return 0; int[] dp = new int[s.length()+1]; dp[0] = 1; dp[1] = 1; for (int i=2; i<=s.length(); i++) { int now = s.charAt(i-1) - '0'; int prenow = (s.charAt(i-2) - '0')*10 + now; if (now == 0 && prenow != 10 && prenow != 20) return 0; int a = now == 0 ? 0 : dp[i-1]; int b = (prenow >= 10 && prenow <= 26) ? dp[i-2] : 0; dp[i] = a + b; } return dp[s.length()]; } /** * https://leetcode.com/problems/decode-ways/discuss/30416/Simple-java-solution-with-O(1)-space */ public int numDecodings5(String s) { int n1 =1, n2=1, n3=0; if(s.length() == 0 || s.charAt(0) == '0') return 0; for (int i=2; i<=s.length(); i++) { n3=0; if(s.charAt(i-1)!='0') n3=n2; int num = Integer.parseInt(s.substring(i-2,i)); if(num>=10 && num<=26) n3+=n1; n1=n2; n2=n3; } return n2; } } ================================================ FILE: src/DecodeWaysII639.java ================================================ /** * A message containing letters from A-Z is being encoded to numbers using the * following mapping way: * * 'A' -> 1 * 'B' -> 2 * ... * 'Z' -> 26 * Beyond that, now the encoded string can also contain the character '*', * which can be treated as one of the numbers from 1 to 9. * * Given the encoded message containing digits and the character '*', return * the total number of ways to decode it. * * Also, since the answer may be very large, you should return the output mod 109 + 7. * * Example 1: * Input: "*" * Output: 9 * * Explanation: The encoded message can be decoded to the string: * "A", "B", "C", "D", "E", "F", "G", "H", "I". * * Example 2: * Input: "1*" * Output: 9 + 9 = 18 * * Note: * The length of the input string will fit in range [1, 105]. * The input string will only contain the character '*' and digits '0' - '9'. */ public class DecodeWaysII639 { public int numDecodings(String s) { if (s == null || s.length() == 0) return 0; long[] dp = new long[s.length()+1]; dp[0] = 1; dp[1] = s.charAt(0) == '0' ? 0 : (s.charAt(0) == '*' ? 9 : 1); for (int i=2; i<=s.length(); i++) { char c = s.charAt(i-1); char pc = s.charAt(i-2); if (c == '*') { dp[i] += dp[i-1]*9; dp[i] += pc == '*' ? dp[i-2]*15 : (pc == '1' ? dp[i-2]*9 : (pc == '2' ? dp[i-2]*6 : 0)); } else { dp[i] += c == '0' ? 0 : dp[i-1]; if (pc == '*') { dp[i] += dp[i-2] * (c <= '6' ? 2 : 1); } else { int two = (pc - '0') * 10 + (c - '0'); dp[i] += (two >= 10 && two <= 26) ? dp[i-2] : 0; } } dp[i] %= 1000000007; } return (int) dp[s.length()]; } public int numDecodings2(String s) { if (s == null || s.length() == 0) return 0; long n0 = 1; long n1 = s.charAt(0) == '0' ? 0 : (s.charAt(0) == '*' ? 9 : 1); long n2 = 0; for (int i=2; i<=s.length(); i++) { n2 = 0; char c = s.charAt(i-1); char pc = s.charAt(i-2); if (c == '*') { n2 += n1*9; n2 += pc == '*' ? n0*15 : (pc == '1' ? n0*9 : (pc == '2' ? n0*6 : 0)); } else { n2 += c == '0' ? 0 : n1; if (pc == '*') { n2 += n0 * (c <= '6' ? 2 : 1); } else { int two = (pc - '0') * 10 + (c - '0'); n2 += (two >= 10 && two <= 26) ? n0 : 0; } } n2 %= 1000000007; n0 = n1; n1 = n2; } return (int) n1; } } ================================================ FILE: src/DecodedStringAtIndex884.java ================================================ /** * An encoded string S is given. To find and write the decoded string to a * tape, the encoded string is read one character at a time and the following * steps are taken: * * If the character read is a letter, that letter is written onto the tape. * If the character read is a digit (say d), the entire current tape is * repeatedly written d-1 more times in total. * Now for some encoded string S, and an index K, find and return the K-th * letter (1 indexed) in the decoded string. * * Example 1: * Input: S = "leet2code3", K = 10 * Output: "o" * Explanation: * The decoded string is "leetleetcodeleetleetcodeleetleetcode". * The 10th letter in the string is "o". * * Example 2: * Input: S = "ha22", K = 5 * Output: "h" * Explanation: * The decoded string is "hahahaha". The 5th letter is "h". * * Example 3: * Input: S = "a2345678999999999999999", K = 1 * Output: "a" * Explanation: * The decoded string is "a" repeated 8301530446056247680 times. * The 1st letter is "a". * * Note: * 2 <= S.length <= 100 * S will only contain lowercase letters and digits 2 through 9. * S starts with a letter. * 1 <= K <= 10^9 * The decoded string is guaranteed to have less than 2^63 letters. */ public class DecodedStringAtIndex884 { public String decodeAtIndex(String S, int K) { char[] chars = S.toCharArray(); int N = chars.length; long[] lens = new long[N]; long len = 0; for (int i=0; i= 'a' && c <= 'z') { len++; } else { int re = Character.getNumericValue(c); len *= re; } lens[i] = len; } for (int i=N-1; i>=0; i--) { char c = chars[i]; if (c >= 'a' && c <= 'z') { if (lens[i] == K) return Character.toString(c); } else { K %= lens[i-1]; if (K == 0) { int j = i-1; while (!(chars[j] >= 'a' && chars[j] <= 'z')) { j--; } return Character.toString(chars[j]); } } } return Character.toString(chars[0]); } } ================================================ FILE: src/DeleteAndEarn740.java ================================================ /** * Given an array nums of integers, you can perform operations on the array. * * In each operation, you pick any nums[i] and delete it to earn nums[i] * points. After, you must delete every element equal to nums[i] - 1 or * nums[i] + 1. * * You start with 0 points. Return the maximum number of points you can earn * by applying such operations. * * Example 1: * Input: nums = [3, 4, 2] * Output: 6 * Explanation: * Delete 4 to earn 4 points, consequently 3 is also deleted. * Then, delete 2 to earn 2 points. 6 total points are earned. * * Example 2: * Input: nums = [2, 2, 3, 3, 3, 4] * Output: 9 * Explanation: * Delete 3 to earn 3 points, deleting both 2's and the 4. * Then, delete 3 again to earn 3 points, and 3 again to earn 3 points. * 9 total points are earned. * * Note: * The length of nums is at most 20000. * Each element nums[i] is an integer in the range [1, 10000]. */ public class DeleteAndEarn740 { public int deleteAndEarn(int[] nums) { if (nums == null || nums.length == 0) return 0; int[] count = new int[10001]; int max = 0; for (int n: nums) { max = Math.max(max, n); count[n]++; } int[] dp = new int[max + 1]; dp[0] = 0; dp[1] = count[1]; for (int i=2; i<=max; i++) { if (count[i] == 0) { dp[i] = Math.max(dp[i-1], dp[i-2]); } else { dp[i] = Math.max(dp[i-1], dp[i-2] + count[i] * i); } } return dp[max]; } public int deleteAndEarn2(int[] nums) { if (nums == null || nums.length == 0) return 0; int[] count = new int[10001]; int max = 0; for (int n: nums) { max = Math.max(max, n); count[n]++; } int dp0 = 0; int dp1 = count[1]; for (int i=2; i<=max; i++) { int tmp = dp1; if (count[i] == 0) { dp1 = Math.max(dp1, dp0); } else { dp1 = Math.max(dp1, dp0 + count[i] * i); } dp0 = tmp; } return dp1; } } ================================================ FILE: src/DeleteNodeInABST450.java ================================================ /** * Given a root node reference of a BST and a key, delete the node with the given * key in the BST. Return the root node reference (possibly updated) of the BST. * * Basically, the deletion can be divided into two stages: * * Search for a node to remove. * If the node is found, delete the node. * Note: Time complexity should be O(height of tree). * * Example: * * root = [5,3,6,2,4,null,7] * key = 3 * * 5 * / \ * 3 6 * / \ \ * 2 4 7 * * Given key to delete is 3. So we find the node with value 3 and delete it. * * One valid answer is [5,4,6,2,null,null,7], shown in the following BST. * * 5 * / \ * 4 6 * / \ * 2 7 * * Another valid answer is [5,2,6,null,4,null,7]. * * 5 * / \ * 2 6 * \ \ * 4 7 * */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class DeleteNodeInABST450 { public TreeNode deleteNode(TreeNode root, int key) { if (root == null) return null; if (key < root.val) { root.left = deleteNode(root.left, key); return root; } if (key > root.val) { root.right = deleteNode(root.right, key); return root; } return delete(root); } private TreeNode delete(TreeNode node) { if (node.left == null) return node.right; if (node.right == null) return node.left; return moveNext(node); } private TreeNode moveNext(TreeNode node) { TreeNode min = node.right; if (min.left == null) { node.val = min.val; node.right = min.right; return node; } while (min.left != null && min.left.left != null) { System.out.println(min.val); min = min.left; } node.val = min.left.val; min.left = delete(min.left); return node; } public TreeNode deleteNode2(TreeNode root, int key) { /* Base Case: If the tree is empty */ if (root == null) return root; /* Otherwise, recur down the tree */ if (key < root.val) { root.left = deleteNode(root.left, key); } else if (key > root.val) { root.right = deleteNode(root.right, key); } else { // node with only one child or no child if (root.left == null) { return root.right; } else if (root.right == null) { return root.left; } // node with two children: Get the inorder successor (smallest // in the right subtree) root.val = minValue(root.right); // Delete the inorder successor root.right = deleteNode(root.right, root.val); } return root; } private int minValue(TreeNode root) { int minv = root.val; while (root.left != null) { minv = root.left.val; root = root.left; } return minv; } } ================================================ FILE: src/DeleteNodeInALinkedList237.java ================================================ /** * Write a function to delete a node (except the tail) in a singly linked list, * given only access to that node. * * Supposed the linked list is 1 -> 2 -> 3 -> 4 and you are given the third * node with value 3, the linked list should become 1 -> 2 -> 4 after calling * your function. */ /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ public class DeleteNodeInALinkedList237 { public void deleteNode(ListNode node) { if (node != null && node.next != null) { node.val = node.next.val; node.next = node.next.next; } } } ================================================ FILE: src/DesignCircularDeque641.java ================================================ /** * Design your implementation of the circular double-ended queue (deque). * * Your implementation should support following operations: * * MyCircularDeque(k): Constructor, set the size of the deque to be k. * insertFront(): Adds an item at the front of Deque. Return true if the operation is successful. * insertLast(): Adds an item at the rear of Deque. Return true if the operation is successful. * deleteFront(): Deletes an item from the front of Deque. Return true if the operation is successful. * deleteLast(): Deletes an item from the rear of Deque. Return true if the operation is successful. * getFront(): Gets the front item from the Deque. If the deque is empty, return -1. * getRear(): Gets the last item from Deque. If the deque is empty, return -1. * isEmpty(): Checks whether Deque is empty or not. * isFull(): Checks whether Deque is full or not. * * Example: * * MyCircularDeque circularDeque = new MycircularDeque(3); // set the size to be 3 * circularDeque.insertLast(1); // return true * circularDeque.insertLast(2); // return true * circularDeque.insertFront(3); // return true * circularDeque.insertFront(4); // return false, the queue is full * circularDeque.getRear(); // return 2 * circularDeque.isFull(); // return true * circularDeque.deleteLast(); // return true * circularDeque.insertFront(4); // return true * circularDeque.getFront(); // return 4 * * Note: * * All values will be in the range of [0, 1000]. * The number of operations will be in the range of [1, 1000]. * Please do not use the built-in Deque library. */ public class DesignCircularDeque641 { class MyCircularDeque { private Node head; private int capacity; private int size; /** Initialize your data structure here. Set the size of the deque to be k. */ public MyCircularDeque(int k) { this.head = new Node(-1); this.head.next = this.head; this.head.prev = this.head; this.capacity = k; this.size = 0; } /** Adds an item at the front of Deque. Return true if the operation is successful. */ public boolean insertFront(int value) { if (this.size >= this.capacity) return false; Node newNode = new Node(value); newNode.next = this.head.next; newNode.prev = this.head; this.head.next.prev = newNode; this.head.next = newNode; this.size++; return true; } /** Adds an item at the rear of Deque. Return true if the operation is successful. */ public boolean insertLast(int value) { if (this.size >= this.capacity) return false; Node newNode = new Node(value); newNode.next = this.head; newNode.prev = this.head.prev; this.head.prev.next = newNode; this.head.prev = newNode; this.size++; return true; } /** Deletes an item from the front of Deque. Return true if the operation is successful. */ public boolean deleteFront() { if (isEmpty()) return false; Node toBeRemoved = this.head.next; dislink(toBeRemoved); this.size--; return true; } /** Deletes an item from the rear of Deque. Return true if the operation is successful. */ public boolean deleteLast() { if (isEmpty()) return false; Node toBeRemoved = this.head.prev; dislink(toBeRemoved); this.size--; return true; } private void dislink(Node node) { node.next.prev = node.prev; node.prev.next = node.next; } /** Get the front item from the deque. */ public int getFront() { if (isEmpty()) return -1; return this.head.next.value; } /** Get the last item from the deque. */ public int getRear() { if (isEmpty()) return -1; return this.head.prev.value; } /** Checks whether the circular deque is empty or not. */ public boolean isEmpty() { return this.size == 0; } /** Checks whether the circular deque is full or not. */ public boolean isFull() { return this.size >= this.capacity; } class Node { Node prev; Node next; int value; Node(int value) { this.value = value; } } } class MyCircularDeque2 { private int[] cache; private int capacity; private int size; private int head; /** Initialize your data structure here. Set the size of the deque to be k. */ public MyCircularDeque(int k) { this.cache = new int[k+1]; this.capacity = k; this.size = 0; this.head = 0; } /** Adds an item at the front of Deque. Return true if the operation is successful. */ public boolean insertFront(int value) { if (this.size >= this.capacity) return false; this.cache[this.head--] = value; if (this.head < 0) this.head += this.cache.length; this.size++; return true; } /** Adds an item at the rear of Deque. Return true if the operation is successful. */ public boolean insertLast(int value) { if (this.size >= this.capacity) return false; this.cache[(this.head + this.size + 1) % this.cache.length] = value; this.size++; return true; } /** Deletes an item from the front of Deque. Return true if the operation is successful. */ public boolean deleteFront() { if (isEmpty()) return false; this.head++; this.head %= this.cache.length; this.size--; return true; } /** Deletes an item from the rear of Deque. Return true if the operation is successful. */ public boolean deleteLast() { if (isEmpty()) return false; this.size--; return true; } /** Get the front item from the deque. */ public int getFront() { if (isEmpty()) return -1; return this.cache[(this.head + 1) % this.cache.length]; } /** Get the last item from the deque. */ public int getRear() { if (isEmpty()) return -1; return this.cache[(this.head + this.size) % this.cache.length]; } /** Checks whether the circular deque is empty or not. */ public boolean isEmpty() { return this.size == 0; } /** Checks whether the circular deque is full or not. */ public boolean isFull() { return this.size >= this.capacity; } } /** * Your MyCircularDeque object will be instantiated and called as such: * MyCircularDeque obj = new MyCircularDeque(k); * boolean param_1 = obj.insertFront(value); * boolean param_2 = obj.insertLast(value); * boolean param_3 = obj.deleteFront(); * boolean param_4 = obj.deleteLast(); * int param_5 = obj.getFront(); * int param_6 = obj.getRear(); * boolean param_7 = obj.isEmpty(); * boolean param_8 = obj.isFull(); */ } ================================================ FILE: src/DesignCircularQueue622.java ================================================ /** * Design your implementation of the circular queue. The circular queue is a * linear data structure in which the operations are performed based on FIFO * (First In First Out) principle and the last position is connected back to * the first position to make a circle. It is also called "Ring Buffer". * * One of the benefits of the circular queue is that we can make use of the * spaces in front of the queue. In a normal queue, once the queue becomes * full, we cannot insert the next element even if there is a space in front * of the queue. But using the circular queue, we can use the space to store * new values. * * Your implementation should support following operations: * * MyCircularQueue(k): Constructor, set the size of the queue to be k. * Front: Get the front item from the queue. If the queue is empty, return -1. * Rear: Get the last item from the queue. If the queue is empty, return -1. * enQueue(value): Insert an element into the circular queue. Return true if the operation is successful. * deQueue(): Delete an element from the circular queue. Return true if the operation is successful. * isEmpty(): Checks whether the circular queue is empty or not. * isFull(): Checks whether the circular queue is full or not. * * Example: * * MyCircularQueue circularQueue = new MycircularQueue(3); // set the size to be 3 * circularQueue.enQueue(1); // return true * circularQueue.enQueue(2); // return true * circularQueue.enQueue(3); // return true * circularQueue.enQueue(4); // return false, the queue is full * circularQueue.Rear(); // return 3 * circularQueue.isFull(); // return true * circularQueue.deQueue(); // return true * circularQueue.enQueue(4); // return true * circularQueue.Rear(); // return 4 * * Note: * All values will be in the range of [0, 1000]. * The number of operations will be in the range of [1, 1000]. * Please do not use the built-in Queue library. */ public class DesignCircularQueue622 { class MyCircularQueue { private Node head; private int capacity; private int size; /** Initialize your data structure here. Set the size of the queue to be k. */ public MyCircularQueue(int k) { this.head = new Node(); this.head.prev = head; this.head.next = head; this.capacity = k; this.size = 0; } /** Insert an element into the circular queue. Return true if the operation is successful. */ public boolean enQueue(int value) { if (isFull()) return false; Node newNode = new Node(value); newNode.next = this.head; newNode.prev = this.head.prev; this.head.prev.next = newNode; this.head.prev = newNode; this.size++; return true; } /** Delete an element from the circular queue. Return true if the operation is successful. */ public boolean deQueue() { if (isEmpty()) return false; dislink(this.head.next); this.size--; return true; } private void dislink(Node node) { node.next.prev = node.prev; node.prev.next = node.next; } /** Get the front item from the queue. */ public int Front() { if (isEmpty()) return -1; return this.head.next.value; } /** Get the last item from the queue. */ public int Rear() { if (isEmpty()) return -1; return this.head.prev.value; } /** Checks whether the circular queue is empty or not. */ public boolean isEmpty() { return this.size == 0; } /** Checks whether the circular queue is full or not. */ public boolean isFull() { return this.size == this.capacity; } class Node { Node prev; Node next; int value; Node() { this.value = -1; } Node(int value) { this.value = value; } } } class MyCircularQueue2 { private int[] cache; private int head; private int capacity; private int size; /** Initialize your data structure here. Set the size of the queue to be k. */ public MyCircularQueue(int k) { this.cache = new int[k + 1]; this.head = 0; this.capacity = k; this.size = 0; } /** Insert an element into the circular queue. Return true if the operation is successful. */ public boolean enQueue(int value) { if (isFull()) return false; this.size++; this.cache[(this.head + this.size) % this.cache.length] = value; return true; } /** Delete an element from the circular queue. Return true if the operation is successful. */ public boolean deQueue() { if (isEmpty()) return false; this.head++; this.head = this.head % this.cache.length; this.size--; return true; } /** Get the front item from the queue. */ public int Front() { if (isEmpty()) return -1; return this.cache[(this.head + 1) % this.cache.length]; } /** Get the last item from the queue. */ public int Rear() { if (isEmpty()) return -1; return this.cache[(this.head + this.size) % this.cache.length]; } /** Checks whether the circular queue is empty or not. */ public boolean isEmpty() { return this.size == 0; } /** Checks whether the circular queue is full or not. */ public boolean isFull() { return this.size == this.capacity; } } /** * Your MyCircularQueue object will be instantiated and called as such: * MyCircularQueue obj = new MyCircularQueue(k); * boolean param_1 = obj.enQueue(value); * boolean param_2 = obj.deQueue(); * int param_3 = obj.Front(); * int param_4 = obj.Rear(); * boolean param_5 = obj.isEmpty(); * boolean param_6 = obj.isFull(); */ } ================================================ FILE: src/DesignCompressedStringIterator604.java ================================================ /** * Design and implement a data structure for a compressed string iterator. It * should support the following operations: next and hasNext. * * The given compressed string will be in the form of each letter followed by * a positive integer representing the number of this letter existing in the * original uncompressed string. * * next() - if the original string still has uncompressed characters, return * the next letter; Otherwise return a white space. * hasNext() - Judge whether there is any letter needs to be uncompressed. * * Note: * Please remember to RESET your class variables declared in StringIterator, * as static/class variables are persisted across multiple test cases. * Please see here for more details. * * Example: * * StringIterator iterator = new StringIterator("L1e2t1C1o1d1e1"); * * iterator.next(); // return 'L' * iterator.next(); // return 'e' * iterator.next(); // return 'e' * iterator.next(); // return 't' * iterator.next(); // return 'C' * iterator.next(); // return 'o' * iterator.next(); // return 'd' * iterator.hasNext(); // return true * iterator.next(); // return 'e' * iterator.hasNext(); // return false * iterator.next(); // return ' ' */ public class DesignCompressedStringIterator604 { class StringIterator { private int index; private int count; private int countLen; private char[] chars; private int len; public StringIterator(String compressedString) { chars = compressedString.toCharArray(); len = chars.length; index = 0; move(); } public char next() { if (index >= len) return ' '; char returned = chars[index]; count--; if (count == 0) { index += countLen + 1; move(); } return returned; } public boolean hasNext() { return index < len; } private void move() { if (index < len) { int i = index + 1; while (i < len && isNumeric(chars[i])) { i++; } countLen = i - index - 1; count = Integer.parseInt(new String(chars, index + 1, countLen)); } } private boolean isNumeric(char c) { return c >= '0' && c <= '9'; } } /** * https://leetcode.com/problems/design-compressed-string-iterator/discuss/103828/Java-Concise-Single-Queue-Solution */ class StringIterator2 { Queue queue = new LinkedList<>(); public StringIterator(String s) { int i = 0, n = s.length(); while (i < n) { int j = i+1; while (j < n && s.charAt(j) - 'A' < 0) j++; queue.add(new int[]{s.charAt(i) - 'A', Integer.parseInt(s.substring(i+1, j))}); i = j; } } public char next() { if (queue.isEmpty()) return ' '; int[] top = queue.peek(); if (--top[1] == 0) queue.poll(); return (char) ('A' + top[0]); } public boolean hasNext() { return !queue.isEmpty(); } } /** * Your StringIterator object will be instantiated and called as such: * StringIterator obj = new StringIterator(compressedString); * char param_1 = obj.next(); * boolean param_2 = obj.hasNext(); */ } ================================================ FILE: src/DesignHashMap706.java ================================================ /** * Design a HashMap without using any built-in hash table libraries. * * To be specific, your design should include these functions: * * put(key, value) : Insert a (key, value) pair into the HashMap. If the value * already exists in the HashMap, update the value. * * get(key): Returns the value to which the specified key is mapped, or -1 if * this map contains no mapping for the key. * * remove(key) : Remove the mapping for the value key if this map contains the * mapping for the key. * * Example: * MyHashMap hashMap = new MyHashMap(); * hashMap.put(1, 1); * hashMap.put(2, 2); * hashMap.get(1); // returns 1 * hashMap.get(3); // returns -1 (not found) * hashMap.put(2, 1); // update the existing value * hashMap.get(2); // returns 1 * hashMap.remove(2); // remove the mapping for 2 * hashMap.get(2); // returns -1 (not found) * * Note: * All keys and values will be in the range of [0, 1000000]. * The number of operations will be in the range of [1, 10000]. * Please do not use the built-in HashMap library. */ public class DesignHashMap706 { class MyHashMap { private Integer[] cache = new Integer[1000000]; /** Initialize your data structure here. */ public MyHashMap() { } /** value will always be non-negative. */ public void put(int key, int value) { cache[key] = value; } /** Returns the value to which the specified key is mapped, or -1 if this map contains no mapping for the key */ public int get(int key) { if (cache[key] == null) return -1; return cache[key]; } /** Removes the mapping of the specified value key if this map contains a mapping for the key */ public void remove(int key) { cache[key] = null; } } class MyHashMap2 { private static final int K = 100000; private ListNode[] cache = new ListNode[100000]; /** Initialize your data structure here. */ public MyHashMap() { } /** value will always be non-negative. */ public void put(int key, int value) { int k = key % K; if (cache[k] == null) { cache[k] = new ListNode(key, value); } else { ListNode head = cache[k]; while (true) { if (head.key == key) { head.value = value; return; } if (head.next == null) { ListNode newNode = new ListNode(key, value); head.next = newNode; newNode.prev = head; return; } head = head.next; } } } /** Returns the value to which the specified key is mapped, or -1 if this map contains no mapping for the key */ public int get(int key) { int k = key % K; if (cache[k] == null) return -1; ListNode head = cache[k]; while (true) { if (head.key == key) { return head.value; } if (head.next == null) { return -1; } head = head.next; } } /** Removes the mapping of the specified value key if this map contains a mapping for the key */ public void remove(int key) { int k = key % K; if (cache[k] == null) return; ListNode head = cache[k]; while (true) { if (head.key == key) { if (head.prev == null) { cache[k] = head.next; } else { if (head.next != null) head.next.prev = head.prev; head.prev.next = head.next; } return; } if (head.next == null) { return; } head = head.next; } } class ListNode { ListNode prev; ListNode next; Integer key; Integer value; ListNode (int key, int value) { this.key = key; this.value = value; } } } class MyHashMap3 { private static final int K = 100000; private TreeNode[] cache = new TreeNode[100000]; /** Initialize your data structure here. */ public MyHashMap() { } /** value will always be non-negative. */ public void put(int key, int value) { int k = key % K; if (cache[k] == null) { cache[k] = new TreeNode(key, value); } else { TreeNode head = cache[k]; while (true) { if (head.key == key) { head.value = value; return; } if (head.key > key) { if (head.left == null) { head.left = new TreeNode(key, value); return; } head = head.left; } else { if (head.right == null) { head.right = new TreeNode(key, value); return; } head = head.right; } if (head == null) return; } } } /** Returns the value to which the specified key is mapped, or -1 if this map contains no mapping for the key */ public int get(int key) { int k = key % K; if (cache[k] == null) return -1; TreeNode head = cache[k]; while (true) { if (head.key == key) { return head.value; } if (head.key > key) { if (head.left == null) { return -1; } head = head.left; } else { if (head.right == null) { return -1; } head = head.right; } if (head == null) return -1; } } /** Removes the mapping of the specified value key if this map contains a mapping for the key */ public void remove(int key) { int k = key % K; cache[k] = delete(cache[k], key); } private TreeNode delete(TreeNode head, int key) { if (head == null) return head; if (key < head.key) { head.left = delete(head.left, key); } else if (key > head.key) { head.right = delete(head.right, key); } else { if (head.left == null) { return head.right; } else if (head.right == null) { return head.left; } head.key = minValue(head.right); head.right = delete(head.right, head.key); } return head; } private int minValue(TreeNode head) { int minv = head.key; while (head.left != null) { minv = head.left.key; head = head.left; } return minv; } class TreeNode { TreeNode left; TreeNode right; Integer key; Integer value; TreeNode (int key, int value) { this.key = key; this.value = value; } } } /** * Your MyHashMap object will be instantiated and called as such: * MyHashMap obj = new MyHashMap(); * obj.put(key,value); * int param_2 = obj.get(key); * obj.remove(key); */ } ================================================ FILE: src/DesignHashSet705.java ================================================ /** * Design a HashSet without using any built-in hash table libraries. * * To be specific, your design should include these functions: * add(value): Insert a value into the HashSet. * contains(value) : Return whether the value exists in the HashSet or not. * remove(value): Remove a value in the HashSet. If the value does not exist * in the HashSet, do nothing. * * Example: * MyHashSet hashSet = new MyHashSet(); * hashSet.add(1); * hashSet.add(2); * hashSet.contains(1); // returns true * hashSet.contains(3); // returns false (not found) * hashSet.add(2); * hashSet.contains(2); // returns true * hashSet.remove(2); * hashSet.contains(2); // returns false (already removed) * * Note: * All values will be in the range of [0, 1000000]. * The number of operations will be in the range of [1, 10000]. * Please do not use the built-in HashSet library. */ public class DesignHashSet705 { class MyHashSet { private static final int K = 10000; private List[] cache = new List[K]; /** Initialize your data structure here. */ public MyHashSet() { } public void add(int key) { int k = key % K; if (cache[k] == null) { cache[k] = new ArrayList<>(); } List list = cache[k]; for (int el: list) { if (el == key) return; } list.add(key); } public void remove(int key) { int k = key % K; if (cache[k] == null) return; List list = cache[k]; for (int i=0; i list = cache[k]; for (int el: list) { if (el == key) return true; } return false; } } class MyHashSet2 { private static final int K = 10000; private TreeNode[] cache = new TreeNode[K]; /** Initialize your data structure here. */ public MyHashSet2() { } public void add(int key) { int k = key % K; cache[k] = addNode(cache[k], key); } TreeNode addNode(TreeNode root, int key) { if (root == null) return new TreeNode(key); if (root.key > key) { root.left = addNode(root.left, key); } else if (root.key < key) { root.right = addNode(root.right, key); } return root; } public void remove(int key) { int k = key % K; cache[k] = removeNode(cache[k], key); } TreeNode removeNode(TreeNode root, int key) { if (root == null) return null; if (root.key > key) { root.left = removeNode(root.left, key); } else if (root.key < key) { root.right = removeNode(root.right, key); } else { if (root.left == null) { return root.right; } else if (root.right == null) { return root.left; } else { root.key = findMin(root.right); root.right = removeNode(root.right, root.key); } } return root; } int findMin(TreeNode root) { while (root.left != null) { root = root.left; } return root.key; } /** Returns true if this set contains the specified element */ public boolean contains(int key) { return containNode(cache[key % K], key); } boolean containNode(TreeNode root, int key) { if (root == null) return false; if (root.key == key) return true; return containNode(root.left, key) || containNode(root.right, key); } class TreeNode { TreeNode left; TreeNode right; int key; TreeNode(int key) { this.key = key; } } } /** * Your MyHashSet object will be instantiated and called as such: * MyHashSet obj = new MyHashSet(); * obj.add(key); * obj.remove(key); * boolean param_3 = obj.contains(key); */ } ================================================ FILE: src/DesignHitCounter362.java ================================================ /** * Design a hit counter which counts the number of hits received in the * past 5 minutes. * * Each function accepts a timestamp parameter (in seconds granularity) and you * may assume that calls are being made to the system in chronological order * (ie, the timestamp is monotonically increasing). You may assume that the * earliest timestamp starts at 1. * * It is possible that several hits arrive roughly at the same time. * * Example: * HitCounter counter = new HitCounter(); * * // hit at timestamp 1. * counter.hit(1); * * // hit at timestamp 2. * counter.hit(2); * * // hit at timestamp 3. * counter.hit(3); * * // get hits at timestamp 4, should return 3. * counter.getHits(4); * * // hit at timestamp 300. * counter.hit(300); * * // get hits at timestamp 300, should return 4. * counter.getHits(300); * * // get hits at timestamp 301, should return 3. * counter.getHits(301); * * Follow up: * What if the number of hits per second could be very large? * Does your design scale? */ public class DesignHitCounter362 { class HitCounter { private int FIVE_MINUTES = 300; private LinkedList cache = new LinkedList<>(); /** Initialize your data structure here. */ public HitCounter() { } /** Record a hit. @param timestamp - The current timestamp (in seconds granularity). */ public void hit(int timestamp) { removeOldHits(timestamp); this.cache.add(timestamp); } /** Return the number of hits in the past 5 minutes. @param timestamp - The current timestamp (in seconds granularity). */ public int getHits(int timestamp) { removeOldHits(timestamp); return this.cache.size(); } private void removeOldHits(int timestamp) { while (!this.cache.isEmpty() && this.cache.getFirst() + FIVE_MINUTES <= timestamp) { this.cache.removeFirst(); } } } class HitCounter2 { private int FIVE_MINUTES = 300; private int[] buckets = new int[FIVE_MINUTES]; private int counts = 0; private int lastTS = 0; /** Initialize your data structure here. */ public HitCounter() { } /** Record a hit. @param timestamp - The current timestamp (in seconds granularity). */ public void hit(int timestamp) { removeOldHits(timestamp); this.buckets[bucketIndex(timestamp)]++; this.counts++; this.lastTS = timestamp; } /** Return the number of hits in the past 5 minutes. @param timestamp - The current timestamp (in seconds granularity). */ public int getHits(int timestamp) { removeOldHits(timestamp); this.lastTS = timestamp; return this.counts; } private void removeOldHits(int timestamp) { int tsDiff = timestamp - this.lastTS; int diff = tsDiff >= FIVE_MINUTES ? FIVE_MINUTES : tsDiff; for (int i=1; i<=diff; i++) { int idx = bucketIndex(this.lastTS+i); this.counts -= this.buckets[idx]; this.buckets[idx] = 0; } } private int bucketIndex(int timestamp) { return (timestamp - 1) % FIVE_MINUTES; } } /** * https://leetcode.com/problems/design-hit-counter/discuss/83483/Super-easy-design-O(1)-hit()-O(s)-getHits()-no-fancy-data-structure-is-needed! */ class HitCounter3 { private int[] times; private int[] hits; /** Initialize your data structure here. */ public HitCounter() { times = new int[300]; hits = new int[300]; } /** Record a hit. @param timestamp - The current timestamp (in seconds granularity). */ public void hit(int timestamp) { int index = timestamp % 300; if (times[index] != timestamp) { times[index] = timestamp; hits[index] = 1; } else { hits[index]++; } } /** Return the number of hits in the past 5 minutes. @param timestamp - The current timestamp (in seconds granularity). */ public int getHits(int timestamp) { int total = 0; for (int i = 0; i < 300; i++) { if (timestamp - times[i] < 300) { total += hits[i]; } } return total; } } /** * Your HitCounter object will be instantiated and called as such: * HitCounter obj = new HitCounter(); * obj.hit(timestamp); * int param_2 = obj.getHits(timestamp); */ } ================================================ FILE: src/DesignInMemoryFileSystem588.java ================================================ /** * Design an in-memory file system to simulate the following functions: * * ls: Given a path in string format. If it is a file path, return a list that * only contains this file's name. If it is a directory path, return the list * of file and directory names in this directory. Your output (file and * directory names together) should in lexicographic order. * * mkdir: Given a directory path that does not exist, you should make a new * directory according to the path. If the middle directories in the path * don't exist either, you should create them as well. This function has void * return type. * * addContentToFile: Given a file path and file content in string format. If * the file doesn't exist, you need to create that file containing given * content. If the file already exists, you need to append given content to * original content. This function has void return type. * * readContentFromFile: Given a file path, return its content in string format. * * Example: * * Input: * ["FileSystem","ls","mkdir","addContentToFile","ls","readContentFromFile"] * [[],["/"],["/a/b/c"],["/a/b/c/d","hello"],["/"],["/a/b/c/d"]] * Output: * [null,[],null,null,["a"],"hello"] * Explanation: * https://leetcode.com/static/images/problemset/filesystem.png * * Note: * You can assume all file or directory paths are absolute paths which begin * with / and do not end with / except that the path is just "/". * You can assume that all operations will be passed valid parameters and users * will not attempt to retrieve file content or list a directory or file that * does not exist. * You can assume that all directory names and file names only contain * lower-case letters, and same names won't exist in the same directory. */ public class DesignInMemoryFileSystem588 { class FileSystem { private Trie root = new Trie(); public FileSystem() { } public List ls(String path) { return root.find(path.split("/")); } public void mkdir(String path) { root.addDir(path.split("/")); } public void addContentToFile(String filePath, String content) { root.addFile(filePath.split("/"), content); } public String readContentFromFile(String filePath) { return root.retrieve(filePath.split("/")); } class Trie { Map children = new HashMap<>(); boolean isDirectory = true; String name = ""; List contents = new ArrayList<>(); private int startPos(String[] path) { return (path.length > 0 && path[0].length() == 0) ? 1 : 0; } List find(String[] path) { return find(path, startPos(path)); } List find(String[] path, int i) { if (path.length == i) { if (isDirectory) { List list = new ArrayList<>(children.keySet()); Collections.sort(list); return list; } else { List list = new ArrayList<>(); list.add(name); return list; } } if (!children.containsKey(path[i])) { return new ArrayList<>(); } return children.get(path[i]).find(path, i+1); } void addDir(String[] path) { addDir(path, startPos(path)); } void addDir(String[] path, int i) { name = path[i-1]; if (path.length == i) { return; } children.computeIfAbsent(path[i], k -> new Trie()).addDir(path, i+1); } void addFile(String[] path, String content) { addFile(path, startPos(path), content); } void addFile(String[] path, int i, String content) { name = path[i-1]; if (path.length == i) { isDirectory = false; contents.add(content); return; } children.computeIfAbsent(path[i], k -> new Trie()).addFile(path, i+1, content); } String retrieve(String[] path) { return retrieve(path, startPos(path)); } String retrieve(String[] path, int i) { if (path.length == i) { StringBuilder sb = new StringBuilder(); for (String c: contents) sb.append(c); return sb.toString(); } if (!children.containsKey(path[i])) { return ""; } return children.get(path[i]).retrieve(path, i+1); } } } /** * Your FileSystem object will be instantiated and called as such: * FileSystem obj = new FileSystem(); * List param_1 = obj.ls(path); * obj.mkdir(path); * obj.addContentToFile(filePath,content); * String param_4 = obj.readContentFromFile(filePath); */ } ================================================ FILE: src/DesignLinkedList707.java ================================================ /** * Design your implementation of the linked list. You can choose to use the * singly linked list or the doubly linked list. A node in a singly linked list * should have two attributes: val and next. val is the value of the current * node, and next is a pointer/reference to the next node. If you want to use * the doubly linked list, you will need one more attribute prev to indicate * the previous node in the linked list. Assume all nodes in the linked list * are 0-indexed. * * Implement these functions in your linked list class: * * get(index) : Get the value of the index-th node in the linked list. If the * index is invalid, return -1. * addAtHead(val) : Add a node of value val before the first element of the * linked list. After the insertion, the new node will be the first node of * the linked list. * addAtTail(val) : Append a node of value val to the last element of the * linked list. * addAtIndex(index, val) : Add a node of value val before the index-th node * in the linked list. If index equals to the length of linked list, the node * will be appended to the end of linked list. If index is greater than the * length, the node will not be inserted. * deleteAtIndex(index) : Delete the index-th node in the linked list, if the * index is valid. * * Example: * MyLinkedList linkedList = new MyLinkedList(); * linkedList.addAtHead(1); * linkedList.addAtTail(3); * linkedList.addAtIndex(1, 2); // linked list becomes 1->2->3 * linkedList.get(1); // returns 2 * linkedList.deleteAtIndex(1); // now the linked list is 1->3 * linkedList.get(1); // returns 3 * * Note: * All values will be in the range of [1, 1000]. * The number of operations will be in the range of [1, 1000]. * Please do not use the built-in LinkedList library. */ public class DesignLinkedList707 { class MyLinkedList { private Node head; /** Initialize your data structure here. */ public MyLinkedList() { head = new Node(0); } /** Get the value of the index-th node in the linked list. If the index is invalid, return -1. */ public int get(int index) { int i = 0; Node p = head.next; while (i < index && p != null) { p = p.next; i++; } if (p == null) return -1; return p.val; } /** Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list. */ public void addAtHead(int val) { Node newNode = new Node(val); newNode.next = head.next; head.next = newNode; } /** Append a node of value val to the last element of the linked list. */ public void addAtTail(int val) { Node p = head; while (p.next != null) { p = p.next; } Node newNode = new Node(val); newNode.next = p.next; p.next = newNode; } /** Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted. */ public void addAtIndex(int index, int val) { int i = 0; Node p = head; while (i < index && p != null) { p = p.next; i++; } if (p == null) return; Node newNode = new Node(val); newNode.next = p.next; p.next = newNode; } /** Delete the index-th node in the linked list, if the index is valid. */ public void deleteAtIndex(int index) { int i = 0; Node p = head; while (i < index && p != null) { p = p.next; i++; } if (p == null || p.next == null) return; p.next = p.next.next; } class Node { Node next; int val; Node (int x) { this.val = x; } } } class MyLinkedList2 { private Node head; /** Initialize your data structure here. */ public MyLinkedList() { head = new Node(0); } /** Get the value of the index-th node in the linked list. If the index is invalid, return -1. */ public int get(int index) { int i = 0; Node p = head.next; while (i < index && p != null) { p = p.next; i++; } if (p == null) return -1; return p.val; } /** Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list. */ public void addAtHead(int val) { Node newNode = new Node(val); newNode.next = head.next; if (head.next != null) head.next.prev = newNode; head.next = newNode; newNode.prev = head; } /** Append a node of value val to the last element of the linked list. */ public void addAtTail(int val) { Node p = head; while (p.next != null) { p = p.next; } Node newNode = new Node(val); newNode.next = p.next; if (p.next != null) p.next.prev = newNode; p.next = newNode; newNode.prev = p; } /** Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted. */ public void addAtIndex(int index, int val) { int i = 0; Node p = head; while (i < index && p != null) { p = p.next; i++; } if (p == null) return; Node newNode = new Node(val); newNode.next = p.next; if (p.next != null) p.next.prev = newNode; p.next = newNode; newNode.prev = p; } /** Delete the index-th node in the linked list, if the index is valid. */ public void deleteAtIndex(int index) { int i = 0; Node p = head; while (i < index && p != null) { p = p.next; i++; } if (p == null || p.next == null) return; p.next = p.next.next; if (p.next != null) p.next.prev = p; } class Node { Node prev; Node next; int val; Node (int x) { this.val = x; } } } /** * Your MyLinkedList object will be instantiated and called as such: * MyLinkedList obj = new MyLinkedList(); * int param_1 = obj.get(index); * obj.addAtHead(val); * obj.addAtTail(val); * obj.addAtIndex(index,val); * obj.deleteAtIndex(index); */ } ================================================ FILE: src/DesignLogStorageSystem635.java ================================================ /** * You are given several logs that each log contains a unique id and timestamp. * Timestamp is a string that has the following format: * Year:Month:Day:Hour:Minute:Second, for example, 2017:01:01:23:59:59. * All domains are zero-padded decimal numbers. * * Design a log storage system to implement the following functions: * * void Put(int id, string timestamp): Given a log's unique id and timestamp, * store the log in your storage system. * * int[] Retrieve(String start, String end, String granularity): Return the * id of logs whose timestamps are within the range from start to end. Start * and end all have the same format as timestamp. However, granularity means * the time level for consideration. For example, * start = "2017:01:01:23:59:59", end = "2017:01:02:23:59:59", * granularity = "Day", it means that we need to find the logs within the range * from Jan. 1st 2017 to Jan. 2nd 2017. * * Example 1: * put(1, "2017:01:01:23:59:59"); * put(2, "2017:01:01:22:59:59"); * put(3, "2016:01:01:00:00:00"); * retrieve("2016:01:01:01:01:01","2017:01:01:23:00:00","Year"); * // return [1,2,3], because you need to return all logs within 2016 and 2017. * retrieve("2016:01:01:01:01:01","2017:01:01:23:00:00","Hour"); * // return [1,2], because you need to return all logs start from * 2016:01:01:01 to 2017:01:01:23, where log 3 is left outside the range. * * Note: * There will be at most 300 operations of Put or Retrieve. * Year ranges from [2000,2017]. Hour ranges from [00,23]. * Output for Retrieve has no order required. */ import java.time.format.DateTimeFormatter; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; public class DesignLogStorageSystem635 { class LogSystem { private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy:MM:dd:HH:mm:ss"); private static final int K = 6; private TreeMap treeMap; public LogSystem() { Comparator comp = (s1, s2) -> s1.compareTo(s2); treeMap = new TreeMap<>(comp); } public void put(int id, String timestamp) { treeMap.put(timestamp, id); } public List retrieve(String s, String e, String gra) { String start = roundLeft(s, gra); String end = roundRight(e, gra); Map subMap = treeMap.subMap(start, end); List res = new ArrayList<>(); for (Integer id: subMap.values()) { res.add(id); } return res; } private String roundLeft(String timestamp, String gra) { TimeUnit unit = TimeUnit.valueOf(gra); return roundLeft(timestamp, unit); } private String roundLeft(String timestamp, TimeUnit unit) { String[] times = timestamp.split(":"); for (int k=K-1; k>unit.pos; k--) { times[k] = "00"; } return String.join(":", times); } private String plus(String timestamp, TimeUnit unit) { LocalDateTime newTime = LocalDateTime.parse(timestamp, formatter).plus(1, ChronoUnit.valueOf(unit.chrono)); return formatter.format(newTime); } private String roundRight(String timestamp, String gra) { TimeUnit unit = TimeUnit.valueOf(gra); String newTs = plus(timestamp, unit); return roundLeft(newTs, unit); } } enum TimeUnit { Year(0, "YEARS"), Month(1, "MONTHS"), Day(2, "DAYS"), Hour(3, "HOURS"), Minute(4, "MINUTES"), Second(5, "SECONDS"); int pos; String chrono; TimeUnit(int position, String chrono) { this.pos = position; this.chrono = chrono; } } /** * https://leetcode.com/problems/design-log-storage-system/discuss/105008/Concise-Java-Solution */ class LogSystem2 { List timestamps = new LinkedList<>(); List units = Arrays.asList("Year", "Month", "Day", "Hour", "Minute", "Second"); int[] indices = new int[]{4,7,10,13,16,19}; public void put(int id, String timestamp) { timestamps.add(new String[]{Integer.toString(id), timestamp}); } public List retrieve(String s, String e, String gra) { List res = new LinkedList<>(); int idx = indices[units.indexOf(gra)]; for (String[] timestamp : timestamps) { if (timestamp[1].substring(0, idx).compareTo(s.substring(0, idx)) >= 0 && timestamp[1].substring(0, idx).compareTo(e.substring(0, idx)) <= 0) res.add(Integer.parseInt(timestamp[0])); } return res; } } /** * Your LogSystem object will be instantiated and called as such: * LogSystem obj = new LogSystem(); * obj.put(id,timestamp); * List param_2 = obj.retrieve(s,e,gra); */ } ================================================ FILE: src/DesignSearchAutocompleteSystem642.java ================================================ /** * Design a search autocomplete system for a search engine. Users may input a * sentence (at least one word and end with a special character '#'). For each * character they type except '#', you need to return the top 3 historical hot * sentences that have prefix the same as the part of sentence already typed. * Here are the specific rules: * * The hot degree for a sentence is defined as the number of times a user typed * the exactly same sentence before. * The returned top 3 hot sentences should be sorted by hot degree (The first is * the hottest one). If several sentences have the same degree of hot, you need * to use ASCII-code order (smaller one appears first). * If less than 3 hot sentences exist, then just return as many as you can. * When the input is a special character, it means the sentence ends, and in this * case, you need to return an empty list. * Your job is to implement the following functions: * * The constructor function: * * AutocompleteSystem(String[] sentences, int[] times): This is the constructor. * The input is historical data. Sentences is a string array consists of * previously typed sentences. Times is the corresponding times a sentence * has been typed. Your system should record these historical data. * * Now, the user wants to input a new sentence. The following function will * provide the next character the user types: * * List input(char c): The input c is the next character typed by the * user. The character will only be lower-case letters ('a' to 'z'), blank * space (' ') or a special character ('#'). Also, the previously typed * sentence should be recorded in your system. The output will be the top 3 * historical hot sentences that have prefix the same as the part of sentence * already typed. * * Example: * Operation: AutocompleteSystem(["i love you", "island","ironman", "i love leetcode"], [5,3,2,2]) * The system have already tracked down the following sentences and their corresponding times: * "i love you" : 5 times * "island" : 3 times * "ironman" : 2 times * "i love leetcode" : 2 times * Now, the user begins another search: * * Operation: input('i') * Output: ["i love you", "island","i love leetcode"] * Explanation: * There are four sentences that have prefix "i". Among them, "ironman" and * "i love leetcode" have same hot degree. Since ' ' has ASCII code 32 and 'r' * has ASCII code 114, "i love leetcode" should be in front of "ironman". Also * we only need to output top 3 hot sentences, so "ironman" will be ignored. * * Operation: input(' ') * Output: ["i love you","i love leetcode"] * Explanation: * There are only two sentences that have prefix "i ". * * Operation: input('a') * Output: [] * Explanation: * There are no sentences that have prefix "i a". * * Operation: input('#') * Output: [] * Explanation: * The user finished the input, the sentence "i a" should be saved as a * historical sentence in system. And the following input will be counted as a * new search. * * Note: * The input sentence will always start with a letter and end with '#', and * only one blank space will exist between two words. * The number of complete sentences that to be searched won't exceed 100. The * length of each sentence including those in the historical data won't exceed * 100. * Please use double-quote instead of single-quote when you write test cases * even for a character input. * Please remember to RESET your class variables declared in class * AutocompleteSystem, as static/class variables are persisted across multiple * test cases. Please see here for more details. */ public class DesignSearchAutocompleteSystem642 { // Trie class AutocompleteSystem { private Map freq; private StringBuilder currSent; private Trie trie; private Trie currTrie; public AutocompleteSystem(String[] sentences, int[] times) { this.freq = new HashMap<>(); this.trie = new Trie(); for (int i=0; i input(char c) { if (c == '#') { String newSent = this.currSent.toString(); this.currSent = new StringBuilder(); this.freq.put(newSent, this.freq.getOrDefault(newSent, 0) + 1); this.currTrie.sentence = newSent; this.currTrie = this.trie; return new ArrayList<>(); } else { this.currSent.append(c); int pos = charPos(c); if (this.currTrie.children[pos] == null) { this.currTrie.children[pos] = new Trie(); } this.currTrie = this.currTrie.children[pos]; PriorityQueue pq = new PriorityQueue<>(3, (s1, s2) -> { int freqDiff = Integer.compare(this.freq.get(s1), this.freq.get(s2)); if (freqDiff != 0) return freqDiff; return -asciiOrder(s1, s2); }); getAllSents(this.currTrie, pq); LinkedList res = new LinkedList<>(); while (!pq.isEmpty()) { res.addFirst(pq.poll()); } return res; } } private void getAllSents(Trie t, PriorityQueue pq) { if (t.sentence != null) { pq.add(t.sentence); if (pq.size() > 3) pq.poll(); } for (Trie child: t.children) { if (child != null) { getAllSents(child, pq); } } } private int asciiOrder(String s1, String s2) { int i = 0; int len1 = s1.length(); int len2 = s2.length(); char[] chars1 = s1.toCharArray(); char[] chars2 = s2.toCharArray(); while (i < len1 && i < len2) { if (chars1[i] == chars2[i]) { i++; continue; } return Integer.compare(chars1[i], chars2[i]); } return Integer.compare(len1, len2); } private int charPos(char ch) { if (ch == ' ') return 26; return ch - 'a'; } class Trie { Trie[] children = new Trie[27]; String sentence; void add(String sen) { add(sen.toCharArray(), 0); } void add(char[] chars, int i) { if (i == chars.length) { this.sentence = new String(chars); return; } int pos = charPos(chars[i]); if (this.children[pos] == null) { this.children[pos] = new Trie(); } this.children[pos].add(chars, i+1); } } } // Tenary Search Tree class AutocompleteSystem2 { private StringBuilder sb; private Map freq; private Node root; private Node currNode; Comparator comp = (s1, s2) -> { int freqDiff = Integer.compare(this.freq.get(s1), this.freq.get(s2)); if (freqDiff != 0) return freqDiff; return -s1.compareTo(s2); }; public AutocompleteSystem2(String[] sentences, int[] times) { int N = sentences.length; this.freq = new HashMap<>(); for (int i=0; i n.ch) { n.right = addNode(n.right, chars, i); } else { if (i+1 < chars.length) { n.eq = addNode(n.eq, chars, i+1); } else { n.sent = new String(chars); } } return n; } public List input(char c) { if (c == '#') { String newSent = this.sb.toString(); this.sb = new StringBuilder(); this.freq.put(newSent, this.freq.getOrDefault(newSent, 0) + 1); this.root = addNode(this.root, newSent); this.currNode = this.root; return new ArrayList<>(); } else { this.sb.append(c); if (this.currNode == null) { return new ArrayList<>(); } Node nn = next(this.currNode, c); this.currNode = nn; PriorityQueue pq = new PriorityQueue<>(3, comp); if (nn != null) { this.currNode = nn.eq; if (nn.sent != null) { pq.add(nn.sent); } nn = nn.eq; } getAllSents(nn, pq); LinkedList res = new LinkedList<>(); while (!pq.isEmpty()) { res.addFirst(pq.poll()); } return res; } } private Node next(Node n, char c) { if (n == null) return null; if (c < n.ch) { return next(n.left, c); } else if (c > n.ch) { return next(n.right, c); } else { return n; } } private void getAllSents(Node n, PriorityQueue pq) { if (n == null) return; if (n.sent != null) { pq.add(n.sent); if (pq.size() > 3) pq.poll(); } getAllSents(n.left, pq); getAllSents(n.eq, pq); getAllSents(n.right, pq); } class Node { char ch; Node left; Node eq; Node right; String sent; Node (char c) { this.ch = c; } } } /** * Your AutocompleteSystem object will be instantiated and called as such: * AutocompleteSystem obj = new AutocompleteSystem(sentences, times); * List param_1 = obj.input(c); */ } ================================================ FILE: src/DesignSnakeGame353.java ================================================ /** * Design a Snake game that is played on a device with screen * size = width x height. Play the game online if you are not familiar with * the game. * * The snake is initially positioned at the top left corner (0,0) with * length = 1 unit. * * You are given a list of food's positions in row-column order. When a snake * eats the food, its length and the game's score both increase by 1. * * Each food appears one by one on the screen. For example, the second food * will not appear until the first food was eaten by the snake. * * When a food does appear on the screen, it is guaranteed that it will not * appear on a block occupied by the snake. * * Example: * * Given width = 3, height = 2, and food = [[1,2],[0,1]]. * * Snake snake = new Snake(width, height, food); * * Initially the snake appears at position (0,0) and the food at (1,2). * * |S| | | * | | |F| * * snake.move("R"); -> Returns 0 * * | |S| | * | | |F| * * snake.move("D"); -> Returns 0 * * | | | | * | |S|F| * * snake.move("R"); -> Returns 1 (Snake eats the first food and right after * that, the second food appears at (0,1) ) * * | |F| | * | |S|S| * * snake.move("U"); -> Returns 1 * * | |F|S| * | | |S| * * snake.move("L"); -> Returns 2 (Snake eats the second food) * * | |S|S| * | | |S| * * snake.move("U"); -> Returns -1 (Game over because snake collides with border) */ public class DesignSnakeGame353 { class SnakeGame { private static Map directions = new HashMap<>(); private Set snake = new HashSet<>(); private Node head; private Node tail; private int score = 0; private int width; private int height; private int[][] food; private int nextFood = 0; /** Initialize your data structure here. @param width - screen width @param height - screen height @param food - A list of food positions E.g food = [[1,1], [1,0]] means the first food is positioned at [1,1], the second is at [1,0]. */ public SnakeGame(int width, int height, int[][] food) { this.width = width; this.height = height; this.snake.add(0); this.head = new Node(0, 0); this.tail = new Node(0, 0); this.tail.prev = this.head; this.head.next = this.tail; this.food = food; directions.put("U", new int[]{-1, 0}); directions.put("L", new int[]{0, -1}); directions.put("R", new int[]{0, 1}); directions.put("D", new int[]{1, 0}); } /** Moves the snake. @param direction - 'U' = Up, 'L' = Left, 'R' = Right, 'D' = Down @return The game's score after the move. Return -1 if game over. Game over when snake crosses the screen boundary or bites its body. */ public int move(String direction) { int[] dir = directions.get(direction); int nextX = head.x + dir[0]; int nextY = head.y + dir[1]; if (nextX < 0 || nextY < 0 || nextX >= this.height || nextY >= this.width) return -1; Node newHead = new Node(nextX, nextY); newHead.next = this.head; this.head.prev = newHead; this.head = newHead; if (isFood(nextX, nextY)) { this.score++; moveNextFood(); } else { this.tail = this.tail.prev; this.tail.next = null; this.snake.remove(this.tail.x * this.width + this.tail.y); } int nextPos = nextX * this.width + nextY; if (this.snake.contains(nextPos)) return -1; this.snake.add(nextPos); return this.score; } private void moveNextFood() { if (this.nextFood < this.food.length) { this.nextFood++; } } private boolean isFood(int nextX, int nextY) { if (this.nextFood >= this.food.length) return false; return this.food[this.nextFood][0] == nextX && this.food[this.nextFood][1] == nextY; } class Node { int x; int y; Node prev; Node next; Node(int i, int j) { this.x = i; this.y = j; } } } /** * Your SnakeGame object will be instantiated and called as such: * SnakeGame obj = new SnakeGame(width, height, food); * int param_1 = obj.move(direction); */ } ================================================ FILE: src/DesignTicTacToe348.java ================================================ /** * Design a Tic-tac-toe game that is played between two players on a n x n grid. * * You may assume the following rules: * * A move is guaranteed to be valid and is placed on an empty block. * Once a winning condition is reached, no more moves is allowed. * A player who succeeds in placing n of their marks in a horizontal, vertical, * or diagonal row wins the game. * * Example: * Given n = 3, assume that player 1 is "X" and player 2 is "O" in the board. * * TicTacToe toe = new TicTacToe(3); * * toe.move(0, 0, 1); -> Returns 0 (no one wins) * |X| | | * | | | | // Player 1 makes a move at (0, 0). * | | | | * * toe.move(0, 2, 2); -> Returns 0 (no one wins) * |X| |O| * | | | | // Player 2 makes a move at (0, 2). * | | | | * * toe.move(2, 2, 1); -> Returns 0 (no one wins) * |X| |O| * | | | | // Player 1 makes a move at (2, 2). * | | |X| * * toe.move(1, 1, 2); -> Returns 0 (no one wins) * |X| |O| * | |O| | // Player 2 makes a move at (1, 1). * | | |X| * * toe.move(2, 0, 1); -> Returns 0 (no one wins) * |X| |O| * | |O| | // Player 1 makes a move at (2, 0). * |X| |X| * * toe.move(1, 0, 2); -> Returns 0 (no one wins) * |X| |O| * |O|O| | // Player 2 makes a move at (1, 0). * |X| |X| * * toe.move(2, 1, 1); -> Returns 1 (player 1 wins) * |X| |O| * |O|O| | // Player 1 makes a move at (2, 1). * |X|X|X| * * Follow up: * Could you do better than O(n2) per move() operation? */ public class DesignTicTacToe348 { class TicTacToe { private Set[] player1Rows; private Set[] player1Cols; private Set[] player1Dias; private Set[] player2Rows; private Set[] player2Cols; private Set[] player2Dias; private int n; /** Initialize your data structure here. */ public TicTacToe(int n) { this.n = n; this.player1Rows = new Set[n]; for (int i=0; i(); this.player1Cols = new Set[n]; for (int i=0; i(); this.player1Dias = new Set[2]; for (int i=0; i<2; i++) this.player1Dias[i] = new HashSet<>(); this.player2Rows = new Set[n]; for (int i=0; i(); this.player2Cols = new Set[n]; for (int i=0; i(); this.player2Dias = new Set[2]; for (int i=0; i<2; i++) this.player2Dias[i] = new HashSet<>(); } /** Player {player} makes a move at ({row}, {col}). @param row The row of the board. @param col The column of the board. @param player The player, can be either 1 or 2. @return The current winning condition, can be either: 0: No one wins. 1: Player 1 wins. 2: Player 2 wins. */ public int move(int row, int col, int player) { if (player == 1) { this.player1Rows[row].add(col); if (this.player1Rows[row].size() == n) return 1; this.player1Cols[col].add(row); if (this.player1Cols[col].size() == n) return 1; if (row == col) { this.player1Dias[0].add(row); if (this.player1Dias[0].size() == n) return 1; } if (row == n-col-1) { this.player1Dias[1].add(row); if (this.player1Dias[1].size() == n) return 1; } } else if (player == 2) { this.player2Rows[row].add(col); if (this.player2Rows[row].size() == n) return 2; this.player2Cols[col].add(row); if (this.player2Cols[col].size() == n) return 2; if (row == col) { this.player2Dias[0].add(row); if (this.player2Dias[0].size() == n) return 2; } if (row == n-col-1) { this.player2Dias[1].add(row); if (this.player2Dias[1].size() == n) return 2; } } return 0; } } /** * https://leetcode.com/problems/design-tic-tac-toe/discuss/81898/Java-O(1)-solution-easy-to-understand */ class TicTacToe2 { private int[] rows; private int[] cols; private int diagonal; private int antiDiagonal; /** Initialize your data structure here. */ public TicTacToe(int n) { rows = new int[n]; cols = new int[n]; } /** Player {player} makes a move at ({row}, {col}). @param row The row of the board. @param col The column of the board. @param player The player, can be either 1 or 2. @return The current winning condition, can be either: 0: No one wins. 1: Player 1 wins. 2: Player 2 wins. */ public int move(int row, int col, int player) { int toAdd = player == 1 ? 1 : -1; rows[row] += toAdd; cols[col] += toAdd; if (row == col) { diagonal += toAdd; } if (col == (cols.length - row - 1)) { antiDiagonal += toAdd; } int size = rows.length; if (Math.abs(rows[row]) == size || Math.abs(cols[col]) == size || Math.abs(diagonal) == size || Math.abs(antiDiagonal) == size) { return player; } return 0; } } /** * https://leetcode.com/problems/design-tic-tac-toe/discuss/81896/78-lines-O(1)-JavaPython */ class TicTacToe3 { public TicTacToe(int n) { count = new int[6*n][3]; } public int move(int row, int col, int player) { int n = count.length / 6; for (int x : new int[]{row, n+col, 2*n+row+col, 5*n+row-col}) if (++count[x][player] == n) return player; return 0; } int[][] count; } class TicTacToe4 { private int[] rows; private int[] cols; private int diag1; private int diag2; private int N; /** Initialize your data structure here. */ public TicTacToe4(int n) { this.rows = new int[n]; this.cols = new int[n]; this.diag1 = 0; this.diag2 = 0; this.N = n; } /** Player {player} makes a move at ({row}, {col}). @param row The row of the board. @param col The column of the board. @param player The player, can be either 1 or 2. @return The current winning condition, can be either: 0: No one wins. 1: Player 1 wins. 2: Player 2 wins. */ public int move(int row, int col, int player) { int diff = player == 1 ? 1 : -1; this.rows[row] += diff; this.cols[col] += diff; if (row == col) this.diag1 += diff; if (row + col == N-1) this.diag2 += diff; if (this.rows[row] == N || this.cols[col] == N || this.diag1 == N || this.diag2 == N) return 1; if (this.rows[row] == -N || this.cols[col] == -N || this.diag1 == -N || this.diag2 == -N) return 2; return 0; } } /** * Your TicTacToe object will be instantiated and called as such: * TicTacToe obj = new TicTacToe(n); * int param_1 = obj.move(row,col,player); */ } ================================================ FILE: src/DesignTwitter355.java ================================================ /** * Design a simplified version of Twitter where users can post tweets, * follow/unfollow another user and is able to see the 10 most recent tweets * in the user's news feed. Your design should support the following methods: * * postTweet(userId, tweetId): Compose a new tweet. * * getNewsFeed(userId): Retrieve the 10 most recent tweet ids in the user's * news feed. Each item in the news feed must be posted by users who the user * followed or by the user herself. Tweets must be ordered from most recent to * least recent. * * follow(followerId, followeeId): Follower follows a followee. * * unfollow(followerId, followeeId): Follower unfollows a followee. * * Example: * * Twitter twitter = new Twitter(); * * // User 1 posts a new tweet (id = 5). * twitter.postTweet(1, 5); * * // User 1's news feed should return a list with 1 tweet id -> [5]. * twitter.getNewsFeed(1); * * // User 1 follows user 2. * twitter.follow(1, 2); * * // User 2 posts a new tweet (id = 6). * twitter.postTweet(2, 6); * * // User 1's news feed should return a list with 2 tweet ids -> [6, 5]. * // Tweet id 6 should precede tweet id 5 because it is posted after tweet id 5. * twitter.getNewsFeed(1); * * // User 1 unfollows user 2. * twitter.unfollow(1, 2); * * // User 1's news feed should return a list with 1 tweet id -> [5], * // since user 1 is no longer following user 2. * twitter.getNewsFeed(1); */ public class DesignTwitter355 { class Twitter { private int time = 0; private Map map = new HashMap<>(); private static final Comparator comp = (t1, t2) -> Long.compare(t2.timestamp, t1.timestamp); /** Initialize your data structure here. */ public Twitter() { } /** Compose a new tweet. */ public void postTweet(int userId, int tweetId) { if (!map.containsKey(userId)) map.put(userId, new User(userId)); map.get(userId).addTweet(tweetId, time++); } /** * Retrieve the 10 most recent tweet ids in the user's news feed. Each * item in the news feed must be posted by users who the user followed * or by the user herself. Tweets must be ordered from most recent to * least recent. */ public List getNewsFeed(int userId) { PriorityQueue pq = new PriorityQueue<>(10, comp); if (!map.containsKey(userId)) return new ArrayList(); User me = map.get(userId); for (Integer uid: me.following) { pq.addAll(map.get(uid).tweets); } pq.addAll(me.tweets); List ids = new ArrayList<>(); int size = pq.size(); for (int i=0; i<10 && i tweets = new LinkedList<>(); Set following = new HashSet<>(); User(int i) { id = i; } public void addTweet(int i, int ts) { tweets.add(new Tweet(i, ts)); while (tweets.size() > 10) { tweets.removeFirst(); } } public void follow(int userId) { following.add(userId); } public void unfollow(int userId) { if (following.contains(userId)) { following.remove(userId); } } } class Tweet { int id; int timestamp; Tweet(int i, int ts) { id = i; timestamp = ts; } } } /** * Your Twitter object will be instantiated and called as such: * Twitter obj = new Twitter(); * obj.postTweet(userId,tweetId); * List param_2 = obj.getNewsFeed(userId); * obj.follow(followerId,followeeId); * obj.unfollow(followerId,followeeId); */ } ================================================ FILE: src/DiagonalTraverse498.java ================================================ /** * Given a matrix of M x N elements (M rows, N columns), return all elements * of the matrix in diagonal order as shown in the below image. * * Example: * Input: * [ * [ 1, 2, 3 ], * [ 4, 5, 6 ], * [ 7, 8, 9 ] * ] * Output: [1,2,4,7,5,3,6,8,9] * * Explanation: * https://leetcode.com/static/images/problemset/diagonal_traverse.png * * Note: * The total number of elements of the given matrix will not exceed 10,000. */ public class DiagonalTraverse498 { public int[] findDiagonalOrder(int[][] matrix) { if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return new int[0]; int M = matrix.length; int N = matrix[0].length; int total = M * N; int[] res = new int[total]; int i = 0; int[] pos = new int[2]; res[i++] = matrix[0][0]; while (i < total) { pos = next(pos, M, N); res[i++] = matrix[pos[0]][pos[1]]; } return res; } private int[] next(int[] pos, int M, int N) { int i = pos[0]; int j = pos[1]; if (isEven(i+j)) { // top-right int ni = i - 1; int nj = j + 1; if (nj == N) { nj = N - 1; ni = i + 1; } else if (ni < 0) { ni = 0; } return new int[]{ni, nj}; } else { // bottom-left int ni = i + 1; int nj = j - 1; if (ni == M) { ni = M - 1; nj = j + 1; } else if (nj < 0) { nj = 0; } return new int[]{ni, nj}; } } private boolean isEven(int x) { return x % 2 == 0; } } ================================================ FILE: src/DiameterOfBinaryTree543.java ================================================ /** * Given a binary tree, you need to compute the length of the diameter of the * tree. The diameter of a binary tree is the length of the longest pathbetween * any two nodes in a tree. This path may or may not pass through the root. * * Example: * Given a binary tree * 1 * / \ * 2 3 * / \ * 4 5 * Return 3, which is the length of the path [4,2,1,3] or [5,2,1,3]. * * Note: The length of path between two nodes is represented by the number of * edges between them. * */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class DiameterOfBinaryTree543 { public int diameterOfBinaryTree(TreeNode root) { return helper(root)[0]; } private int[] helper(TreeNode root) { if (root == null) return new int[]{0, 0}; int[] l = helper(root.left); int[] r = helper(root.right); return new int[]{Math.max(Math.max(l[0], r[0]), l[1] + r[1]), Math.max(l[1], r[1]) + 1}; } } ================================================ FILE: src/DifferentWaysToAddParentheses241.java ================================================ /** * Given a string of numbers and operators, return all possible results from * computing all the different possible ways to group numbers and operators. * The valid operators are +, - and *. * * Example 1 * Input: "2-1-1". * * ((2-1)-1) = 0 * (2-(1-1)) = 2 * Output: [0, 2] * * * Example 2 * Input: "2*3-4*5" * * (2*(3-(4*5))) = -34 * ((2*3)-(4*5)) = -14 * ((2*(3-4))*5) = -10 * (2*((3-4)*5)) = -10 * (((2*3)-4)*5) = 10 * Output: [-34, -14, -10, -10, 10] * */ public class DifferentWaysToAddParentheses241 { public List diffWaysToCompute(String input) { List res = new LinkedList(); for (int i=0; i res1 = diffWaysToCompute(input.substring(0, i)); List res2 = diffWaysToCompute(input.substring(i+1)); for (Integer int1: res1) { for (Integer int2: res2) { res.add(cal(int1, int2, c)); } } } if (res.size() == 0) { res.add(Integer.valueOf(input)); } return res; } private Integer cal(Integer int1, Integer int2, Character op) { switch (op) { case '+': return int1 + int2; case '-': return int1 - int2; case '*': return int1 * int2; } return 0; } } ================================================ FILE: src/DivideTwoIntegers29.java ================================================ /** * Divide two integers without using multiplication, division and mod operator. * * If it is overflow, return MAX_INT. */ public class DivideTwoIntegers29 { public int divide(int dividend, int divisor) { if (divisor == 0) return Integer.MAX_VALUE; if (dividend == 0) return 0; long result = helper(dividend, divisor); return result > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) result; } public long helper(long dividend, long divisor) { boolean isNegative = dividend < 0 != divisor < 0; dividend = Math.abs(dividend); divisor = Math.abs(divisor); if (dividend < divisor) return 0; long res = 0; while (dividend >= divisor) { long t = divisor; long p = 1; long tt = t << 1; while (dividend > tt) { t = tt; p <<= 1; tt <<= 1; } res += p; dividend -= t; } return isNegative ? -res : res; } } ================================================ FILE: src/DominoAndTrominoTiling790.java ================================================ /** * We have two types of tiles: a 2x1 domino shape, and an "L" tromino shape. * These shapes may be rotated. * * XX <- domino * * XX <- "L" tromino * X * Given N, how many ways are there to tile a 2 x N board? Return your answer * modulo 10^9 + 7. * * (In a tiling, every square must be covered by a tile. Two tilings are * different if and only if there are two 4-directionally adjacent cells on * the board such that exactly one of the tilings has both squares occupied * by a tile.) * * Example: * Input: 3 * Output: 5 * Explanation: * The five different ways are listed below, different letters indicates * different tiles: * XYZ XXZ XYY XXY XYY * XYZ YYZ XZZ XYY XXY */ public class DominoAndTrominoTiling790 { private static int MOD = 1000000007; public int numTilings(int N) { long[][] dp = new long[N+1][3]; dp[0][0] = 1; dp[1][0] = 1; for (int i=2; i<=N; i++) { dp[i][0] = (dp[i-1][0] + dp[i-2][0] + dp[i-1][1] + dp[i-1][2]) % MOD; dp[i][1] = (dp[i-2][0] + dp[i-1][2]) % MOD; dp[i][2] = (dp[i-2][0] + dp[i-1][1]) % MOD; } return (int) dp[N][0]; } public int numTilings2(int N) { long[][] dp = new long[N+1][2]; dp[0][0] = 1; dp[1][0] = 1; for (int i=2; i<=N; i++) { dp[i][0] = (dp[i-1][0] + dp[i-2][0] + 2 * dp[i-1][1]) % MOD; dp[i][1] = (dp[i-2][0] + dp[i-1][1]) % MOD; } return (int) dp[N][0]; } public int numTilings3(int N) { long[][] dp = new long[3][2]; dp[0][0] = 1; dp[1][0] = 1; for (int i=2; i<=N; i++) { dp[i%3][0] = (dp[(i+2)%3][0] + dp[(i+1)%3][0] + 2 * dp[(i+2)%3][1]) % MOD; dp[i%3][1] = (dp[(i+1)%3][0] + dp[(i+2)%3][1]) % MOD; } return (int) dp[N%3][0]; } public int numTilings4(int N) { if (N == 0) return 1; if (N == 1 || N == 2) return N; long[] dp = new long[N+1]; dp[0] = 1; dp[1] = 1; dp[2] = 2; for (int i=3; i<=N; i++) { dp[i] = (dp[i - 3] + dp[i - 1] * 2) % MOD; } return (int) dp[N]; } public int numTilings5(int N) { if (N == 0) return 1; if (N == 1 || N == 2) return N; long[] dp = new long[4]; dp[0] = 1; dp[1] = 1; dp[2] = 2; for (int i=3; i<=N; i++) { dp[i%4] = (dp[(i+1)%4] + dp[(i+3)%4] * 2) % MOD; } return (int) dp[N%4]; } /** * https://leetcode.com/problems/domino-and-tromino-tiling/solution/ */ public int numTilings6(int N) { long[] dp = new long[]{1, 0, 0, 0}; for (int i = 0; i < N; ++i) { long[] ndp = new long[4]; ndp[0b00] = (dp[0b00] + dp[0b11]) % MOD; ndp[0b01] = (dp[0b00] + dp[0b10]) % MOD; ndp[0b10] = (dp[0b00] + dp[0b01]) % MOD; ndp[0b11] = (dp[0b00] + dp[0b01] + dp[0b10]) % MOD; dp = ndp; } return (int) dp[0]; } } ================================================ FILE: src/EditDistance72.java ================================================ /** * Given two words word1 and word2, find the minimum number of steps required * to convert word1 to word2. (each operation is counted as 1 step.) * * You have the following 3 operations permitted on a word: * * a) Insert a character * b) Delete a character * c) Replace a character */ import java.util.Arrays; public class EditDistance72 { // time: O(mn); space: O(mn) public int minDistance(String word1, String word2) { int m = word1.length(); int n = word2.length(); int[][] d = new int[m + 1][n + 1]; for (int i = 0; i <= m; i++) d[i][0] = i; for (int i = 1; i <= n; i++) d[0][i] = i; for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { if (word1.charAt(i-1) == word2.charAt(j-1)) { d[i][j] = d[i-1][j-1]; } else { d[i][j] = Math.min(d[i-1][j], d[i][j-1]) + 1; d[i][j] = Math.min(d[i][j], d[i-1][j-1] + 1); } } } return d[m][n]; } // time: O(mn); space: O(n) public int minDistance2(String word1, String word2) { int m = word1.length(); int n = word2.length(); if (n == 0) { return m; } int[] d = new int[n + 1]; for (int j = 0; j <= n; j++) d[j] = j; for (int i = 1; i <= m; i++) { int last = d[0]; for (int j = 1; j <= n; j++) { int saveLast = d[j]; d[0] = i; if (word1.charAt(i-1) == word2.charAt(j-1)) { d[j] = last; } else { d[j] = Math.min(d[j], d[j-1]) + 1; d[j] = Math.min(d[j], last + 1); } last = saveLast; } } return d[n]; } public int minDistance3(String word1, String word2) { int len1 = word1.length(); int len2 = word2.length(); if (len1 == 0) return len2; if (len2 == 0) return len1; int[] dp = new int[len2+1]; for (int j=0; j<=len2; j++) dp[j] = j; for (int i=1; i<=len1; i++) { int pre = dp[0]; dp[0] = i; for (int j=1; j<=len2; j++) { int nextPre = dp[j]; dp[j] = Math.min(pre + (word1.charAt(i-1) == word2.charAt(j-1) ? 0 : 1), Math.min(dp[j], dp[j-1]) + 1); pre = nextPre; } } return dp[len2]; } public static void main(String[] args) { EditDistance72 ed = new EditDistance72(); System.out.println(ed.minDistance2("word1", "word3")); System.out.println(ed.minDistance2("aaabbb", "aababb")); System.out.println(ed.minDistance2("b", "")); System.out.println(ed.minDistance2("", "b")); } } ================================================ FILE: src/EmployeeFreeTime759.java ================================================ /** * We are given a list schedule of employees, which represents the working time * for each employee. * * Each employee has a list of non-overlapping Intervals, and these intervals * are in sorted order. * * Return the list of finite intervals representing common, positive-length * free time for all employees, also in sorted order. * * Example 1: * Input: schedule = [[[1,2],[5,6]],[[1,3]],[[4,10]]] * Output: [[3,4]] * Explanation: * There are a total of three employees, and all common * free time intervals would be [-inf, 1], [3, 4], [10, inf]. * We discard any intervals that contain inf as they aren't finite. * * Example 2: * Input: schedule = [[[1,3],[6,7]],[[2,4]],[[2,5],[9,12]]] * Output: [[5,6],[7,9]] * (Even though we are representing Intervals in the form [x, y], the objects * inside are Intervals, not lists or arrays. For example, * schedule[0][0].start = 1, schedule[0][0].end = 2, and * schedule[0][0][0] is not defined.) * * Also, we wouldn't include intervals like [5, 5] in our answer, as they have * zero length. * * Note: * schedule and schedule[i] are lists with lengths in range [1, 50]. * 0 <= schedule[i].start < schedule[i].end <= 10^8. */ /** * Definition for an interval. * public class Interval { * int start; * int end; * Interval() { start = 0; end = 0; } * Interval(int s, int e) { start = s; end = e; } * } */ public class EmployeeFreeTime759 { public List employeeFreeTime(List> schedule) { if (schedule == null || schedule.size() == 0) return new ArrayList<>(); LinkedList starts = new LinkedList<>(); LinkedList ends = new LinkedList<>(); for (List emp: schedule) { for (Interval inv: emp) { starts.add(inv.start); ends.add(inv.end); } } Collections.sort(starts); Collections.sort(ends); List res = new ArrayList<>(); int count = 0; int time = Integer.MIN_VALUE; while (!starts.isEmpty() && !ends.isEmpty()) { if (starts.getFirst() <= ends.getFirst()) { count++; time = starts.getFirst(); starts.removeFirst(); } else { count--; time = ends.getFirst(); ends.removeFirst(); } if (count == 0 && !starts.isEmpty() && time < starts.getFirst()) { res.add(new Interval(time, starts.getFirst())); } } return res; } public List employeeFreeTime2(List> schedule) { if (schedule == null || schedule.size() == 0) return new ArrayList<>(); Comparator comp = (i1, i2) -> Integer.compare(i1.start ,i2.start); PriorityQueue pq = new PriorityQueue<>(1, comp); for (List emp: schedule) { for (Interval inv: emp) { pq.add(inv); } } List res = new ArrayList<>(); if (pq.isEmpty()) return res; int maxEnd = pq.poll().end; while (!pq.isEmpty()) { Interval curr = pq.poll(); if (curr.start <= maxEnd) { maxEnd = Math.max(maxEnd, curr.end); } else { res.add(new Interval(maxEnd, curr.start)); maxEnd = curr.end; } } return res; } } ================================================ FILE: src/EncodeAndDecodeStrings271.java ================================================ /** * Design an algorithm to encode a list of strings to a string. The encoded * string is then sent over the network and is decoded back to the original * list of strings. * * Machine 1 (sender) has the function: * * string encode(vector strs) { * // ... your code * return encoded_string; * } * * * Machine 2 (receiver) has the function: * vector decode(string s) { * //... your code * return strs; * } * * * So Machine 1 does: * string encoded_string = encode(strs); * * and Machine 2 does: * vector strs2 = decode(encoded_string); * * strs2 in Machine 2 should be the same as strs in Machine 1. * * Implement the encode and decode methods. * * Note: * The string may contain any possible characters out of 256 valid ascii * characters. Your algorithm should be generalized enough to work on any * possible characters. * Do not use class member/global/static variables to store states. Your * encode and decode algorithms should be stateless. * Do not rely on any library method such as eval or serialize methods. You * should implement your own encode/decode algorithm. */ public class EncodeAndDecodeStrings271 { public class Codec { // Encodes a list of strings to a single string. public String encode(List strs) { StringBuilder sb = new StringBuilder(); for (String str: strs) { sb.append(str.length()).append('|').append(str); } return sb.toString(); } // Decodes a single string to a list of strings. public List decode(String s) { List list = new ArrayList<>(); int i=0; while (i < s.length()) { int j = i; while (s.charAt(j) != '|') j++; String sizeString = s.substring(i, j); int size = Integer.valueOf(sizeString); String str = s.substring(j+1, j+size+1); list.add(str); i += sizeString.length() + 1 + size; } return list; } } // Your Codec object will be instantiated and called as such: // Codec codec = new Codec(); // codec.decode(codec.encode(strs)); } ================================================ FILE: src/EncodeAndDecodeTinyURL535.java ================================================ /** * Note: This is a companion problem to the System Design problem: * Design TinyURL (https://leetcode.com/problems/design-tinyurl/) * * TinyURL is a URL shortening service where you enter a URL such as * https://leetcode.com/problems/design-tinyurl and it returns a short URL * such as http://tinyurl.com/4e9iAk. * * Design the encode and decode methods for the TinyURL service. There is no * restriction on how your encode/decode algorithm should work. You just need * to ensure that a URL can be encoded to a tiny URL and the tiny URL can be * decoded to the original URL. * */ public class EncodeAndDecodeTinyURL535 { public class Codec { public static final char[] ALPHABETS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '-', '_' }; public static final int BASE = 64; public static final Random rand = new Random(); private Map lookup = new HashMap<>(); // Encodes a URL to a shortened URL. public String encode(String longUrl) { StringBuilder str = new StringBuilder(); for (int i=0; i<7; i++) { str.append(ALPHABETS[rand.nextInt(BASE)]); } String key = str.toString(); lookup.put(key, longUrl); return key; } // Decodes a shortened URL to its original URL. public String decode(String shortUrl) { return lookup.get(shortUrl); } } public class Codec2 { private char[] BASE62 = new char[]{ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; Map map = new HashMap<>(); int id = 0; // Encodes a URL to a shortened URL. public String encode(String longUrl) { StringBuilder sb = new StringBuilder(); int n = id; while (n != 0) { sb.append(BASE62[n % 26]); n /= 62; } sb.append(BASE62[n % 26]); String key = sb.toString(); if (!map.containsKey(key)) { map.put(key, longUrl); id++; } return key; } // Decodes a shortened URL to its original URL. public String decode(String shortUrl) { return map.get(shortUrl); } } // Your Codec object will be instantiated and called as such: // Codec codec = new Codec(); // codec.decode(codec.encode(url)); } ================================================ FILE: src/EqualTreePartition663.java ================================================ /** * Given a binary tree with n nodes, your task is to check if it's possible to * partition the tree to two trees which have the equal sum of values after * removing exactly one edge on the original tree. * * Example 1: * Input: * 5 * / \ * 10 10 * / \ * 2 3 * * Output: True * * Explanation: * 5 * / * 10 * Sum: 15 * * 10 * / \ * 2 3 * Sum: 15 * * Example 2: * * Input: * 1 * / \ * 2 10 * / \ * 2 20 * * Output: False * * Explanation: You can't split the tree into two trees with equal sum after * removing exactly one edge on the tree. * * Note: * The range of tree node value is in the range of [-100000, 100000]. * 1 <= n <= 10000 */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class EqualTreePartition663 { public boolean checkEqualTree(TreeNode root) { Set set = new HashSet<>(); int total = sum(root, set, true); return total % 2 == 0 && set.contains(total / 2); } private int sum(TreeNode root, Set set, boolean isRoot) { if (root == null) return 0; int left = sum(root.left, set, false); int right = sum(root.right, set, false); int s = left + root.val + right; if (!isRoot) set.add(s); return s; } } ================================================ FILE: src/EvaluateDivision399.java ================================================ /** * Equations are given in the format A / B = k, where A and B are variables * represented as strings, and k is a real number (floating point number). * Given some queries, return the answers. If the answer does not exist, * return -1.0. * * Example: * Given a / b = 2.0, b / c = 3.0. * queries are: a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ? . * return [6.0, 0.5, -1.0, 1.0, -1.0 ]. * * The input is: vector> equations, vector& values, * vector> queries , where equations.size() == values.size(), * and the values are positive. This represents the equations. * Return vector. * * According to the example above: * * equations = [ ["a", "b"], ["b", "c"] ], * values = [2.0, 3.0], * queries = [ ["a", "c"], ["b", "a"], ["a", "e"], ["a", "a"], ["x", "x"] ]. * * The input is always valid. You may assume that evaluating the queries will * result in no division by zero and there is no contradiction. * */ public class EvaluateDivision399 { public double[] calcEquation(String[][] equations, double[] values, String[][] queries) { double[] res = new double[queries.length]; Map> graph = new HashMap<>(); Map> weights = new HashMap<>(); initGraph(equations, values, graph, weights); for (int i=0; i visited = new HashSet<>(); res[i] = dfs(graph, weights, q[0], q[1], visited, 1.0); } } return res; } private double dfs(Map> graph, Map> weights, String from, String to, Set visited, double pre) { if (from.equals(to)) return 1.0; visited.add(from); Set set = graph.get(from); if (set.contains(to)) { return (weights.get(from).get(to) == -1.0) ? -1.0 : weights.get(from).get(to) * pre; } for (String next: set) { if (visited.contains(next)) continue; Double newVal = dfs(graph, weights, next, to, visited, pre); if (newVal == -1.0) continue; return pre * weights.get(from).get(next) * newVal; } visited.remove(from); return -1.0; } private void initGraph(String[][] equations, double[] values, Map> graph, Map> weights) { for (int i=0; i> weights, String from, String to, Double weight) { Map map = weights.getOrDefault(from, new HashMap()); map.put(to, weight); weights.put(from, map); } private void addToValueSet(Map> graph, String from, String to) { Set set = graph.getOrDefault(from, new HashSet()); set.add(to); graph.put(from, set); } public double[] calcEquation2(String[][] equations, double[] values, String[][] queries) { UnionFind uf = new UnionFind(); int N = equations.length; for (int i = 0; i parents = new HashMap<>(); private Parent find(String A) { if (!parents.containsKey(A)) return null; Parent pa = parents.get(A); if (!pa.parent.equals(A)) { Parent p = find(pa.parent); pa.parent = p.parent; pa.times *= p.times; } return pa; } private void union(String A, String B, double times) { boolean hasA = parents.containsKey(A); boolean hasB = parents.containsKey(B); if (!hasA && !hasB) { parents.put(A, new Parent(A, 1.0)); parents.put(B, new Parent(A, times)); } else if (!hasA) { parents.put(A, new Parent(B, 1.0 / times)); } else if (!hasB) { parents.put(B, new Parent(A, times)); } else { Parent pa = find(A); Parent pb = find(B); pb.parent = pa.parent; pb.times = (pa.times / pb.times) * times; } } } class Parent { String parent; Double times; Parent(String parent, Double times) { this.parent = parent; this.times = times; } } } ================================================ FILE: src/EvaluateReversePolishNotation150.java ================================================ /** * Evaluate the value of an arithmetic expression in Reverse Polish Notation. * * Valid operators are +, -, *, /. Each operand may be an integer or another expression. * * Note: * * Division between two integers should truncate toward zero. * The given RPN expression is always valid. That means the expression would * always evaluate to a result and there won't be any divide by zero operation. * * Example 1: * Input: ["2", "1", "+", "3", "*"] * Output: 9 * Explanation: ((2 + 1) * 3) = 9 * * Example 2: * Input: ["4", "13", "5", "/", "+"] * Output: 6 * Explanation: (4 + (13 / 5)) = 6 * * Example 3: * Input: ["10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"] * Output: 22 * Explanation: * ((10 * (6 / ((9 + 3) * -11))) + 17) + 5 * = ((10 * (6 / (12 * -11))) + 17) + 5 * = ((10 * (6 / -132)) + 17) + 5 * = ((10 * 0) + 17) + 5 * = (0 + 17) + 5 * = 17 + 5 * = 22 */ public class EvaluateReversePolishNotation150 { public int evalRPN(String[] tokens) { Stack stack = new Stack<>(); for (String t: tokens) { switch (t) { case "+": Integer i1 = stack.pop(); Integer i2 = stack.pop(); stack.push(i2 + i1); break; case "-": Integer i3 = stack.pop(); Integer i4 = stack.pop(); stack.push(i4 - i3); break; case "*": Integer i5 = stack.pop(); Integer i6 = stack.pop(); stack.push(i6 * i5); break; case "/": Integer i7 = stack.pop(); Integer i8 = stack.pop(); stack.push(i8 / i7); break; default: stack.push(Integer.valueOf(t)); } } return stack.pop(); } } ================================================ FILE: src/ExamRoom855.java ================================================ /** * In an exam room, there are N seats in a single row, numbered 0, 1, 2, ..., N-1. * * When a student enters the room, they must sit in the seat that maximizes the * distance to the closest person. If there are multiple such seats, they sit * in the seat with the lowest number. (Also, if no one is in the room, then * the student sits at seat number 0.) * * Return a class ExamRoom(int N) that exposes two functions: ExamRoom.seat() * returning an int representing what seat the student sat in, and * ExamRoom.leave(int p) representing that the student in seat number p now * leaves the room. It is guaranteed that any calls to ExamRoom.leave(p) have * a student sitting in seat p. * * Example 1: * Input: ["ExamRoom","seat","seat","seat","seat","leave","seat"], [[10],[],[],[],[],[4],[]] * Output: [null,0,9,4,2,null,5] * * Explanation: * ExamRoom(10) -> null * seat() -> 0, no one is in the room, then the student sits at seat number 0. * seat() -> 9, the student sits at the last seat number 9. * seat() -> 4, the student sits at the last seat number 4. * seat() -> 2, the student sits at the last seat number 2. * leave(4) -> null * seat() -> 5, the student​​​​​​​ sits at the last seat number 5. ​​​​​​​ * * Note: * 1 <= N <= 10^9 * ExamRoom.seat() and ExamRoom.leave() will be called at most 10^4 times across all test cases. * Calls to ExamRoom.leave(p) are guaranteed to have a student currently sitting in seat number p. */ public class ExamRoom855 { class ExamRoom { private PriorityQueue pq; private Map lefts; private Map rights; private int N; public ExamRoom(int N) { this.pq = new PriorityQueue(1, new Comparator() { @Override public int compare(Range r1, Range r2) { int rangeDiff = Integer.compare(dis(r2), dis(r1)); if (rangeDiff != 0) return rangeDiff; return Integer.compare(r1.left, r2.left); } }); this.lefts = new HashMap<>(); this.rights = new HashMap<>(); this.N = N; Range first = new Range(-1, N); this.pq.add(first); this.lefts.put(first.left, first); this.rights.put(first.right, first); } public int seat() { if (this.pq.isEmpty()) return -1; Range curr = this.pq.poll(); this.lefts.remove(curr.left); this.rights.remove(curr.right); int pos = sitPos(curr); Range l = new Range(curr.left, pos); this.lefts.put(l.left, l); this.rights.put(l.right, l); if (curr.left + 1 < pos) { this.pq.add(l); } Range r = new Range(pos, curr.right); this.lefts.put(r.left, r); this.rights.put(r.right, r); if (pos + 1 < curr.right) { this.pq.add(r); } return pos; } public void leave(int p) { Range r = this.lefts.get(p); Range l = this.rights.get(p); this.pq.remove(r); this.pq.remove(l); Range merged = new Range(l.left, r.right); this.pq.add(merged); this.lefts.put(merged.left, merged); this.rights.put(merged.right, merged); } private int sitPos(Range r) { return sitPos(r.left, r.right); } private int sitPos(int left, int right) { if (left + 1 >= right) return -1; if (left < 0) return 0; if (right >= this.N) return this.N - 1; return (right - left) / 2 + left; } private int dis(Range r) { return dis(r.left, r.right); } private int dis(int left, int right) { if (left < 0) return right; if (right >= this.N) return this.N - 1 - left; return (right - left) / 2; } } class Range { int left; int right; Range (int l, int r) { this.left = l; this.right = r; } } /** * Your ExamRoom object will be instantiated and called as such: * ExamRoom obj = new ExamRoom(N); * int param_1 = obj.seat(); * obj.leave(p); */ } ================================================ FILE: src/ExclusiveTimeOfFunctions636.java ================================================ /** * Given the running logs of n functions that are executed in a nonpreemptive * single threaded CPU, find the exclusive time of these functions. * * Each function has a unique id, start from 0 to n-1. A function may be called * recursively or by another function. * * A log is a string has this format : function_id:start_or_end:timestamp. For * example, "0:start:0" means function 0 starts from the very beginning of * time 0. "0:end:0" means function 0 ends to the very end of time 0. * * Exclusive time of a function is defined as the time spent within this * function, the time spent by calling other functions should not be considered * as this function's exclusive time. You should return the exclusive time of * each function sorted by their function id. * * Example 1: * Input: * n = 2 * logs = * ["0:start:0", * "1:start:2", * "1:end:5", * "0:end:6"] * Output:[3, 4] * * Explanation: * Function 0 starts at time 0, then it executes 2 units of time and reaches * the end of time 1. * Now function 0 calls function 1, function 1 starts at time 2, executes 4 * units of time and end at time 5. * Function 0 is running again at time 6, and also end at the time 6, thus * executes 1 unit of time. * So function 0 totally execute 2 + 1 = 3 units of time, and function 1 * totally execute 4 units of time. * * Note: * Input logs will be sorted by timestamp, NOT log id. * Your output should be sorted by function id, which means the 0th element of * your output corresponds to the exclusive time of function 0. * Two functions won't start or end at the same time. * Functions could be called recursively, and will always end. * 1 <= n <= 100 */ public class ExclusiveTimeOfFunctions636 { public int[] exclusiveTime(int n, List logs) { int[] res = new int[n]; Stack actives = new Stack<>(); int preTime = 0; boolean preIsStart = true; for (String log: logs) { String[] strs = log.split(":"); int id = Integer.valueOf(strs[0]); boolean isStart = strs[1].equals("start"); int now = Integer.valueOf(strs[2]); if (isStart) { if (!actives.isEmpty()) { res[actives.peek()] += now - preTime - (preIsStart ? 0 : 1); } actives.push(id); } else { res[actives.peek()] += now - preTime + (preIsStart ? 1 : 0); actives.pop(); } preTime = now; preIsStart = isStart; } return res; } } ================================================ FILE: src/ExpressionAddOperators282.java ================================================ /** * Given a string that contains only digits 0-9 and a target value, return all * possibilities to add binary operators (not unary) +, -, or * between the * digits so they evaluate to the target value. * * Examples: * "123", 6 -> ["1+2+3", "1*2*3"] * "232", 8 -> ["2*3+2", "2+3*2"] * "105", 5 -> ["1*0+5","10-5"] * "00", 0 -> ["0+0", "0-0", "0*0"] * "3456237490", 9191 -> [] * */ public class ExpressionAddOperators282 { public List addOperators(String num, int target) { List res = new ArrayList<>(); if (num == null || num.length() == 0) return res; if (num.charAt(0) == '0') { helper(num, target, res, "0", 1, 1, 0, 0L); } else { for (int i=0; i res, String s, int i1, int i2, long pre, long last) { if (i2 >= num.length()) { if (i1 == i2 && (pre + last) == target) res.add(s); return; } String curr = num.substring(i1, i2+1); Long i = Long.parseLong(curr); if (!(i1 == i2 && curr.charAt(0) == '0')) { helper(num, target, res, s, i1, i2+1, pre, last); } helper(num, target, res, s+"+"+curr, i2+1, i2+1, pre+last, i); helper(num, target, res, s+"-"+curr, i2+1, i2+1, pre+last, -i); helper(num, target, res, s+"*"+curr, i2+1, i2+1, pre, last*i); } /** * https://discuss.leetcode.com/topic/35942/java-ac-solution-19ms-beat-100-00 */ public List addOperators2(String num, int target) { List ret = new LinkedList<>(); if (num.length() == 0) return ret; char[] path = new char[num.length() * 2 - 1]; char[] digits = num.toCharArray(); long n = 0; for (int i = 0; i < digits.length; i++) { n = n * 10 + digits[i] - '0'; path[i] = digits[i]; dfs(ret, path, i + 1, 0, n, digits, i + 1, target); if (n == 0) break; } return ret; } private void dfs(List ret, char[] path, int len, long left, long cur, char[] digits, int pos, int target) { if (pos == digits.length) { if (left + cur == target) ret.add(new String(path, 0, len)); return; } long n = 0; int j = len + 1; for (int i = pos; i < digits.length; i++) { n = n * 10 + digits[i] - '0'; path[j++] = digits[i]; path[len] = '+'; dfs(ret, path, j, left + cur, n, digits, i + 1, target); path[len] = '-'; dfs(ret, path, j, left + cur, -n, digits, i + 1, target); path[len] = '*'; dfs(ret, path, j, left, cur * n, digits, i + 1, target); if (digits[pos] == '0') break; } } } ================================================ FILE: src/FindAllAnagramsInAString438.java ================================================ /** * Given a string s and a non-empty string p, find all the start indices of * p's anagrams in s. * * Strings consists of lowercase English letters only and the length of both * strings s and p will not be larger than 20,100. * * The order of output does not matter. * * Example 1: * Input: * s: "cbaebabacd" p: "abc" * Output: * [0, 6] * Explanation: * The substring with start index = 0 is "cba", which is an anagram of "abc". * The substring with start index = 6 is "bac", which is an anagram of "abc". * * Example 2: * Input: * s: "abab" p: "ab" * Output: * [0, 1, 2] * Explanation: * The substring with start index = 0 is "ab", which is an anagram of "ab". * The substring with start index = 1 is "ba", which is an anagram of "ab". * The substring with start index = 2 is "ab", which is an anagram of "ab". */ public class FindAllAnagramsInAString438 { public List findAnagrams(String s, String p) { int[] map = new int[26]; for (char c: p.toCharArray()) { map[c - 'a']++; } List res = new ArrayList<>(); int lenS = s.length(); int count = p.length(); if (lenS < count) return res; char[] chars = s.toCharArray(); int i = 0; int j = 0; while (j < lenS) { char c = chars[j]; while (i <= j && map[c - 'a'] <= 0) { map[chars[i] - 'a']++; i++; } map[c - 'a']--; j++; if (j - i == count) { res.add(i); map[chars[i] - 'a']++; i++; } } return res; } public List findAnagrams2(String s, String p) { int[] map = new int[26]; for (char c: p.toCharArray()) { map[c - 'a']++; } List res = new ArrayList<>(); int lenS = s.length(); int lenP = p.length(); if (lenS < lenP) return res; char[] chars = s.toCharArray(); int[] window = new int[26]; for (int i=0; i findAnagrams3(String s, String p) { List list = new ArrayList<>(); if (s == null || s.length() == 0 || p == null || p.length() == 0) return list; int[] hash = new int[256]; //character hash //record each character in p to hash for (char c : p.toCharArray()) { hash[c]++; } //two points, initialize count to p's length int left = 0, right = 0, count = p.length(); while (right < s.length()) { //move right everytime, if the character exists in p's hash, decrease the count //current hash value >= 1 means the character is existing in p if (hash[s.charAt(right++)]-- >= 1) count--; //when the count is down to 0, means we found the right anagram //then add window's left to result list if (count == 0) list.add(left); //if we find the window's size equals to p, then we have to move left (narrow the window) to find the new match window //++ to reset the hash because we kicked out the left //only increase the count if the character is in p //the count >= 0 indicate it was original in the hash, cuz it won't go below 0 if (right - left == p.length() && hash[s.charAt(left++)]++ >= 0) count++; } return list; } /** * https://leetcode.com/problems/find-all-anagrams-in-a-string/discuss/92007/Sliding-Window-algorithm-template-to-solve-all-the-Leetcode-substring-search-problem. */ public List findAnagrams4(String s, String t) { List result = new LinkedList<>(); if(t.length()> s.length()) return result; Map map = new HashMap<>(); for(char c : t.toCharArray()){ map.put(c, map.getOrDefault(c, 0) + 1); } int counter = map.size(); int begin = 0, end = 0; int head = 0; int len = Integer.MAX_VALUE; while(end < s.length()){ char c = s.charAt(end); if( map.containsKey(c) ){ map.put(c, map.get(c)-1); if(map.get(c) == 0) counter--; } end++; while(counter == 0){ char tempc = s.charAt(begin); if(map.containsKey(tempc)){ map.put(tempc, map.get(tempc) + 1); if(map.get(tempc) > 0){ counter++; } } if(end-begin == t.length()){ result.add(begin); } begin++; } } return result; } public List findAnagrams5(String s, String p) { List res = new ArrayList<>(); if (s.length() < p.length()) return res; int[] map = new int[26]; int M = 0; for (char c: p.toCharArray()) { if (map[c - 'a'] == 0) M++; map[c - 'a']++; } char[] charS = s.toCharArray(); int N = charS.length; int P = p.length(); int left = 0; int right = 0; while (right < N) { char rc = charS[right++]; map[rc - 'a']--; if (map[rc - 'a'] == 0) M--; if (M == 0) res.add(left); if (right - left == P) { char lc = charS[left++]; if (map[lc - 'a'] == 0) M++; map[lc - 'a']++; } } return res; } } ================================================ FILE: src/FindAllNumbersDisappearedInAnArray448.java ================================================ /** * Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some * elements appear twice and others appear once. * * Find all the elements of [1, n] inclusive that do not appear in this array. * * Could you do it without extra space and in O(n) runtime? You may assume the * returned list does not count as extra space. * * Example: * * Input: * [4,3,2,7,8,2,3,1] * * Output: * [5,6] */ public class FindAllNumbersDisappearedInAnArray448 { public List findDisappearedNumbers(int[] nums) { if (nums == null || nums.length <= 1) return new ArrayList<>(); int len = nums.length; int i = 0; while (i < len) { int curr = nums[i]; while (curr != i + 1) { int next = nums[curr-1]; if (curr == next) break; swap(nums, i, curr-1); curr = nums[i]; } i++; } List res = new ArrayList<>(); for (int j=0; j D = new HashMap(); for (int i = 0; i < B.length; ++i) D.put(B[i], i); int[] ans = new int[A.length]; int t = 0; for (int x: A) ans[t++] = D.get(x); return ans; } } ================================================ FILE: src/FindAndReplacePattern890.java ================================================ /** * You have a list of words and a pattern, and you want to know which words in * words matches the pattern. * * A word matches the pattern if there exists a permutation of letters p so * that after replacing every letter x in the pattern with p(x), we get the * desired word. * * (Recall that a permutation of letters is a bijection from letters to * letters: every letter maps to another letter, and no two letters map to * the same letter.) * * Return a list of the words in words that match the given pattern. * * You may return the answer in any order. * * Example 1: * Input: words = ["abc","deq","mee","aqq","dkd","ccc"], pattern = "abb" * Output: ["mee","aqq"] * Explanation: "mee" matches the pattern because there is a permutation {a -> m, b -> e, ...}. * "ccc" does not match the pattern because {a -> c, b -> c, ...} is not a permutation, * since a and b map to the same letter. * * Note: * 1 <= words.length <= 50 * 1 <= pattern.length = words[i].length <= 20 */ public class FindAndReplacePattern890 { public List findAndReplacePattern(String[] words, String pattern) { List res = new ArrayList<>(); char[] pat = pattern.toCharArray(); int N = pattern.length(); for (String word: words) { if (isPermutation(word.toCharArray(), pat, N)) { res.add(word); } } return res; } public boolean isPermutation(char[] word, char[] pattern, int N) { Map map = new HashMap<>(); for (int i=0; i findAndReplacePattern2(String[] words, String pattern) { List res = new ArrayList<>(); int code = encode(pattern); for (String w: words) { if (code == encode(w)) { res.add(w); } } return res; } public int encode(String s) { int res = 0; char[] chars = s.toCharArray(); char first = chars[0]; Map map = new HashMap<>(); map.put(0, 0); int i = 1; for (int j=0; j q = new LinkedList<>(); q.add(root); while (!q.isEmpty()) { Queue ql = new LinkedList<>(); System.out.println(q.peek().val); res = q.peek().val; while (!q.isEmpty()) { TreeNode n = q.poll(); if (n.left != null) ql.offer(n.left); if (n.right != null) ql.offer(n.right); } q = ql; } return res; } public int findBottomLeftValue2(TreeNode root) { int res = root.val; Map lefts = new HashMap<>(); int level = helper(root, 0, lefts); return lefts.get(level); } private int helper(TreeNode node, int level, Map lefts) { if (node == null) return level-1; if (!lefts.containsKey(level)) lefts.put(level, node.val); int leftLevel = helper(node.left, level+1, lefts); int rightLevel = helper(node.right, level+1, lefts); return Math.max(leftLevel, rightLevel); } /** * https://discuss.leetcode.com/topic/78962/simple-java-solution-beats-100-0 */ public int findBottomLeftValue3(TreeNode root) { return findBottomLeftValue(root, 1, new int[]{0,0}); } public int findBottomLeftValue(TreeNode root, int depth, int[] res) { if (res[1] findDuplicateSubtrees(TreeNode root) { List res = new ArrayList<>(); if (root == null) return res; Map visited = new HashMap<>(); findDuplicates(root, visited, res); return res; } private String findDuplicates(TreeNode root, Map visited, List res) { if (root == null) { return "N"; } String self = Integer.toString(root.val); String left = findDuplicates(root.left, visited, res); String right = findDuplicates(root.right, visited, res); String curr = self + "-" + left + "-" + right; if (!visited.containsKey(curr)) { visited.put(curr, false); } else { if (!visited.get(curr)) { res.add(root); visited.put(curr, true); } } return curr; } } ================================================ FILE: src/FindEventualSafeStates802.java ================================================ /** * In a directed graph, we start at some node and every turn, walk along a * directed edge of the graph. If we reach a node that is terminal (that is, * it has no outgoing directed edges), we stop. * * Now, say our starting node is eventually safe if and only if we must * eventually walk to a terminal node. More specifically, there exists a * natural number K so that for any choice of where to walk, we must have * stopped at a terminal node in less than K steps. * * Which nodes are eventually safe? Return them as an array in sorted order. * * The directed graph has N nodes with labels 0, 1, ..., N-1, where N is the * length of graph. The graph is given in the following form: graph[i] is a * list of labels j such that (i, j) is a directed edge of the graph. * * Example: * Input: graph = [[1,2],[2,3],[5],[0],[5],[],[]] * Output: [2,4,5,6] * * Here is a diagram of the above graph. * https://s3-lc-upload.s3.amazonaws.com/uploads/2018/03/17/picture1.png * * Note: * graph will have length at most 10000. * The number of edges in the graph will not exceed 32000. * Each graph[i] will be a sorted list of different integers, chosen within * the range [0, graph.length - 1]. */ public class FindEventualSafeStates802 { public List eventualSafeNodes(int[][] graph) { List res = new ArrayList<>(); if (graph == null || graph.length == 0) return res; int N = graph.length; boolean[] saved = new boolean[N]; boolean[] visited = new boolean[N]; for (int i=0; i eventualSafeNodes2(int[][] graph) { int N = graph.length; int[] color = new int[N]; List ans = new ArrayList(); for (int i = 0; i < N; ++i) if (dfs(i, color, graph)) ans.add(i); return ans; } // colors: WHITE 0, GRAY 1, BLACK 2; public boolean dfs(int node, int[] color, int[][] graph) { if (color[node] > 0) return color[node] == 2; color[node] = 1; for (int nei: graph[node]) { if (color[node] == 2) continue; if (color[nei] == 1 || !dfs(nei, color, graph)) return false; } color[node] = 2; return true; } } ================================================ FILE: src/FindKClosestElements658.java ================================================ /** * Given a sorted array, two integers k and x, find the k closest elements to x * in the array. The result should also be sorted in ascending order. If there * is a tie, the smaller elements are always preferred. * * Example 1: * Input: [1,2,3,4,5], k=4, x=3 * Output: [1,2,3,4] * * Example 2: * Input: [1,2,3,4,5], k=4, x=-1 * Output: [1,2,3,4] * * Note: * The value k is positive and will always be smaller than the length of the sorted array. * Length of the given array is positive and will not exceed 104 * Absolute value of elements in the array and x will not exceed 104 * * UPDATE (2017/9/19): * The arr parameter had been changed to an array of integers (instead of a * list of integers). Please reload the code definition to get the latest * changes. */ public class FindKClosestElements658 { public List findClosestElements(int[] arr, int k, int x) { int pos = binarySearch(arr, x, 0, arr.length-1); pos = updatePos(arr, x, pos); LinkedList res = new LinkedList<>(); int left = pos - 1; int right = pos; int i = 0; while (i < k) { if (left >= 0 && right < arr.length) { if (Math.abs(arr[left] - x) <= Math.abs(arr[right] - x)) { res.addFirst(arr[left--]); } else { res.addLast(arr[right++]); } } else if (left >= 0) { res.addFirst(arr[left--]); } else { res.addLast(arr[right++]); } i++; } return res; } public int binarySearch(int[] arr, int x, int lo, int hi) { if (lo == hi) return lo; if (hi - lo == 1) return hi; int mid = (lo + hi) / 2; if (arr[mid] == x) return mid; else if (arr[mid] > x) { return binarySearch(arr, x, lo, mid); } else { return binarySearch(arr, x, mid, hi); } } private int updatePos(int[] arr, int x, int pos) { if (arr[pos] == x || pos == 0) return pos; return (Math.abs(arr[pos-1]-x) <= Math.abs(arr[pos]-x)) ? pos - 1 : pos; } // /** // * https://leetcode.com/problems/find-k-closest-elements/solution/ // */ // public List findClosestElements2(List arr, int k, int x) { // Collections.sort(arr, (a,b) -> a == b ? a - b : Math.abs(a-x) - Math.abs(b-x)); // arr = arr.subList(0, k); // Collections.sort(arr); // return arr; // } public List findClosestElements3(int[] arr, int k, int x) { List res = new ArrayList<>(); int N = arr.length; int start = 0; int end = N - k; /* 0...............................mid.....|....mid+k................(N-k) arr[mid] >= x, end = mid arr[mid] < x: x - arr[mid] > arr[mid+k] - x, start = mid + 1; x - arr[mid] <= arr[mid+k] - x, end = mid */ while (start < end) { int mid = (end + start) / 2; // if (arr[mid] >= x) { // end = mid; // } else { // arr[mid] < x if (x - arr[mid] > arr[mid+k] - x) { start = mid + 1; } else { end = mid; } // } } for (int i=0; i findClosestElements4(int[] arr, int k, int x) { List res = new ArrayList<>(); if (arr == null || arr.length == 0) return res; int idx = binarySearch(arr, x); int lo = idx - 1; int hi = idx; while (hi - lo - 1 < k) { if (lo < 0 && hi >= arr.length) break; if (lo < 0) { hi++; } else if (hi >= arr.length) { lo--; } else { if (Math.abs(arr[lo] - x) <= Math.abs(arr[hi] - x)) { lo--; } else { hi++; } } } for (int i=lo+1; i kSmallestPairs(int[] nums1, int[] nums2, int k) { PriorityQueue que = new PriorityQueue<>((a,b)->a[0]+a[1]-b[0]-b[1]); List res = new ArrayList<>(); if(nums1.length==0 || nums2.length==0 || k==0) return res; for(int i=0; i 0 && !que.isEmpty()){ int[] cur = que.poll(); res.add(new int[]{cur[0], cur[1]}); if(cur[2] == nums2.length-1) continue; que.offer(new int[]{cur[0], nums2[cur[2]+1], cur[2]+1}); } return res; } /** * https://discuss.leetcode.com/topic/50529/java-9ms-heap-queue-solution-k-log-k */ public List kSmallestPairs2(int[] nums1, int[] nums2, int k) { List ret = new ArrayList<>(); if (nums1==null || nums2==null || nums1.length ==0 || nums2.length ==0) return ret; int len1 = nums1.length, len2=nums2.length; PriorityQueue q = new PriorityQueue(k, new CompPair()); for (int i=0; i { public int compare(Pair p1, Pair p2){ return Long.compare(p1.sum, p2.sum); } } /** * https://discuss.leetcode.com/topic/52953/share-my-solution-which-beat-96-42 */ public List kSmallestPairs3(int[] nums1, int[] nums2, int k) { PriorityQueue pq = new PriorityQueue(); int m = nums1.length, n = nums2.length; List res = new ArrayList(); if(nums1 == null || nums1.length == 0 || nums2 == null || nums2.length == 0 || k <= 0) return res; for(int j = 0; j <= n-1; j++) pq.offer(new Tuple(0, j, nums1[0]+nums2[j])); for(int i = 0; i < Math.min(k, m *n); i++) { Tuple t = pq.poll(); res.add(new int[]{nums1[t.x], nums2[t.y]}); if(t.x == m - 1) continue; pq.offer(new Tuple (t.x + 1, t.y, nums1[t.x + 1] + nums2[t.y])); } return res; } class Tuple implements Comparable { int x, y, val; public Tuple (int x, int y, int val) { this.x = x; this.y = y; this.val = val; } @Override public int compareTo (Tuple that) { return this.val - that.val; } } } ================================================ FILE: src/FindKthSmallestPairDistance719.java ================================================ /** * Given an integer array, return the k-th smallest distance among all the * pairs. The distance of a pair (A, B) is defined as the absolute difference * between A and B. * * Example 1: * Input: * nums = [1,3,1] * k = 1 * Output: 0 * * Explanation: * Here are all the pairs: * (1,3) -> 2 * (1,1) -> 0 * (3,1) -> 2 * * Then the 1st smallest distance pair is (1,1), and its distance is 0. * * Note: * 2 <= len(nums) <= 10000. * 0 <= nums[i] < 1000000. * 1 <= k <= len(nums) * (len(nums) - 1) / 2. */ public class FindKthSmallestPairDistance719 { public int smallestDistancePair(int[] nums, int k) { int len = nums.length; int[] buckets = new int[1000000]; for (int i=0; i= k) { return i; } } return -1; } public int smallestDistancePair3(int[] nums, int k) { int len = nums.length; if (k == 0 || len == 0) return -1; Arrays.sort(nums); int lo = 0; int hi = nums[nums.length - 1] - nums[0]; while (lo < hi) { int mid = (lo + hi) / 2; int cnt = count(nums, mid); if (k <= cnt) { hi = mid; } else { lo = mid+1; } } return lo; } private int count(int[] nums, int x) { int count = 0; int left = 0; int right = 0; while (right < nums.length) { while (nums[right] - nums[left] > x) { left++; } count += right - left; right++; } return count; } } ================================================ FILE: src/FindLargestValueInEachTreeRow515.java ================================================ /** * You need to find the largest value in each row of a binary tree. * * Example: * Input: * * 1 * / \ * 3 2 * / \ \ * 5 3 9 * * Output: [1, 3, 9] */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class FindLargestValueInEachTreeRow515 { public List largestValues(TreeNode root) { List res = new ArrayList<>(); if (root == null) return res; Queue q = new LinkedList<>(); q.add(root); while (!q.isEmpty()) { int size = q.size(); int maxVal = Integer.MIN_VALUE; for (int i=0; i largestValues2(TreeNode root) { List res = new ArrayList(); helper(root, res, 0); return res; } private void helper(TreeNode root, List res, int d){ if (root == null) return; if (d == res.size()) { //expand list size res.add(root.val); } else{ //or set value res.set(d, Math.max(res.get(d), root.val)); } helper(root.left, res, d+1); helper(root.right, res, d+1); } } ================================================ FILE: src/FindMedianFromDataStream295.java ================================================ /** * Median is the middle value in an ordered integer list. If the size of the * list is even, there is no middle value. So the median is the mean of the two * middle value. * * For example, * [2,3,4], the median is 3 * * [2,3], the median is (2 + 3) / 2 = 2.5 * * Design a data structure that supports the following two operations: * * void addNum(int num) - Add a integer number from the data stream to the data structure. * double findMedian() - Return the median of all elements so far. * * Example: * addNum(1) * addNum(2) * findMedian() -> 1.5 * addNum(3) * findMedian() -> 2 */ public class FindMedianFromDataStream295 { class MedianFinder { private PriorityQueue maxQ = new PriorityQueue<>(10, (i1, i2) -> Integer.compare(i2, i1)); private PriorityQueue minQ = new PriorityQueue<>(); /** initialize your data structure here. */ public MedianFinder() { } public void addNum(int num) { if (maxQ.size() == 0 && minQ.size() == 0) { maxQ.add(num); } else if (maxQ.size() == 0) { if (minQ.peek() < num) { minQ.add(num); } else { maxQ.add(num); } } else { if (maxQ.peek() > num) { maxQ.add(num); } else { minQ.add(num); } } while (maxQ.size() != 0 && maxQ.size() > minQ.size()) { minQ.add(maxQ.poll()); } while (minQ.size() != 0 && maxQ.size() < minQ.size()) { maxQ.add(minQ.poll()); } } public double findMedian() { if (maxQ.size() == minQ.size()) { return (maxQ.peek() + minQ.peek()) * 1.0 / 2; } else if (maxQ.size() > minQ.size()) { return maxQ.peek(); } else { return minQ.peek(); } } } class MedianFinder2 { private PriorityQueue maxQ = new PriorityQueue<>(10, (i1, i2) -> Integer.compare(i2, i1)); private PriorityQueue minQ = new PriorityQueue<>(); /** initialize your data structure here. */ public MedianFinder() { } // slower than previous solution MedianFinder, but code is clearner public void addNum(int num) { maxQ.add(num); minQ.add(maxQ.pop()); while (minQ.size() != 0 && maxQ.size() < minQ.size()) { maxQ.add(minQ.poll()); } } public double findMedian() { if (maxQ.size() == minQ.size()) { return (maxQ.peek() + minQ.peek()) * 1.0 / 2; } else if (maxQ.size() > minQ.size()) { return maxQ.peek(); } else { return minQ.peek(); } } } /** * https://leetcode.com/problems/find-median-from-data-stream/discuss/74119/18ms-beats-100-Java-Solution-with-BST */ class MedianFinder3 { class TreeNode{ int val; TreeNode parent,left,right; TreeNode(int val, TreeNode p){ this.val=val; this.parent=p; left=null; right=null; } void add(int num){ if(num>=val){ if(right==null) right=new TreeNode(num,this); else right.add(num); }else{ if(left==null) left=new TreeNode(num,this); else left.add(num); } } TreeNode next(){ TreeNode ret; if(right!=null){ ret=right; while(ret.left!=null) ret=ret.left; }else{ ret=this; while(ret.parent.right==ret) ret=ret.parent; ret=ret.parent; } return ret; } TreeNode prev(){ TreeNode ret; if(left!=null){ ret=left; while(ret.right!=null) ret=ret.right; }else{ ret=this; while(ret.parent.left==ret) ret=ret.parent; ret=ret.parent; } return ret; } } int n; TreeNode root, curr; // Adds a number into the data structure. public void addNum(int num) { if(root==null){ root = new TreeNode(num,null); curr=root; n=1; }else{ root.add(num); n++; if(n%2==1){ if(curr.val<=num) curr=curr.next(); }else if(curr.val>num) curr=curr.prev(); } } // Returns the median of current data stream public double findMedian() { if(n%2==0){ return ((double)curr.next().val+curr.val)/2; }else return curr.val; } }; class MedianFinder4 { private PriorityQueue left; private PriorityQueue right; /** initialize your data structure here. */ public MedianFinder() { left = new PriorityQueue<>((i1, i2) -> Integer.compare(i2, i1)); right = new PriorityQueue<>((i1, i2) -> Integer.compare(i1, i2)); } public void addNum(int num) { if (right.size() != 0 && right.peek() < num) { right.add(num); if (left.size() < right.size()) { left.add(right.poll()); } } else { left.add(num); if (left.size() > right.size() + 1) { right.add(left.poll()); } } } public double findMedian() { if (left.size() == right.size()) { return ((double) left.peek() + (double) right.peek()) / 2.0; } else { return (double) left.peek(); } } } /** * Your MedianFinder object will be instantiated and called as such: * MedianFinder obj = new MedianFinder(); * obj.addNum(num); * double param_2 = obj.findMedian(); */ } ================================================ FILE: src/FindMinimumInRotatedSortedArray153.java ================================================ /** * Suppose an array sorted in ascending order is rotated at some pivot unknown * to you beforehand. * * (i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]). * * Find the minimum element. * * You may assume no duplicate exists in the array. * * Example 1: * * Input: [3,4,5,1,2] * Output: 1 * Example 2: * * Input: [4,5,6,7,0,1,2] * Output: 0 * */ public class FindMinimumInRotatedSortedArray153 { public int findMin(int[] nums) { return findMin(nums, 0, nums.length-1); } public int findMin(int[] nums, int s, int e) { if (nums[s] <= nums[e]) return nums[s]; int mid = (s + e) / 2; return Math.min(findMin(nums, s, mid), findMin(nums, mid+1, e)); } public int findMin2(int[] nums) { int s = 0; int e = nums.length-1; while (s < e) { int mid = (s + e) / 2; if (nums[mid] > nums[e]) { s = mid + 1; } else { e = mid; } } return nums[e]; } public int findMin3(int[] nums) { int start = 0; int end = nums.length - 1; int startVal = nums[start]; int endVal = nums[end]; while (start + 1 < end) { int mid = start + (end - start) / 2; if (nums[mid] > startVal) { start = mid; } else if (nums[mid] < endVal) { end = mid; } } return Math.min(nums[end], Math.min(nums[start], Math.min(startVal, endVal))); } public int findMin4(int[] nums) { for (int i=1; i nums[e]) { s = mid + 1; } else { e--; } } return nums[s]; } } ================================================ FILE: src/FindModeInBinarySearchTree501.java ================================================ /** * Given a binary search tree (BST) with duplicates, find all the mode(s) * (the most frequently occurred element) in the given BST. * * Assume a BST is defined as follows: * - The left subtree of a node contains only nodes with keys less than or equal to the node's key. * - The right subtree of a node contains only nodes with keys greater than or equal to the node's key. * - Both the left and right subtrees must also be binary search trees. * For example: * Given BST [1,null,2,2], * * 1 * \ * 2 * / * 2 * * return [2]. * * Note: If a tree has more than one mode, you can return them in any order. * * Follow up: Could you do that without using any extra space? (Assume that the * implicit stack space incurred due to recursion does not count). */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class FindModeInBinarySearchTree501 { public int[] findMode(TreeNode root) { Result result = new Result(); findMode(root, result); int[] output = new int[result.res.size()]; int i = 0; for (int r: result.res) { output[i++] = r; } return output; } private void findMode(TreeNode root, Result result) { if (root == null) return; findMode(root.left, result); if (result.maxCount == -1) { result.maxCount = 1; result.currCount = 1; result.curr = root.val; result.res = new HashSet<>(); result.res.add(root.val); } else if (result.curr != root.val) { result.currCount = 1; result.curr = root.val; if (result.maxCount == result.currCount) { result.res.add(root.val); } } else { result.currCount++; if (result.maxCount == result.currCount) { result.res.add(root.val); } else if (result.maxCount < result.currCount) { result.maxCount = result.currCount; result.res = new HashSet<>(); result.res.add(root.val); } } findMode(root.right, result); } class Result { int maxCount; int currCount; int curr; Set res; Result() { this.maxCount = -1; this.currCount = -1; this.curr = 0; this.res = new HashSet<>(); } } /** * https://leetcode.com/problems/find-mode-in-binary-search-tree/discuss/98101/Proper-O(1)-space */ public int[] findMode2(TreeNode root) { inorder(root); modes = new int[modeCount]; modeCount = 0; currCount = 0; inorder(root); return modes; } private int currVal; private int currCount = 0; private int maxCount = 0; private int modeCount = 0; private int[] modes; private void handleValue(int val) { if (val != currVal) { currVal = val; currCount = 0; } currCount++; if (currCount > maxCount) { maxCount = currCount; modeCount = 1; } else if (currCount == maxCount) { if (modes != null) modes[modeCount] = currVal; modeCount++; } } private void inorder(TreeNode root) { if (root == null) return; inorder(root.left); handleValue(root.val); inorder(root.right); } } ================================================ FILE: src/FindPeakElement162.java ================================================ /** * A peak element is an element that is greater than its neighbors. * * Given an input array where num[i] ≠ num[i+1], find a peak element and return * its index. * * The array may contain multiple peaks, in that case return the index to any * one of the peaks is fine. * * You may imagine that num[-1] = num[n] = -∞. * * For example, in array [1, 2, 3, 1], 3 is a peak element and your function * should return the index number 2. * * Note: * Your solution should be in logarithmic complexity. */ public class FindPeakElement162 { public int findPeakElement(int[] nums) { if (nums == null || nums.length == 0) return -1; if (nums.length == 1) return 0; if (nums[0] > nums[1]) { return 0; } else if (nums[nums.length-1] > nums[nums.length-2]) { return nums.length-1; } else { for (int i=1; i nums[i-1] && nums[i] > nums[i+1]) return i; } } return -1; } /** * https://leetcode.com/problems/find-peak-element/solution/ */ public int findPeakElement2(int[] nums) { for (int i = 0; i < nums.length - 1; i++) { if (nums[i] > nums[i + 1]) return i; } return nums.length - 1; } public int findPeakElement3(int[] nums) { return search(nums, 0, nums.length - 1); } public int search(int[] nums, int l, int r) { if (l == r) return l; int mid = (l + r) / 2; if (nums[mid] > nums[mid + 1]) return search(nums, l, mid); return search(nums, mid + 1, r); } public int findPeakElement4(int[] nums) { int l = 0, r = nums.length - 1; while (l < r) { int mid = (l + r) / 2; if (nums[mid] > nums[mid + 1]) r = mid; else l = mid + 1; } return l; } } ================================================ FILE: src/FindTheCelebrity277.java ================================================ /** * Suppose you are at a party with n people (labeled from 0 to n - 1) and among * them, there may exist one celebrity. The definition of a celebrity is that * all the other n - 1 people know him/her but he/she does not know any of them. * * Now you want to find out who the celebrity is or verify that there is not * one. The only thing you are allowed to do is to ask questions like: * "Hi, A. Do you know B?" to get information of whether A knows B. You need to * find out the celebrity (or verify there is not one) by asking as few * questions as possible (in the asymptotic sense). * * You are given a helper function bool knows(a, b) which tells you whether A * knows B. Implement a function int findCelebrity(n), your function should * minimize the number of calls to knows. * * Note: There will be exactly one celebrity if he/she is in the party. Return * the celebrity's label if there is a celebrity in the party. If there is no * celebrity, return -1. */ /* The knows API is defined in the parent class Relation. boolean knows(int a, int b); */ public class FindTheCelebrity277 { // brutal force, accepted public int findCelebrity(int n) { boolean[] notCelebrity = new boolean[n]; int[] known = new int[n]; for (int a=0; a celebrities = new HashSet<>(); for (int i=0; i isMissing = new ArrayList<>(); isMissing.add(false); int firstMissing = 1; for (int i = 0; i < nums.length; i++) { int now = nums[i]; if (now > 0) { try { if (isMissing.get(now)) { isMissing.set(now, false); } } catch (IndexOutOfBoundsException e) { while (isMissing.size() < now) { isMissing.add(true); } isMissing.add(false); } } try { while (!isMissing.get(firstMissing)) { firstMissing++; } } catch (IndexOutOfBoundsException e) { isMissing.add(true); } } return firstMissing; } /** * */ public int firstMissingPositive2(int[] nums) { if (nums == null || nums.length == 0) { return 1; } for (int i = 0; i < nums.length; ++i) { while (nums[i] > 0 && nums[i] <= nums.length && nums[i] - 1 != i) { int tmp = nums[nums[i] - 1]; if (tmp == nums[i]) { break; } nums[nums[i] - 1] = nums[i]; nums[i] = tmp; } } for (int i = 0; i < nums.length; ++i) { if (nums[i] != i + 1) { return i + 1; } } return nums.length + 1; } /** * https://leetcode.com/problems/first-missing-positive/discuss/17083/O(1)-space-Java-Solution */ public int firstMissingPositive3(int[] A) { int i = 0; while(i < A.length){ if(A[i] == i+1 || A[i] <= 0 || A[i] > A.length) i++; else if (A[A[i]-1] != A[i]) swap(A, i, A[i]-1); else i++; } i = 0; while(i < A.length && A[i] == i+1) i++; return i+1; } private void swap(int[] A, int i, int j){ int temp = A[i]; A[i] = A[j]; A[j] = temp; } public int firstMissingPositive4(int[] nums) { if (nums == null || nums.length == 0) return 1; int N = nums.length; for (int i=0; i= 0 && idx < N && val > 0 && val <= N && nums[idx] != idx + 1) { int newVal = nums[val - 1]; nums[val - 1] = val; idx = newVal - 1; val = newVal; } } for (int i=0; i 1) slow++; if (slow >= len) return -1; // no unique character exist if (count[cc[slow]]==0) { // not yet visited by the fast pointer count[cc[slow]]++; fast=slow; // reset the fast pointer } fast++; } return slow; } /** * https://leetcode.com/problems/first-unique-character-in-a-string/discuss/86359/my-4-lines-Java-solution */ public static int firstUniqChar4(String s) { char[] a = s.toCharArray(); for(int i=0; i 1) slow++; if (fast == N) break; map[chars[fast]-'a']++; fast++; } return slow == N ? -1 : slow; } public int firstUniqChar6(String s) { int[] map = new int[26]; char[] chars = s.toCharArray(); int slow = 0; int fast = 0; int N = chars.length; while (slow < N) { map[chars[fast]-'a']++; fast++; while (slow < fast && map[chars[slow]-'a'] > 1) slow++; if (fast == N) break; } return slow == N ? -1 : slow; } } ================================================ FILE: src/FizzBuzz412.java ================================================ /** * Write a program that outputs the string representation of numbers from 1 to n. * * But for multiples of three it should output “Fizz” instead of the number and * for the multiples of five output “Buzz”. For numbers which are multiples of * both three and five output “FizzBuzz”. * * Example: n = 15, * Return: * [ * "1", * "2", * "Fizz", * "4", * "Buzz", * "Fizz", * "7", * "8", * "Fizz", * "Buzz", * "11", * "Fizz", * "13", * "14", * "FizzBuzz" * ] */ public class FizzBuzz412 { public List fizzBuzz(int n) { List res = new ArrayList<>(); for (int i=1; i<=n; i++) { boolean isFizz = i % 3 == 0; boolean isBuzz = i % 5 == 0; if (isFizz && isBuzz) { res.add("FizzBuzz"); } else if (isFizz) { res.add("Fizz"); } else if (isBuzz) { res.add("Buzz"); } else { res.add(Integer.toString(i)); } } return res; } } ================================================ FILE: src/Flatten2DVector251.java ================================================ /** * Implement an iterator to flatten a 2d vector. * * Example: * * Input: 2d vector = * [ * [1,2], * [3], * [4,5,6] * ] * Output: [1,2,3,4,5,6] * Explanation: By calling next repeatedly until hasNext returns false, * the order of elements returned by next should be: [1,2,3,4,5,6]. * * Follow up: * As an added challenge, try to code it using only iterators in C++ or * iterators in Java. */ public class Flatten2DVector251 { class Vector2D implements Iterator { private Iterator> iter2d; private Iterator iter; public Vector2D(List> vec2d) { iter2d = vec2d.iterator(); if (iter2d.hasNext()) { iter = iter2d.next().iterator(); } else { iter = (new ArrayList()).iterator(); } } @Override public Integer next() { hasNext(); return iter.next(); } @Override public boolean hasNext() { while (!iter.hasNext()) { if (!iter2d.hasNext()) return false; iter = iter2d.next().iterator(); } return iter.hasNext(); } } /** * Your Vector2D object will be instantiated and called as such: * Vector2D i = new Vector2D(vec2d); * while (i.hasNext()) v[f()] = i.next(); */ } ================================================ FILE: src/FlattenBinaryTreeToLinkedList114.java ================================================ /** * Given a binary tree, flatten it to a linked list in-place. * * For example, * Given * 1 * / \ * 2 5 * / \ \ * 3 4 6 * * The flattened tree should look like: * 1 * \ * 2 * \ * 3 * \ * 4 * \ * 5 * \ * 6 */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class FlattenBinaryTreeToLinkedList114 { public void flatten(TreeNode root) { flattenNode(root); } private TreeNode flattenNode(TreeNode root) { if (root == null) return null; TreeNode left = root.left; TreeNode right = root.right; root.left = null; if (left == null && right == null) { return root; } else if (left == null && right != null) { TreeNode rightEnd = flattenNode(right); return rightEnd; } else if (left != null && right == null) { TreeNode leftEnd = flattenNode(left); root.right = left; return leftEnd; } else { TreeNode leftEnd = flattenNode(left); TreeNode rightEnd = flattenNode(right); leftEnd.right = right; root.right = left; return rightEnd; } } public void flatten2(TreeNode root) { helper(root); } private TreeNode helper(TreeNode root) { if (root == null || (root.left == null && root.right == null)) return root; TreeNode leftLast = helper(root.left); if (leftLast != null) { leftLast.right = root.right; root.right = root.left; root.left = null; } return helper(root.right); } /** * https://leetcode.com/problems/flatten-binary-tree-to-linked-list/discuss/37010/Share-my-simple-NON-recursive-solution-O(1)-space-complexity! */ public void flatten3(TreeNode root) { TreeNode cur = root; while (cur != null) { if (cur.left != null) { TreeNode last = cur.left; while (last.right != null) last = last.right; last.right = cur.right; cur.right = cur.left; cur.left = null; } cur = cur.right; } } /** * https://leetcode.com/problems/flatten-binary-tree-to-linked-list/discuss/36977/My-short-post-order-traversal-Java-solution-for-share */ public void flatten4(TreeNode root) { flatten(root,null); } private TreeNode flatten(TreeNode root, TreeNode pre) { if(root==null) return pre; pre=flatten(root.right,pre); pre=flatten(root.left,pre); root.right=pre; root.left=null; pre=root; return pre; } public static void main(String[] args) { FlattenBinaryTreeToLinkedList114 fbt2ll = new FlattenBinaryTreeToLinkedList114(); TreeNode n1 = new TreeNode(1); TreeNode n2 = new TreeNode(2); TreeNode n3 = new TreeNode(3); TreeNode n4 = new TreeNode(4); TreeNode n5 = new TreeNode(5); TreeNode n6 = new TreeNode(6); n1.left = n2; n1.right = n5; n2.left = n3; n2.right = n4; n5.right = n6; fbt2ll.flatten(n1); System.out.println("Out!"); System.out.println(n1.val); System.out.println(n1.right.val); System.out.println(n1.right.right.val); System.out.println(n1.right.right.right.val); System.out.println(n1.right.right.right.right.val); System.out.println(n1.right.right.right.right.right.val); } } ================================================ FILE: src/FlipGame293.java ================================================ /** * You are playing the following Flip Game with your friend: Given a string * that contains only these two characters: + and -, you and your friend take * turns to flip two consecutive "++" into "--". The game ends when a person * can no longer make a move and therefore the other person will be the winner. * * Write a function to compute all possible states of the string after one * valid move. * * Example: * Input: s = "++++" * Output: * [ * "--++", * "+--+", * "++--" * ] * Note: If there is no valid move, return an empty list []. */ public class FlipGame293 { public List generatePossibleNextMoves(String s) { List res = new ArrayList<>(); if (s == null || s.length() <= 1) return res; char[] chars = s.toCharArray(); for (int i=0; i> fourSum(int[] nums, int target) { Arrays.sort(nums); List> res = new ArrayList<>(); for (int i=0; i expected) { hi--; } else { lo++; } } } } } } return res; } /** * https://leetcode.com/problems/4sum/discuss/8575/Clean-accepted-java-O(n3)-solution-based-on-3sum */ public List> fourSum2(int[] num, int target) { ArrayList> ans = new ArrayList<>(); if(num.length<4)return ans; Arrays.sort(num); for(int i=0; itarget)break; //first candidate too large, search finished if(num[i]+num[num.length-1]+num[num.length-2]+num[num.length-3]0&&num[i]==num[i-1])continue; //prevents duplicate result in ans list for(int j=i+1; jtarget)break; //second candidate too large if(num[i]+num[j]+num[num.length-1]+num[num.length-2]i+1&&num[j]==num[j-1])continue; //prevents duplicate results in ans list int low=j+1, high=num.length-1; while(low> fourSum3(int[] nums, int target) { len = nums.length; Arrays.sort(nums); return kSum(nums, target, 4, 0); } private ArrayList> kSum(int[] nums, int target, int k, int index) { ArrayList> res = new ArrayList>(); if(index >= len) { return res; } if(k == 2) { int i = index, j = len - 1; while(i < j) { //find a pair if(target - nums[i] == nums[j]) { List temp = new ArrayList<>(); temp.add(nums[i]); temp.add(target-nums[i]); res.add(temp); //skip duplication while(i nums[j]) { i++; //move right bound } else { j--; } } } else{ for (int i = index; i < len - k + 1; i++) { //use current number to reduce ksum into k-1sum ArrayList> temp = kSum(nums, target - nums[i], k-1, i+1); if(temp != null){ //add previous results for (List t : temp) { t.add(0, nums[i]); } res.addAll(temp); } while (i < len-1 && nums[i] == nums[i+1]) { //skip duplicated numbers i++; } } } return res; } } ================================================ FILE: src/FourSumII454.java ================================================ /** * Given four lists A, B, C, D of integer values, compute how many tuples * (i, j, k, l) there are such that A[i] + B[j] + C[k] + D[l] is zero. * * To make problem a bit easier, all A, B, C, D have same length of N where * 0 ≤ N ≤ 500. All integers are in the range of -228 to 228 - 1 and the result * is guaranteed to be at most 231 - 1. * * Example: * Input: * A = [ 1, 2] * B = [-2,-1] * C = [-1, 2] * D = [ 0, 2] * * Output: 2 * * Explanation: * The two tuples are: * 1. (0, 0, 0, 1) -> A[0] + B[0] + C[0] + D[1] = 1 + (-2) + (-1) + 2 = 0 * 2. (1, 1, 0, 0) -> A[1] + B[1] + C[0] + D[0] = 2 + (-1) + (-1) + 0 = 0 */ public class FourSumII454 { public int fourSumCount(int[] A, int[] B, int[] C, int[] D) { if (invalid(A) || invalid(B) || invalid(C) || invalid(D)) return 0; int N = A.length; HashMap map = new HashMap<>(); for (int i=0; i map = new HashMap<>(); for (int i=0; i= 0 && denominator >= 0) || (numerator < 0 && denominator < 0); long nume = Math.abs((long)numerator); long deno = Math.abs((long)denominator); Long ones = nume / deno; List decimals = new ArrayList<>(); long left = nume % deno; Map map = new HashMap<>(); left *= 10; int pos = 0; int repeat = -1; while (true) { if (left == 0) break; if (map.containsKey(left)) { repeat = map.get(left); break; } long newOne = Math.abs(left / deno); long newLeft = left % deno; decimals.add(newOne); map.put(left, pos); left = newLeft*10; pos++; } String pre = (sameSign || ones <= 0L) ? ones.toString() : ("-" + ones.toString()); if (decimals.size() == 0) return pre; StringBuilder sb = new StringBuilder(); for (int i=0; i map = new HashMap<>(); while (remainder != 0) { if (map.containsKey(remainder)) { fraction.insert(map.get(remainder), "("); fraction.append(")"); break; } map.put(remainder, fraction.length()); remainder *= 10; fraction.append(remainder / denom); remainder = remainder % denom; } return fraction.toString(); } } ================================================ FILE: src/FriendCircles547.java ================================================ /** * There are N students in a class. Some of them are friends, while some are not. * Their friendship is transitive in nature. For example, if A is a direct * friend of B, and B is a direct friend of C, then A is an indirect friend of C. * And we defined a friend circle is a group of students who are direct or * indirect friends. * * Given a N*N matrix M representing the friend relationship between students * in the class. If M[i][j] = 1, then the ith and jth students are direct friends * with each other, otherwise not. And you have to output the total number of * friend circles among all the students. * * Example 1: * Input: * [[1,1,0], * [1,1,0], * [0,0,1]] * * Output: 2 * Explanation:The 0th and 1st students are direct friends, so they are in a * friend circle. * The 2nd student himself is in a friend circle. So return 2. * Example 2: * Input: * [[1,1,0], * [1,1,1], * [0,1,1]] * * Output: 1 * Explanation:The 0th and 1st students are direct friends, the 1st and 2nd * students are direct friends, so the 0th and 2nd students are indirect * friends. All of them are in the same friend circle, so return 1. * * Note: * N is in range [1,200]. * M[i][i] = 1 for all students. * If M[i][j] = 1, then M[j][i] = 1. */ public class FriendCircles547 { public int findCircleNum(int[][] M) { boolean[] visited = new boolean[M.length]; int res = 0; for (int i=0; i=M.length) { return; } visited[i] = true; for (int j=0; j> map = new HashMap<>(); for (int s: stones) { map.put(s, new HashSet<>()); } map.get(0).add(1); int N = stones.length; int last = stones[N-1]; for (int i=0; i jumps = map.get(curr); for (int j: jumps) { int next = curr + j; if (next == last) return true; Set after = map.get(next); if (after != null) { if (j-1>0) after.add(j-1); after.add(j); after.add(j+1); } } } return !map.get(last).isEmpty(); } } ================================================ FILE: src/GameOfLife289.java ================================================ /** * According to the Wikipedia's article: "The Game of Life, also known simply * as Life, is a cellular automaton devised by the British mathematician * John Horton Conway in 1970." * * Given a board with m by n cells, each cell has an initial state live (1) or * dead (0). Each cell interacts with its eight neighbors (horizontal, vertical, * diagonal) using the following four rules (taken from the above Wikipedia * article): * * Any live cell with fewer than two live neighbors dies, as if caused by under-population. * Any live cell with two or three live neighbors lives on to the next generation. * Any live cell with more than three live neighbors dies, as if by over-population.. * Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction. * * Write a function to compute the next state (after one update) of the board given its current state. * * Follow up: * Could you solve it in-place? Remember that the board needs to be updated at * the same time: You cannot update some cells first and then use their updated * values to update other cells. * * In this question, we represent the board using a 2D array. In principle, the * board is infinite, which would cause problems when the active area encroaches * the border of the array. How would you address these problems? */ public class GameOfLife289 { public void gameOfLife(int[][] board) { if (board == null || board.length == 0 || board[0].length == 0) return; int n = board.length; int m = board[0].length; int[][] newBoard = new int[n][m]; for (int i=0; i= n) continue; for (int j=y-1; j<=y+1; j++) { if (j < 0 || j >= m || (i == x && j == y)) continue; if (board[i][j] == 1) res++; } } return res; } /** * https://leetcode.com/problems/game-of-life/discuss/73223/Easiest-JAVA-solution-with-explanation */ public void gameOfLife2(int[][] board) { if (board == null || board.length == 0) return; int m = board.length, n = board[0].length; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { int lives = liveNeighbors(board, m, n, i, j); // In the beginning, every 2nd bit is 0; // So we only need to care about when will the 2nd bit become 1. if (board[i][j] == 1 && lives >= 2 && lives <= 3) { board[i][j] = 3; // Make the 2nd bit 1: 01 ---> 11 } if (board[i][j] == 0 && lives == 3) { board[i][j] = 2; // Make the 2nd bit 1: 00 ---> 10 } } } for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { board[i][j] >>= 1; // Get the 2nd state. } } } public int liveNeighbors(int[][] board, int m, int n, int i, int j) { int lives = 0; for (int x = Math.max(i - 1, 0); x <= Math.min(i + 1, m - 1); x++) { for (int y = Math.max(j - 1, 0); y <= Math.min(j + 1, n - 1); y++) { lives += board[x][y] & 1; } } lives -= board[i][j] & 1; return lives; } public void gameOfLife3(int[][] board) { int M = board.length; int N = board[0].length; for (int i=0; i= M) continue; for (int y=j-1; y<=j+1; y++) { if (y < 0 || y >= N || (x == i && y == j)) continue; if ((board[x][y] & 1) == 1) lives++; } } boolean wasLive = (board[i][j] & 1) == 1; if (wasLive) { if (lives == 2 || lives == 3) { board[i][j] |= 1 << 1; } } else { if (lives == 3) { board[i][j] |= 1 << 1; } } } private void refresh(int[][] board, int i, int j) { board[i][j] = board[i][j] >> 1; } } ================================================ FILE: src/GeneralizedAbbreviation320.java ================================================ /** * Write a function to generate the generalized abbreviations of a word. * * Note: The order of the output does not matter. * * Example: * Input: "word" * Output: * ["word", "1ord", "w1rd", "wo1d", "wor1", "2rd", "w2d", "wo2", "1o1d", * "1or1", "w1r1", "1o2", "2r1", "3d", "w3", "4"] */ public class GeneralizedAbbreviation320 { public List generateAbbreviations(String word) { List res = new ArrayList<>(); int N = word.length(); backtrace(word.toCharArray(), res, true, 0, new StringBuilder()); return res; } private void backtrace(char[] word, List res, boolean prevIsWord, int i, StringBuilder sb) { if (word.length == i) { res.add(sb.toString()); return; } sb.append(word[i]); backtrace(word, res, true, i+1, sb); sb.deleteCharAt(sb.length() - 1); if (prevIsWord) { for (int j=i; j generateAbbreviations2(String word) { List ans = new ArrayList<>(); for (int x = 0; x < (1 << word.length()); ++x) // loop through all possible x ans.add(abbr(word, x)); return ans; } // build the abbreviation for word from number x private String abbr(String word, int x) { StringBuilder builder = new StringBuilder(); int k = 0, n = word.length(); // k is the count of consecutive ones in x for (int i = 0; i < n; ++i, x >>= 1) { if ((x & 1) == 0) { // bit is zero, we keep word.charAt(i) if (k != 0) { // we have abbreviated k characters builder.append(k); k = 0; // reset the counter k } builder.append(word.charAt(i)); } else // bit is one, increase k ++k; } if (k != 0) builder.append(k); //don't forget to append the last k if non zero return builder.toString(); } } ================================================ FILE: src/GenerateParentheses22.java ================================================ /** * Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses. * For example, given n = 3, a solution set is: * [ * "((()))", * "(()())", * "(())()", * "()(())", * "()()()" * ] */ import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; public class GenerateParentheses22 { public List generateParenthesis(int n) { if (n <= 0) { return new ArrayList(); } else if (n == 1) { List temp = new ArrayList(); temp.add("()"); return temp; } else { return addOnePair(generateParenthesis(n-1), n); } } private List addOnePair(List source, Integer n) { Set returned = new HashSet(); for (String prev: source) { for (int i=0; i generateParenthesis2(int n) { List list = new ArrayList(); backtrack(list, "", 0, 0, n); return list; } private void backtrack(List list, String str, int open, int close, int max){ if(str.length() == max*2){ list.add(str); return; } if(open < max) backtrack(list, str+"(", open+1, close, max); if(close < open) backtrack(list, str+")", open, close+1, max); } /** ------------------------------------------------------------------- * Top Solution (same idea above, but more efficient): * https://discuss.leetcode.com/topic/8724/easy-to-understand-java-backtracking-solution * -------------------------------------------------------------------- */ public List generateParenthesis3(int n) { List res = new ArrayList<>(); helper(res, new StringBuilder(), 0, 0, n); return res; } private void helper(List res, StringBuilder sb, int open, int close, int n) { if(open == n && close == n) { res.add(sb.toString()); return; } if(open < n) { sb.append("("); helper(res, sb, open+1, close, n); sb.setLength(sb.length()-1); } if(close < open) { sb.append(")"); helper(res, sb, open, close+1, n); sb.setLength(sb.length()-1); } } public static void main(String[] args) { GenerateParentheses22 gp = new GenerateParentheses22(); System.out.println(gp.generateParenthesis(3)); System.out.println(gp.generateParenthesis2(3)); System.out.println(gp.generateParenthesis3(3)); } } ================================================ FILE: src/GraphValidTree261.java ================================================ /** * Given n nodes labeled from 0 to n-1 and a list of undirected edges (each * edge is a pair of nodes), write a function to check whether these edges make * up a valid tree. * * Example 1: * Input: n = 5, and edges = [[0,1], [0,2], [0,3], [1,4]] * Output: true * * Example 2: * Input: n = 5, and edges = [[0,1], [1,2], [2,3], [1,3], [1,4]] * Output: false * Note: you can assume that no duplicate edges will appear in edges. Since all * edges are undirected, [0,1] is the same as [1,0] and thus will not appear * together in edges. */ public class GraphValidTree261 { // 1. construct Graph // 2. detection cycle -- DFS // 3. check not more than one tree public boolean validTree(int n, int[][] edges) { if (n == 0) return false; if (n == 1) return true; Map> graph = constructGraph(n, edges); boolean[] visited = new boolean[n]; // if cycle detected, return false if (!isValid(graph, visited, 0, -1)) return false; for (int i=0; i> graph, boolean[] visited, int curr, int parent) { if (visited[curr]) { return false; } visited[curr] = true; if (!graph.containsKey(curr)) return true; for (int i: graph.get(curr)) { if (i != parent && !isValid(graph, visited, i, curr)) return false; } return true; } private Map> constructGraph(int n, int[][] edges) { Map> graph = new HashMap<>(); for (int i=0; i()); } for (int[] edge: edges) { graph.get(edge[0]).add(edge[1]); graph.get(edge[1]).add(edge[0]); } return graph; } public boolean validTree2(int n, int[][] edges) { DisjointSet djs = new DisjointSet(n); for (int[] edge: edges) { int x = djs.find(edge[0]); int y = djs.find(edge[1]); if (x == y) return false; djs.union(x, y); } int root = djs.find(0); for (int i=1; i rank[yy]) { parent[yy] = xx; } else if (rank[xx] < rank[yy]) { parent[xx] = yy; } else { parent[xx] = yy; rank[yy]++; } } } /** * https://leetcode.com/problems/graph-valid-tree/discuss/69018/AC-Java-Union-Find-solution */ public boolean validTree3(int n, int[][] edges) { // initialize n isolated islands int[] nums = new int[n]; Arrays.fill(nums, -1); // perform union find for (int i = 0; i < edges.length; i++) { int x = find(nums, edges[i][0]); int y = find(nums, edges[i][1]); // if two vertices happen to be in the same set // then there's a cycle if (x == y) return false; // union nums[x] = y; } return edges.length == n - 1; } int find(int nums[], int i) { if (nums[i] == -1) return i; return find(nums, nums[i]); } } ================================================ FILE: src/GroupAnagrams49.java ================================================ /** * Given an array of strings, group anagrams together. * * For example, given: ["eat", "tea", "tan", "ate", "nat", "bat"], * Return: * [ * ["ate", "eat","tea"], * ["nat","tan"], * ["bat"] * ] * * Note: All inputs will be in lower-case. */ public class GroupAnagrams49 { public List> groupAnagrams(String[] strs) { Map> map = new HashMap<>(); for (String s: strs) { String mapKey = getSortedString(s); List newList = (List) map.getOrDefault(mapKey, new ArrayList()); newList.add(s); map.put(mapKey, newList); } return new ArrayList>(map.values()); } private String getSortedString(String s) { char[] chars = s.toCharArray(); Arrays.sort(chars); return String.valueOf(chars); } /** * https://discuss.leetcode.com/topic/45639/java-beat-100-use-prime-number */ public static List> groupAnagrams2(String[] strs) { int[] prime = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103}; //最多10609个z List> res = new ArrayList<>(); HashMap map = new HashMap<>(); for (String s : strs) { int key = 1; for (char c : s.toCharArray()) { key *= prime[c - 'a']; } List t; if (map.containsKey(key)) { t = res.get(map.get(key)); } else { t = new ArrayList<>(); res.add(t); map.put(key, res.size() - 1); } t.add(s); } return res; } } ================================================ FILE: src/GroupShiftedStrings249.java ================================================ /** * Given a string, we can "shift" each of its letter to its successive letter, * for example: "abc" -> "bcd". We can keep "shifting" which forms the sequence: * * "abc" -> "bcd" -> ... -> "xyz" * Given a list of strings which contains only lowercase alphabets, group all * strings that belong to the same shifting sequence. * * Example: * * Input: ["abc", "bcd", "acef", "xyz", "az", "ba", "a", "z"], * Output: * [ * ["abc","bcd","xyz"], * ["az","ba"], * ["acef"], * ["a","z"] * ] */ public class GroupShiftedStrings249 { public List> groupStrings(String[] strings) { Map> map = new HashMap<>(); for (String s: strings) { boolean found = false; for (String k: map.keySet()) { if (s.length() != k.length()) continue; boolean b = true; int diff = getDiff(s.charAt(0), k.charAt(0)); for (int i=1; i tmp = new ArrayList<>(); tmp.add(s); map.put(s, tmp); } } return new ArrayList>(map.values()); } private int getDiff(char c1, char c2) { int init = c1 - c2; while (init < 0) { init += 26; } return init; } /** * https://leetcode.com/problems/group-shifted-strings/discuss/127090/Short-Java-solution */ public List> groupStrings2(String[] strings) { Map> groups = new HashMap>(); for (String s : strings) { int shift = 'z' - s.charAt(0); StringBuilder sb = new StringBuilder(); for (int i = 0; i < s.length(); i++) { sb.append((s.charAt(i) + shift) % 26); } if (!groups.containsKey(sb.toString())) { groups.put(sb.toString(), new ArrayList()); } groups.get(sb.toString()).add(s); } return new ArrayList>(groups.values()); } } ================================================ FILE: src/GuessNumberHigherOrLowerII375.java ================================================ /** * We are playing the Guess Game. The game is as follows: * * I pick a number from 1 to n. You have to guess which number I picked. * * Every time you guess wrong, I'll tell you whether the number I picked is * higher or lower. * * However, when you guess a particular number x, and you guess wrong, you * pay $x. You win the game when you guess the number I picked. * * Example: * n = 10, I pick 8. * First round: You guess 5, I tell you that it's higher. You pay $5. * Second round: You guess 7, I tell you that it's higher. You pay $7. * Third round: You guess 9, I tell you that it's lower. You pay $9. * * Game over. 8 is the number I picked. * You end up paying $5 + $7 + $9 = $21. * * Given a particular n ≥ 1, find out how much money you need to have to * guarantee a win. */ public class GuessNumberHigherOrLowerII375 { // // LTE // public int getMoneyAmount(int n) { // return getMoneyAmount(1, n); // } // public int getMoneyAmount(int l, int r) { // if (l >= r) return 0; // if (l + 1 == r) return l; // if (l + 2 == r) return l + 1; // int res = Integer.MAX_VALUE; // for (int i=l; i<=r; i++) { // int left = getMoneyAmount(l, i-1); // int right = getMoneyAmount(i+1, r); // res = Math.min(res, Math.max(left, right) + i); // } // return res; // } public int getMoneyAmount(int n) { return getMoneyAmount(1, n, new int[n][n]); } public int getMoneyAmount(int l, int r, int[][] memo) { if (l >= r) return 0; if (memo[l-1][r-1] != 0) return memo[l-1][r-1]; int res = Integer.MAX_VALUE; for (int i=l; i<=r; i++) { int left = getMoneyAmount(l, i-1, memo); int right = getMoneyAmount(i+1, r, memo); res = Math.min(res, Math.max(left, right) + i); } memo[l-1][r-1] = res; return res; } public int getMoneyAmount2(int n) { int[][] dp = new int[n+1][n+1]; for (int l=1; l<=n; l++) { for (int i=1; i<=n-l; i++) { int j = i+l; int tmp = Integer.MAX_VALUE; for (int k=i; k<=j; k++) { int left = i <= k-1 ? dp[i][k-1] : 0; int right = k+1 <= j ? dp[k+1][j] : 0; tmp = Math.min(tmp, Math.max(left, right) + k); } dp[i][j] = tmp; } } return dp[1][n]; } public int getMoneyAmount3(int n) { int[][] dp = new int[n+1][n+1]; for (int l=1; l<=n; l++) { for (int i=1; i<=n-l; i++) { int j = i+l; int tmp = Integer.MAX_VALUE; for (int k=i+(l-1)/2; k<=j; k++) { int left = i <= k-1 ? dp[i][k-1] : 0; int right = k+1 <= j ? dp[k+1][j] : 0; tmp = Math.min(tmp, Math.max(left, right) + k); } dp[i][j] = tmp; } } return dp[1][n]; } } ================================================ FILE: src/GuessTheWord843.java ================================================ /** * This problem is an interactive problem new to the LeetCode platform. * * We are given a word list of unique words, each word is 6 letters long, and * one word in this list is chosen as secret. * * You may call master.guess(word) to guess a word. The guessed word should * have type string and must be from the original list with 6 lowercase letters. * * This function returns an integer type, representing the number of exact * matches (value and position) of your guess to the secret word. Also, if * your guess is not in the given wordlist, it will return -1 instead. * * For each test case, you have 10 guesses to guess the word. At the end of * any number of calls, if you have made 10 or less calls to master.guess and * at least one of these guesses was the secret, you pass the testcase. * * Besides the example test case below, there will be 5 additional test cases, * each with 100 words in the word list. The letters of each word in those * testcases were chosen independently at random from 'a' to 'z', such that * every word in the given word lists is unique. * * Example 1: * Input: secret = "acckzz", wordlist = ["acckzz","ccbazz","eiowzz","abcczz"] * * Explanation: * master.guess("aaaaaa") returns -1, because "aaaaaa" is not in wordlist. * master.guess("acckzz") returns 6, because "acckzz" is secret and has all 6 matches. * master.guess("ccbazz") returns 3, because "ccbazz" has 3 matches. * master.guess("eiowzz") returns 2, because "eiowzz" has 2 matches. * master.guess("abcczz") returns 4, because "abcczz" has 4 matches. * * We made 5 calls to master.guess and one of them was the secret, so we pass * the test case. * Note: Any solutions that attempt to circumvent the judge will result in * disqualification. */ /** * // This is the Master's API interface. * // You should not implement it, or speculate about its implementation * interface Master { * public int guess(String word) {} * } */ public class GuessTheWord843 { /** * https://leetcode.com/problems/guess-the-word/discuss/133862/Random-Guess-and-Minimax-Guess-with-Comparison */ public void findSecretWord(String[] wordlist, Master master) { for (int i = 0, x = 0; i < 10 && x < 6; ++i) { String guess = wordlist[new Random().nextInt(wordlist.length)]; x = master.guess(guess); List wordlist2 = new ArrayList<>(); for (String w : wordlist) if (match(guess, w) == x) wordlist2.add(w); wordlist = wordlist2.toArray(new String[wordlist2.size()]); } } public int match(String a, String b) { int matches = 0; for (int i = 0; i < a.length(); ++i) if (a.charAt(i) == b.charAt(i)) matches ++; return matches; } /** * https://leetcode.com/problems/guess-the-word/discuss/133862/Random-Guess-and-Minimax-Guess-with-Comparison */ public void findSecretWord2(String[] wordlist, Master master) { for (int i = 0, x = 0; i < 10 && x < 6; ++i) { HashMap count = new HashMap<>(); for (String w1 : wordlist) for (String w2 : wordlist) if (match(w1, w2) == 0) count.put(w1, count.getOrDefault(w1 , 0) + 1); Pair minimax = new Pair("", 1000); for (String w : wordlist) if (count.getOrDefault(w, 0) < minimax.i) minimax = new Pair(w, count.getOrDefault(w, 0)); x = master.guess(minimax.s); List wordlist2 = new ArrayList(); for (String w : wordlist) if (match(minimax.s, w) == x) wordlist2.add(w); wordlist = wordlist2.toArray(new String[0]); } } class Pair { String s; Integer i; Pair (String s, Integer i) { this.s = s; this.i = i; } } } ================================================ FILE: src/HIndex274.java ================================================ /** * Given an array of citations (each citation is a non-negative integer) of a * researcher, write a function to compute the researcher's h-index. * * According to the definition of h-index on Wikipedia: "A scientist has * index h if h of his/her N papers have at least h citations each, and the * other N − h papers have no more than h citations each." * * For example, given citations = [3, 0, 6, 1, 5], which means the researcher * has 5 papers in total and each of them had received 3, 0, 6, 1, 5 citations * respectively. Since the researcher has 3 papers with at least 3 citations * each and the remaining two with no more than 3 citations each, his h-index is 3. * * Note: If there are several possible values for h, the maximum one is taken * as the h-index. */ public class HIndex274 { public int hIndex(int[] citations) { int hIndex = 0; int L = citations.length; for (int i=0; i now) ? 1:0; same += (citations[j] == now) ? 1:0; } for (int h = high+same; h >= high; h--) { if (now >= h) { hIndex = Math.max(hIndex, h); break; } } } return hIndex; } public int hIndex2(int[] citations) { int L = citations.length; for (int i=L; i>=0; i--) { int high = 0; int low = 0; for (int j=0; j i) ? 1:0; low += (citations[j] < i) ? 1:0; } if (i >= high && i <= L-low) return i; } return 0; } public int hIndex3(int[] citations) { final int L = citations.length; List less = new ArrayList<>(); int i = L; int more = 0; for (int j=0; j i) { more++; } } if (i >= more && i <= L-less.size()) return L; for (i=L-1; i>=0; i--) { int S = less.size(); more = L-S; List newLess = new ArrayList<>(); for (int j=0; j i) { more++; } } less = newLess; if (i >= more && i <= L-less.size()) return i; } return 0; } /** * https://discuss.leetcode.com/topic/23307/my-o-n-time-solution-use-java */ public int hIndex4(int[] citations) { int length = citations.length; if (length == 0) { return 0; } int[] array2 = new int[length + 1]; for (int i = 0; i < length; i++) { if (citations[i] > length) { array2[length] += 1; } else { array2[citations[i]] += 1; } } int t = 0; int result = 0; for (int i = length; i >= 0; i--) { t = t + array2[i]; if (t >= i) { return i; } } return 0; } /** * https://discuss.leetcode.com/topic/23310/my-easy-solution */ public int hIndex5(int[] citations) { Arrays.sort(citations); int len=citations.length; for(int i=0;i=len-i) return len-i; } return 0; } /** * https://leetcode.com/problems/h-index/solution/ */ public int hIndex6(int[] citations) { int n = citations.length; int[] papers = new int[n + 1]; // counting papers for each citation number for (int c: citations) papers[Math.min(n, c)]++; // finding the h-index int k = n; for (int s = papers[n]; k > s; s += papers[k]) k--; return k; } public int hIndex7(int[] citations) { if (citations == null || citations.length == 0) return 0; Arrays.sort(citations); if (citations[citations.length-1] == 0) return 0; int i = 1; while (i < citations.length) { if (citations[citations.length-i] >= i && citations[citations.length-i-1] <= i) { return i; } i++; } return citations.length; } } ================================================ FILE: src/HandOfStraights846.java ================================================ /** * Alice has a hand of cards, given as an array of integers. * * Now she wants to rearrange the cards into groups so that each group is * size W, and consists of W consecutive cards. * * Return true if and only if she can. * * Example 1: * Input: hand = [1,2,3,6,2,3,4,7,8], W = 3 * Output: true * Explanation: Alice's hand can be rearranged as [1,2,3],[2,3,4],[6,7,8]. * * Example 2: * Input: hand = [1,2,3,4,5], W = 4 * Output: false * Explanation: Alice's hand can't be rearranged into groups of 4. * * Note: * 1 <= hand.length <= 10000 * 0 <= hand[i] <= 10^9 * 1 <= W <= hand.length */ public class HandOfStraights846 { public boolean isNStraightHand(int[] hand, int W) { if (hand == null) return false; if (hand.length == 0 && W == 0) return true; if (hand.length == 0 || W == 0 || hand.length % W != 0) return false; PriorityQueue pq = new PriorityQueue<>(); for (int card: hand) { pq.add(card); } while (!pq.isEmpty()) { int first = pq.peek(); for (int i = 0; i count = new TreeMap(); for (int card: hand) { if (!count.containsKey(card)) count.put(card, 1); else count.replace(card, count.get(card) + 1); } while (count.size() > 0) { int first = count.firstKey(); for (int card = first; card < first + W; ++card) { if (!count.containsKey(card)) return false; int c = count.get(card); if (c == 1) count.remove(card); else count.replace(card, c - 1); } } return true; } /** * https://leetcode.com/problems/hand-of-straights/discuss/153519/copy-from-the-quickest-java-solutions-with-explanation(10-ms-Beats-100) */ public boolean isNStraightHand3(int[] hands, int W) { if (W == 1) return true; if (hands.length % W != 0) return false; int H = hands.length / W; int[][] buckets = new int[W][H]; int[] bucketSize = new int[W]; for (int h : hands) { int indexInBucket = h % W, bucketId = bucketSize[indexInBucket]++; if (bucketId >= H) return false; buckets[indexInBucket][bucketId] = h; } for (int i = 0; i < W; i++) Arrays.sort(buckets[i]); for (int i = 0; i < H; i++) for (int j = 1; j < W; j++) //consider case 3,1,2 and 3,4,2 if (buckets[j][i] != buckets[j - 1][i] + 1 && buckets[j - 1][i] - buckets[j][i] != W - 1) return false; return true; } } ================================================ FILE: src/HappyNumber202.java ================================================ /** * Write an algorithm to determine if a number is "happy". * * A happy number is a number defined by the following process: Starting with * any positive integer, replace the number by the sum of the squares of its * digits, and repeat the process until the number equals 1 (where it will * stay), or it loops endlessly in a cycle which does not include 1. Those * numbers for which this process ends in 1 are happy numbers. * * Example: * * Input: 19 * Output: true * Explanation: * 12 + 92 = 82 * 82 + 22 = 68 * 62 + 82 = 100 * 12 + 02 + 02 = 1 */ public class HappyNumber202 { public boolean isHappy(int n) { if (n <= 0) return false; Set set = new HashSet<>(); set.add(n); while (true) { int next = next(n); if (next == 1) return true; if (set.contains(next)) return false; set.add(n); n = next; } } private int next(int n) { int res = 0; while (n != 0) { int t = n % 10; res += t * t; n /= 10; } return res; } /** * https://leetcode.com/problems/happy-number/discuss/56917/My-solution-in-C(-O(1)-space-and-no-magic-math-property-involved-) */ public boolean isHappy2(int n) { int slow, fast; slow = fast = n; do { slow = digitSquareSum(slow); fast = digitSquareSum(fast); fast = digitSquareSum(fast); } while(slow != fast); if (slow == 1) return true; else return false; } private int digitSquareSum(int n) { int sum = 0, tmp; while (n != 0) { tmp = n % 10; sum += tmp * tmp; n /= 10; } return sum; } } ================================================ FILE: src/HighestPopulationYear.java ================================================ /** * Given a list of people with their birth and death years, find the year with the highest population. */ import java.util.Arrays; import java.util.HashMap; import java.util.Map; public class HighestPopulationYear { // brute force public static int find(int[][] people) { int minB = Integer.MAX_VALUE; int maxD = Integer.MIN_VALUE; for (int[] bd: people) { if (bd[0] < minB) minB = bd[0]; if (bd[1] > maxD) maxD = bd[1]; } int highest = -1; int year = -1; for (int i = minB; i <= maxD; i++) { int c = 0; for (int[] bd: people) { if (bd[0] <= i && bd[1] >= i) c++; } if (c > highest) { highest = c; year = i; } } return year; } public static int find2(int[][] people) { Map map = new HashMap<>(); int max = Integer.MIN_VALUE; int year = -1; for (int[] p: people) { if (map.containsKey(p[0])) { continue; } else { int c = 0; for (int[] q: people) { if (q[0] <= p[0] && q[1] >= p[0]) c++; } map.put(p[0], c); if (c > max) { max = c; year = p[0]; } } } return year; } public static int find3(int[][] people) { int minB = Integer.MAX_VALUE; int maxB = Integer.MIN_VALUE; for (int[] p: people) { if (p[0] < minB) minB = p[0]; if (p[0] > maxB) maxB = p[0]; } int[] arr = new int[maxB - minB + 1]; for (int[] p: people) { arr[p[0]-minB] += 1; if (p[1] <= maxB) { arr[p[1]-minB] -= 1; } } int year = -1; int max = Integer.MIN_VALUE; for (int i = 0; i < maxB - minB; i++) { if (arr[i] > max) { max = arr[i]; year = i + minB; } } return year; } public static void main(String[] args) { // Arrays.sort(people, (p1, p2) -> Integer.compare(p1[0], p2[0])); int[][] people = { {2000, 2010}, {1975, 2005}, {1975, 2003}, {1803, 1809}, {1750, 1869}, {1890, 1935}, {1803, 1921}, {1894, 1921} }; System.out.println(HighestPopulationYear.find(people)); System.out.println(HighestPopulationYear.find2(people)); System.out.println(HighestPopulationYear.find3(people)); } } ================================================ FILE: src/HouseRobber198.java ================================================ /** * You are a professional robber planning to rob houses along a street. Each * house has a certain amount of money stashed, the only constraint stopping * you from robbing each of them is that adjacent houses have security system * connected and it will automatically contact the police if two adjacent houses * were broken into on the same night. * * Given a list of non-negative integers representing the amount of money of * each house, determine the maximum amount of money you can rob tonight without * alerting the police. * */ public class HouseRobber198 { public int rob(int[] nums) { if (nums.length == 0) { return 0; } if (nums.length == 1) { return nums[0]; } int[] dp = new int[nums.length+1]; dp[0] = 0; dp[1] = nums[0]; for (int i=1; i= 0 && jj >= 0 && ii < lenI && jj < lenJ) { sum += M[ii][jj]; count++; } } newScale[i][j] = sum / count; } } return newScale; } } ================================================ FILE: src/ImplementMagicDictionary676.java ================================================ /** * Implement a magic directory with buildDict, and search methods. * * For the method buildDict, you'll be given a list of non-repetitive words to * build a dictionary. * * For the method search, you'll be given a word, and judge whether if you * modify exactly one character into another character in this word, the * modified word is in the dictionary you just built. * * Example 1: * Input: buildDict(["hello", "leetcode"]), Output: Null * Input: search("hello"), Output: False * Input: search("hhllo"), Output: True * Input: search("hell"), Output: False * Input: search("leetcoded"), Output: False * * Note: * You may assume that all the inputs are consist of lowercase letters a-z. * For contest purpose, the test data is rather small by now. You could think * about highly efficient algorithm after the contest. * Please remember to RESET your class variables declared in class * MagicDictionary, as static/class variables are persisted across multiple * test cases. Please see here for more details. */ public class ImplementMagicDictionary676 { class MagicDictionary { private Trie trie = new Trie(); /** Initialize your data structure here. */ public MagicDictionary() { } /** Build a dictionary through a list of words */ public void buildDict(String[] dict) { for (String word: dict) { trie.add(word); } } /** Returns if there is any word in the trie that equals to the given word after modifying exactly one character */ public boolean search(String word) { return trie.search(word); } class Trie { Trie[] children = new Trie[26]; boolean isWord; void add(String word) { if (word == null || word.length() == 0) return; add(word.toCharArray(), 0); } void add(char[] word, int i) { if (word.length == i) { isWord = true; return; } if (children[word[i]-'a'] == null) { children[word[i]-'a'] = new Trie(); } children[word[i]-'a'].add(word, i+1); } boolean search(String word) { if (word == null) return false; return search(word.toCharArray(), 0, false); } boolean search(char[] word, int start, boolean modified) { if (word.length == start) { return modified && isWord; } for (int i=0; i<26; i++) { if (children[i] == null) continue; if (word[start] == (i + 'a')) { if (children[i].search(word, start+1, modified)) return true; } else { if (modified) continue; if (children[i].search(word, start+1, true)) return true; } } return false; } } } /** * https://leetcode.com/problems/implement-magic-dictionary/solution/ */ class MagicDictionary2 { Map> buckets; public MagicDictionary() { buckets = new HashMap(); } public void buildDict(String[] words) { for (String word: words) { buckets.computeIfAbsent(word.length(), x -> new ArrayList()).add(word); } } public boolean search(String word) { if (!buckets.containsKey(word.length())) return false; for (String candidate: buckets.get(word.length())) { int mismatch = 0; for (int i = 0; i < word.length(); ++i) { if (word.charAt(i) != candidate.charAt(i)) { if (++mismatch > 1) break; } } if (mismatch == 1) return true; } return false; } } /** * https://leetcode.com/problems/implement-magic-dictionary/solution/ */ public class MagicDictionary3 { Set words; Map count; public MagicDictionary() { words = new HashSet(); count = new HashMap(); } private ArrayList generalizedNeighbors(String word) { ArrayList ans = new ArrayList(); char[] ca = word.toCharArray(); for (int i = 0; i < word.length(); ++i) { char letter = ca[i]; ca[i] = '*'; String magic = new String(ca); ans.add(magic); ca[i] = letter; } return ans; } public void buildDict(String[] words) { for (String word: words) { this.words.add(word); for (String nei: generalizedNeighbors(word)) { count.put(nei, count.getOrDefault(nei, 0) + 1); } } } public boolean search(String word) { for (String nei: generalizedNeighbors(word)) { int c = count.getOrDefault(nei, 0); if (c > 1 || c == 1 && !words.contains(word)) return true; } return false; } } /** * Your MagicDictionary object will be instantiated and called as such: * MagicDictionary obj = new MagicDictionary(); * obj.buildDict(dict); * boolean param_2 = obj.search(word); */ } ================================================ FILE: src/ImplementQueueUsingStacks232.java ================================================ /** * Implement the following operations of a queue using stacks. * * push(x) -- Push element x to the back of queue. * pop() -- Removes the element from in front of queue. * peek() -- Get the front element. * empty() -- Return whether the queue is empty. * * Example: * * MyQueue queue = new MyQueue(); * * queue.push(1); * queue.push(2); * queue.peek(); // returns 1 * queue.pop(); // returns 1 * queue.empty(); // returns false * * Notes: * * You must use only standard operations of a stack -- which means only push to * top, peek/pop from top, size, and is empty operations are valid. * Depending on your language, stack may not be supported natively. You may * simulate a stack by using a list or deque (double-ended queue), as long as * you use only standard operations of a stack. * You may assume that all operations are valid (for example, no pop or peek * operations will be called on an empty queue). */ public class ImplementQueueUsingStacks232 { class MyQueue { private Stack st; /** Initialize your data structure here. */ public MyQueue() { this.st = new Stack(); } /** Push element x to the back of queue. */ public void push(int x) { Stack temp = new Stack<>(); int preSize = this.st.size(); for (int i=0; i q1 = new LinkedList<>(); private Queue q2 = new LinkedList<>(); private int top = 0; /** Initialize your data structure here. */ public MyStack() { } /** Push element x onto stack. */ public void push(int x) { if (empty()) { q1.add(x); } else { if (q1.isEmpty()) { q2.add(x); } else { q1.add(x); } } top = x; } /** Removes the element on top of the stack and returns that element. */ public int pop() { if (q1.isEmpty()) { int len = q2.size(); for (int i=1; i q = new LinkedList<>(); /** Initialize your data structure here. */ public MyStack() { } /** Push element x onto stack. */ public void push(int x) { q.add(x); int s = q.size(); while (s > 1) { q.add(q.remove()); s--; } } /** Removes the element on top of the stack and returns that element. */ public int pop() { return q.remove(); } /** Get the top element. */ public int top() { return q.peek(); } /** Returns whether the stack is empty. */ public boolean empty() { return q.isEmpty(); } } } /** * Your MyStack object will be instantiated and called as such: * MyStack obj = new MyStack(); * obj.push(x); * int param_2 = obj.pop(); * int param_3 = obj.top(); * boolean param_4 = obj.empty(); */ ================================================ FILE: src/ImplementStrStr28.java ================================================ /** * Implement strStr(). http://www.cplusplus.com/reference/cstring/strstr/ * * Return the index of the first occurrence of needle in haystack, or -1 if * needle is not part of haystack. * * Example 1: * Input: haystack = "hello", needle = "ll" * Output: 2 * * Example 2: * Input: haystack = "aaaaa", needle = "bba" * Output: -1 * */ public class ImplementStrStr28 { public int strStr(String haystack, String needle) { if (needle == null || needle.length() == 0) return 0; if (haystack == null || haystack.length() == 0 || haystack.length() < needle.length()) return -1; int i = 0; while (i <= haystack.length() - needle.length()) { int j = 0; int t = i; while (j < needle.length() && haystack.charAt(t) == needle.charAt(j)) { j++; t++; } if (j == needle.length()) return i; i++; } return -1; } /** * https://leetcode.com/problems/implement-strstr/discuss/12811/Share-my-accepted-java-solution */ public int strStr2(String haystack, String needle) { int l1 = haystack.length(), l2 = needle.length(); if (l1 < l2) { return -1; } else if (l2 == 0) { return 0; } int threshold = l1 - l2; for (int i = 0; i <= threshold; ++i) { if (haystack.substring(i,i+l2).equals(needle)) { return i; } } return -1; } } ================================================ FILE: src/ImplementTriePrefixTree208.java ================================================ /** * Implement a trie with insert, search, and startsWith methods. * * Example: * * Trie trie = new Trie(); * * trie.insert("apple"); * trie.search("apple"); // returns true * trie.search("app"); // returns false * trie.startsWith("app"); // returns true * trie.insert("app"); * trie.search("app"); // returns true * * Note: * You may assume that all inputs are consist of lowercase letters a-z. * All inputs are guaranteed to be non-empty strings. */ public class ImplementTriePrefixTree208 { class Trie { private Trie[] children = new Trie[26]; private boolean isWord = false; /** Initialize your data structure here. */ public Trie() { } /** Inserts a word into the trie. */ public void insert(String word) { insert(word.toCharArray(), 0); } private void insert(char[] chars, int i) { if (i == chars.length) { this.isWord = true; return; } if (this.children[chars[i]-'a'] == null) { this.children[chars[i]-'a'] = new Trie(); } this.children[chars[i]-'a'].insert(chars, i+1); } /** Returns if the word is in the trie. */ public boolean search(String word) { return search(word.toCharArray(), 0); } private boolean search(char[] chars, int i) { if (i == chars.length) return this.isWord; if (this.children[chars[i]-'a'] == null) return false; return this.children[chars[i]-'a'].search(chars, i+1); } /** Returns if there is any word in the trie that starts with the given prefix. */ public boolean startsWith(String prefix) { return startsWith(prefix.toCharArray(), 0); } private boolean startsWith(char[] chars, int i) { if (i == chars.length) return true; if (this.children[chars[i]-'a'] == null) return false; return this.children[chars[i]-'a'].startsWith(chars, i+1); } } /** * https://leetcode.com/problems/implement-trie-prefix-tree/solution/ */ class Trie2 { private TrieNode root; /** Initialize your data structure here. */ public Trie() { root = new TrieNode(); } /** Inserts a word into the trie. */ public void insert(String word) { TrieNode node = root; for (int i = 0; i < word.length(); i++) { char c = word.charAt(i); if (!node.containsKey(c)) { node.put(c, new TrieNode()); } node = node.get(c); } node.setLeaf(); } /** Returns if the word is in the trie. */ public boolean search(String word) { TrieNode node = root; for (int i = 0; i < word.length(); i++) { char c = word.charAt(i); if (!node.containsKey(c)) { return false; } node = node.get(c); } return node.isLeaf(); } /** Returns if there is any word in the trie that starts with the given prefix. */ public boolean startsWith(String prefix) { TrieNode node = root; for (int i = 0; i < prefix.length(); i++) { char c = prefix.charAt(i); if (!node.containsKey(c)) { return false; } node = node.get(c); } return true; } } class TrieNode { // R links to node children private TrieNode[] links; private final int R = 26; private boolean isLeaf; public TrieNode() { links = new TrieNode[R]; } public boolean containsKey(char c) { return links[c -'a'] != null; } public TrieNode get(char c) { return links[c -'a']; } public void put(char c, TrieNode node) { links[c -'a'] = node; } public void setLeaf() { isLeaf = true; } public boolean isLeaf() { return isLeaf; } } /** * Your Trie object will be instantiated and called as such: * Trie obj = new Trie(); * obj.insert(word); * boolean param_2 = obj.search(word); * boolean param_3 = obj.startsWith(prefix); */ } ================================================ FILE: src/IncreasingSubsequences491.java ================================================ /** * Given an integer array, your task is to find all the different possible * increasing subsequences of the given array, and the length of an increasing * subsequence should be at least 2 . * * Example: * Input: [4, 6, 7, 7] * Output: [[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7, 7], [7,7], [4,7,7]] * * Note: * The length of the given array will not exceed 15. * The range of integer in the given array is [-100,100]. * The given array may contain duplicates, and two equal integers should also * be considered as a special case of increasing sequence. */ public class IncreasingSubsequences491 { public List> findSubsequences(int[] nums) { List> res = new ArrayList<>(); helper(nums, Integer.MIN_VALUE, 0, new ArrayList<>(), res); return res; } private void helper(int[] nums, int pre, int start, List path, List> res) { if (path.size() >= 2) res.add(new ArrayList<>(path)); if (start == nums.length) return; boolean[] visited = new boolean[201]; for (int i=start; i= pre) { path.add(nums[i]); helper(nums, nums[i], i+1, path, res); path.remove(path.size() - 1); } } } } ================================================ FILE: src/IncreasingTripletSubsequence334.java ================================================ /** * Given an unsorted array return whether an increasing subsequence of length * 3 exists or not in the array. * * Formally the function should: * Return true if there exists i, j, k * such that arr[i] < arr[j] < arr[k] given 0 ≤ i < j < k ≤ n-1 else return false. * Your algorithm should run in O(n) time complexity and O(1) space complexity. * * Examples: * Given [1, 2, 3, 4, 5], * return true. * * Given [5, 4, 3, 2, 1], * return false. */ public class IncreasingTripletSubsequence334 { public boolean increasingTriplet(int[] nums) { if (nums == null || nums.length < 3) return false; int a = nums[0]; int b = Integer.MAX_VALUE; for (int i=1; i b) return true; else if (nums[i] > a) b = nums[i]; else a = nums[i]; } return false; } public boolean increasingTriplet2(int[] nums) { if (nums == null || nums.length < 3) return false; int N = nums.length; int[] dp = new int[3]; int size = 0; for (int i=0; i nums[j-1] && dp[j] + 1 > tmp) { tmp = dp[j] + 1; } if (tmp >= 3) return true; } dp[i] = tmp; } return false; } } ================================================ FILE: src/InorderSuccessorInBST285.java ================================================ /** * Given a binary search tree and a node in it, find the in-order successor of * that node in the BST. * * Note: If the given node has no in-order successor in the tree, return null. */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class InorderSuccessorInBST285 { // Iteratively public TreeNode inorderSuccessor(TreeNode root, TreeNode p) { if (p.right != null) return findMin(p.right); TreeNode succ = null; while (root != null) { if (root.val == p.val) break; if (root.val > p.val) { succ = root; root = root.left; } else { root = root.right; } } return succ; } private TreeNode findMin(TreeNode n) { if (n == null) return null; TreeNode t = n; while (t.left != null) t = t.left; return t; } // Recursively public TreeNode inorderSuccessor2(TreeNode root, TreeNode x) { if (x.right != null) return findMin(x.right); return inorderSuccessor2(root, x, null); } public TreeNode inorderSuccessor2(TreeNode root, TreeNode x, TreeNode succ) { if (root == null || x == null || root.val == x.val) return succ; if (root.val > x.val) { return inorderSuccessor2(root.left, x, root); } else { return inorderSuccessor2(root.right, x, succ); } } public TreeNode inorderSuccessor3(TreeNode root, TreeNode p) { return inorderSuccessor3(root, p, null); } public TreeNode inorderSuccessor3(TreeNode root, TreeNode p, TreeNode pre) { if (root.val == p.val) { if (root.right == null) { return pre; } else { return findMin(root.right); } } else if (root.val > p.val) { return inorderSuccessor3(root.left, p, root); } else { return inorderSuccessor3(root.right, p, pre); } } /** * https://leetcode.com/problems/inorder-successor-in-bst/discuss/72653/Share-my-Java-recursive-solution */ public TreeNode inorderSuccessor4(TreeNode root, TreeNode p) { if (root == null) return null; if (root.val <= p.val) { return successor(root.right, p); } else { TreeNode left = successor(root.left, p); return (left != null) ? left : root; } } } ================================================ FILE: src/InsertDeleteGetRandomOOne380.java ================================================ /** * Design a data structure that supports all following operations in average * O(1) time. * * insert(val): Inserts an item val to the set if not already present. * remove(val): Removes an item val from the set if present. * getRandom: Returns a random element from current set of elements. * Each element must have the same probability of being returned. * * Example: * * // Init an empty set. * RandomizedSet randomSet = new RandomizedSet(); * * // Inserts 1 to the set. Returns true as 1 was inserted successfully. * randomSet.insert(1); * * // Returns false as 2 does not exist in the set. * randomSet.remove(2); * * // Inserts 2 to the set, returns true. Set now contains [1,2]. * randomSet.insert(2); * * // getRandom should return either 1 or 2 randomly. * randomSet.getRandom(); * * // Removes 1 from the set, returns true. Set now contains [2]. * randomSet.remove(1); * * // 2 was already in the set, so return false. * randomSet.insert(2); * * // Since 2 is the only number in the set, getRandom always return 2. * randomSet.getRandom(); * */ public class InsertDeleteGetRandomOOne380 { public class RandomizedSet { private Set set; private Random rand; /** Initialize your data structure here. */ public RandomizedSet() { this.set = new HashSet(); this.rand = new Random(); } /** Inserts a value to the set. Returns true if the set did not already contain the specified element. */ public boolean insert(int val) { return this.set.add(val); } /** Removes a value from the set. Returns true if the set contained the specified element. */ public boolean remove(int val) { return this.set.remove(val); } /** Get a random element from the set. */ public int getRandom() { Object[] values = this.set.toArray(); return (Integer) values[rand.nextInt(values.length)]; } } public class RandomizedSet2 { private Map map; private ArrayList values; private Random rand; /** Initialize your data structure here. */ public RandomizedSet() { this.map = new HashMap(); this.values = new ArrayList(); this.rand = new Random(); } /** Inserts a value to the set. Returns true if the set did not already contain the specified element. */ public boolean insert(int val) { if (map.containsKey(val)) return false; map.put(val, values.size()); values.add(val); return true; } /** Removes a value from the set. Returns true if the set contained the specified element. */ public boolean remove(int val) { if (!map.containsKey(val)) return false; int pos = map.get(val); int len = values.size(); if (pos != len-1) { int temp = values.get(len-1); values.set(pos, temp); map.put(temp, pos); } map.remove(val); values.remove(len-1); return true; } /** Get a random element from the set. */ public int getRandom() { return values.get(rand.nextInt(values.size())); } } class RandomizedSet3 { private Map indexToValue = new HashMap<>(); private Map valueToIndex = new HashMap<>(); private Queue q = new LinkedList<>(); private int index = 0; private Random rand = new Random(); /** Initialize your data structure here. */ public RandomizedSet() { } /** Inserts a value to the set. Returns true if the set did not already contain the specified element. */ public boolean insert(int val) { if (valueToIndex.containsKey(val)) return false; if (q.isEmpty()) { indexToValue.put(index, val); valueToIndex.put(val, index); index++; } else { int currIdx = q.poll(); indexToValue.put(currIdx, val); valueToIndex.put(val, currIdx); } return true; } /** Removes a value from the set. Returns true if the set contained the specified element. */ public boolean remove(int val) { if (!valueToIndex.containsKey(val)) return false; int idx = valueToIndex.remove(val); indexToValue.remove(idx); q.add(idx); return true; } /** Get a random element from the set. */ public int getRandom() { if (valueToIndex.isEmpty()) return -1; while (true) { int idx = rand.nextInt(index); if (!indexToValue.containsKey(idx)) continue; return indexToValue.get(idx); } } } /** * Your RandomizedSet object will be instantiated and called as such: * RandomizedSet obj = new RandomizedSet(); * boolean param_1 = obj.insert(val); * boolean param_2 = obj.remove(val); * int param_3 = obj.getRandom(); */ } ================================================ FILE: src/InsertInterval57.java ================================================ /** * Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary). * * You may assume that the intervals were initially sorted according to their start times. * * Example 1: * Given intervals [1,3],[6,9], insert and merge [2,5] in as [1,5],[6,9]. * * Example 2: * Given [1,2],[3,5],[6,7],[8,10],[12,16], insert and merge [4,9] in as [1,2],[3,10],[12,16]. * * This is because the new interval [4,9] overlaps with [3,5],[6,7],[8,10]. */ /** * Definition for an interval. * public class Interval { * int start; * int end; * Interval() { start = 0; end = 0; } * Interval(int s, int e) { start = s; end = e; } * } */ import java.util.Arrays; import java.util.ArrayList; import java.util.List; public class InsertInterval57 { public List insert(List intervals, Interval newInterval) { int start = newInterval.start; int end = newInterval.end; List result = new ArrayList<>(); boolean newAdded = false; for (Interval in: intervals) { if (in.end < start) { result.add(in); } else if (in.start > end) { if (!newAdded) { result.add(new Interval(start, end)); newAdded = true; } result.add(in); } else { start = Math.min(in.start, start); end = Math.max(in.end, end); } } if (!newAdded) { result.add(new Interval(start, end)); } return result; } public static void main(String[] args) { InsertInterval57 ii = new InsertInterval57(); System.out.println(ii.insert(new ArrayList(Arrays.asList(new Interval(1, 3), new Interval(6, 9))), new Interval(2, 5))); } } ================================================ FILE: src/InsertIntoACyclicSortedList.java ================================================ /** * Given a node from a cyclic linked list which is sorted in ascending order, * write a function to insert a value into the list such that it remains a * cyclic sorted list. The given node can be a reference to any single node in * the list, and may not be necessarily the smallest value in the cyclic list. * * If there are multiple suitable places for insertion, you may choose any * place to insert the new value. After the insertion, the cyclic list should * remain sorted. * * If the list is empty (i.e., given node is null), you should create a new * single cyclic list and return the reference to that single node. * * Otherwise, you should return the original given node. * * The following example may help you understand the problem better: * https://leetcode.com/static/images/problemset/InsertCyclicBefore.png * * In the figure above, there is a cyclic sorted list of three elements. You * are given a reference to the node with value 3, and we need to insert 2 * into the list. * https://leetcode.com/static/images/problemset/InsertCyclicAfter.png * * The new node should insert between node 1 and node 3. After the insertion, * the list should look like this, and we should still return node 3. */ /* // Definition for a Node. class Node { public int val; public Node next; public Node() {} public Node(int _val,Node _next) { val = _val; next = _next; } }; */ public class InsertIntoACyclicSortedList { public Node insert(Node head, int insertVal) { Node newNode = new Node(insertVal, null); if (head == null) { newNode.next = newNode; return newNode; } Node p = head; boolean inserted = false; do { if (p == p.next || p.val == insertVal || (p.val < insertVal && p.next.val > insertVal) || (((p.val > insertVal && p.next.val > insertVal) || (p.val < insertVal && p.next.val < insertVal)) && p.next.val < p.val)) { newNode.next = p.next; p.next = newNode; inserted = true; break; } p = p.next; } while (p != head); if (!inserted) { newNode.next = p.next; p.next = newNode; } return head; } public Node insert2(Node head, int insertVal) { Node newNode = new Node(); newNode.val = insertVal; if (head == null) { newNode.next = newNode; return newNode; } Node p = head; Node dec = null; while (true) { if (p.val <= insertVal && p.next.val >= insertVal) { newNode.next = p.next; p.next = newNode; return head; } if (p.val > p.next.val) { dec = p; } p = p.next; if (p == head) break; } if (dec == null) dec = head; newNode.next = dec.next; dec.next = newNode; return head; } } ================================================ FILE: src/InsertionSortList147.java ================================================ /** * Sort a linked list using insertion sort. */ /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ public class InsertionSortList147 { public ListNode insertionSortList(ListNode head) { if (head == null || head.next == null) return head; ListNode dummy = new ListNode(0); ListNode end = new ListNode(head.val); dummy.next = end; ListNode p = head.next; while (p != null) { ListNode n = new ListNode(p.val); if (n.val >= end.val) { end.next = n; end = n; } else { insert(dummy, n); } p = p.next; } return dummy.next; } private void insert(ListNode dummy, ListNode newNode) { ListNode pre = dummy; ListNode now = dummy.next; while (now != null) { if (now.val >= newNode.val) { pre.next = newNode; newNode.next = now; return; } now = now.next; pre = pre.next; } } /** * https://discuss.leetcode.com/topic/8570/an-easy-and-clear-way-to-sort-o-1-space */ public ListNode insertionSortList2(ListNode head) { if( head == null ){ return head; } ListNode helper = new ListNode(0); //new starter of the sorted list ListNode cur = head; //the node will be inserted ListNode pre = helper; //insert node between pre and pre.next ListNode next = null; //the next node will be inserted //not the end of input list while( cur != null ){ next = cur.next; //find the right place to insert while( pre.next != null && pre.next.val < cur.val ){ pre = pre.next; } //insert between pre and pre.next cur.next = pre.next; pre.next = cur; pre = helper; cur = next; } return helper.next; } } ================================================ FILE: src/IntegerBreak343.java ================================================ /** * Given a positive integer n, break it into the sum of at least two positive * integers and maximize the product of those integers. Return the maximum * product you can get. * * Example 1: * Input: 2 * Output: 1 * Explanation: 2 = 1 + 1, 1 × 1 = 1. * * Example 2: * Input: 10 * Output: 36 * Explanation: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36. * Note: You may assume that n is not less than 2 and not larger than 58. */ public class IntegerBreak343 { public int integerBreak(int n) { int[] dp = new int[n+1]; dp[1] = 1; for (int i=2; i<=n; i++) { int tmp = 0; for (int j=1; j4){ product*=3; n-=3; } product*=n; return product; } } ================================================ FILE: src/IntegerToEnglishWords273.java ================================================ /** * Convert a non-negative integer to its english words representation. Given * input is guaranteed to be less than 231 - 1. * * For example, * 123 -> "One Hundred Twenty Three" * 12345 -> "Twelve Thousand Three Hundred Forty Five" * 1234567 -> "One Million Two Hundred Thirty Four Thousand Five Hundred Sixty Seven" */ public class IntegerToEnglishWords273 { private static final String[] UNITS = { "Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"}; private static final String[] TENS = {"Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"}; private static final String[] THOUSANDS = {"", "Thousand", "Million", "Billion"}; public String numberToWords(int num) { if (num == 0) return "Zero"; int i = 0; String words = ""; while (num > 0) { if (num % 1000 != 0) { words = threeDigits(num % 1000) + " " + THOUSANDS[i] + " " + words; } num /= 1000; i++; } return words.trim(); } private String threeDigits(int num) { if (num >= 100) { int h = num/100; String twoDigits = twoDigits(num%100); return UNITS[h] + " Hundred" + ((twoDigits.length() == 0) ? "" : " " + twoDigits); } return twoDigits(num); } private String twoDigits(int num) { if (num == 0) return ""; if (num > 0 && num < 20) { return UNITS[num]; } int t = num/10; int n = num%10; return TENS[t-2] + ((n == 0) ? "": (" " + UNITS[n])); } } ================================================ FILE: src/IntegerToRoman12.java ================================================ /** * Roman numerals are represented by seven different symbols: I, V, X, L, C, D and M. * * Symbol Value * I 1 * V 5 * X 10 * L 50 * C 100 * D 500 * M 1000 * * For example, two is written as II in Roman numeral, just two one's added * together. Twelve is written as, XII, which is simply X + II. The number * twenty seven is written as XXVII, which is XX + V + II. * * Roman numerals are usually written largest to smallest from left to right. * However, the numeral for four is not IIII. Instead, the number four is * written as IV. Because the one is before the five we subtract it making * four. The same principle applies to the number nine, which is written as IX. * * There are six instances where subtraction is used: * * I can be placed before V (5) and X (10) to make 4 and 9. * X can be placed before L (50) and C (100) to make 40 and 90. * C can be placed before D (500) and M (1000) to make 400 and 900. * * Given an integer, convert it to a roman numeral. Input is guaranteed to be * within the range from 1 to 3999. * * Example 1: * Input: 3 * Output: "III" * * Example 2: * Input: 4 * Output: "IV" * * Example 3: * Input: 9 * Output: "IX" * * Example 4: * Input: 58 * Output: "LVIII" * Explanation: L = 50, V = 5, III = 3. * * Example 5: * Input: 1994 * Output: "MCMXCIV" * Explanation: M = 1000, CM = 900, XC = 90 and IV = 4. */ public class IntegerToRoman12 { // 1, 5, 10, 50, 100, 500, 1000 private static char[] R = new char[]{'I', 'V', 'X', 'L', 'C', 'D', 'M'}; public String intToRoman(int num) { StringBuilder sb = new StringBuilder(); int base = 0; while (num > 0) { int digit = num % 10; if (digit > 0) { char[] cur = curr(digit, base); sb.insert(0, cur); } num /= 10; base += 2; } return sb.toString(); } private char[] curr(int digit, int base) { if (digit >= 1 && digit <= 3) { char[] res = new char[digit]; Arrays.fill(res, R[base]); return res; } else if (digit == 4) { return new char[]{R[base], R[base+1]}; } else if (digit == 5) { return new char[]{R[base+1]}; } else if (digit >= 6 && digit <= 8) { char[] res = new char[digit-5+1]; Arrays.fill(res, R[base]); res[0] = R[base+1]; return res; } else { // 9 return new char[]{R[base], R[base+2]}; } } /** * https://leetcode.com/problems/integer-to-roman/discuss/6274/Simple-Solution */ public static String intToRoman2(int num) { String M[] = {"", "M", "MM", "MMM"}; String C[] = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"}; String X[] = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"}; String I[] = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"}; return M[num/1000] + C[(num%1000)/100] + X[(num%100)/10] + I[num%10]; } } ================================================ FILE: src/InterleavingString97.java ================================================ /** * Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. * * For example, * Given: * s1 = "aabcc", * s2 = "dbbca", * * When s3 = "aadbbcbcac", return true. * When s3 = "aadbbbaccc", return false. * */ import java.util.Stack; public class InterleavingString97 { // cannot pass time limit class Pair { int i; int j; int k; Pair(int i, int j, int k) { this.i = i; this.j = j; this.k = k; } } public boolean isInterleave(String s1, String s2, String s3) { int l1 = s1.length(); int l2 = s2.length(); int l3 = s3.length(); if ((l1 + l2) != l3) return false; Stack track = new Stack<>(); int i = 0; int j = 0; int k = 0; boolean b = true; while (k < l3) { if (i setNums1 = new HashSet<>(); for (int i1: nums1) { setNums1.add(i1); } Set resSet = new HashSet<>(); for (int i2: nums2) { if (setNums1.contains(i2)) { resSet.add(i2); } } int[] res = new int[resSet.size()]; int i = 0; for (Integer resInt: resSet) { res[i++] = (int) resInt; } return res; } /** * https://leetcode.com/problems/intersection-of-two-arrays/discuss/81969/Three-Java-Solutions */ public int[] intersection2(int[] nums1, int[] nums2) { Set set = new HashSet<>(); Arrays.sort(nums1); Arrays.sort(nums2); int i = 0; int j = 0; while (i < nums1.length && j < nums2.length) { if (nums1[i] < nums2[j]) { i++; } else if (nums1[i] > nums2[j]) { j++; } else { set.add(nums1[i]); i++; j++; } } int[] result = new int[set.size()]; int k = 0; for (Integer num : set) { result[k++] = num; } return result; } } ================================================ FILE: src/IntersectionOfTwoArraysII350.java ================================================ /** * Given two arrays, write a function to compute their intersection. * * Example: * Given nums1 = [1, 2, 2, 1], nums2 = [2, 2], return [2, 2]. * * Note: * Each element in the result should appear as many times as it shows in both arrays. * The result can be in any order. * * Follow up: * What if the given array is already sorted? How would you optimize your algorithm? * What if nums1's size is small compared to nums2's size? Which algorithm is better? * What if elements of nums2 are stored on disk, and the memory is limited such * that you cannot load all elements into the memory at once? * */ public class IntersectionOfTwoArraysII350 { public int[] intersect(int[] nums1, int[] nums2) { if (nums1.length == 0 || nums2.length == 0) return new int[0]; Map m1 = new HashMap<>(); for (int i=0; i m2 = new HashMap<>(); for (int i=0; i res = new ArrayList<>(); if (m1.size() > m2.size()) { Map temp = m1; m1 = m2; m2 = temp; } for (Map.Entry e: m1.entrySet()) { if (m2.containsKey(e.getKey())) { int minVal = Math.min(e.getValue(), m2.get(e.getKey())); while (minVal > 0) { res.add(e.getKey()); minVal--; } } } int[] arr = new int[res.size()]; for (int i=0; i m1 = new HashMap<>(); for (int i=0; i 0) { m1.put(nums2[i], m1.get(nums2[i])-1); arr[size] = nums2[i]; size++; } } return Arrays.copyOfRange(arr, 0, size); } public int[] intersect3(int[] nums1, int[] nums2) { int len = Math.min(nums1.length, nums2.length); int[] arr = new int[len]; if (len == 0) return arr; Arrays.sort(nums1); Arrays.sort(nums2); int i = 0; int j = 0; int size = 0; while (i < nums1.length && j < nums2.length) { int n1 = nums1[i]; int n2 = nums2[j]; if (n1 == n2) { arr[size] = n1; i++; j++; size++; } else if (n1 < n2) { do { i++; } while (i < nums1.length && nums1[i] == n1); } else { do { j++; } while (j < nums2.length && nums2[j] == n2); } } return Arrays.copyOfRange(arr, 0, size); } } ================================================ FILE: src/IntersectionOfTwoLinkedLists160.java ================================================ /** * Write a program to find the node at which the intersection of two singly linked lists begins. * * For example, the following two linked lists: * * A: a1 → a2 * ↘ * c1 → c2 → c3 * ↗ * B: b1 → b2 → b3 * begin to intersect at node c1. * * * Notes: * * If the two linked lists have no intersection at all, return null. * The linked lists must retain their original structure after the function returns. * You may assume there are no cycles anywhere in the entire linked structure. * Your code should preferably run in O(n) time and use only O(1) memory. * */ /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ public class IntersectionOfTwoLinkedLists160 { public ListNode getIntersectionNode(ListNode headA, ListNode headB) { int lA = 0; ListNode tA = headA; while (tA != null) { lA++; tA = tA.next; } int lB = 0; ListNode tB = headB; while (tB != null) { lB++; tB = tB.next; } if (lA < lB) { for (int i=1; i<=(lB-lA); i++) headB = headB.next; } else if (lB < lA) { for (int i=1; i<=(lA-lB); i++) headA = headA.next; } while (headA != null && headB != null) { if (headA == headB) { return headA; } headA = headA.next; headB = headB.next; } return null; } public ListNode getIntersectionNode2(ListNode headA, ListNode headB) { if (headA == null || headB == null) return null; ListNode a = headA; ListNode b = headB; while (a != null && b != null) { if (a == b) return a; a = a.next; b = b.next; } if (a == null && b == null) return null; if (a == null) { a = headB; } else { b = headA; } while (a != null && b != null) { a = a.next; b = b.next; } if (a == null) { a = headB; } else { b = headA; } while (a != null && b != null) { if (a == b) return a; a = a.next; b = b.next; } return null; } /** * https://leetcode.com/problems/intersection-of-two-linked-lists/discuss/49785/Java-solution-without-knowing-the-difference-in-len! * * You can prove that: say A length = a + c, B length = b + c, after * switching pointer, pointer A will move another b + c steps, pointer B * will move a + c more steps, since a + c + b + c = b + c + a + c, it * does not matter what value c is. Pointer A and B must meet after * a + c + b (b + c + a) steps. If c == 0, they meet at NULL. * */ public ListNode getIntersectionNode3(ListNode headA, ListNode headB) { //boundary check if(headA == null || headB == null) return null; ListNode a = headA; ListNode b = headB; //if a & b have different len, then we will stop the loop after second iteration while( a != b){ //for the end of first iteration, we just reset the pointer to the head of another linkedlist a = a == null? headB : a.next; b = b == null? headA : b.next; } return a; } public ListNode getIntersectionNode4(ListNode headA, ListNode headB) { if (headA == null || headB == null) return null; ListNode pa = headA; ListNode pb = headB; while (pa != pb) { pa = pa.next; pb = pb.next; if (pa == pb) return pa; if (pa == null) pa = headB; if (pb == null) pb = headA; } return pa; } } ================================================ FILE: src/Interval.java ================================================ /** * Definition for an interval. */ public class Interval { int start; int end; Interval() { start = 0; end = 0; } Interval(int s, int e) { start = s; end = e; } } ================================================ FILE: src/InvertBinaryTree226.java ================================================ /** * Invert a binary tree. * * 4 * / \ * 2 7 * / \ / \ * 1 3 6 9 * * to * * 4 * / \ * 7 2 * / \ / \ * 9 6 3 1 * */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class InvertBinaryTree226 { public TreeNode invertTree(TreeNode root) { if (root == null || (root.left == null && root.right == null)) { return root; } TreeNode left = invertTree(root.right); TreeNode right = invertTree(root.left); root.left = left; root.right = right; return root; } } ================================================ FILE: src/IsGraphBipartite785.java ================================================ /** * Given an undirected graph, return true if and only if it is bipartite. * * Recall that a graph is bipartite if we can split it's set of nodes into two * independent subsets A and B such that every edge in the graph has one node * in A and another node in B. * * The graph is given in the following form: graph[i] is a list of indexes j * for which the edge between nodes i and j exists. Each node is an integer * between 0 and graph.length - 1. There are no self edges or parallel * edges: graph[i] does not contain i, and it doesn't contain any element twice. * * Example 1: * Input: [[1,3], [0,2], [1,3], [0,2]] * Output: true * Explanation: * The graph looks like this: * 0----1 * | | * | | * 3----2 * We can divide the vertices into two groups: {0, 2} and {1, 3}. * * Example 2: * Input: [[1,2,3], [0,2], [0,1,3], [0,2]] * Output: false * Explanation: * The graph looks like this: * 0----1 * | \ | * | \ | * 3----2 * We cannot find a way to divide the set of nodes into two independent subsets. * * Note: * graph will have length in range [1, 100]. * graph[i] will contain integers in range [0, graph.length - 1]. * graph[i] will not contain i or duplicate values. * The graph is undirected: if any element j is in graph[i], then i will be * in graph[j]. */ public class IsGraphBipartite785 { public boolean isBipartite(int[][] graph) { if (graph.length == 0) return true; int N = graph.length; int[] visited = new int[N]; for (int i=0; i q = new LinkedList<>(); visited[i] = 1; q.add(i); while (!q.isEmpty()) { int curr = q.poll(); for (int next: graph[curr]) { if (visited[next] == 0) { visited[next] = - visited[curr]; q.add(next); } else { if (visited[next] == visited[curr]) return false; } } } } } return true; } /** * https://leetcode.com/problems/is-graph-bipartite/discuss/118959/JAVA-union-find-easy-solution */ public boolean isBipartite3(int[][] graph) { int n= graph.length; int[] parent= new int[n]; for(int i=0; i0){ if(findParent(parent,i)==findParent(parent,graph[i][0])) return false; } } return true; } private int findParent(int[]parent, int p){ if(parent[p]==p) return p; parent[p]=findParent(parent, parent[p]); return parent[p]; } } ================================================ FILE: src/IsSubsequence392.java ================================================ /** * Given a string s and a string t, check if s is subsequence of t. * * You may assume that there is only lower case English letters in both s and t. * t is potentially a very long (length ~= 500,000) string, and s is a short * string (<=100). * * A subsequence of a string is a new string which is formed from the original * string by deleting some (can be none) of the characters without disturbing * the relative positions of the remaining characters. (ie, "ace" is a * subsequence of "abcde" while "aec" is not). * * Example 1: * s = "abc", t = "ahbgdc" * Return true. * * Example 2: * s = "axc", t = "ahbgdc" * Return false. * * Follow up: * If there are lots of incoming S, say S1, S2, ... , Sk where k >= 1B, and you * want to check one by one to see if T has its subsequence. In this scenario, * how would you change your code? */ public class IsSubsequence392 { public boolean isSubsequence(String s, String t) { if (s == null && t == null) return true; if (s == null || t == null) return true; int lenS = s.length(); int lenT = t.length(); char[] charS = s.toCharArray(); char[] charT = t.toCharArray(); int i = 0; int j = 0; while (i < lenS && j < lenT) { while (j < lenT && charT[j] != charS[i]) { j++; } if (j == lenT) break; j++; i++; } return i == lenS; } /** * https://leetcode.com/problems/is-subsequence/discuss/87297/Java.-Only-2ms.-Much-faster-than-normal-2-pointers. */ public boolean isSubsequence2(String s, String t) { if(t.length() < s.length()) return false; int prev = 0; for(int i = 0; i < s.length();i++) { char tempChar = s.charAt(i); prev = t.indexOf(tempChar,prev); if(prev == -1) return false; prev++; } return true; } public boolean isSubsequence3(String s, String t) { int i = 0; int j = 0; char[] chars = s.toCharArray(); char[] chart = t.toCharArray(); while (i < chars.length && j < chart.length) { if (chars[i] == chart[j]) { i++; j++; } else { j++; } } return i == chars.length; } } ================================================ FILE: src/IslandPerimeter463.java ================================================ /** * You are given a map in form of a two-dimensional integer grid where 1 * represents land and 0 represents water. Grid cells are connected * horizontally/vertically (not diagonally). The grid is completely surrounded * by water, and there is exactly one island (i.e., one or more connected land * cells). The island doesn't have "lakes" (water inside that isn't connected * to the water around the island). One cell is a square with side length 1. * The grid is rectangular, width and height don't exceed 100. Determine the * perimeter of the island. * * Example: * * [[0,1,0,0], * [1,1,1,0], * [0,1,0,0], * [1,1,0,0]] * * Answer: 16 * Explanation: The perimeter is the 16 yellow stripes in the image below: * https://leetcode.com/static/images/problemset/island.png */ public class IslandPerimeter463 { private static int[][] dir = new int[][]{{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; public int islandPerimeter(int[][] grid) { if (grid == null || grid.length == 0 || grid[0].length == 0) return 0; int res = 0; for (int i=0; i= n || y < 0 || y >= m || grid[x][y] == 0) { res++; } } return res; } /** * https://leetcode.com/problems/island-perimeter/discuss/95001/clear-and-easy-java-solution */ public int islandPerimeter2(int[][] grid) { int islands = 0, neighbours = 0; for (int i = 0; i < grid.length; i++) { for (int j = 0; j < grid[i].length; j++) { if (grid[i][j] == 1) { islands++; // count islands if (i < grid.length - 1 && grid[i + 1][j] == 1) neighbours++; // count down neighbours if (j < grid[i].length - 1 && grid[i][j + 1] == 1) neighbours++; // count right neighbours } } } return islands * 4 - neighbours * 2; } } ================================================ FILE: src/IsomorphicStrings205.java ================================================ /** * Given two strings s and t, determine if they are isomorphic. * * Two strings are isomorphic if the characters in s can be replaced to get t. * * All occurrences of a character must be replaced with another character * while preserving the order of characters. No two characters may map to the * same character but a character may map to itself. * * Example 1: * Input: s = "egg", t = "add" * Output: true * * Example 2: * Input: s = "foo", t = "bar" * Output: false * * Example 3: * Input: s = "paper", t = "title" * Output: true * * Note: * You may assume both s and t have the same length. */ public class IsomorphicStrings205 { public boolean isIsomorphic(String s, String t) { if (s == null && t == null) return true; if (s == null || t == null || s.length() != t.length()) return false; int N = s.length(); char[] charS = s.toCharArray(); char[] charT = t.toCharArray(); Map map = new HashMap<>(); for (int i=0; i= 0; j--) { dp[i] = dp[j] && (nums[j] >= i - j); if (dp[i]) { break; } } } return dp[length - 1]; } /** * https://discuss.leetcode.com/topic/3443/simplest-o-n-solution-with-constant-space */ public boolean canJump2(int[] nums) { return canJumpHelper(nums, nums.length); } boolean canJumpHelper(int A[], int n) { int last=n-1,i,j; for(i=n-2;i>=0;i--){ if(i+A[i]>=last)last=i; } return last<=0; } /** * https://discuss.leetcode.com/topic/7661/java-solution-easy-to-understand */ public boolean canJump3(int[] A) { int max = 0; for(int i=0;imax) {return false;} max = Math.max(A[i]+i,max); } return true; } /** * https://discuss.leetcode.com/topic/36578/java-98-percentile-solution/7 */ public boolean canJump4(int[] nums) { if(nums.length < 2) return true; for(int curr = nums.length-2; curr>=0;curr--){ if(nums[curr] == 0){ int neededJumps = 1; while(neededJumps > nums[curr]){ neededJumps++; curr--; if(curr < 0) return false; } } } return true; } } ================================================ FILE: src/JumpGameII45.java ================================================ /** * Given an array of non-negative integers, you are initially positioned at * the first index of the array. * * Each element in the array represents your maximum jump length at that position. * * Your goal is to reach the last index in the minimum number of jumps. * * Example: * Input: [2,3,1,1,4] * Output: 2 * Explanation: The minimum number of jumps to reach the last index is 2. * Jump 1 step from index 0 to 1, then 3 steps to the last index. * * Note: * You can assume that you can always reach the last index. */ public class JumpGameII45 { public int jump(int[] nums) { int N = nums.length; int[] dp = new int[N]; Arrays.fill(dp, Integer.MAX_VALUE); dp[0] = 0; for (int i=0; i 0) { if (slot2days[i] < slot2days[j]) { if ((j - i - 1) == k) ans = Math.min(ans, Math.max(slot2days[i], slot2days[j])); j--; i = j-1; min = Integer.MAX_VALUE; } else if (slot2days[i] < min && slot2days[i] > slot2days[j]) { if ((j - i - 1) == k) ans = Math.min(ans, Math.max(slot2days[i], slot2days[j])); min = slot2days[i]; i--; } else { i--; } if ((j - i - 1) > k) { j--; i = j-1; min = Integer.MAX_VALUE; } } return ans < Integer.MAX_VALUE ? ans : -1; } /** * https://leetcode.com/problems/k-empty-slots/solution/ */ public int kEmptySlots2(int[] flowers, int k) { int[] days = new int[flowers.length]; for (int i = 0; i < flowers.length; i++) { days[flowers[i] - 1] = i + 1; } int ans = Integer.MAX_VALUE; int left = 0, right = k+1; search: while (right < days.length) { for (int i = left+1; i < right; ++i) { if (days[i] < days[left] || days[i] < days[right]) { left = i; right = i + k + 1; continue search; } } ans = Math.min(ans, Math.max(days[left], days[right])); left = right; right = left + k + 1; } return ans < Integer.MAX_VALUE ? ans : -1; } } ================================================ FILE: src/KMP.java ================================================ /** * */ public class KMP { /** * https://www.jianshu.com/p/e2bd1ee482c3 */ public static int find(String txt, String pat, int[] next) { int M = txt.length(); int N = pat.length(); int i = 0; int j = 0; while (i < M && j < N) { if (j == -1 || txt.charAt(i) == pat.charAt(j)) { i++; j++; } else { j = next[j]; } if (j == N) return i - j; } return -1; } public static int[] getNext(String pat) { int N = pat.length(); int[] next = new int[N]; next[0] = -1; int k = -1; int j = 0; while (j < N - 1) { if (k == -1 || pat.charAt(j) == pat.charAt(k)) { k++; j++; next[j] = k; } else { k = next[k]; } } return next; } public static void main(String[] args) { String txt = "BBC ABCDAB CDABABCDABCDABDE"; String pat = "ABCDABD"; int[] next = getNext(pat); System.out.println(find(txt, pat, next)); } } ================================================ FILE: src/KeysAndRooms841.java ================================================ /** * There are N rooms and you start in room 0. Each room has a distinct number * in 0, 1, 2, ..., N-1, and each room may have some keys to access the next * room. * * Formally, each room i has a list of keys rooms[i], and each key rooms[i][j] * is an integer in [0, 1, ..., N-1] where N = rooms.length. A key * rooms[i][j] = v opens the room with number v. * * Initially, all the rooms start locked (except for room 0). * * You can walk back and forth between rooms freely. * * Return true if and only if you can enter every room. * * Example 1: * Input: [[1],[2],[3],[]] * Output: true * Explanation: * We start in room 0, and pick up key 1. * We then go to room 1, and pick up key 2. * We then go to room 2, and pick up key 3. * We then go to room 3. Since we were able to go to every room, we return true. * * Example 2: * Input: [[1,3],[3,0,1],[2],[0]] * Output: false * Explanation: We can't enter the room with number 2. * * Note: * 1 <= rooms.length <= 1000 * 0 <= rooms[i].length <= 1000 * The number of keys in all rooms combined is at most 3000. */ public class KeysAndRooms841 { public boolean canVisitAllRooms(List> rooms) { int N = rooms.size(); Set visited = new HashSet<>(); Queue q = new LinkedList<>(); q.add(0); while (!q.isEmpty()) { int curr = q.poll(); if (visited.contains(curr)) continue; visited.add(curr); for (Integer next: rooms.get(curr)) { if (!visited.contains(next)) { q.add(next); } } } return visited.size() == N; } /** * https://leetcode.com/problems/keys-and-rooms/discuss/133895/Clean-Code */ HashSet enteredRooms = new HashSet<>(); public boolean canVisitAllRooms2(List> rooms) { enterRoom(0, rooms); return enteredRooms.size() == rooms.size(); } private void enterRoom(int roomId, List> rooms) { enteredRooms.add(roomId); List keysInRoom = rooms.get(roomId); for (int key: keysInRoom) if (!enteredRooms.contains(key)) enterRoom(key, rooms); } } ================================================ FILE: src/KillProcess582.java ================================================ /** * Given n processes, each process has a unique PID (process id) and its PPID * (parent process id). * * Each process only has one parent process, but may have one or more children * processes. This is just like a tree structure. Only one process has PPID * that is 0, which means this process has no parent process. All the PIDs will * be distinct positive integers. * * We use two list of integers to represent a list of processes, where the * first list contains PID for each process and the second list contains the * corresponding PPID. * * Now given the two lists, and a PID representing a process you want to kill, * return a list of PIDs of processes that will be killed in the end. You * should assume that when a process is killed, all its children processes will * be killed. No order is required for the final answer. * * Example 1: * Input: * pid = [1, 3, 10, 5] * ppid = [3, 0, 5, 3] * kill = 5 * Output: [5,10] * Explanation: * 3 * / \ * 1 5 * / * 10 * Kill 5 will also kill 10. * * Note: * The given kill id is guaranteed to be one of the given PIDs. * n >= 1. */ public class KillProcess582 { public List killProcess(List pid, List ppid, int kill) { TreeNode root = constructTree(pid, ppid); List res = new ArrayList<>(); findNode(root, kill, res); return res; } private TreeNode constructTree(List pid, List ppid) { Map map = new HashMap<>(); int size = pid.size(); TreeNode root = null; for (int i=0; i res) { Queue q = new LinkedList<>(); q.add(root); while (!q.isEmpty()) { TreeNode currNode = q.poll(); if (currNode.value == kill) { gatherResults(currNode, res); return; } for (TreeNode child: currNode.children.values()) { q.add(child); } } } private void gatherResults(TreeNode found, List res) { if (found == null) return; res.add(found.value); for (TreeNode child: found.children.values()) { gatherResults(child, res); } } class TreeNode { int value; Map children = new HashMap<>(); TreeNode(int x) { this.value = x; } } public List killProcess2(List pid, List ppid, int kill) { TreeNode found = findKill(pid, ppid, kill); List res = new ArrayList<>(); gatherResults(found, res); return res; } private TreeNode findKill(List pid, List ppid, int kill) { Map map = new HashMap<>(); int size = pid.size(); TreeNode found = null; for (int i=0; i children = new ArrayList < > (); } public List < Integer > killProcess3(List < Integer > pid, List < Integer > ppid, int kill) { HashMap < Integer, Node > map = new HashMap < > (); for (int id: pid) { Node node = new Node(); node.val = id; map.put(id, node); } for (int i = 0; i < ppid.size(); i++) { if (ppid.get(i) > 0) { Node par = map.get(ppid.get(i)); par.children.add(map.get(pid.get(i))); } } List < Integer > l = new ArrayList < > (); l.add(kill); getAllChildren(map.get(kill), l); return l; } public void getAllChildren(Node pn, List < Integer > l) { for (Node n: pn.children) { l.add(n.val); getAllChildren(n, l); } } /** * https://leetcode.com/problems/kill-process/discuss/103176/Java-Solution-HashMap */ public List killProcess4(List pid, List ppid, int kill) { // Kill root, return all nodes if (kill == 0) return pid; int n = pid.size(); Map> tree = new HashMap<>(); for (int i = 0; i < n; i++) { if (!tree.containsKey(ppid.get(i))) { tree.put(ppid.get(i), new HashSet<>()); } tree.get(ppid.get(i)).add(pid.get(i)); } List result = new ArrayList<>(); traverse(tree, result, kill); return result; } private void traverse(Map> tree, List result, int pid) { result.add(pid); if (!tree.containsKey(pid)) { return; } for (Integer child : tree.get(pid)) { traverse(tree, result, child); } } /** * https://leetcode.com/problems/kill-process/solution/ */ public List < Integer > killProcess5(List < Integer > pid, List < Integer > ppid, int kill) { HashMap < Integer, List < Integer >> map = new HashMap < > (); for (int i = 0; i < ppid.size(); i++) { if (ppid.get(i) > 0) { List < Integer > l = map.getOrDefault(ppid.get(i), new ArrayList < Integer > ()); l.add(pid.get(i)); map.put(ppid.get(i), l); } } Queue < Integer > queue = new LinkedList < > (); List < Integer > l = new ArrayList < > (); queue.add(kill); while (!queue.isEmpty()) { int r = queue.remove(); l.add(r); if (map.containsKey(r)) for (int id: map.get(r)) queue.add(id); } return l; } } ================================================ FILE: src/KokoEatingBananas875.java ================================================ /** * Koko loves to eat bananas. There are N piles of bananas, the i-th pile has * piles[i] bananas. The guards have gone and will come back in H hours. * * Koko can decide her bananas-per-hour eating speed of K. Each hour, she * chooses some pile of bananas, and eats K bananas from that pile. If the * pile has less than K bananas, she eats all of them instead, and won't eat * any more bananas during this hour. * * Koko likes to eat slowly, but still wants to finish eating all the bananas * before the guards come back. * * Return the minimum integer K such that she can eat all the bananas within H hours. * * Example 1: * Input: piles = [3,6,7,11], H = 8 * Output: 4 * * Example 2: * Input: piles = [30,11,23,4,20], H = 5 * Output: 30 * * Example 3: * Input: piles = [30,11,23,4,20], H = 6 * Output: 23 * * Note: * 1 <= piles.length <= 10^4 * piles.length <= H <= 10^9 * 1 <= piles[i] <= 10^9 */ public class KokoEatingBananas875 { public int minEatingSpeed(int[] piles, int H) { int lo = 1; int hi = Integer.MAX_VALUE - 1; while (lo < hi) { int mid = (lo + hi) / 2; int h = countHours(piles, mid); if (h <= H) hi = mid; else lo = mid + 1; } return lo; } private int countHours(int[] piles, int K) { int h = 0; for (int i=0; i pq = new PriorityQueue<>(); for(int val : nums) { pq.offer(val); if(pq.size() > k) { pq.poll(); } } return pq.peek(); } /** * https://discuss.leetcode.com/topic/14597/solution-explained */ public int findKthLargest3(int[] nums, int k) { k = nums.length - k; int lo = 0; int hi = nums.length - 1; while (lo < hi) { final int j = partition(nums, lo, hi); if(j < k) { lo = j + 1; } else if (j > k) { hi = j - 1; } else { break; } } return nums[k]; } private int partition(int[] a, int lo, int hi) { int i = lo; int j = hi + 1; while(true) { while(i < hi && less(a[++i], a[lo])); while(j > lo && less(a[lo], a[--j])); if(i >= j) { break; } exch(a, i, j); } exch(a, lo, j); return j; } private void exch(int[] a, int i, int j) { final int tmp = a[i]; a[i] = a[j]; a[j] = tmp; } private boolean less(int v, int w) { return v < w; } /** * https://discuss.leetcode.com/topic/14597/solution-explained */ public int findKthLargest4(int[] nums, int k) { shuffle(nums); k = nums.length - k; int lo = 0; int hi = nums.length - 1; while (lo < hi) { final int j = partition(nums, lo, hi); if(j < k) { lo = j + 1; } else if (j > k) { hi = j - 1; } else { break; } } return nums[k]; } private void shuffle(int a[]) { final Random random = new Random(); for(int ind = 1; ind < a.length; ind++) { final int r = random.nextInt(ind + 1); exch(a, ind, r); } } public int findKthLargest5(int[] nums, int k) { int min = Integer.MAX_VALUE; int max = Integer.MIN_VALUE; for (int n: nums) { min = Math.min(min, n); max = Math.max(max, n); } if (min == max) return min; while (min < max) { int mid = min + (max - min) / 2; int c = count(nums, mid); if (c >= k) { min = mid + 1; } else { max = mid; } } return min; } private int count(int[] nums, int mid) { int res = 0; for (int n: nums) { if (n > mid) res++; } return res; } public int findKthLargest6(int[] nums, int k) { int len = nums.length; int lo = 0; int hi = len - 1; while (lo < hi) { int p = partition2(nums, lo, hi); if (p == (len - k)) return nums[p]; if (p > (len - k)) { hi = p - 1; } else { lo = p + 1; } } return nums[lo]; } private int partition2(int[] nums, int lo, int hi) { if (lo == hi) return lo; int slow = lo+1; int fast = lo+1; while (fast <= hi) { if (nums[fast] < nums[lo]) { swap(nums, slow, fast); slow++; } fast++; } swap(nums, lo, slow-1); return slow-1; } private void swap(int[] nums, int i, int j) { if (i == j) return ; int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; } } ================================================ FILE: src/KthSmallestElementInABST230.java ================================================ /** * Given a binary search tree, write a function kthSmallest to find the kth * smallest element in it. * * Note: * You may assume k is always valid, 1 ≤ k ≤ BST's total elements. * * Follow up: * What if the BST is modified (insert/delete operations) often and you need to * find the kth smallest frequently? How would you optimize the kthSmallest * routine? * */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class KthSmallestElementInABST230 { public int kthSmallest(TreeNode root, int k) { Stack st = new Stack<>(); kthSmallest(root, k, st); return st.pop(); } public void kthSmallest(TreeNode root, int k, Stack st) { if (root == null) return; kthSmallest(root.left, k, st); if (st.size() == k) return; st.push(root.val); if (st.size() == k) return; kthSmallest(root.right, k, st); } public int kthSmallest2(TreeNode root, int k) { int[] i = new int[]{0, 0}; kthSmallest(root, k, i); return i[1]; } public void kthSmallest(TreeNode root, int k, int[] i) { if (root.left != null) kthSmallest(root.left, k, i); if (i[0] == k) return ; i[0] = i[0] + 1; i[1] = root.val; if (i[0] == k) return; if (root.right != null) kthSmallest(root.right, k, i); } public int kthSmallest3(TreeNode root, int k) { int l = kth(root.left); if (l >= k) { return kthSmallest3(root.left, k); } else if (l + 1 == k) { return root.val; } else { return kthSmallest3(root.right, k-l-1); } } public int kth(TreeNode root) { if (root == null) return 0; return kth(root.left) + kth(root.right) + 1; } } ================================================ FILE: src/KthSmallestElementInASortedMatrix378.java ================================================ /** * Given a n x n matrix where each of the rows and columns are sorted in * ascending order, find the kth smallest element in the matrix. * * Note that it is the kth smallest element in the sorted order, not the * kth distinct element. * * Example: * * matrix = [ * [ 1, 5, 9], * [10, 11, 13], * [12, 13, 15] * ], * k = 8, * * return 13. * * Note: * You may assume k is always valid, 1 ≤ k ≤ n2. * */ public class KthSmallestElementInASortedMatrix378 { /** * https://discuss.leetcode.com/topic/52948/share-my-thoughts-and-clean-java-code * * Binary Search: The key point for any binary search is to figure out the * "Search Space". For me, I think there are two kind of "Search Space" -- * index and range(the range from the smallest number to the biggest number). * Most usually, when the array is sorted in one direction, we can use index * as "search space", when the array is unsorted and we are going to find a * specific number, we can use "range". * * The reason why we did not use index as "search space" for this problem * is the matrix is sorted in two directions, we can not find a linear way * to map the number and its index. * */ public int kthSmallest(int[][] matrix, int k) { int lo = matrix[0][0], hi = matrix[matrix.length - 1][matrix[0].length - 1]; while(lo < hi) { int mid = lo + (hi - lo) / 2; int count = 0, j = matrix[0].length - 1; for(int i = 0; i < matrix.length; i++) { while(j >= 0 && matrix[i][j] > mid) j--; count += (j + 1); } if(count < k) lo = mid + 1; else hi = mid; } return lo; } /** * https://discuss.leetcode.com/topic/52948/share-my-thoughts-and-clean-java-code * * Heap: * 1. Build a minHeap of elements from the first row. * 2. Do the following operations k-1 times : * Every time when you poll out the root(Top Element in Heap), you need * to know the row number and column number of that element(so we can * create a tuple class here), replace that root with the next element * from the same column. * */ public int kthSmallest2(int[][] matrix, int k) { int n = matrix.length; PriorityQueue pq = new PriorityQueue(); for(int j = 0; j <= n-1; j++) pq.offer(new Tuple(0, j, matrix[0][j])); for(int i = 0; i < k-1; i++) { Tuple t = pq.poll(); if(t.x == n-1) continue; pq.offer(new Tuple(t.x+1, t.y, matrix[t.x+1][t.y])); } return pq.poll().val; } class Tuple implements Comparable { int x, y, val; public Tuple (int x, int y, int val) { this.x = x; this.y = y; this.val = val; } @Override public int compareTo (Tuple that) { return this.val - that.val; } } } ================================================ FILE: src/KthSmallestPrimeFraction786.java ================================================ /** * A sorted list A contains 1, plus some number of primes. Then, for every p < q * in the list, we consider the fraction p/q. * * What is the K-th smallest fraction considered? Return your answer as an * array of ints, where answer[0] = p and answer[1] = q. * * Examples: * Input: A = [1, 2, 3, 5], K = 3 * Output: [2, 5] * Explanation: * The fractions to be considered in sorted order are: * 1/5, 1/3, 2/5, 1/2, 3/5, 2/3. * The third fraction is 2/5. * * Input: A = [1, 7], K = 1 * Output: [1, 7] * * Note: * A will have length between 2 and 2000. * Each A[i] will be between 1 and 30000. * K will be between 1 and A.length * (A.length - 1) / 2. */ /** * https://leetcode.com/problems/k-th-smallest-prime-fraction/discuss/115819/Summary-of-solutions-for-problems-%22reducible%22-to-LeetCode-378 */ public class KthSmallestPrimeFraction786 { public int[] kthSmallestPrimeFraction(int[] A, int K) { Comparator comp = (int[] a, int[] b) -> { return Double.compare(A[a[0]] * 1.0 / A[a[1]], A[b[0]] * 1.0 / A[b[1]]); }; PriorityQueue q = new PriorityQueue<>(comp); int len = A.length; q.add(new int[]{0, len-1}); boolean[][] mark = new boolean[len][len]; mark[0][len-1] = true; int c = 0; while (c + 1 < K) { int[] tmp = q.remove(); c++; int i = tmp[0]; int j = tmp[1]; if (i+1 < len && i+1 < j && !mark[i+1][j]) { q.add(new int[]{i+1, j}); mark[i+1][j] = true; } if (j-1 >= 0 && i < j-1 && !mark[i][j-1]) { q.add(new int[]{i, j-1}); mark[i][j-1] = true; } if (i+1 < len && j-1 >= 0 && i+1 < j-1 && !mark[i+1][j-1]) { q.add(new int[]{i+1, j-1}); mark[i+1][j-1] = true; } } int[] tmp = q.peek(); return new int[]{A[tmp[0]], A[tmp[1]]}; } /** * https://leetcode.com/problems/k-th-smallest-prime-fraction/discuss/115486/Java-AC-O(max(nk)-*-logn)-Short-Easy-PriorityQueue */ public int[] kthSmallestPrimeFraction2(int[] a, int k) { int n = a.length; // 0: numerator idx, 1: denominator idx PriorityQueue pq = new PriorityQueue<>(new Comparator() { @Override public int compare(int[] o1, int[] o2) { int s1 = a[o1[0]] * a[o2[1]]; int s2 = a[o2[0]] * a[o1[1]]; return s1 - s2; } }); for (int i = 0; i < n-1; i++) { pq.add(new int[]{i, n-1}); } for (int i = 0; i < k-1; i++) { int[] pop = pq.remove(); int ni = pop[0]; int di = pop[1]; if (pop[1] - 1 > pop[0]) { pop[1]--; pq.add(pop); } } int[] peek = pq.peek(); return new int[]{a[peek[0]], a[peek[1]]}; } /** * https://leetcode.com/problems/k-th-smallest-prime-fraction/discuss/116107/Java-Better-than-O(NlogN)-it-can-be-O(KlogK) */ public int[] kthSmallestPrimeFraction3(int[] A, int K) { PriorityQueue pq = new PriorityQueue<>((a, b) -> A[a[0]] * A[b[1]] - A[a[1]] * A[b[0]]); pq.offer(new int[]{0, A.length - 1}); while (K > 1 && !pq.isEmpty()) { int[] cur = pq.poll(); if (cur[1] == A.length - 1 && cur[0] + 1 < cur[1]) { pq.offer(new int[]{cur[0] + 1, cur[1]}); } if (cur[0] < cur[1] - 1) { pq.offer(new int[]{cur[0], cur[1] - 1}); } K--; } if (pq.isEmpty()) { throw new RuntimeException("invalid input."); } return new int[]{A[pq.peek()[0]], A[pq.peek()[1]]}; } } ================================================ FILE: src/KthSymbolInGrammar779.java ================================================ /** * On the first row, we write a 0. Now in every subsequent row, we look at the * previous row and replace each occurrence of 0 with 01, and each occurrence * of 1 with 10. * * Given row N and index K, return the K-th indexed symbol in row N. * (The values of K are 1-indexed.) (1 indexed). * * Examples: * Input: N = 1, K = 1 * Output: 0 * * Input: N = 2, K = 1 * Output: 0 * * Input: N = 2, K = 2 * Output: 1 * * Input: N = 4, K = 5 * Output: 1 * * Explanation: * row 1: 0 * row 2: 01 * row 3: 0110 * row 4: 01101001 * * Note: * N will be an integer in the range [1, 30]. * K will be an integer in the range [1, 2^(N-1)]. */ public class KthSymbolInGrammar779 { public int kthGrammar(int N, int K) { if (N == 1 && K == 1) return 0; return (kthGrammar(N-1, (K+1) / 2) == 0) ^ (K % 2 == 0) ? 0 : 1; } } ================================================ FILE: src/LFUCache460.java ================================================ /** * Design and implement a data structure for Least Frequently Used (LFU) cache. * It should support the following operations: get and put. * * get(key) - Get the value (will always be positive) of the key if the key * exists in the cache, otherwise return -1. * put(key, value) - Set or insert the value if the key is not already present. * When the cache reaches its capacity, it should invalidate the least * frequently used item before inserting a new item. For the purpose of this * problem, when there is a tie (i.e., two or more keys that have the same * frequency), the least recently used key would be evicted. * * Follow up: * Could you do both operations in O(1) time complexity? * * Example: * LFUCache cache = new LFUCache( 2 ); // capacity * * cache.put(1, 1); * cache.put(2, 2); * cache.get(1); // returns 1 * cache.put(3, 3); // evicts key 2 * cache.get(2); // returns -1 (not found) * cache.get(3); // returns 3. * cache.put(4, 4); // evicts key 1. * cache.get(1); // returns -1 (not found) * cache.get(3); // returns 3 * cache.get(4); // returns 4 */ public class LFUCache460 { class LFUCache { // freq -> Linked List private TreeMap treeMap = new TreeMap<>(); // key -> Node private Map map = new HashMap<>(); private int capacity; public LFUCache(int capacity) { this.capacity = capacity; } public int get(int key) { if (!this.map.containsKey(key)) return -1; Node node = map.get(key); deleteFromTreeMap(node); node.freq++; addOnTreeMap(node); return node.val; } private void deleteFromList(Node node) { node.prev.next = node.next; node.next.prev = node.prev; } private void addToListEnd(Node head, Node node) { node.prev = head.prev; node.next = head; head.prev.next = node; head.prev = node; } private void addOnTreeMap(Node node) { Node head = treeMap.get(node.freq); if (head == null) { head = newHead(); } addToListEnd(head, node); this.treeMap.put(node.freq, head); } private void deleteFromTreeMap(Node node) { deleteFromList(node); Node head = treeMap.get(node.freq); if (head.next.freq == -1) { this.treeMap.remove(node.freq); } } public void put(int key, int value) { if (this.capacity == 0) return; Node node = this.map.get(key); if (node == null) { node = new Node(key, value, 1); if (this.map.size() == this.capacity) { Map.Entry first = this.treeMap.firstEntry(); Integer firstKey = first.getKey(); Node firstHead = first.getValue(); Node toBeRemoved = firstHead.next; deleteFromTreeMap(toBeRemoved); this.map.remove(toBeRemoved.key); } this.map.put(key, node); } else { node.val = value; deleteFromTreeMap(node); node.freq++; } addOnTreeMap(node); } private Node newHead() { Node head = new Node(0, 0, -1); head.prev = head; head.next = head; return head; } class Node { Node next; Node prev; int key; int val; int freq; Node(int key, int val, int freq) { this.key = key; this.val = val; this.freq = freq; } } } class LFUCache2 { private FreqNode head; private Map freqMap = new HashMap<>(); private Map itemMap = new HashMap<>(); private int capacity; public LFUCache(int capacity) { this.capacity = capacity; this.head = new FreqNode(); this.head.next = this.head; this.head.prev = this.head; } public int get(int key) { if (!this.itemMap.containsKey(key)) return -1; ItemNode item = this.itemMap.get(key); updateNodeFreq(item); return item.val; } private void updateNodeFreq(ItemNode item) { dislinkNode(item); Integer freq = item.freq; item.freq++; FreqNode currFreqNode = freqMap.get(freq); FreqNode newFreqNode = freqMap.get(freq+1); if (newFreqNode == null) { newFreqNode = new FreqNode(freq+1); freqMap.put(freq+1, newFreqNode); addAfter(currFreqNode, newFreqNode); } addBefore(newFreqNode.itemHead, item); if (itemNodeIsEmpty(currFreqNode.itemHead)) { removeNode(currFreqNode); } } private boolean itemNodeIsEmpty(ItemNode node) { return node.next == node; } private void removeNode(FreqNode node) { dislinkNode(node); this.freqMap.remove(node.freq); } private void removeNode(ItemNode node) { dislinkNode(node); this.itemMap.remove(node.key); } private void dislinkNode(FreqNode node) { node.prev.next = node.next; node.next.prev = node.prev; } private void dislinkNode(ItemNode node) { node.prev.next = node.next; node.next.prev = node.prev; } private void addAfter(FreqNode currNode, FreqNode newNode) { newNode.next = currNode.next; newNode.prev = currNode; currNode.next.prev = newNode; currNode.next = newNode; } private void addAfter(ItemNode currNode, ItemNode newNode) { newNode.next = currNode.next; newNode.prev = currNode; currNode.next.prev = newNode; currNode.next = newNode; } private void addBefore(ItemNode currNode, ItemNode newNode) { newNode.next = currNode; newNode.prev = currNode.prev; currNode.prev.next = newNode; currNode.prev = newNode; } public void put(int key, int value) { if (this.capacity == 0) return; if (this.itemMap.containsKey(key)) { ItemNode item = this.itemMap.get(key); item.val = value; updateNodeFreq(item); return; } if (this.itemMap.size() == this.capacity) { FreqNode first = this.head.next; ItemNode toBeRemoved = first.itemHead.next; removeNode(toBeRemoved); if (itemNodeIsEmpty(first.itemHead)) { removeNode(first); } } FreqNode newFreqNode = freqMap.get(1); if (newFreqNode == null) { newFreqNode = new FreqNode(1); freqMap.put(1, newFreqNode); addAfter(this.head, newFreqNode); } ItemNode newItem = new ItemNode(key, value, 1); addBefore(newFreqNode.itemHead, newItem); this.itemMap.put(key, newItem); } private ItemNode newItemHead() { ItemNode head = new ItemNode(); head.prev = head; head.next = head; return head; } class ItemNode { ItemNode next; ItemNode prev; int key; int val; int freq; ItemNode(int key, int val, int freq) { this.key = key; this.val = val; this.freq = freq; } ItemNode() { this.key = -1; this.val = -1; this.freq = -1; } } class FreqNode { FreqNode next; FreqNode prev; int freq; ItemNode itemHead; FreqNode(int freq) { this.freq = freq; this.itemHead = newItemHead(); } FreqNode() { this.freq = -1; } } } /** * Your LFUCache object will be instantiated and called as such: * LFUCache obj = new LFUCache(capacity); * int param_1 = obj.get(key); * obj.put(key,value); */ } ================================================ FILE: src/LRUCache146.java ================================================ /** * 146. LRU Cache * * Design and implement a data structure for Least Recently Used (LRU) cache. * https://en.wikipedia.org/wiki/Cache_replacement_policies#LRU * * It should support the following operations: get and put. * * get(key) - Get the value (will always be positive) of the key if the key * exists in the cache, otherwise return -1. * put(key, value) - Set or insert the value if the key is not already present. * When the cache reached its capacity, it should invalidate * the least recently used item before inserting a new item. * * Follow up: * Could you do both operations in O(1) time complexity? * * Example: * * LRUCache cache = new LRUCache( 2 ); // capacity * * cache.put(1, 1); * cache.put(2, 2); * cache.get(1); // returns 1 * cache.put(3, 3); // evicts key 2 * cache.get(2); // returns -1 (not found) * cache.put(4, 4); // evicts key 1 * cache.get(1); // returns -1 (not found) * cache.get(3); // returns 3 * cache.get(4); // returns 4 */ /** * Your LRUCache object will be instantiated and called as such: * LRUCache obj = new LRUCache(capacity); * int param_1 = obj.get(key); * obj.put(key,value); */ public class LRUCache { private class Node{ int key, value; Node prev, next; Node(int k, int v){ this.key = k; this.value = v; } Node(){ this(0, 0); } } private int capacity; private Map map; private Node head, tail; public LRUCache(int capacity) { this.capacity = capacity; map = new HashMap<>(); head = new Node(); tail = new Node(); head.next = tail; tail.prev = head; } public int get(int key) { Node n = map.get(key); if(null==n){ return -1; } update(n); return n.value; } public void put(int key, int value) { Node n = map.get(key); if(null==n){ n = new Node(key, value); map.put(key, n); add(n); } else{ n.value = value; update(n); } if(map.size()>capacity){ Node toDel = tail.prev; remove(toDel); map.remove(toDel.key); } } private void update(Node node){ remove(node); add(node); } private void add(Node node){ Node after = head.next; head.next = node; node.prev = head; node.next = after; after.prev = node; } private void remove(Node node){ Node before = node.prev, after = node.next; before.next = after; after.prev = before; } } /** * Easy LinkedHashMap Implementation */ import java.util.LinkedHashMap; import java.util.Map; public class LRUCache { private Map map; private Integer capacity; public LRUCache(int capacity) { map = new LinkedHashMap(capacity) { @Override protected boolean removeEldestEntry(Map.Entry eldest) { return size() > capacity; } }; this.capacity = capacity; } public int get(int key) { if (map.containsKey(key)) { Integer i = map.get(key); map.remove(key); map.put(key, i); return i; } return -1; } public void put(int key, int value) { if (value < 0) return; if (map.containsKey(key)) { map.remove(key); } map.put(key, value); } } // class LRUCache { // // private Map map = new HashMap<>(); // private Node head = new Node(-1, -1); // private Node tail = new Node(-1, -1); // private int capacity; // // public LRUCache(int capacity) { // this.capacity = capacity; // head.next = tail; // tail.pre = head; // } // // public int get(int key) { // Node n = map.get(key); // if (n == null) return -1; // detach(n); // toEnd(n); // return n.val; // } // // public void put(int key, int value) { // Node n = map.get(key); // if (n == null) { // n = new Node(key, value); // if (map.size() >= capacity) { // Node first = head.next; // if (first.val != -1) { // detach(first); // map.remove(first.key); // } // } // toEnd(n); // map.put(key, n); // } else { // n.key = key; // n.val = value; // detach(n); // toEnd(n); // } // } // // private void detach(Node n) { // n.pre.next = n.next; // n.next.pre = n.pre; // } // // private void toEnd(Node n) { // n.pre = tail.pre; // tail.pre.next = n; // tail.pre = n; // n.next = tail; // } // // class Node { // int val; // int key; // Node pre; // Node next; // public Node(int key, int val) { // this.key = key; // this.val = val; // } // } // // } ================================================ FILE: src/LargestBSTSubtree333.java ================================================ /** * Given a binary tree, find the largest subtree which is a Binary Search Tree * (BST), where largest means subtree with largest number of nodes in it. * * Note: * A subtree must include all of its descendants. * * Example: * Input: [10,5,15,1,8,null,7] * * 10 * / \ * 5 15 * / \ \ * 1 8 7 * Output: 3 * Explanation: The Largest BST Subtree in this case is the highlighted one. * The return value is the subtree's size, which is 3. * * Follow up: * Can you figure out ways to solve it with O(n) time complexity? */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class LargestBSTSubtree333 { public int largestBSTSubtree(TreeNode root) { if (root == null) return 0; return helper(root)[0]; } public int[] helper(TreeNode root) { // 0 1 2 3 // {res, isBST(0/1), lower, upper} if (root == null) return null; int[] left = helper(root.left); int[] right = helper(root.right); if (left == null && right == null) { return new int[]{1, 1, root.val, root.val}; } else if (left == null) { boolean isBST = right[1] == 1 && root.val < right[2]; int res = right[0] + (isBST ? 1 : 0); int lower = isBST ? root.val : 0; int upper = isBST ? right[3] : 0; return new int[]{res, isBST ? 1 : 0, lower, upper}; } else if (right == null) { boolean isBST = left[1] == 1 && root.val > left[3]; int res = left[0] + (isBST ? 1 : 0); int lower = isBST ? left[2] : 0; int upper = isBST ? root.val : 0; return new int[]{res, isBST ? 1 : 0, lower, upper}; } else { boolean isBST = left[1] == 1 && right[1] == 1 && root.val > left[3] && root.val < right[2]; int res = isBST ? (left[0] + right[0] + 1) : Math.max(left[0], right[0]); int lower = isBST ? left[2] : 0; int upper = isBST ? right[3] : 0; return new int[]{res, isBST ? 1 : 0, lower, upper}; } } } ================================================ FILE: src/LargestDivisibleSubset368.java ================================================ /** * Given a set of distinct positive integers, find the largest subset such that * every pair (Si, Sj) of elements in this subset satisfies: * Si % Sj = 0 or Sj % Si = 0. * * If there are multiple solutions, return any subset is fine. * * Example 1: * nums: [1,2,3] * Result: [1,2] (of course, [1,3] will also be ok) * * Example 2: * nums: [1,2,4,8] * Result: [1,2,4,8] */ public class LargestDivisibleSubset368 { public List largestDivisibleSubset(int[] nums) { if (nums == null || nums.length == 0) return new ArrayList<>(); Arrays.sort(nums); int N = nums.length; int[] dp = new int[N + 1]; int[] track = new int[N + 1]; int maxIdx = 1; int maxSize = 0; for (int i=1; i<=N; i++) { dp[i] = 1; for (int j=1; j dp[i]) { dp[i] = dp[j] + 1; track[i] = j; } } } if (dp[i] > maxSize) { maxSize = dp[i]; maxIdx = i; } } List res = new ArrayList<>(); int i = maxIdx; while (i != 0) { res.add(nums[i-1]); i = track[i]; } return res; } } ================================================ FILE: src/LargestNumber179.java ================================================ /** * Given a list of non negative integers, arrange them such that they form the * largest number. * * For example, given [3, 30, 34, 5, 9], the largest formed number is 9534330. * * Note: The result may be very large, so you need to return a string instead * of an integer. * */ public class LargestNumber179 { public String largestNumber(int[] nums) { String[] newNums = new String[nums.length]; boolean allZeros = true; for (int i=0; i() { @Override public int compare(String s1, String s2) { String sum1 = s1 + s2; String sum2 = s2 + s1; return sum2.compareTo(sum1); } }); return String.join("", newNums); } /** * https://discuss.leetcode.com/topic/7235/my-3-lines-code-in-java-and-python */ public String largestNumber2(int[] num) { String[] array = Arrays.stream(num).mapToObj(String::valueOf).toArray(String[]::new); Arrays.sort(array, (String s1, String s2) -> (s2 + s1).compareTo(s1 + s2)); return Arrays.stream(array).reduce((x, y) -> x.equals("0") ? y : x + y).get(); } } ================================================ FILE: src/LargestRectangleInHistogram84.java ================================================ /** * Given n non-negative integers representing the histogram's bar height where * the width of each bar is 1, find the area of largest rectangle in the histogram. * * https://leetcode.com/static/images/problemset/histogram.png * Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3]. * * https://leetcode.com/static/images/problemset/histogram_area.png * The largest rectangle is shown in the shaded area, which has area = 10 unit. * * For example, * Given heights = [2,1,5,6,2,3], * return 10. * */ public class LargestRectangleInHistogram84 { /** * https://discuss.leetcode.com/topic/7599/o-n-stack-based-java-solution */ public int largestRectangleArea(int[] height) { int len = height.length; Stack s = new Stack(); int maxArea = 0; for(int i = 0; i <= len; i++){ int h = (i == len ? 0 : height[i]); if(s.isEmpty() || h >= height[s.peek()]){ s.push(i); }else{ int tp = s.pop(); maxArea = Math.max(maxArea, height[tp] * (s.isEmpty() ? i : i - 1 - s.peek())); i--; } } return maxArea; } /** * https://discuss.leetcode.com/topic/39151/5ms-o-n-java-solution-explained-beats-96 */ public int largestRectangleArea2(int[] height) { if (height == null || height.length == 0) { return 0; } int[] lessFromLeft = new int[height.length]; // idx of the first bar the left that is lower than current int[] lessFromRight = new int[height.length]; // idx of the first bar the right that is lower than current lessFromRight[height.length - 1] = height.length; lessFromLeft[0] = -1; for (int i = 1; i < height.length; i++) { int p = i - 1; while (p >= 0 && height[p] >= height[i]) { p = lessFromLeft[p]; } lessFromLeft[i] = p; } for (int i = height.length - 2; i >= 0; i--) { int p = i + 1; while (p < height.length && height[p] >= height[i]) { p = lessFromRight[p]; } lessFromRight[i] = p; } int maxArea = 0; for (int i = 0; i < height.length; i++) { maxArea = Math.max(maxArea, height[i] * (lessFromRight[i] - lessFromLeft[i] - 1)); } return maxArea; } /** * https://discuss.leetcode.com/topic/2424/my-modified-answer-from-geeksforgeeks-in-java */ public int largestRectangleArea3(int[] height) { if (height==null) return 0;//Should throw exception if (height.length==0) return 0; Stack index= new Stack(); index.push(-1); int max=0; for (int i=0;i-1) if (height[index.peek()]>height[i]){ int top=index.pop(); max=Math.max(max,height[top]*(i-1-index.peek())); }else break; index.push(i); } while(index.peek()!=-1){ int top=index.pop(); max=Math.max(max,height[top]*(height.length-1-index.peek())); } return max; } /** * https://discuss.leetcode.com/topic/39836/share-my-2ms-java-solution-beats-100-java-submissions */ public int largestRectangleArea4(int[] heights) { if (heights == null || heights.length == 0) return 0; return getMax(heights, 0, heights.length); } private int getMax(int[] heights, int s, int e) { if (s + 1 >= e) return heights[s]; int min = s; boolean sorted = true; for (int i = s; i < e; i++) { if (i > s && heights[i] < heights[i - 1]) sorted = false; if (heights[min] > heights[i]) min = i; } if (sorted) { int max = 0; for (int i = s; i < e; i++) { max = Math.max(max, heights[i] * (e - i)); } return max; } int left = (min > s) ? getMax(heights, s, min) : 0; int right = (min < e - 1) ? getMax(heights, min + 1, e) : 0; return Math.max(Math.max(left, right), (e - s) * heights[min]); } } ================================================ FILE: src/LemonadeChange860.java ================================================ /** * At a lemonade stand, each lemonade costs $5. * * Customers are standing in a queue to buy from you, and order one at a time * (in the order specified by bills). * * Each customer will only buy one lemonade and pay with either a $5, $10, or * $20 bill. You must provide the correct change to each customer, so that * the net transaction is that the customer pays $5. * * Note that you don't have any change in hand at first. * * Return true if and only if you can provide every customer with correct change. * * Example 1: * Input: [5,5,5,10,20] * Output: true * Explanation: * From the first 3 customers, we collect three $5 bills in order. * From the fourth customer, we collect a $10 bill and give back a $5. * From the fifth customer, we give a $10 bill and a $5 bill. * Since all customers got correct change, we output true. * * Example 2: * Input: [5,5,10] * Output: true * * Example 3: * Input: [10,10] * Output: false * * Example 4: * Input: [5,5,10,10,20] * Output: false * Explanation: * From the first two customers in order, we collect two $5 bills. * For the next two customers in order, we collect a $10 bill and give back a $5 bill. * For the last customer, we can't give change of $15 back because we only have two $10 bills. * Since not every customer received correct change, the answer is false. * * Note: * 0 <= bills.length <= 10000 * bills[i] will be either 5, 10, or 20. */ public class LemonadeChange860 { public boolean lemonadeChange(int[] bills) { int five = 0, ten = 0; for (int bill: bills) { if (bill == 5) { five++; } else if (bill == 10) { if (five == 0) return false; five--; ten++; } else { if (five > 0 && ten > 0) { five--; ten--; } else if (five >= 3) { five -= 3; } else { return false; } } } return true; } } ================================================ FILE: src/LengthOfLongestFibonacciSubsequence873.java ================================================ /** * A sequence X_1, X_2, ..., X_n is fibonacci-like if: * n >= 3 * X_i + X_{i+1} = X_{i+2} for all i + 2 <= n * * Given a strictly increasing array A of positive integers forming a sequence, * find the length of the longest fibonacci-like subsequence of A. * If one does not exist, return 0. * * (Recall that a subsequence is derived from another sequence A by deleting * any number of elements (including none) from A, without changing the order * of the remaining elements. For example, [3, 5, 8] is a subsequence of * [3, 4, 5, 6, 7, 8].) * * Example 1: * Input: [1,2,3,4,5,6,7,8] * Output: 5 * Explanation: * The longest subsequence that is fibonacci-like: [1,2,3,5,8]. * * Example 2: * Input: [1,3,7,11,12,14,18] * Output: 3 * Explanation: * The longest subsequence that is fibonacci-like: * [1,11,12], [3,11,14] or [7,11,18]. * * Note: * * 3 <= A.length <= 1000 * 1 <= A[0] < A[1] < ... < A[A.length - 1] <= 10^9 * (The time limit has been reduced by 50% for submissions in Java, C, and C++.) */ public class LengthOfLongestFibonacciSubsequence873 { public int lenLongestFibSubseq(int[] A) { int len = A.length; int longest = Integer.MIN_VALUE; for (int i=0; i= 0 && idx < len) { l++; a = b; b = A[idx]; if (idx >= len) break; idx = Arrays.binarySearch(A, idx + 1, len, a + b); } if (l > longest) { longest = l; } } } return longest == Integer.MIN_VALUE ? 0 : longest; } public int lenLongestFibSubseq2(int[] A) { int N = A.length; int[][] dp = new int[N + 1][N + 1]; int res = 0; for (int i=2; i A[i-2]) break; int idx = Arrays.binarySearch(A, 0, i-1, toBeFound); if (idx >= 0) { if (dp[idx+1][i] == 0) { dp[i][j] = 3; } else { dp[i][j] += dp[idx+1][i] + 1; } } if (dp[i][j] > res) res = dp[i][j]; } } return res; } public int lenLongestFibSubseq3(int[] A) { int N = A.length; Map index = new HashMap(); for (int i = 0; i < N; ++i) index.put(A[i], i); int[][] dp = new int[N + 1][N + 1]; int res = 0; for (int i=2; i A[i-2]) break; if (index.containsKey(toBeFound)) { int idx = index.get(toBeFound); if (dp[idx+1][i] == 0) { dp[i][j] = 3; } else { dp[i][j] += dp[idx+1][i] + 1; } } if (dp[i][j] > res) res = dp[i][j]; } } return res; } /** * https://leetcode.com/problems/length-of-longest-fibonacci-subsequence/solution/ */ public int lenLongestFibSubseq4(int[] A) { int N = A.length; Map index = new HashMap(); for (int i = 0; i < N; ++i) index.put(A[i], i); Map longest = new HashMap(); int ans = 0; for (int k = 0; k < N; ++k) { for (int j = 0; j < k; ++j) { int i = index.getOrDefault(A[k] - A[j], -1); if (i >= 0 && i < j) { // Encoding tuple (i, j) as integer (i * N + j) int cand = longest.getOrDefault(i * N + j, 2) + 1; longest.put(j * N + k, cand); ans = Math.max(ans, cand); } } } return ans >= 3 ? ans : 0; } /** * https://leetcode.com/problems/length-of-longest-fibonacci-subsequence/discuss/152343/C++JavaPython-Check-Pair */ public int lenLongestFibSubseq5(int[] A) { Set s = new HashSet(); for (int x : A) s.add(x); int res = 2; for (int i = 0; i < A.length; ++i) { for (int j = i + 1; j < A.length; ++j) { int a = A[i], b = A[j], l = 2; while (s.contains(a + b)) { b = a + b; a = b - a; l++; } res = Math.max(res, l); } } return res > 2 ? res : 0; } /** * https://leetcode.com/problems/length-of-longest-fibonacci-subsequence/discuss/152343/C++JavaPython-Check-Pair */ public int lenLongestFibSubseq6(int[] A) { int res = 0; int[][] dp = new int[A.length][A.length]; Map index = new HashMap<>(); for (int j = 0; j < A.length; j++) { index.put(A[j], j); for (int i = 0; i < j; i++) { int k = index.getOrDefault(A[j] - A[i], -1); dp[i][j] = (A[j] - A[i] < A[i] && k >= 0) ? dp[k][i] + 1 : 2; res = Math.max(res, dp[i][j]); } } return res > 2 ? res : 0; } } ================================================ FILE: src/LetterCombinationsOfAPhoneNumber17.java ================================================ /** * Given a digit string, return all possible letter combinations that the number * could represent. * * A mapping of digit to letters (just like on the telephone buttons) is given below. * * Image: http://upload.wikimedia.org/wikipedia/commons/thumb/7/73/Telephone-keypad2.svg/200px-Telephone-keypad2.svg.png * * Input:Digit string "23" * Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]. * * * Note: * Although the above answer is in lexicographical order, your answer could be * in any order you want. * */ public class LetterCombinationsOfAPhoneNumber17 { /** * https://discuss.leetcode.com/topic/8465/my-java-solution-with-fifo-queue */ public List letterCombinations(String digits) { LinkedList ans = new LinkedList(); int L = digits.length(); if (L == 0) return ans; String[] mapping = new String[] {"0", "1", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}; ans.add(""); for(int i =0; i letterCombinations2(String digits) { List ret = new LinkedList(); if (digits.length() == 0) return ret; combination("", digits, 0, ret); return ret; } private void combination(String prefix, String digits, int offset, List ret) { if (offset >= digits.length()) { ret.add(prefix); return; } String letters = KEYS[(digits.charAt(offset) - '0')]; for (int i = 0; i < letters.length(); i++) { combination(prefix + letters.charAt(i), digits, offset + 1, ret); } } private String[] alphas = new String[]{"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}; public List letterCombinations4(String digits) { List res = new ArrayList<>(); if (digits == null || digits.length() == 0) return res; String[] letters = new String[digits.length()]; for (int i=0; i res, String[] letters, int i, StringBuilder sb) { if (i >= letters.length) { res.add(sb.toString()); return; } char[] chars = letters[i].toCharArray(); for (char c: chars) { sb.append(c); helper(res, letters, i+1, sb); sb.deleteCharAt(sb.length()-1); } } } ================================================ FILE: src/LexicographicalNumbers386.java ================================================ /** * Given an integer n, return 1 - n in lexicographical order. * * For example, given 13, return: [1,10,11,12,13,2,3,4,5,6,7,8,9]. * * Please optimize your algorithm to use less time and space. * The input size may be as large as 5,000,000. */ public class LexicographicalNumbers386 { public List lexicalOrder(int n) { List res = new ArrayList<>(); for (int i=1; i<=9; i++) { helper(i, res, n); } return res; } private void helper(int curr, List res, int n) { if (curr > n) return; res.add(curr); for (int i=0; i<=9; i++) { helper(10*curr+i, res, n); } } /** * https://leetcode.com/problems/lexicographical-numbers/discuss/86269/Simple-Java-DFS-Solution-(beats-85-12-lines) */ public List lexicalOrder2(int n) { List res = new ArrayList<>(n); // from 1 to 9. // 0 is can't be a soution. dfs(1, 9, n, res); return res; } private void dfs(int start, int end, int n, List res){ // <= n make the solution can't bigger than n for (int i = start; i <= end && i <= n; i++){ res.add(i); // 10 -> next recursion: 100(->next recursion 1000), 101,102.... // next loop: 11 -> next recursion: 110, 111,112.... // next loop: 12 -> next recursion: 120, 121,122.... // from 0 to 9 different from the dfs call in method lexicalOrder dfs(i * 10, i * 10 + 9, n, res); } } /** * https://leetcode.com/problems/lexicographical-numbers/discuss/86242/Java-O(n)-time-O(1)-space-iterative-solution-130ms */ public List lexicalOrder3(int n) { List res = new ArrayList<>(); int curr = 1; for (int i=1; i<=n; i++) { res.add(curr); if (curr * 10 <= n) { curr *= 10; } else if (curr % 10 != 9 && curr + 1 <= n) { curr++; } else { while ((curr / 10) % 10 == 9) { curr /= 10; } curr = curr / 10 + 1; } } return res; } } ================================================ FILE: src/LicenseKeyFormatting482.java ================================================ /** * You are given a license key represented as a string S which consists only * alphanumeric character and dashes. The string is separated into N+1 groups * by N dashes. * * Given a number K, we would want to reformat the strings such that each group * contains exactly K characters, except for the first group which could be * shorter than K, but still must contain at least one character. Furthermore, * there must be a dash inserted between two groups and all lowercase letters * should be converted to uppercase. * * Given a non-empty string S and a number K, format the string according to * the rules described above. * * Example 1: * Input: S = "5F3Z-2e-9-w", K = 4 * Output: "5F3Z-2E9W" * Explanation: The string S has been split into two parts, each part has 4 * characters. Note that the two extra dashes are not needed and can be removed. * * Example 2: * Input: S = "2-5g-3-J", K = 2 * Output: "2-5G-3J" * Explanation: The string S has been split into three parts, each part has 2 * characters except the first part as it could be shorter as mentioned above. * * Note: * The length of string S will not exceed 12,000, and K is a positive integer. * String S consists only of alphanumerical characters (a-z and/or A-Z and/or 0-9) * and dashes(-). * String S is non-empty. */ public class LicenseKeyFormatting482 { public String licenseKeyFormatting(String S, int K) { char[] chars = S.toCharArray(); int i = chars.length - 1; int loop = -1; StringBuilder sb = new StringBuilder(); while (i >= 0) { if (chars[i] == '-') { i--; continue; } sb.append(Character.toUpperCase(chars[i])); i--; loop = (loop + 1) % K; if (loop == K-1) { sb.append("-"); } } sb = sb.reverse(); if (sb.length() > 0 && sb.charAt(0) == '-') sb.deleteCharAt(0); return sb.toString(); } } ================================================ FILE: src/LinkedListCycle141.java ================================================ /** * Given a linked list, determine if it has a cycle in it. * * Follow up: * Can you solve it without using extra space? * */ /** * Definition for singly-linked list. * class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ public class LinkedListCycle141 { public boolean hasCycle(ListNode head) { ListNode slow = head; ListNode fast = head; while(slow != null && fast != null && fast.next != null) { slow = slow.next; fast = fast.next.next; if (slow == fast) { return true; } } return false; } } ================================================ FILE: src/LinkedListCycleII142.java ================================================ /** * Given a linked list, return the node where the cycle begins. * If there is no cycle, return null. * * Note: Do not modify the linked list. * * Follow up: * Can you solve it without using extra space? */ /** * Definition for singly-linked list. * class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ public class LinkedListCycleII142 { public ListNode detectCycle(ListNode head) { ListNode slow = head; ListNode fast = head; while(slow != null && fast != null && fast.next != null) { slow = slow.next; fast = fast.next.next; if (slow == fast) { fast = head; while (slow != fast) { slow = slow.next; fast = fast.next; } return fast; } } return null; } } ================================================ FILE: src/LinkedListRandomNode382.java ================================================ /** * Given a singly linked list, return a random node's value from the linked * list. Each node must have the same probability of being chosen. * * Follow up: * What if the linked list is extremely large and its length is unknown to * you? Could you solve this efficiently without using extra space? * * Example: * * // Init a singly linked list [1,2,3]. * ListNode head = new ListNode(1); * head.next = new ListNode(2); * head.next.next = new ListNode(3); * Solution solution = new Solution(head); * * // getRandom() should return either 1, 2, or 3 randomly. Each element should * have equal probability of returning. * solution.getRandom(); */ /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ public class LinkedListRandomNode382 { class Solution { private ListNode head; private Random rand = new Random(); /** @param head The linked list's head. Note that the head is guaranteed to be not null, so it contains at least one node. */ public Solution(ListNode head) { this.head = head; } /** Returns a random node's value. */ public int getRandom() { int count = 0; int res = -1; ListNode p = head; while (p != null) { count++; if (count == 1) { res = p.val; } else { int idx = rand.nextInt(count); if (idx == count - 1) res = p.val; } p = p.next; } return res; } } /** * Your Solution object will be instantiated and called as such: * Solution obj = new Solution(head); * int param_1 = obj.getRandom(); */ } ================================================ FILE: src/ListNode.java ================================================ /** * Definition for singly-linked list. */ public class ListNode { int val; ListNode next; ListNode(int x) { val = x; } } ================================================ FILE: src/LoggerRateLimiter359.java ================================================ /** * Design a logger system that receive stream of messages along with its * timestamps, each message should be printed if and only if it is not printed * in the last 10 seconds. * * Given a message and a timestamp (in seconds granularity), return true if * the message should be printed in the given timestamp, otherwise returns * false. * * It is possible that several messages arrive roughly at the same time. * * Example: * * Logger logger = new Logger(); * * // logging string "foo" at timestamp 1 * logger.shouldPrintMessage(1, "foo"); returns true; * * // logging string "bar" at timestamp 2 * logger.shouldPrintMessage(2,"bar"); returns true; * * // logging string "foo" at timestamp 3 * logger.shouldPrintMessage(3,"foo"); returns false; * * // logging string "bar" at timestamp 8 * logger.shouldPrintMessage(8,"bar"); returns false; * * // logging string "foo" at timestamp 10 * logger.shouldPrintMessage(10,"foo"); returns false; * * // logging string "foo" at timestamp 11 * logger.shouldPrintMessage(11,"foo"); returns true; */ public class LoggerRateLimiter359 { class Logger { Map map = new HashMap<>(); /** Initialize your data structure here. */ public Logger() { } /** Returns true if the message should be printed in the given timestamp, otherwise returns false. If this method returns false, the message will not be printed. The timestamp is in seconds granularity. */ public boolean shouldPrintMessage(int timestamp, String message) { if (!map.containsKey(message) || map.get(message) + 10 <= timestamp) { map.put(message, timestamp); return true; } return false; } } /** * https://leetcode.com/problems/logger-rate-limiter/discuss/83254/Java-with-a-LinkedHashMap-and-using-removeEldestEntry */ class Logger2 { public Map map; int lastSecond = 0; /** Initialize your data structure here. */ public Logger() { map = new LinkedHashMap(100, 0.6f, true) { protected boolean removeEldestEntry(Map.Entry eldest) { return lastSecond - eldest.getValue() > 10; } }; } /** Returns true if the message should be printed in the given timestamp, otherwise returns false. If this method returns false, the message will not be printed. The timestamp is in seconds granularity. */ public boolean shouldPrintMessage(int timestamp, String message) { lastSecond = timestamp; if(!map.containsKey(message)||timestamp - map.get(message) >= 10){ map.put(message,timestamp); return true; } return false; } } /** * Your Logger object will be instantiated and called as such: * Logger obj = new Logger(); * boolean param_1 = obj.shouldPrintMessage(timestamp,message); */ } ================================================ FILE: src/LonelyPixelI531.java ================================================ /** * Given a picture consisting of black and white pixels, find the number of * black lonely pixels. * * The picture is represented by a 2D char array consisting of 'B' and 'W', * which means black and white pixels respectively. * * A black lonely pixel is character 'B' that located at a specific position * where the same row and same column don't have any other black pixels. * * Example: * Input: * [['W', 'W', 'B'], * ['W', 'B', 'W'], * ['B', 'W', 'W']] * Output: 3 * Explanation: All the three 'B's are black lonely pixels. * * Note: * The range of width and height of the input 2D array is [1,500]. */ public class LonelyPixelI531 { public int findLonelyPixel(char[][] picture) { if (picture == null || picture.length == 0 || picture[0].length == 0) return 0; int M = picture.length; int N = picture[0].length; int[] hori = new int[M]; int[] vert = new int[N]; for (int i=0; i stack = new Stack<>(); int currentLength = 0; int longest = 0; while (i < len) { int currentLevel = stack.size(); String path = paths[i]; int level = levelOf(path); int diff = currentLevel - level; for (int k=0; k stack = new ArrayDeque<>(); stack.push(0); // "dummy" length int maxLen = 0; for(String s:input.split("\n")){ int lev = s.lastIndexOf("\t")+1; // number of "\t" while(lev+1 0){ Arrays.sort(strs); char [] a = strs[0].toCharArray(); char [] b = strs[strs.length-1].toCharArray(); for (int i = 0; i < a.length; i ++){ if (b.length > i && b[i] == a[i]){ result.append(b[i]); } else { return result.toString(); } } } return result.toString(); } } ================================================ FILE: src/LongestConsecutiveSequence128.java ================================================ /** * Given an unsorted array of integers, find the length of the longest * consecutive elements sequence. * * For example, * Given [100, 4, 200, 1, 3, 2], * The longest consecutive elements sequence is [1, 2, 3, 4]. * Return its length: 4. * * Your algorithm should run in O(n) complexity. * */ public class LongestConsecutiveSequence128 { public int longestConsecutive(int[] nums) { if (nums == null || nums.length == 0) return 0; Map ranges = new HashMap<>(); Set found = new HashSet<>(); int res = 1; for (int i=0; i set = new HashSet<>(); for (int n : nums) set.add(n); int res = 1; for (int n : set) { if (set.contains(n-1)) continue; int curr = n; int temp = 1; while (set.contains(curr+1)) { curr += 1; temp += 1; } res = Math.max(res, temp); } return res; } } ================================================ FILE: src/LongestContinuousIncreasingSubsequence674.java ================================================ /** * Given an unsorted array of integers, find the length of longest continuous * increasing subsequence (subarray). * * Example 1: * Input: [1,3,5,4,7] * Output: 3 * Explanation: The longest continuous increasing subsequence is [1,3,5], its * length is 3. * Even though [1,3,5,7] is also an increasing subsequence, it's not a * continuous one where 5 and 7 are separated by 4. * * Example 2: * Input: [2,2,2,2,2] * Output: 1 * Explanation: The longest continuous increasing subsequence is [2], its * length is 1. * * Note: Length of the array will not exceed 10,000. */ public class LongestContinuousIncreasingSubsequence674 { public int findLengthOfLCIS(int[] nums) { int len = 0; int res = 0; if (nums == null || nums.length == 0) return res; int pre = nums[0]-1; for (int n: nums) { if (n > pre) { len++; } else { res = Math.max(res, len); len = 1; } pre = n; } return Math.max(res, len); } public int findLengthOfLCIS2(int[] nums) { int count = 0; int res = 0; for (int i=0; i nums[i-1]) { count++; } else { count = 1; } } res = Math.max(res, count); } return res; } } ================================================ FILE: src/LongestHarmoniousSubsequence594.java ================================================ /** * We define a harmonious array is an array where the difference between its * maximum value and its minimum value is exactly 1. * * Now, given an integer array, you need to find the length of its longest * harmonious subsequence among all its possible subsequences. * * Subsequences: https://en.wikipedia.org/wiki/Subsequence * * Example 1: * Input: [1,3,2,2,5,2,3,7] * Output: 5 * Explanation: The longest harmonious subsequence is [3,2,2,2,3]. * * Note: The length of the input array will not exceed 20,000. */ public class LongestHarmoniousSubsequence594 { public int findLHS(int[] nums) { if (nums == null || nums.length == 0) return 0; int res = 0; Map map = new HashMap<>(); for (int n: nums) { map.put(n, map.getOrDefault(n, 0)+1); int b = map.get(n); if (map.containsKey(n-1)) { int a = map.get(n-1); if (a + b > res) res = a + b; } if (map.containsKey(n+1)) { int a = map.get(n+1); if (a + b > res) res = a + b; } } return res; } /** * https://leetcode.com/problems/longest-harmonious-subsequence/solution/ */ public int findLHS2(int[] nums) { HashMap < Integer, Integer > map = new HashMap < > (); int res = 0; for (int num: nums) { map.put(num, map.getOrDefault(num, 0) + 1); } for (int key: map.keySet()) { if (map.containsKey(key + 1)) res = Math.max(res, map.get(key) + map.get(key + 1)); } return res; } /** * https://leetcode.com/problems/longest-harmonious-subsequence/solution/ */ public int findLHS3(int[] nums) { Arrays.sort(nums); int prev_count = 1, res = 0; for (int i = 0; i < nums.length; i++) { int count = 1; if (i > 0 && nums[i] - nums[i - 1] == 1) { while (i < nums.length - 1 && nums[i] == nums[i + 1]) { count++; i++; } res = Math.max(res, count + prev_count); prev_count = count; } else { while (i < nums.length - 1 && nums[i] == nums[i + 1]) { count++; i++; } prev_count = count; } } return res; } public int findLHS4(int[] nums) { if (nums == null || nums.length == 0) return 0; Arrays.sort(nums); int N = nums.length; int res = 0; int preCount = -1; int pre = 0; int count = 1; int curr = nums[0]; int i = 1; while (i < N && nums[i] == curr) { count++; i++; } while (i < N) { if (nums[i] == curr) { count++; } else { if (preCount != -1 && curr == pre + 1 && (count + preCount) > res) { res = count + preCount; } preCount = count; pre = curr; count = 1; curr = nums[i]; } i++; } if (preCount != -1 && curr == pre + 1 && (count + preCount) > res) { res = count + preCount; } return res; } } ================================================ FILE: src/LongestIncreasingSubsequence300.java ================================================ /** * Given an unsorted array of integers, find the length of longest increasing * subsequence. * * For example, * Given [10, 9, 2, 5, 3, 7, 101, 18], * The longest increasing subsequence is [2, 3, 7, 101], therefore the length * is 4. Note that there may be more than one LIS combination, it is only * necessary for you to return the length. * * Your algorithm should run in O(n2) complexity. * * Follow up: Could you improve it to O(n log n) time complexity? */ public class LongestIncreasingSubsequence300 { public int lengthOfLIS(int[] nums) { if (nums == null || nums.length == 0) return 0; int N = nums.length; int[] dp = new int[N + 1]; int res = 0; for (int i=1; i<=N; i++) { dp[i] = 1; for (int j=1; j nums[j-1]) { dp[i] = Math.max(dp[i], dp[j] + 1); } } if (dp[i] > res) res = dp[i]; } return res; } /** * https://leetcode.com/problems/longest-increasing-subsequence/solution/ * https://www.geeksforgeeks.org/longest-monotonically-increasing-subsequence-size-n-log-n/ */ public int lengthOfLIS2(int[] nums) { int[] dp = new int[nums.length]; int len = 0; for (int num : nums) { int i = Arrays.binarySearch(dp, 0, len, num); if (i < 0) { i = -(i + 1); } dp[i] = num; if (i == len) { len++; } } return len; } /** * https://leetcode.com/problems/longest-increasing-subsequence/solution/ */ public int lengthOfLIS3(int[] nums) { int memo[][] = new int[nums.length + 1][nums.length]; for (int[] l : memo) { Arrays.fill(l, -1); } return lengthofLIS(nums, -1, 0, memo); } public int lengthofLIS(int[] nums, int previndex, int curpos, int[][] memo) { if (curpos == nums.length) { return 0; } if (memo[previndex + 1][curpos] >= 0) { return memo[previndex + 1][curpos]; } int taken = 0; if (previndex < 0 || nums[curpos] > nums[previndex]) { taken = 1 + lengthofLIS(nums, curpos, curpos + 1, memo); } int nottaken = lengthofLIS(nums, previndex, curpos + 1, memo); memo[previndex + 1][curpos] = Math.max(taken, nottaken); return memo[previndex + 1][curpos]; } /** * https://leetcode.com/problems/longest-increasing-subsequence/discuss/74824/JavaPython-Binary-search-O(nlogn)-time-with-explanation */ public int lengthOfLIS4(int[] nums) { int[] tails = new int[nums.length]; int size = 0; for (int x : nums) { int i = 0, j = size; while (i != j) { int m = (i + j) / 2; if (tails[m] < x) i = m + 1; else j = m; } tails[i] = x; if (i == size) ++size; } return size; } } ================================================ FILE: src/LongestMountainInArray845.java ================================================ /** * Let's call any (contiguous) subarray B (of A) a mountain if the following * properties hold: * - B.length >= 3 * - There exists some 0 < i < B.length - 1 such that * B[0] < B[1] < ... B[i-1] < B[i] > B[i+1] > ... > B[B.length - 1] * (Note that B could be any subarray of A, including the entire array A.) * * Given an array A of integers, return the length of the longest mountain. * * Return 0 if there is no mountain. * * Example 1: * Input: [2,1,4,7,3,2,5] * Output: 5 * Explanation: The largest mountain is [1,4,7,3,2] which has length 5. * * Example 2: * Input: [2,2,2] * Output: 0 * Explanation: There is no mountain. * * Note: * 0 <= A.length <= 10000 * 0 <= A[i] <= 10000 * * Follow up: * Can you solve it using only one pass? * Can you solve it in O(1) space? */ public class LongestMountainInArray845 { public int longestMountain(int[] A) { if (A == null || A.length < 3) return 0; int len = A.length; boolean up = false; boolean down = false; int left = 0; int longest = 0; for (int i=1; i A[i-1]) { if (!(up && !down)) { up = true; down = false; left = i-1; } } else { down = up; if (!up) { left = i; } } if (up && down && i - left + 1 > longest) { longest = i - left + 1; } } return longest; } } ================================================ FILE: src/LongestPalindrome409.java ================================================ /** * Given a string which consists of lowercase or uppercase letters, find the * length of the longest palindromes that can be built with those letters. * * This is case sensitive, for example "Aa" is not considered a palindrome here. * * Note: * Assume the length of given string will not exceed 1,010. * * Example: * Input: * "abccccdd" * Output: * 7 * * Explanation: * One longest palindrome that can be built is "dccaccd", whose length is 7. */ public class LongestPalindrome409 { public int longestPalindrome(String s) { Map map = new HashMap<>(); for (char ch: s.toCharArray()) { map.put(ch, map.getOrDefault(ch, 0) + 1); } int res = 0; boolean hasOdd = false; for (int i: map.values()) { if (i % 2 == 0) { res += i; } else { res += i - 1; hasOdd = true; } } return res + (hasOdd ? 1 : 0); } /** * https://leetcode.com/problems/longest-palindrome/discuss/89604/Simple-HashSet-solution-Java */ public int longestPalindrome2(String s) { if(s==null || s.length()==0) return 0; HashSet hs = new HashSet(); int count = 0; for(int i=0; i=0; i--) { dp[i][i] = 1; for (int j=i+1; j j) return 0; if (i == j) return 1; if (chars[i] == chars[j]) { dp[i][j] = helper(chars, i+1, j-1, dp) + 2; } else { dp[i][j] = Math.max(helper(chars, i+1, j, dp), helper(chars, i, j-1, dp)); } return dp[i][j]; } } ================================================ FILE: src/LongestPalindromicSubstring5.java ================================================ /** * Given a string s, find the longest palindromic substring in s. You may * assume that the maximum length of s is 1000. * * Example: * * Input: "babad" * * Output: "bab" * * Note: "aba" is also a valid answer. * Example: * * Input: "cbbd" * * Output: "bb" */ import java.util.Arrays; public class LongestPalindromicSubstring5 { public String longestPalindrome(String s) { char[] input = s.toCharArray(); int length = input.length; if (length == 1) { return s; } String output = ""; for (int i = 0; i < length; i++) { for (int j = 0; j < 2; j++) { int left = i; int right = i + j; while (left >= 0 && right < length && input[left] == input[right]) { left--; right++; } left++; right--; if (output.length() < right - left + 1) { output = String.valueOf(Arrays.copyOfRange(input, left, right+1)); } } } return output; } /** * https://discuss.leetcode.com/topic/23498/very-simple-clean-java-solution */ private int lo, maxLen; public String longestPalindrome2(String s) { int len = s.length(); if (len < 2) return s; for (int i = 0; i < len-1; i++) { extendPalindrome(s, i, i); //assume odd length, try to extend Palindrome as possible extendPalindrome(s, i, i+1); //assume even length. } return s.substring(lo, lo + maxLen); } private void extendPalindrome(String s, int j, int k) { while (j >= 0 && k < s.length() && s.charAt(j) == s.charAt(k)) { j--; k++; } if (maxLen < k - j - 1) { lo = j + 1; maxLen = k - j - 1; } } /** * https://leetcode.com/problems/longest-palindromic-substring/discuss/2921/Share-my-Java-solution-using-dynamic-programming */ public String longestPalindrome3(String s) { int n = s.length(); String res = null; boolean[][] dp = new boolean[n][n]; for (int i = n - 1; i >= 0; i--) { for (int j = i; j < n; j++) { dp[i][j] = s.charAt(i) == s.charAt(j) && (j - i < 3 || dp[i + 1][j - 1]); if (dp[i][j] && (res == null || j - i + 1 > res.length())) { res = s.substring(i, j + 1); } } } return res; } public String longestPalindrome4(String s) { if (s == null || s.length() <= 1) return s; int N = s.length(); int[][] dp = new int[N][N]; char[] chars = s.toCharArray(); int end = -1; int len = Integer.MIN_VALUE; for (int i=N-1; i>=0; i--) { for (int j=i; j len) { len = dp[i][j]; end = j; } } } return s.substring(end+1-len, end+1); } /** * https://leetcode.com/problems/longest-palindromic-substring/solution/ */ public String longestPalindrome5(String s) { if (s == null || s.length() < 1) return ""; int start = 0, end = 0; for (int i = 0; i < s.length(); i++) { int len1 = expandAroundCenter(s, i, i); int len2 = expandAroundCenter(s, i, i + 1); int len = Math.max(len1, len2); if (len > end - start) { start = i - (len - 1) / 2; end = i + len / 2; } } return s.substring(start, end + 1); } private int expandAroundCenter(String s, int left, int right) { int L = left, R = right; while (L >= 0 && R < s.length() && s.charAt(L) == s.charAt(R)) { L--; R++; } return R - L - 1; } } ================================================ FILE: src/LongestRepeatingCharacterReplacement424.java ================================================ /** * Given a string that consists of only uppercase English letters, you can * replace any letter in the string with another letter at most k times. Find * the length of a longest substring containing all repeating letters you can * get after performing the above operations. * * Note: * Both the string's length and k will not exceed 104. * * Example 1: * Input: * s = "ABAB", k = 2 * Output: * 4 * * Explanation: * Replace the two 'A's with two 'B's or vice versa. * * Example 2: * Input: * s = "AABABBA", k = 1 * Output: * 4 * * Explanation: * Replace the one 'A' in the middle with 'B' and form "AABBBBA". * The substring "BBBB" has the longest repeating letters, which is 4. */ public class LongestRepeatingCharacterReplacement424 { public int characterReplacement(String s, int k) { if (s == null || s.length() == 0) return 0; int N = s.length(); char[] chars = s.toCharArray(); int[] map = new int[26]; Comparator comp = (p1, p2) -> Integer.compare(p2.count, p1.count); PriorityQueue pq = new PriorityQueue(26, comp); int res = 0; int left = 0; int right = 0; while (right < N) { char c = chars[right++]; pq.remove(new Point(c, map[c-'A'])); pq.add(new Point(c, map[c-'A'] + 1)); map[c-'A']++; while (right - left - pq.peek().count > k) { char leftC = chars[left++]; pq.remove(new Point(leftC, map[leftC-'A'])); pq.add(new Point(leftC, map[leftC-'A'] - 1)); map[leftC-'A']--; } if (right - left > res) { res = right - left; } } return res; } class Point { char ch; int count; Point(char c, int cnt) { ch = c; count = cnt; } } public int characterReplacement2(String s, int k) { if (s == null || s.length() == 0) return 0; int N = s.length(); char[] chars = s.toCharArray(); int[] map = new int[26]; int res = 0; int left = 0; int right = 0; while (right < N) { char c = chars[right++]; map[c-'A']++; while (right - left - getMax(map) > k) { char leftC = chars[left++]; map[leftC-'A']--; } if (right - left > res) { res = right - left; } } return res; } private int getMax(int[] map) { int res = 0; for (int c: map) { if (c > res) { res = c; } } return res; } /** * https://leetcode.com/problems/longest-repeating-character-replacement/discuss/91271/Java-12-lines-O(n)-sliding-window-solution-with-explanation * * maxCount may be invalid at some points, but this doesn't matter, because * it was valid earlier in the string, and all that matters is finding the * max window that occurred anywhere in the string. Additionally, it will * expand if and only if enough repeating characters appear in the window * to make it expand. So whenever it expands, it's a valid expansion. */ public int characterReplacement3(String s, int k) { int len = s.length(); int[] count = new int[26]; int start = 0, maxCount = 0, maxLength = 0; for (int end = 0; end < len; end++) { maxCount = Math.max(maxCount, ++count[s.charAt(end) - 'A']); while (end - start + 1 - maxCount > k) { count[s.charAt(start) - 'A']--; start++; } maxLength = Math.max(maxLength, end - start + 1); } return maxLength; } } ================================================ FILE: src/LongestSubstringWithAtMostKDistinctCharacters340.java ================================================ /** * Given a string, find the length of the longest substring T that contains * at most k distinct characters. * * For example, Given s = “eceba” and k = 2, * * T is "ece" which its length is 3. */ public class LongestSubstringWithAtMostKDistinctCharacters340 { public int lengthOfLongestSubstringKDistinct(String s, int k) { if (s == null || s.length() == 0) return 0; int len = s.length(); int left = 0; int right = 0; int res = 0; int count = 0; int[] map = new int[256]; char[] chars = s.toCharArray(); while (right < len) { if (map[chars[right]] == 0) { count++; } map[chars[right]]++; right++; if (count <= k && right - left > res) { res = right - left; } while (count == k + 1) { map[chars[left]]--; if (map[chars[left]] == 0) { count--; } left++; } } return res; } /** * https://leetcode.com/problems/longest-substring-with-at-most-k-distinct-characters/discuss/80044/Java-O(nlogk)-using-TreeMap-to-keep-last-occurrence-Interview-%22follow-up%22-question! */ public int lengthOfLongestSubstringKDistinct2(String str, int k) { if (str == null || str.isEmpty() || k == 0) { return 0; } TreeMap lastOccurrence = new TreeMap<>(); Map inWindow = new HashMap<>(); int j = 0; int max = 1; for (int i = 0; i < str.length(); i++) { char in = str.charAt(i); while (inWindow.size() == k && !inWindow.containsKey(in)) { int first = lastOccurrence.firstKey(); char out = lastOccurrence.get(first); inWindow.remove(out); lastOccurrence.remove(first); j = first + 1; } //update or add in's position in both maps if (inWindow.containsKey(in)) { lastOccurrence.remove(inWindow.get(in)); } inWindow.put(in, i); lastOccurrence.put(i, in); max = Math.max(max, i - j + 1); } return max; } /** * https://leetcode.com/problems/longest-substring-with-at-most-k-distinct-characters/discuss/80082/Solution-to-the-follow-up */ public int lengthOfLongestSubstringKDistinct3(String s, int k) { if(s==null || s.length()==0 || k<=0) return 0; int len=s.length(); int i=0, j=0; int maxLen=0; LinkedHashMap map=new LinkedHashMap(); for(char x:s.toCharArray()){ if(map.containsKey(x)){ map.remove(x); map.put(x,j); }else{ if(map.size()==k){ maxLen=Math.max(maxLen,j-i); char toRemove=map.keySet().iterator().next(); i=map.get(toRemove)+1; map.remove(toRemove); } map.put(x,j); } j++; } maxLen=Math.max(maxLen,j-i); return maxLen; } } ================================================ FILE: src/LongestSubstringWithAtMostTwoDistinctCharacters159.java ================================================ /** * Given a string s , find the length of the longest substring t that contains * at most 2 distinct characters. * * Example 1: * Input: "eceba" * Output: 3 * Explanation: t is "ece" which its length is 3. * * Example 2: * Input: "ccaabbb" * Output: 5 * Explanation: t is "aabbb" which its length is 5. */ public class LongestSubstringWithAtMostTwoDistinctCharacters159 { public int lengthOfLongestSubstringTwoDistinct(String s) { return lengthOfLongestSubstringKDistinct(s, 2); } // 340. Longest Substring with At Most K Distinct Characters public int lengthOfLongestSubstringKDistinct(String s, int k) { if (s == null || s.length() == 0 || k == 0) return 0; int[] map = new int[256]; int left = 0; int right = 0; int N = s.length(); char[] chars = s.toCharArray(); int num = 0; int res = 0; while (right < N) { char c = chars[right++]; if (map[c] == 0) { num++; } map[c]++; while (num > k) { char leftC = chars[left++]; if (map[leftC] == 1) { num--; } map[leftC]--; } if (right - left > res) { res = right - left; } } return res; } } ================================================ FILE: src/LongestSubstringWithoutRepeatingCharacters3.java ================================================ /** * Given a string, find the length of the longest substring without repeating characters. * * Examples: * * Given "abcabcbb", the answer is "abc", which the length is 3. * * Given "bbbbb", the answer is "b", with the length of 1. * * Given "pwwkew", the answer is "wke", with the length of 3. Note that the * answer must be a substring, "pwke" is a subsequence and not a substring. */ import java.util.Map; import java.util.HashMap; public class LongestSubstringWithoutRepeatingCharacters3 { public int lengthOfLongestSubstring(String s) { if (s.length() < 2) { return s.length(); } int start = 0; int ll = 1; Map found = new HashMap<>(); found.put(s.charAt(0), 0); int i; for (i = 1; i < s.length(); i++) { if (found.containsKey(s.charAt(i))) { int newStart = remove(start, i, s.charAt(i), found, s); if (i - start > ll) { ll = i - start; } start = newStart; } else { found.put(s.charAt(i), i); } } return Math.max(ll, i - start); } private int remove(int start, int now, char re, Map found, String s) { int j; for (j = start; j < now; j++) { if (s.charAt(j) == re) { found.remove(s.charAt(j)); break; } found.remove(s.charAt(j)); } found.put(s.charAt(now), now); return j + 1; } /** * https://discuss.leetcode.com/topic/8232/11-line-simple-java-solution-o-n-with-explanation */ public int lengthOfLongestSubstring2(String s) { if (s.length()==0) return 0; HashMap map = new HashMap(); int max=0; for (int i=0, j=0; i maxLen) { maxLen = right - left; } while (map[curr] > 1) { char leftChar = chars[left++]; map[leftChar]--; } } return maxLen; } } ================================================ FILE: src/LongestUnivaluePath687.java ================================================ /** * Given a binary tree, find the length of the longest path where each node in * the path has the same value. This path may or may not pass through the root. * * Note: The length of path between two nodes is represented by the number of edges between them. * * Example 1: * Input: * * 5 * / \ * 4 5 * / \ \ * 1 1 5 * Output: 2 * * Example 2: * Input: * * 1 * / \ * 4 5 * / \ \ * 4 4 5 * Output: 2 * * Note: The given binary tree has not more than 10000 nodes. The height of the * tree is not more than 1000. */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class LongestUnivaluePath687 { public int longestUnivaluePath(TreeNode root) { if (root == null) return 0; return helper(root)[1]; } private int[] helper(TreeNode root) { int[] res = new int[]{0, 0}; if (root.left != null && root.right != null) { int[] left = helper(root.left); int[] right = helper(root.right); if (root.val == root.left.val && root.val == root.right.val) { res[0] = Math.max(left[0], right[0]) + 1; res[1] = left[0] + right[0] + 2; } else if (root.val == root.left.val) { res[0] = left[0] + 1; } else if (root.val == root.right.val) { res[0] = right[0] + 1; } res[1] = Math.max(Math.max(Math.max(left[1], right[1]), res[1]), res[0]); } else if (root.left != null) { int[] left = helper(root.left); res[0] = root.val == root.left.val ? left[0] + 1 : 0; res[1] = Math.max(left[1], res[0]); } else if (root.right != null) { int[] right = helper(root.right); res[0] = root.val == root.right.val ? right[0] + 1 : 0; res[1] = Math.max(right[1], res[0]); } return res; } /** * https://leetcode.com/problems/longest-univalue-path/solution/ */ int ans; public int longestUnivaluePath2(TreeNode root) { ans = 0; arrowLength(root); return ans; } public int arrowLength(TreeNode node) { if (node == null) return 0; int left = arrowLength(node.left); int right = arrowLength(node.right); int arrowLeft = 0, arrowRight = 0; if (node.left != null && node.left.val == node.val) { arrowLeft += left + 1; } if (node.right != null && node.right.val == node.val) { arrowRight += right + 1; } ans = Math.max(ans, arrowLeft + arrowRight); return Math.max(arrowLeft, arrowRight); } } ================================================ FILE: src/LongestValidParentheses32.java ================================================ /** * Given a string containing just the characters '(' and ')', find the length * of the longest valid (well-formed) parentheses substring. * * Example 1: * Input: "(()" * Output: 2 * Explanation: The longest valid parentheses substring is "()" * * Example 2: * Input: ")()())" * Output: 4 * Explanation: The longest valid parentheses substring is "()()" */ public class LongestValidParentheses32 { public int longestValidParentheses(String s) { int len = s.length(); if (len <= 1) return 0; boolean[] valid = new boolean[len]; Stack stack = new Stack<>(); char[] chars = s.toCharArray(); for (int i=0; i stack = new Stack<>(); stack.push(-1); for (int i = 0; i < s.length(); i++) { if (s.charAt(i) == '(') { stack.push(i); } else { stack.pop(); if (stack.empty()) { stack.push(i); } else { maxans = Math.max(maxans, i - stack.peek()); } } } return maxans; } /** * https://leetcode.com/problems/longest-valid-parentheses/solution/ */ public int longestValidParentheses3(String s) { int left = 0, right = 0, maxlength = 0; for (int i = 0; i < s.length(); i++) { if (s.charAt(i) == '(') { left++; } else { right++; } if (left == right) { maxlength = Math.max(maxlength, 2 * right); } else if (right >= left) { left = right = 0; } } left = right = 0; for (int i = s.length() - 1; i >= 0; i--) { if (s.charAt(i) == '(') { left++; } else { right++; } if (left == right) { maxlength = Math.max(maxlength, 2 * left); } else if (left >= right) { left = right = 0; } } return maxlength; } } ================================================ FILE: src/LongestWordInDictionary720.java ================================================ /** * Given a list of strings words representing an English Dictionary, find the * longest word in words that can be built one character at a time by other * words in words. If there is more than one possible answer, return the * longest word with the smallest lexicographical order. * * If there is no answer, return the empty string. * * Example 1: * Input: * words = ["w","wo","wor","worl", "world"] * Output: "world" * Explanation: * The word "world" can be built one character at a time by "w", "wo", "wor", and "worl". * * Example 2: * Input: * words = ["a", "banana", "app", "appl", "ap", "apply", "apple"] * Output: "apple" * Explanation: * Both "apply" and "apple" can be built from other words in the dictionary. * However, "apple" is lexicographically smaller than "apply". * * Note: * All the strings in the input will only contain lowercase letters. * The length of words will be in the range [1, 1000]. * The length of words[i] will be in the range [1, 30]. */ public class LongestWordInDictionary720 { public String longestWord(String[] words) { Arrays.sort(words); int N = words.length; String res = ""; Stack stack = new Stack<>(); for (int i=0; i= words[i].length()) { stack.pop(); } String curr = stack.isEmpty() ? "" : stack.peek(); if (curr.length() + 1 == words[i].length() && words[i].startsWith(curr)) { stack.push(words[i]); } if (!stack.isEmpty() && stack.peek().length() > res.length()) { res = stack.peek(); } } return res; } /** * https://leetcode.com/problems/longest-word-in-dictionary/discuss/109114/JavaC%2B%2B-Clean-Code */ public String longestWord2(String[] words) { Arrays.sort(words); Set built = new HashSet(); String res = ""; for (String w : words) { if (w.length() == 1 || built.contains(w.substring(0, w.length() - 1))) { res = w.length() > res.length() ? w : res; built.add(w); } } return res; } public String longestWord3(String[] words) { Trie trie = constructTrie(words); trie.isWord = true; String[] res = new String[]{""}; dfs(trie, new StringBuilder(), res); return res[0]; } private void dfs(Trie trie, StringBuilder sb, String[] res) { if (trie == null || !trie.isWord) return; if (sb.length() > res[0].length()) { res[0] = sb.toString(); } for (char ch='a'; ch<='z'; ch++) { Trie child = trie.children[ch-'a']; if (child == null) continue; sb.append(ch); dfs(child, sb, res); sb.deleteCharAt(sb.length()-1); } } private Trie constructTrie(String[] words) { Trie trie = new Trie(); for (String word: words) { trie.add(word); } return trie; } class Trie { Trie[] children = new Trie[26]; boolean isWord; void add(String word) { add(word.toCharArray(), 0); } void add(char[] word, int i) { if (i == word.length) { this.isWord = true; return; } int idx = word[i] - 'a'; if (this.children[idx] == null) { this.children[idx] = new Trie(); } this.children[idx].add(word, i+1); } } } ================================================ FILE: src/LowestCommonAncestorOfABinarySearchTree235.java ================================================ /** * Given a binary search tree (BST), find the lowest common ancestor (LCA) of * two given nodes in the BST. * * According to the definition of LCA on Wikipedia: “The lowest common ancestor * is defined between two nodes p and q as the lowest node in T that has both p * and q as descendants (where we allow a node to be a descendant of itself).” * * Given binary search tree: root = [6,2,8,0,4,7,9,null,null,3,5] * * _______6______ * / \ * ___2__ ___8__ * / \ / \ * 0 _4 7 9 * / \ * 3 5 * * Example 1: * Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8 * Output: 6 * Explanation: The LCA of nodes 2 and 8 is 6. * * Example 2: * Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4 * Output: 2 * Explanation: The LCA of nodes 2 and 4 is 2, since a node can be a descendant * of itself according to the LCA definition. * * Note: * All of the nodes' values will be unique. * p and q are different and both values will exist in the BST. */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class LowestCommonAncestorOfABinarySearchTree235 { public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { if (root == null) return root; if (p.val > root.val && q.val > root.val) { return lowestCommonAncestor(root.right, p, q); } else if (p.val < root.val && q.val < root.val) { return lowestCommonAncestor(root.left, p, q); } else { return root; } } public TreeNode lowestCommonAncestor2(TreeNode root, TreeNode p, TreeNode q) { while ((root.val - p.val) * (root.val - q.val) > 0) root = p.val < root.val ? root.left : root.right; return root; } public TreeNode lowestCommonAncestor3(TreeNode root, TreeNode p, TreeNode q) { return (root.val - p.val) * (root.val - q.val) < 1 ? root : lowestCommonAncestor(p.val < root.val ? root.left : root.right, p, q); } // in case the node p or q is not in the BST public TreeNode lowestCommonAncestor4(TreeNode root, TreeNode p, TreeNode q) { if (root == null || p == null || q == null) return null; if (root.val > p.val && root.val > q.val) { return lowestCommonAncestor(root.left, p, q); } else if (root.val < p.val && root.val < q.val) { return lowestCommonAncestor(root.right, p, q); } else if (find(root, p) && find(root, q)) { return root; } else { return null; } } private boolean find(TreeNode root, TreeNode n) { if (root == null || n == null) return false; if (root.val == n.val) { return true; } else if (root.val > n.val) { return find(root.left, n); } else { return find(root.right, n); } } } ================================================ FILE: src/LowestCommonAncestorOfABinaryTree236.java ================================================ /** * Given a binary tree, find the lowest common ancestor (LCA) of two given * nodes in the tree. * * According to the definition of LCA on Wikipedia: “The lowest common ancestor * is defined between two nodes p and q as the lowest node in T that has both p * and q as descendants (where we allow a node to be a descendant of itself).” * * Given the following binary search tree: root = [3,5,1,6,2,0,8,null,null,7,4] * * _______3______ * / \ * ___5__ ___1__ * / \ / \ * 6 _2 0 8 * / \ * 7 4 * * Example 1: * Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 * Output: 3 * Explanation: The LCA of of nodes 5 and 1 is 3. * * Example 2: * Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 * Output: 5 * Explanation: The LCA of nodes 5 and 4 is 5, since a node can be a descendant * of itself according to the LCA definition. * * Note: * All of the nodes' values will be unique. * p and q are different and both values will exist in the binary tree. */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class LowestCommonAncestorOfABinaryTree236 { public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { if (root == null) return null; if (root.val == p.val || root.val == q.val) return root; TreeNode left = lowestCommonAncestor(root.left, p, q); TreeNode right = lowestCommonAncestor(root.right, p, q); if (left != null && right != null) { return root; } else if (left != null) { return left; } else { return right; } } } ================================================ FILE: src/MagicalString481.java ================================================ /** * A magical string S consists of only '1' and '2' and obeys the following rules: * * The string S is magical because concatenating the number of contiguous * occurrences of characters '1' and '2' generates the string S itself. * * The first few elements of string S is the following: S = "1221121221221121122……" * * If we group the consecutive '1's and '2's in S, it will be: * * 1 22 11 2 1 22 1 22 11 2 11 22 ...... * * and the occurrences of '1's or '2's in each group are: * * 1 2 2 1 1 2 1 2 2 1 2 2 ...... * * You can see that the occurrence sequence above is the S itself. * * Given an integer N as input, return the number of '1's in the first N number * in the magical string S. * * Note: N will not exceed 100,000. * * Example 1: * Input: 6 * Output: 3 * Explanation: The first 6 elements of magical string S is "12211" and it * contains three 1's, so return 3. */ public class MagicalString481 { public int magicalString(int N) { if (N == 0) return 0; if (N <= 3) return 1; int[] arr = new int[N]; arr[0] = 1; arr[1] = 2; arr[2] = 2; int now = 1; int i = 2; int j = 3; int res = 1; while (j < N) { int curr = arr[i]; for (int k=0; k= N) break; if (now == 1) res++; arr[j++] = now; } now = now == 1 ? 2 : 1; i++; } return res; } } ================================================ FILE: src/MajorityElement169.java ================================================ /** * Given an array of size n, find the majority element. The majority element is * the element that appears more than ⌊ n/2 ⌋ times. * * You may assume that the array is non-empty and the majority element always * exist in the array. */ public class MajorityElement169 { public int majorityElement(int[] nums) { Map map = new HashMap<>(); int N = nums.length; for (int i=0; i (N/2)) { return nums[i]; } } return nums[0]; } /** * https://discuss.leetcode.com/topic/8692/o-n-time-o-1-space-fastest-solution * Moore voting algorithm */ public int majorityElement2(int[] num) { int major=num[0], count = 1; for(int i=1; i>(31-i) & 1) == 1) bit[i]++; int ret=0; for (int i=0; i<32; i++) { bit[i]=bit[i]>nums.length/2?1:0; ret += bit[i]*(1<<(31-i)); } return ret; } } ================================================ FILE: src/MapSumPairs677.java ================================================ /** * Implement a MapSum class with insert, and sum methods. * * For the method insert, you'll be given a pair of (string, integer). The * string represents the key and the integer represents the value. If the key * already existed, then the original key-value pair will be overridden to * the new one. * * For the method sum, you'll be given a string representing the prefix, and * you need to return the sum of all the pairs' value whose key starts with * the prefix. * * Example 1: * Input: insert("apple", 3), Output: Null * Input: sum("ap"), Output: 3 * Input: insert("app", 2), Output: Null * Input: sum("ap"), Output: 5 * */ public class MapSumPairs677 { class MapSum { private Trie trie = new Trie(); /** Initialize your data structure here. */ public MapSum() { } public void insert(String key, int val) { trie.add(key, val); } public int sum(String prefix) { return trie.getSum(prefix); } class Trie { Trie[] children = new Trie[256]; Integer value; Integer sum = 0; public void add(String key, int val) { add(key.toCharArray(), val, 0); } private Integer add(char[] chars, int val, int i) { if (i == chars.length) { int diff = (value == null) ? val : val - value; value = val; sum += diff; return diff; } int nextI = (int) (chars[i] - 'a'); if (children[nextI] == null) { children[nextI] = new Trie(); } Integer pre = sum; Integer diff = children[nextI].add(chars, val, i+1); sum = pre + diff; return diff; } public int getSum(String prefix) { int s = getSum(prefix.toCharArray(), 0); return s; } private int getSum(char[] chars, int i) { if (i == chars.length) return sum; if (children[chars[i] - 'a'] == null) return 0; return children[chars[i] - 'a'].getSum(chars, i+1); } } } class MapSum2 { private Map map = new HashMap<>(); private Trie trie = new Trie(); /** Initialize your data structure here. */ public MapSum() { } public void insert(String key, int val) { int now = map.getOrDefault(key, 0); trie.add(key, val - now); map.put(key, val); } public int sum(String prefix) { return trie.getSum(prefix); } class Trie { Trie[] children = new Trie[256]; Integer sum = 0; public void add(String key, int diff) { add(key.toCharArray(), diff, 0); } private void add(char[] chars, int diff, int i) { if (i == chars.length) { sum += diff; return; } int nextI = (int) (chars[i] - 'a'); if (children[nextI] == null) { children[nextI] = new Trie(); } sum += diff; children[nextI].add(chars, diff, i+1); } public int getSum(String prefix) { return getSum(prefix.toCharArray(), 0); } private int getSum(char[] chars, int i) { if (i == chars.length) return sum; if (children[chars[i] - 'a'] == null) return 0; return children[chars[i] - 'a'].getSum(chars, i+1); } } } /** * Your MapSum object will be instantiated and called as such: * MapSum obj = new MapSum(); * obj.insert(key,val); * int param_2 = obj.sum(prefix); */ } ================================================ FILE: src/MatchsticksToSquare473.java ================================================ /** * Remember the story of Little Match Girl? By now, you know exactly what * matchsticks the little match girl has, please find out a way you can make * one square by using up all those matchsticks. You should not break any * stick, but you can link them up, and each matchstick must be used exactly * one time. * * Your input will be several matchsticks the girl has, represented with their * stick length. Your output will either be true or false, to represent whether * you could make one square using all the matchsticks the little match girl * has. * * Example 1: * Input: [1,1,2,2,2] * Output: true * Explanation: You can form a square with length 2, one side of the square * came two sticks with length 1. * * Example 2: * Input: [3,3,3,3,4] * Output: false * Explanation: You cannot find a way to form a square with all the matchsticks. * * Note: * The length sum of the given matchsticks is in the range of 0 to 10^9. * The length of the given matchstick array will not exceed 15. */ public class MatchsticksToSquare473 { public boolean makesquare(int[] nums) { if (nums == null || nums.length <= 3) return false; return canPartitionKSubsets(nums, 4); } // PartitionToKEqualSumSubsets698 public boolean canPartitionKSubsets(int[] nums, int k) { int sum = 0; int N = nums.length; for (int i=0; i q = new LinkedList<>(); q.add(new int[]{i, j}); visited[i][j] = true; int res = 0; while (!q.isEmpty()) { int[] curr = q.poll(); res++; for (int[] dir: DIRECTIONS) { int x = curr[0] + dir[0]; int y = curr[1] + dir[1]; if (x < 0 || y < 0 || x >= grid.length || y >= grid[0].length || visited[x][y] || grid[x][y] != 1) continue; q.add(new int[]{x, y}); visited[x][y] = true; } } return res; } // DFS public int maxAreaOfIsland2(int[][] grid) { if (grid == null || grid.length == 0 || grid[0].length == 0) return 0; int M = grid.length; int N = grid[0].length; boolean[][] visited = new boolean[M][N]; int res = 0; for (int i=0; i= grid.length || j >= grid[0].length || grid[i][j] != 1 || visited[i][j]) return 0; visited[i][j] = true; int res = 1; for (int[] dir: DIRECTIONS) { int x = i + dir[0]; int y = j + dir[1]; res += dfs(grid, visited, x, y); } return res; } // Union-Find public int maxAreaOfIsland3(int[][] grid) { if (grid == null || grid.length == 0 || grid[0].length == 0) return 0; int M = grid.length; int N = grid[0].length; int res = 0; UinionFind uf = new UinionFind(grid); for (int i=0; i= M || y >= N || grid[x][y] != 1) continue; res = Math.max(res, uf.union(pre, x * N + y)); } return res; } class UinionFind { int[] parent; int[] size; int[] rank; UinionFind(int[][] grid) { int M = grid.length; int N = grid[0].length; this.parent = new int[M * N]; for (int i=0; i this.rank[py]) { this.parent[py] = px; this.size[px] = this.size[px] + this.size[py]; return this.size[px]; } else if (this.rank[px] < this.rank[py]) { this.parent[px] = py; this.size[py] = this.size[px] + this.size[py]; return this.size[py]; } else { this.parent[px] = py; this.rank[py]++; this.size[py] = this.size[px] + this.size[py]; return this.size[py]; } } int getSize(int x) { return this.size[find(x)]; } } } ================================================ FILE: src/MaxChunksToMakeSorted769.java ================================================ /** * Given an array arr that is a permutation of [0, 1, ..., arr.length - 1], we * split the array into some number of "chunks" (partitions), and individually * sort each chunk. After concatenating them, the result equals the sorted * array. * * What is the most number of chunks we could have made? * * Example 1: * Input: arr = [4,3,2,1,0] * Output: 1 * Explanation: * Splitting into two or more chunks will not return the required result. * For example, splitting into [4, 3], [2, 1, 0] will result in [3, 4, 0, 1, 2], * which isn't sorted. * * Example 2: * Input: arr = [1,0,2,3,4] * Output: 4 * Explanation: * We can split into two chunks, such as [1, 0], [2, 3, 4]. * However, splitting into [1, 0], [2], [3], [4] is the highest number of * chunks possible. * * Note: * arr will have length in range [1, 10]. * arr[i] will be a permutation of [0, 1, ..., arr.length - 1]. */ public class MaxChunksToMakeSorted769 { public int maxChunksToSorted(int[] arr) { if (arr == null || arr.length == 0) return 0; int res = 0; int max = arr[0]; for (int i=0; i stack = new Stack<>(); for (int i=0; i arr[i]) { stack.pop(); } stack.push(top); } } return stack.size(); } /** * https://leetcode.com/problems/max-chunks-to-make-sorted-ii/discuss/113462/Java-solution-left-max-and-right-min. */ public int maxChunksToSorted2(int[] arr) { int n = arr.length; int[] maxOfLeft = new int[n]; int[] minOfRight = new int[n]; maxOfLeft[0] = arr[0]; for (int i = 1; i < n; i++) { maxOfLeft[i] = Math.max(maxOfLeft[i-1], arr[i]); } minOfRight[n - 1] = arr[n - 1]; for (int i = n - 2; i >= 0; i--) { minOfRight[i] = Math.min(minOfRight[i + 1], arr[i]); } int res = 0; for (int i = 0; i < n - 1; i++) { if (maxOfLeft[i] <= minOfRight[i + 1]) res++; } return res + 1; } } ================================================ FILE: src/MaxConsecutiveOnes485.java ================================================ /** * Given a binary array, find the maximum number of consecutive 1s in this array. * * Example 1: * Input: [1,1,0,1,1,1] * Output: 3 * * Explanation: The first two digits or the last three digits are consecutive 1s. * The maximum number of consecutive 1s is 3. * * Note: * The input array will only contain 0 and 1. * The length of input array is a positive integer and will not exceed 10,000 */ public class MaxConsecutiveOnes485 { public int findMaxConsecutiveOnes(int[] nums) { if (nums == null || nums.length == 0) return 0; int left = 0; int right = 0; int max = 0; while (right < nums.length) { if (nums[right] == 1) { right++; continue; } max = Math.max(max, right-left); left = right; while (left < nums.length && nums[left] == 0) left++; right = left; } max = Math.max(max, right-left); return max; } /** * https://leetcode.com/problems/max-consecutive-ones/discuss/96693/Java-4-lines-concise-solution-with-explanation */ public int findMaxConsecutiveOnes2(int[] nums) { int maxHere = 0, max = 0; for (int n : nums) max = Math.max(max, maxHere = n == 0 ? 0 : maxHere + 1); return max; } } ================================================ FILE: src/MaxConsecutiveOnesII487.java ================================================ /** * Given a binary array, find the maximum number of consecutive 1s in this * array if you can flip at most one 0. * * Example 1: * Input: [1,0,1,1,0] * Output: 4 * Explanation: Flip the first zero will get the the maximum number of consecutive 1s. * After flipping, the maximum number of consecutive 1s is 4. * * Note: * The input array will only contain 0 and 1. * The length of input array is a positive integer and will not exceed 10,000 * * Follow up: * What if the input numbers come in one by one as an infinite stream? In other * words, you can't store all numbers coming from the stream as it's too large * to hold in memory. Could you solve it efficiently? */ public class MaxConsecutiveOnesII487 { public int findMaxConsecutiveOnes(int[] nums) { if (nums == null || nums.length == 0) return 0; int left = 0; int right = 0; int max = 0; int zeros = 0; while (right < nums.length) { if (nums[right] == 1) { right++; continue; } else if (nums[right] == 0 && zeros == 0) { right++; zeros++; continue; } max = Math.max(max, right - left); while (left < nums.length && nums[left] == 1) left++; if (left < nums.length && nums[left] == 0) { left++; zeros--; } } return Math.max(max, right-left); } } ================================================ FILE: src/MaxIncreaseToKeepCitySkyline807.java ================================================ /** * In a 2 dimensional array grid, each value grid[i][j] represents the height * of a building located there. We are allowed to increase the height of any * number of buildings, by any amount (the amounts can be different for * different buildings). Height 0 is considered to be a building as well. * * At the end, the "skyline" when viewed from all four directions of the grid, * i.e. top, bottom, left, and right, must be the same as the skyline of the * original grid. A city's skyline is the outer contour of the rectangles * formed by all the buildings when viewed from a distance. See the following * example. * * What is the maximum total sum that the height of the buildings can be * increased? * * Example: * Input: grid = [[3,0,8,4],[2,4,5,7],[9,2,6,3],[0,3,1,0]] * Output: 35 * Explanation: * The grid is: * [ [3, 0, 8, 4], * [2, 4, 5, 7], * [9, 2, 6, 3], * [0, 3, 1, 0] ] * * The skyline viewed from top or bottom is: [9, 4, 8, 7] * The skyline viewed from left or right is: [8, 7, 9, 3] * * The grid after increasing the height of buildings without affecting skylines * is: * * gridNew = [ [8, 4, 8, 7], * [7, 4, 7, 7], * [9, 4, 8, 7], * [3, 3, 3, 3] ] * * Notes: * 1 < grid.length = grid[0].length <= 50. * All heights grid[i][j] are in the range [0, 100]. * All buildings in grid[i][j] occupy the entire grid cell: that is, they are * a 1 x 1 x grid[i][j] rectangular prism. */ public class MaxIncreaseToKeepCitySkyline807 { public int maxIncreaseKeepingSkyline(int[][] grid) { int M = grid.length; int N = grid[0].length; int[] top = new int[N]; int[] left = new int[M]; for (int i=0; i lines = new HashMap<>(); Point p1 = points[i]; int same = 0; int localMax = 0; for (int j=i+1; j lines = new HashMap<>(); Point p1 = points[i]; int same = 0; int localMax = 0; for (int j=i+1; j 5 * stack.popMax(); -> 5 * stack.top(); -> 1 * stack.peekMax(); -> 5 * stack.pop(); -> 1 * stack.top(); -> 5 * * Note: * -1e7 <= x <= 1e7 * Number of operations won't exceed 10000. * The last four operations won't be called when stack is empty. */ public class MaxStack716 { class MaxStack { private Stack stack; /** initialize your data structure here. */ public MaxStack() { this.stack = new Stack<>(); } public void push(int x) { int max = this.stack.isEmpty() ? x : Math.max(x, this.peekMax()); this.stack.push(new Element(x, max)); } public int pop() { return this.stack.pop().val; } public int top() { return this.stack.peek().val; } public int peekMax() { return this.stack.peek().max; } public int popMax() { int max = this.peekMax(); Stack temp = new Stack<>(); while (this.top() != max) { temp.push(this.pop()); } this.pop(); while (!temp.isEmpty()) { this.push(temp.pop()); } return max; } class Element { int val; int max; public Element(int val, int max) { this.val = val; this.max = max; } } } /** * Your MaxStack object will be instantiated and called as such: * MaxStack obj = new MaxStack(); * obj.push(x); * int param_2 = obj.pop(); * int param_3 = obj.top(); * int param_4 = obj.peekMax(); * int param_5 = obj.popMax(); */ } ================================================ FILE: src/MaxSumOfRectangleNoLargerThanK363.java ================================================ /** * Given a non-empty 2D matrix matrix and an integer k, find the max sum of a * rectangle in the matrix such that its sum is no larger than k. * * Example: * Given matrix = [ * [1, 0, 1], * [0, -2, 3] * ] * k = 2 * The answer is 2. Because the sum of rectangle [[0, 1], [-2, 3]] is 2 and 2 * is the max number no larger than k (k = 2). * * Note: * The rectangle inside the matrix must have an area > 0. * What if the number of rows is much larger than the number of columns? */ public class MaxSumOfRectangleNoLargerThanK363 { public int maxSumSubmatrix(int[][] matrix, int k) { int m = matrix.length; int n = matrix[0].length; int[][] sum = new int[m+1][n+1]; for (int i=0; i res && tmp <= k) { res = tmp; } } } } } return res; } } ================================================ FILE: src/MaximalRectangle85.java ================================================ /** * Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle * containing only 1's and return its area. * * For example, given the following matrix: * * 1 0 1 0 0 * 1 0 1 1 1 * 1 1 1 1 1 * 1 0 0 1 0 * Return 6. * */ public class MaximalRectangle85 { public int maximalRectangle(char[][] matrix) { int N = matrix.length; if (N == 0) return 0; int M = matrix[0].length; if (M == 0) return 0; int[][] left = new int[N+1][M+1]; int[][] top = new int[N+1][M+1]; int maxArea = 0; for (int i=1; i<=N; i++) { for (int j=1; j<=M; j++) { if (matrix[i-1][j-1] == '1') { left[i][j] = left[i][j-1] + 1; top[i][j] = top[i-1][j] + 1; maxArea = Math.max(maxArea, helper(left, top, i, j)); } } } return maxArea; } private int helper(int[][] left, int[][] top, int i, int j) { int maxArea = 0; int move = 0; int minH = top[i][j]; while (move < left[i][j]) { minH = Math.min(minH, top[i][j-move]); maxArea = Math.max(maxArea, (move+1) * minH); move++; } return maxArea; } /** * https://discuss.leetcode.com/topic/1634/a-o-n-2-solution-based-on-largest-rectangle-in-histogram */ public int maximalRectangle2(char[][] matrix) { if (matrix==null||matrix.length==0||matrix[0].length==0) return 0; int cLen = matrix[0].length; // column length int rLen = matrix.length; // row length // height array int[] h = new int[cLen+1]; h[cLen]=0; int max = 0; for (int row=0;row s = new Stack(); for (int i=0;imax) max = area; } s.push(i); } } } return max; } /** * https://discuss.leetcode.com/topic/21772/my-java-solution-based-on-maximum-rectangle-in-histogram-with-explanation */ public int maximalRectangle3(char[][] matrix) { if(matrix == null || matrix.length == 0 || matrix[0].length == 0) return 0; int[] height = new int[matrix[0].length]; for(int i = 0; i < matrix[0].length; i ++){ if(matrix[0][i] == '1') height[i] = 1; } int result = largestInLine(height); for(int i = 1; i < matrix.length; i ++){ resetHeight(matrix, height, i); result = Math.max(result, largestInLine(height)); } return result; } private void resetHeight(char[][] matrix, int[] height, int idx){ for(int i = 0; i < matrix[0].length; i ++){ if(matrix[idx][i] == '1') height[i] += 1; else height[i] = 0; } } public int largestInLine(int[] height) { if(height == null || height.length == 0) return 0; int len = height.length; Stack s = new Stack(); int maxArea = 0; for(int i = 0; i <= len; i++){ int h = (i == len ? 0 : height[i]); if(s.isEmpty() || h >= height[s.peek()]){ s.push(i); }else{ int tp = s.pop(); maxArea = Math.max(maxArea, height[tp] * (s.isEmpty() ? i : i - 1 - s.peek())); i--; } } return maxArea; } /** * https://discuss.leetcode.com/topic/42761/java-7ms-solution-beats-100-using-largest-rectangle-in-histogram-solved-by-stack-simulation */ public int maximalRectangle4(char[][] matrix) { /** * idea: using [LC84 Largest Rectangle in Histogram]. For each row * of the matrix, construct the histogram based on the current row * and the previous histogram (up to the previous row), then compute * the largest rectangle area using LC84. */ int m = matrix.length, n; if (m == 0 || (n = matrix[0].length) == 0) return 0; int i, j, res = 0; int[] heights = new int[n]; for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { if (matrix[i][j] == '0') heights[j] = 0; else heights[j] += 1; } res = Math.max(res, largestRectangleArea(heights)); } return res; } public int largestRectangleArea(int[] heights) { /** * idea: scan and store if a[i-1]<=a[i] (increasing), then as long * as a[i]a[i], which is a[j]*(i-j). * And meanwhile, all these bars (a[j]'s) are already done, and thus * are throwable (using pop() with a stack). * * We can use an array nLeftGeq[] of size n to simulate a stack. * nLeftGeq[i] = the number of elements to the left of [i] having * value greater than or equal to a[i] (including a[i] itself). It * is also the index difference between [i] and the next index on * the top of the stack. */ int n = heights.length; if (n == 0) return 0; int[] nLeftGeq = new int[n]; // the number of elements to the left // of [i] with value >= heights[i] nLeftGeq[0] = 1; // preIdx=the index of stack.peek(), res=max area so far int preIdx = 0, res = 0; for (int i = 1; i < n; i++) { nLeftGeq[i] = 1; // notice that preIdx = i - 1 = peek() while (preIdx >= 0 && heights[i] < heights[preIdx]) { res = Math.max(res, heights[preIdx] * (nLeftGeq[preIdx] + i - preIdx - 1)); nLeftGeq[i] += nLeftGeq[preIdx]; // pop() preIdx = preIdx - nLeftGeq[preIdx]; // peek() current top } if (preIdx >= 0 && heights[i] == heights[preIdx]) nLeftGeq[i] += nLeftGeq[preIdx]; // pop() // otherwise nothing to do preIdx = i; } // compute the rest largest rectangle areas with (indices of) bases // on stack while (preIdx >= 0 && 0 < heights[preIdx]) { res = Math.max(res, heights[preIdx] * (nLeftGeq[preIdx] + n - preIdx - 1)); preIdx = preIdx - nLeftGeq[preIdx]; // peek() current top } return res; } /** * https://discuss.leetcode.com/topic/20902/my-solution-on-java-using-dp */ public int maximalRectangle5(char[][] matrix) { int area = 0, new_area, r, l; if(matrix.length > 0){ int[] line = new int[matrix[0].length]; boolean[] is_processed = new boolean[matrix[0].length]; for(int i = 0; i < matrix.length; i++){ for(int j = 0; j < matrix[i].length; j++){ if (matrix[i][j] == '1') { line[j]++; is_processed[j] = false; } else { line[j] = 0; is_processed[j] = true; } } for(int j = 0; j < matrix[i].length; j++){ if(is_processed[j]) continue; r = l = 1; while((j + r < line.length)&&(line[j + r] >= line[j])){ if(line[j + r] == line[j]) is_processed[j + r] = true; r++; } while((j - l >= 0)&&(line[j - l] >= line[j])) l++; new_area = (r + l - 1)*line[j]; if (new_area > area) area = new_area; } } } return area; } public int maximalRectangle6(char[][] matrix) { if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return 0; int M = matrix.length; int N = matrix[0].length; int[][] dp = new int[M][N+1]; int res = 0; for (int i=0; i=0; k--) { width = Math.min(width, dp[k][j]); local = Math.max(local, width * (i - k + 1)); } res = Math.max(res, local); } } } return res; } public int maximalRectangle7(char[][] matrix) { if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return 0; int M = matrix.length; int N = matrix[0].length; int[] left = new int[N]; int[] right = new int[N]; Arrays.fill(right, N); int[] height = new int[N]; int res = 0; for (int i=0; i=0; j--) { if (matrix[i][j] == '1') { right[j] = Math.min(currRight, right[j]); } else { right[j] = N; currRight = j; } } for (int j=0; j 0 ? matrix[0].length : 0; int[][] dp = new int[rows + 1][cols + 1]; int maxsqlen = 0; for (int i = 1; i <= rows; i++) { for (int j = 1; j <= cols; j++) { if (matrix[i-1][j-1] == '1'){ dp[i][j] = Math.min(Math.min(dp[i][j - 1], dp[i - 1][j]), dp[i - 1][j - 1]) + 1; maxsqlen = Math.max(maxsqlen, dp[i][j]); } } } return maxsqlen * maxsqlen; } /** * https://leetcode.com/problems/maximal-square/solution/ */ public int maximalSquare3(char[][] matrix) { int rows = matrix.length, cols = rows > 0 ? matrix[0].length : 0; int[] dp = new int[cols + 1]; int maxsqlen = 0, prev = 0; for (int i = 1; i <= rows; i++) { for (int j = 1; j <= cols; j++) { int temp = dp[j]; if (matrix[i - 1][j - 1] == '1') { dp[j] = Math.min(Math.min(dp[j - 1], prev), dp[j]) + 1; maxsqlen = Math.max(maxsqlen, dp[j]); } else { dp[j] = 0; } prev = temp; } } return maxsqlen * maxsqlen; } } ================================================ FILE: src/MaximizeDistanceToClosestPerson849.java ================================================ /** * In a row of seats, 1 represents a person sitting in that seat, and 0 * represents that the seat is empty. * * There is at least one empty seat, and at least one person sitting. * * Alex wants to sit in the seat such that the distance between him and the * closest person to him is maximized. * * Return that maximum distance to closest person. * * Example 1: * Input: [1,0,0,0,1,0,1] * Output: 2 * * Explanation: * If Alex sits in the second open seat (seats[2]), then the closest person * has distance 2. * If Alex sits in any other open seat, the closest person has distance 1. * Thus, the maximum distance to the closest person is 2. * * Example 2: * Input: [1,0,0,0] * Output: 3 * * Explanation: * If Alex sits in the last seat, the closest person is 3 seats away. * This is the maximum distance possible, so the answer is 3. * * Note: * 1 <= seats.length <= 20000 * seats contains only 0s or 1s, at least one 0, and at least one 1. */ public class MaximizeDistanceToClosestPerson849 { public int maxDistToClosest(int[] seats) { int L = seats.length; int dis = -1; int pre = -1; for (int i=0; i dis) dis = d; } pre = i; } return Math.max(L - 1 - pre, dis); } } ================================================ FILE: src/MaximumAverageSubarrayI643.java ================================================ /** * Given an array consisting of n integers, find the contiguous subarray of * given length k that has the maximum average value. And you need to output * the maximum average value. * * Example 1: * Input: [1,12,-5,-6,50,3], k = 4 * Output: 12.75 * Explanation: Maximum average is (12-5-6+50)/4 = 51/4 = 12.75 * * Note: * 1 <= k <= n <= 30,000. * Elements of the given array will be in the range [-10,000, 10,000]. */ public class MaximumAverageSubarrayI643 { public double findMaxAverage(int[] nums, int k) { if (nums.length < k) return 0.0; int len = nums.length; long res = 0; for (int i=0; i res) res = tmp; } return res / (k * 1.0); } } ================================================ FILE: src/MaximumBinaryTree654.java ================================================ /** * Given an integer array with no duplicates. A maximum tree building on this * array is defined as follow: * * The root is the maximum number in the array. * The left subtree is the maximum tree constructed from left part subarray * divided by the maximum number. * The right subtree is the maximum tree constructed from right part subarray * divided by the maximum number. * * Construct the maximum tree by the given array and output the root node of * this tree. * * Example 1: * Input: [3,2,1,6,0,5] * Output: return the tree root node representing the following tree: * * 6 * / \ * 3 5 * \ / * 2 0 * \ * 1 * Note: * The size of the given array will be in the range [1,1000]. */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class MaximumBinaryTree654 { public TreeNode constructMaximumBinaryTree(int[] nums) { return constructMaximumBinaryTree(nums, 0, nums.length-1); } public TreeNode constructMaximumBinaryTree(int[] nums, int lo, int hi) { if (lo > hi) return null; if (lo == hi) return new TreeNode(nums[lo]); int idx = maxIndex(nums, lo, hi); TreeNode root = new TreeNode(nums[idx]); root.left = constructMaximumBinaryTree(nums, lo, idx-1); root.right = constructMaximumBinaryTree(nums, idx+1, hi); return root; } private int maxIndex(int[] nums, int lo, int hi) { int res = lo; int max = nums[lo]; for (int i=lo; i<=hi; i++) { if (nums[i] > max) { max = nums[i]; res = i; } } return res; } public TreeNode constructMaximumBinaryTree2(int[] nums) { Stack stack = new Stack<>(); for (int i=0; i nums[i]) { stack.push(curr); continue; } TreeNode left = null; while (!stack.isEmpty() && stack.peek().val < nums[i]) { TreeNode temp = stack.pop(); temp.right = left; left = temp; } curr.left = left; stack.push(curr); } TreeNode res = null; while (!stack.isEmpty()) { TreeNode temp = stack.pop(); temp.right = res; res = temp; } return res; } /** * https://leetcode.com/problems/maximum-binary-tree/discuss/106156/Java-worst-case-O(N)-solution */ public TreeNode constructMaximumBinaryTree3(int[] nums) { Deque stack = new LinkedList<>(); for(int i = 0; i < nums.length; i++) { TreeNode curr = new TreeNode(nums[i]); while(!stack.isEmpty() && stack.peek().val < nums[i]) { curr.left = stack.pop(); } if(!stack.isEmpty()) { stack.peek().right = curr; } stack.push(curr); } return stack.isEmpty() ? null : stack.removeLast(); } } ================================================ FILE: src/MaximumDepthOfBinaryTree104.java ================================================ /** * Given a binary tree, find its maximum depth. * * The maximum depth is the number of nodes along the longest path from the * root node down to the farthest leaf node. */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ import java.util.Stack; public class MaximumDepthOfBinaryTree104 { public int maxDepth(TreeNode root) { if (root == null){ return 0; } int left = maxDepth(root.left); int right = maxDepth(root.right); return Math.max(left, right) + 1; } } ================================================ FILE: src/MaximumFrequencyStack895.java ================================================ /** * Implement FreqStack, a class which simulates the operation of a stack-like * data structure. * * FreqStack has two functions: * push(int x), which pushes an integer x onto the stack. * pop(), which removes and returns the most frequent element in the stack. * * If there is a tie for most frequent element, the element closest to the top * of the stack is removed and returned. * * Example 1: * Input: * ["FreqStack","push","push","push","push","push","push","pop","pop","pop","pop"], * [[],[5],[7],[5],[7],[4],[5],[],[],[],[]] * Output: [null,null,null,null,null,null,null,5,7,5,4] * Explanation: * After making six .push operations, the stack is [5,7,5,7,4,5] from bottom * to top. Then: * * pop() -> returns 5, as 5 is the most frequent. * The stack becomes [5,7,5,7,4]. * * pop() -> returns 7, as 5 and 7 is the most frequent, but 7 is closest to the top. * The stack becomes [5,7,5,4]. * * pop() -> returns 5. * The stack becomes [5,7,4]. * * pop() -> returns 4. * The stack becomes [5,7]. * * Note: * Calls to FreqStack.push(int x) will be such that 0 <= x <= 10^9. * It is guaranteed that FreqStack.pop() won't be called if the stack has zero elements. * The total number of FreqStack.push calls will not exceed 10000 in a single test case. * The total number of FreqStack.pop calls will not exceed 10000 in a single test case. * The total number of FreqStack.push and FreqStack.pop calls will not exceed 150000 across all test cases. */ public class MaximumFrequencyStack895 { /** * https://leetcode.com/problems/maximum-frequency-stack/solution/ */ class FreqStack { Map freq; Map> group; int maxfreq; public FreqStack() { freq = new HashMap(); group = new HashMap(); maxfreq = 0; } public void push(int x) { int f = freq.getOrDefault(x, 0) + 1; freq.put(x, f); if (f > maxfreq) maxfreq = f; group.computeIfAbsent(f, z-> new Stack()).push(x); } public int pop() { int x = group.get(maxfreq).pop(); freq.put(x, freq.get(x) - 1); if (group.get(maxfreq).size() == 0) maxfreq--; return x; } } /** * Your FreqStack object will be instantiated and called as such: * FreqStack obj = new FreqStack(); * obj.push(x); * int param_2 = obj.pop(); */ } ================================================ FILE: src/MaximumLengthOfPairChain646.java ================================================ /** * You are given n pairs of numbers. In every pair, the first number is always * smaller than the second number. * * Now, we define a pair (c, d) can follow another pair (a, b) if and * only if b < c. Chain of pairs can be formed in this fashion. * * Given a set of pairs, find the length longest chain which can be formed. * You needn't use up all the given pairs. You can select pairs in any order. * * Example 1: * Input: [[1,2], [2,3], [3,4]] * Output: 2 * Explanation: The longest chain is [1,2] -> [3,4] * * Note: * The number of given pairs will be in the range [1, 1000]. */ public class MaximumLengthOfPairChain646 { public int findLongestChain(int[][] pairs) { if (pairs == null || pairs.length == 0) return 0; Arrays.sort(pairs, (p1, p2) -> Integer.compare(p1[0], p2[0])); int N = pairs.length; int[] dp = new int[N + 1]; int res = 0; for (int i=1; i<=N; i++) { int local = 1; for (int j=1; j pairs[j-1][1] && dp[j] + 1 > local) { local = dp[j] + 1; } } dp[i] = local; if (local > res) { res = local; } } return res; } public int findLongestChain2(int[][] pairs) { if (pairs == null || pairs.length == 0) return 0; Arrays.sort(pairs, (p1, p2) -> Integer.compare(p1[0], p2[0])); LinkedList list = new LinkedList<>(); for (int[] p: pairs) { if (list.isEmpty() || list.getLast()[1] < p[0]) { list.add(p); } else { if (p[1] < list.getLast()[1]) { list.removeLast(); list.add(p); } } } return list.size(); } public int findLongestChain3(int[][] pairs) { if (pairs == null || pairs.length == 0) return 0; Arrays.sort(pairs, (p1, p2) -> Integer.compare(p1[0], p2[0])); int[] last = null; int res = 0; for (int[] p: pairs) { if (last == null || last[1] < p[0]) { last = p; res++; } else { if (p[1] < last[1]) { last = p; } } } return res; } } ================================================ FILE: src/MaximumLengthOfRepeatedSubarray718.java ================================================ /** * Given two integer arrays A and B, return the maximum length of an subarray * that appears in both arrays. * * Example 1: * Input: * A: [1,2,3,2,1] * B: [3,2,1,4,7] * Output: 3 * * Explanation: * The repeated subarray with maximum length is [3, 2, 1]. * * Note: * 1 <= len(A), len(B) <= 1000 * 0 <= A[i], B[i] < 100 * */ public class MaximumLengthOfRepeatedSubarray718 { public int findLength(int[] A, int[] B) { int[][] res = new int[A.length+1][B.length+1]; int[][] lens = new int[A.length+1][B.length+1]; for (int i=1; i<=A.length; i++) { for (int j=1; j<=B.length; j++) { lens[i][j] = (A[i-1] == B[j-1]) ? lens[i-1][j-1] + 1 : 0 ; res[i][j] = Math.max(lens[i][j], Math.max(res[i][j-1], res[i-1][j])); } } return res[A.length][B.length]; } public int findLength2(int[] A, int[] B) { int[] res = new int[B.length+1]; int[] lens = new int[B.length+1]; int lens0 = 0; for (int i=1; i<=A.length; i++) { for (int j=1; j<=B.length; j++) { int tempLens = lens[j]; lens[j] = (A[i-1] == B[j-1]) ? lens0 + 1 : 0; lens0 = tempLens; res[j] = Math.max(lens[j], Math.max(res[j-1], res[j])); } lens0 = 0; } return res[B.length]; } /** * https://leetcode.com/problems/maximum-length-of-repeated-subarray/solution/ */ public int findLength3(int[] A, int[] B) { int ans = 0; int[][] memo = new int[A.length + 1][B.length + 1]; for (int i = A.length - 1; i >= 0; --i) { for (int j = B.length - 1; j >= 0; --j) { if (A[i] == B[j]) { memo[i][j] = memo[i+1][j+1] + 1; ans = Math.max(ans, memo[i][j]); } } } return ans; } /** * https://discuss.leetcode.com/topic/108760/java-c-clean-code-8-lines */ public int findLength4(int[] a, int[] b) { int m = a.length, n = b.length; if (m == 0 || n == 0) return 0; int[] dp = new int[n + 1]; int max = 0; for (int i = m - 1; i >= 0; i--) for (int j = 0; j < n; j++) max = Math.max(max, dp[j] = a[i] == b[j] ? 1 + dp[j + 1] : 0); return max; } public int findLength5(int[] A, int[] B) { int lenA = A.length; int lenB = B.length; int res = 0; int[][] dp = new int[lenA + 1][lenB + 1]; for (int i=1; i<=lenA; i++) { for (int j=1; j<=lenB; j++) { if (A[i-1] == B[j-1]) { dp[i][j] = dp[i-1][j-1] + 1; if (dp[i][j] > res) res = dp[i][j]; } } } return res; } public int findLength6(int[] A, int[] B) { int lenA = A.length; int lenB = B.length; int res = 0; int[] dp = new int[lenB + 1]; for (int i=1; i<=lenA; i++) { int pre = 0; for (int j=1; j<=lenB; j++) { int tmp = dp[j]; if (A[i-1] == B[j-1]) { dp[j] = pre + 1; if (dp[j] > res) res = dp[j]; } else { dp[j] = 0; } pre = tmp; } } return res; } } ================================================ FILE: src/MaximumProductOfThreeNumbers628.java ================================================ /** * Given an integer array, find three numbers whose product is maximum and * output the maximum product. * * Example 1: * Input: [1,2,3] * Output: 6 * * Example 2: * Input: [1,2,3,4] * Output: 24 * * Note: * The length of the given array will be in range [3,104] and all elements are * in the range [-1000, 1000]. * Multiplication of any three numbers in the input won't exceed the range of * 32-bit signed integer. * */ public class MaximumProductOfThreeNumbers628 { public int maximumProduct(int[] nums) { if (nums == null || nums.length < 3) return 0; int len = nums.length; Arrays.sort(nums); return Math.max(nums[0] * nums[1] * nums[len - 1], nums[len - 1] * nums[len - 2] * nums[len - 3]); } /** * https://leetcode.com/problems/maximum-product-of-three-numbers/solution/ */ public int maximumProduct2(int[] nums) { int min1 = Integer.MAX_VALUE, min2 = Integer.MAX_VALUE; int max1 = Integer.MIN_VALUE, max2 = Integer.MIN_VALUE, max3 = Integer.MIN_VALUE; for (int n: nums) { if (n <= min1) { min2 = min1; min1 = n; } else if (n <= min2) { // n lies between min1 and min2 min2 = n; } if (n >= max1) { // n is greater than max1, max2 and max3 max3 = max2; max2 = max1; max1 = n; } else if (n >= max2) { // n lies betweeen max1 and max2 max3 = max2; max2 = n; } else if (n >= max3) { // n lies betwen max2 and max3 max3 = n; } } return Math.max(min1 * min2 * max1, max1 * max2 * max3); } } ================================================ FILE: src/MaximumProductOfWordLengths318.java ================================================ /** * Given a string array words, find the maximum value of * length(word[i]) * length(word[j]) where the two words do not share common * letters. You may assume that each word will contain only lower case letters. * If no such two words exist, return 0. * * Example 1: * Input: ["abcw","baz","foo","bar","xtfn","abcdef"] * Output: 16 * Explanation: The two words can be "abcw", "xtfn". * * Example 2: * Input: ["a","ab","abc","d","cd","bcd","abcd"] * Output: 4 * Explanation: The two words can be "ab", "cd". * * Example 3: * Input: ["a","aa","aaa","aaaa"] * Output: 0 * Explanation: No such pair of words. */ public class MaximumProductOfWordLengths318 { public int maxProduct(String[] words) { if (words == null || words.length == 0) return 0; int len = words.length; int[] map = new int[len]; for (int i=0; i 0) { pos[i+1] = pos[i] == 0 ? now : pos[i] * now; neg[i+1] = neg[i] == 0 ? 0 : neg[i] * now; } else if (now < 0) { pos[i+1] = neg[i] == 0 ? 0 : neg[i] * now; neg[i+1] = pos[i] == 0 ? now : pos[i] * now; } else { hasZero = true; } if (pos[i+1] != 0 && pos[i+1] > res) { res = pos[i+1]; } if (neg[i+1] != 0 && neg[i+1] > res) { res = neg[i+1]; } } return (hasZero && res < 0) ? 0 : res; } // time O(n), space O(1) public int maxProduct2(int[] nums) { if (nums == null || nums.length == 0) return 0; int len = nums.length; if (len == 1) return nums[0]; boolean hasZero = false; int pos = 0; int neg = 0; int res = Integer.MIN_VALUE; for (int i=0; i 0) { pos = oldPos == 0 ? now : oldPos * now; neg = oldNeg == 0 ? 0 : oldNeg * now; } else if (now < 0) { pos = oldNeg == 0 ? 0 : oldNeg * now; neg = oldPos == 0 ? now : oldPos * now; } else { hasZero = true; pos = 0; neg = 0; } if (pos != 0 && pos > res) { res = pos; } if (neg != 0 && neg > res) { res = neg; } } return (hasZero && res < 0) ? 0 : res; } /** * https://leetcode.com/problems/maximum-product-subarray/discuss/48330/Simple-Java-code */ public int maxProduct3(int[] A) { if (A == null || A.length == 0) { return 0; } int max = A[0], min = A[0], result = A[0]; for (int i = 1; i < A.length; i++) { int temp = max; max = Math.max(Math.max(max * A[i], min * A[i]), A[i]); min = Math.min(Math.min(temp * A[i], min * A[i]), A[i]); if (max > result) { result = max; } } return result; } /** * https://leetcode.com/problems/maximum-product-subarray/discuss/48230/Possibly-simplest-solution-with-O(n)-time-complexity */ public int maxProduct4(int A[]) { // store the result that is the max we have found so far int r = A[0]; // imax/imin stores the max/min product of // subarray that ends with the current number A[i] for (int i = 1, imax = r, imin = r; i < A.length; i++) { // multiplied by a negative makes big number smaller, small number bigger // so we redefine the extremums by swapping them if (A[i] < 0) { int t = imax; imax = imin; imin = t; } // max/min product for the current number is either the current number itself // or the max/min by the previous number times the current one imax = Math.max(A[i], imax * A[i]); imin = Math.min(A[i], imin * A[i]); // the newly computed max value is a candidate for our global result r = Math.max(r, imax); } return r; } } ================================================ FILE: src/MaximumSizeSubarraySumEqualsK325.java ================================================ /** * Given an array nums and a target value k, find the maximum length of a * subarray that sums to k. If there isn't one, return 0 instead. * * Note: * The sum of the entire nums array is guaranteed to fit within the 32-bit * signed integer range. * * Example 1: * Given nums = [1, -1, 5, -2, 3], k = 3, * return 4. (because the subarray [1, -1, 5, -2] sums to 3 and is the longest) * * Example 2: * Given nums = [-2, -1, 2, 1], k = 1, * return 2. (because the subarray [-1, 2] sums to 1 and is the longest) * * Follow Up: * Can you do it in O(n) time? * */ public class MaximumSizeSubarraySumEqualsK325 { // brute force public int maxSubArrayLen(int[] nums, int k) { int max = Integer.MIN_VALUE; for (int i=0; i map = new HashMap<>(); for (int i=0; i map = new HashMap<>(); int len = nums.length; int res = 0; int sum = 0; map.put(0, -1); for (int i=0; i res) res = i - idx; } if (!map.containsKey(sum)) map.put(sum, i); } return res; } } ================================================ FILE: src/MaximumSubarray53.java ================================================ /** * Find the contiguous subarray within an array (containing at least one number) * which has the largest sum. * * For example, given the array [-2,1,-3,4,-1,2,1,-5,4], * the contiguous subarray [4,-1,2,1] has the largest sum = 6. * * More practice: * If you have figured out the O(n) solution, try coding another solution using * the divide and conquer approach, which is more subtle. */ import java.util.Arrays; public class MaximumSubarray53 { public int maxSubArray(int[] nums) { int n = nums.length; if (n == 0) { return 0; } int[] dp = new int[n]; dp[0] = nums[0]; for (int i = 1; i < n; i++) { dp[i] = Math.max(nums[i], Math.max(dp[i-1] + nums[i], nums[i-1] + nums[i])); } int max = Integer.MIN_VALUE; for(int i = 0; i < dp.length; i++) { if(dp[i] > max) { max = dp[i]; } } return max; } /** * https://leetcode.com/problems/maximum-subarray/discuss/20210/O(n)-Java-solution */ public int maxSubArray2(int[] A) { int max = Integer.MIN_VALUE, sum = 0; for (int i = 0; i < A.length; i++) { if (sum < 0) sum = A[i]; else sum += A[i]; if (sum > max) max = sum; } return max; } // divide-and-conquer public int maxSubArray3(int[] nums) { if (nums == null || nums.length == 0) return 0; return maxSubArray(nums, 0, nums.length-1); } private int maxSubArray(int[] nums, int left, int right) { if (left > right) return Integer.MIN_VALUE; if (left == right) return nums[left]; int mid = (left + right) / 2; int L = maxSubArray(nums, left, mid-1); int R = maxSubArray(nums, mid+1, right); int leftSum = 0; int tmp = 0; for (int i=mid-1; i>=left; i--) { tmp += nums[i]; if (tmp > leftSum) leftSum = tmp; } tmp = 0; int rightSum = 0; for (int i=mid+1; i<=right; i++) { tmp += nums[i]; if (tmp > rightSum) rightSum = tmp; } return Math.max(Math.max(L, R), leftSum + rightSum + nums[mid]); } public static void main(String[] args) { MaximumSubarray53 ms = new MaximumSubarray53(); System.out.println(ms.maxSubArray(new int[]{-2, 1, -3, 4, -1, 2, 1, -5, 4})); System.out.println(ms.maxSubArray(new int[]{-2, 1, -3, 4, -1, 2, 1, -5, 8})); System.out.println(ms.maxSubArray(new int[]{-2, -1})); System.out.println(ms.maxSubArray(new int[]{8, -19, 5, -4, 20})); } } ================================================ FILE: src/MaximumSumOf3NonOverlappingSubarrays689.java ================================================ /** * In a given array nums of positive integers, find three non-overlapping * subarrays with maximum sum. * * Each subarray will be of size k, and we want to maximize the sum of all * 3*k entries. * * Return the result as a list of indices representing the starting position of * each interval (0-indexed). If there are multiple answers, return the * lexicographically smallest one. * * Example: * Input: [1,2,1,2,6,7,5,1], 2 * Output: [0, 3, 5] * Explanation: Subarrays [1, 2], [2, 6], [7, 5] correspond to the starting * indices [0, 3, 5]. * * We could have also taken [2, 1], but an answer of [1, 3, 5] would be * lexicographically larger. * * Note: * nums.length will be between 1 and 20000. * nums[i] will be between 1 and 65535. * k will be between 1 and floor(nums.length / 3). * */ public class MaximumSumOf3NonOverlappingSubarrays689 { public int[] maxSumOfThreeSubarrays(int[] nums, int k) { int[] sums = new int[nums.length+1]; for (int i=1; i<=nums.length; i++) sums[i] = sums[i-1] + nums[i-1]; int[][] dp = new int[4][nums.length+1]; boolean[][] choose = new boolean[3][nums.length]; for (int i=1; i<=3; i++) { int start = i * k; for (int j=start; j<=nums.length; j++) { int pre = dp[i][j-1]; int cur = dp[i-1][j-k] + sums[j] - sums[j-k]; dp[i][j] = Math.max(cur, pre); if (cur > pre) choose[i-1][j-1] = true; } } int[] res = new int[3]; int i = 2; int j = nums.length-1; while (i >= 0) { while (choose[i][j] == false) j--; res[i] = j-k+1; i--; j = j-k; } return res; } /** * https://leetcode.com/problems/maximum-sum-of-3-non-overlapping-subarrays/solution/ */ public int[] maxSumOfThreeSubarrays2(int[] nums, int K) { //W is an array of sums of windows int[] W = new int[nums.length - K + 1]; int sum = 0; for (int i = 0; i < nums.length; i++) { sum += nums[i]; if (i >= K) sum -= nums[i-K]; if (i >= K-1) W[i-K+1] = sum; } int[] left = new int[W.length]; int best = 0; for (int i = 0; i < W.length; i++) { if (W[i] > W[best]) best = i; left[i] = best; } int[] right = new int[W.length]; best = W.length - 1; for (int i = W.length - 1; i >= 0; i--) { if (W[i] >= W[best]) best = i; right[i] = best; } int[] ans = new int[]{-1, -1, -1}; for (int j = K; j < W.length - K; j++) { int i = left[j - K], k = right[j + K]; if (ans[0] == -1 || W[i] + W[j] + W[k] > W[ans[0]] + W[ans[1]] + W[ans[2]]) { ans[0] = i; ans[1] = j; ans[2] = k; } } return ans; } } ================================================ FILE: src/MaximumVacationDays568.java ================================================ /** * LeetCode wants to give one of its best employees the option to travel among * N cities to collect algorithm problems. But all work and no play makes Jack * a dull boy, you could take vacations in some particular cities and weeks. * Your job is to schedule the traveling to maximize the number of vacation * days you could take, but there are certain rules and restrictions you need * to follow. * * Rules and restrictions: * You can only travel among N cities, represented by indexes from 0 to N-1. * Initially, you are in the city indexed 0 on Monday. * * The cities are connected by flights. The flights are represented as a N*N * matrix (not necessary symmetrical), called flights representing the airline * status from the city i to the city j. If there is no flight from the city i * to the city j, flights[i][j] = 0; Otherwise, flights[i][j] = 1. Also, * flights[i][i] = 0 for all i. * * You totally have K weeks (each week has 7 days) to travel. You can only take * flights at most once per day and can only take flights on each week's Monday * morning. Since flight time is so short, we don't consider the impact of * flight time. * * For each city, you can only have restricted vacation days in different * weeks, given an N*K matrix called days representing this relationship. * For the value of days[i][j], it represents the maximum days you could take * vacation in the city i in the week j. * * You're given the flights matrix and days matrix, and you need to output the * maximum vacation days you could take during K weeks. * * Example 1: * Input:flights = [[0,1,1],[1,0,1],[1,1,0]], days = [[1,3,1],[6,0,3],[3,3,3]] * Output: 12 * Explanation: * Ans = 6 + 3 + 3 = 12. * * One of the best strategies is: * 1st week : fly from city 0 to city 1 on Monday, and play 6 days and work 1 day. * (Although you start at city 0, we could also fly to and start at other cities since it is Monday.) * 2nd week : fly from city 1 to city 2 on Monday, and play 3 days and work 4 days. * 3rd week : stay at city 2, and play 3 days and work 4 days. * * Example 2: * Input:flights = [[0,0,0],[0,0,0],[0,0,0]], days = [[1,1,1],[7,7,7],[7,7,7]] * Output: 3 * Explanation: * Ans = 1 + 1 + 1 = 3. * * Since there is no flights enable you to move to another city, you have to * stay at city 0 for the whole 3 weeks. * For each week, you only have one day to play and six days to work. * So the maximum number of vacation days is 3. * * Example 3: * Input:flights = [[0,1,1],[1,0,1],[1,1,0]], days = [[7,0,0],[0,7,0],[0,0,7]] * Output: 21 * Explanation: * Ans = 7 + 7 + 7 = 21 * * One of the best strategies is: * 1st week : stay at city 0, and play 7 days. * 2nd week : fly from city 0 to city 1 on Monday, and play 7 days. * 3rd week : fly from city 1 to city 2 on Monday, and play 7 days. * * Note: * N and K are positive integers, which are in the range of [1, 100]. * In the matrix flights, all the values are integers in the range of [0, 1]. * In the matrix days, all the values are integers in the range [0, 7]. * You could stay at a city beyond the number of vacation days, but you should * work on the extra days, which won't be counted as vacation days. * If you fly from the city A to the city B and take the vacation on that day, * the deduction towards vacation days will count towards the vacation days of * city B in that week. * We don't consider the impact of flight hours towards the calculation of * vacation days. */ public class MaximumVacationDays568 { public int maxVacationDays(int[][] flights, int[][] days) { if (days.length == 0 || days[0].length == 0) return 0; int N = days.length; int K = days[0].length; int[][] dp = new int[N][K]; for (int i=0; i=0; k--) { for (int i=0; i temp) { temp = dp[j][k+1]; } } dp[i][k] = temp + days[i][k]; } } int res = 0; for (int i=0; i res) { res = dp[i][0]; } } return res; } public int maxVacationDays2(int[][] flights, int[][] days) { if (days.length == 0 || days[0].length == 0) return 0; int N = days.length; int K = days[0].length; int[][] dp = new int[N][2]; int col = K; for (int i=0; i=0; k--) { for (int i=0; i temp) { temp = dp[j][pre]; } } dp[i][col%2] = temp + days[i][k]; } col--; } col++; int res = 0; for (int i=0; i res) { res = dp[i][col%2]; } } return res; } /** * https://leetcode.com/problems/maximum-vacation-days/discuss/138174/Beats-99.82-without-any-extra-space.-DP-solution */ public int maxVacationDays3(int[][] flights, int[][] days) { for(int day=days[0].length-2;day>=0;day--){ for(int city=0;city q = new LinkedList<>(); q.add(root); int maxWidth = 0; while (!q.isEmpty()) { int count = 0; int left = -1; int size = q.size(); for (int i=0; i maxWidth) { maxWidth = i - left + 1; } } if (count == 0) break; } return maxWidth; } public int widthOfBinaryTree2(TreeNode root) { if (root == null) return 0; Queue q = new LinkedList<>(); q.add(new NodeWrapper(root, 0)); int maxWidth = 0; while (!q.isEmpty()) { int count = 0; int left = -1; int size = q.size(); for (int i=0; i maxWidth) { maxWidth = wrapper.idx - left + 1; } } if (count == 0) break; } return maxWidth; } class NodeWrapper { TreeNode node; int idx; NodeWrapper(TreeNode n, int i) { node = n; idx = i; } } /** * https://leetcode.com/problems/maximum-width-of-binary-tree/solution/ */ int ans; Map left; public int widthOfBinaryTree3(TreeNode root) { ans = 0; left = new HashMap(); dfs(root, 0, 0); return ans; } public void dfs(TreeNode root, int depth, int pos) { if (root == null) return; left.computeIfAbsent(depth, x-> pos); ans = Math.max(ans, pos - left.get(depth) + 1); dfs(root.left, depth + 1, 2 * pos); dfs(root.right, depth + 1, 2 * pos + 1); } } ================================================ FILE: src/MaximumXOROfTwoNumbersInAnArray421.java ================================================ /** * Given a non-empty array of numbers, a0, a1, a2, … , an-1, where 0 ≤ ai < 231. * * Find the maximum result of ai XOR aj, where 0 ≤ i, j < n. * * Could you do this in O(n) runtime? * * Example: * Input: [3, 10, 5, 25, 2, 8] * Output: 28 * Explanation: The maximum result is 5 ^ 25 = 28. */ public class MaximumXOROfTwoNumbersInAnArray421 { public int findMaximumXOR(int[] nums) { Trie trie = new Trie(); for (int n: nums) trie.add(n); int res = Integer.MIN_VALUE; for (int n: nums) { int d = trie.search(n); if ((n ^ d) > res) res = n ^ d; } return Math.max(res, 0); } class Trie { Trie zero; Trie one; Integer num; void add(int n) { add(n, 31); } void add(int n, int i) { if (i == -1) { num = n; return; } int k = (n >> i) & 1; if (k == 0) { if (zero == null) zero = new Trie(); zero.add(n, i-1); } else { if (one == null) one = new Trie(); one.add(n, i-1); } } int search(int n) { return search(n, 31); } int search(int n, int i) { if (i == -1) { return num; } int k = (n >> i) & 1; if (zero == null) return one.search(n, i-1); if (one == null) return zero.search(n, i-1); if (k == 0) return one.search(n, i-1); return zero.search(n, i-1); } } /** * https://leetcode.com/problems/maximum-xor-of-two-numbers-in-an-array/discuss/91049/Java-O(n)-solution-using-bit-manipulation-and-HashMap */ public int findMaximumXOR2(int[] nums) { int max = 0, mask = 0; for(int i = 31; i >= 0; i--){ mask = mask | (1 << i); Set set = new HashSet<>(); for(int num : nums){ set.add(num & mask); } int tmp = max | (1 << i); for(int prefix : set){ if(set.contains(tmp ^ prefix)) { max = tmp; break; } } } return max; } public int findMaximumXOR3(int[] nums){ int N = nums.length; if (N == 1) return 0; int res = Integer.MIN_VALUE; for (int i=0; i res) res = newRes; } } return Math.max(res, 0); } } ================================================ FILE: src/MedianOfTwoSortedArrays4.java ================================================ /** * There are two sorted arrays nums1 and nums2 of size m and n respectively. * * Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)). * * Example 1: * nums1 = [1, 3] * nums2 = [2] * * The median is 2.0 * * * Example 2: * nums1 = [1, 2] * nums2 = [3, 4] * * The median is (2 + 3)/2 = 2.5 * */ public class MedianOfTwoSortedArrays4 { public double findMedianSortedArrays(int[] nums1, int[] nums2) { int l1 = 0; int r1 = nums1.length-1; int l2 = 0; int r2 = nums2.length-1; int L = 0; int R = 0; while (l1 <= r1 && l2 <= r2) { if (nums1[l1] <= nums2[l2]) { L = nums1[l1]; l1++; } else { L = nums2[l2]; l2++; } if (nums1[r1] <= nums2[r2]) { R = nums2[r2]; r2--; } else { R = nums1[r1]; r1--; } } if (l1 > r1 && l2 > r2) { return (L + R) / 2.0; } else if (l1 > r1) { int mid = (l2 + r2) / 2; if ((l2 + r2)%2 == 0) { return nums2[mid]; } else { return (nums2[mid] + nums2[mid+1]) / 2.0; } } else { int mid = (l1 + r1) / 2; if ((l1 + r1)%2 == 0) { return nums1[mid]; } else { return (nums1[mid] + nums1[mid+1]) / 2.0; } } } /** * https://leetcode.com/articles/median-of-two-sorted-arrays/ */ public double findMedianSortedArrays2(int[] A, int[] B) { int m = A.length; int n = B.length; if (m > n) { // to ensure m<=n int[] temp = A; A = B; B = temp; int tmp = m; m = n; n = tmp; } int iMin = 0, iMax = m, halfLen = (m + n + 1) / 2; while (iMin <= iMax) { int i = (iMin + iMax) / 2; int j = halfLen - i; if (i < iMax && B[j-1] > A[i]){ iMin = iMin + 1; // i is too small } else if (i > iMin && A[i-1] > B[j]) { iMax = iMax - 1; // i is too big } else { // i is perfect int maxLeft = 0; if (i == 0) { maxLeft = B[j-1]; } else if (j == 0) { maxLeft = A[i-1]; } else { maxLeft = Math.max(A[i-1], B[j-1]); } if ( (m + n) % 2 == 1 ) { return maxLeft; } int minRight = 0; if (i == m) { minRight = B[j]; } else if (j == n) { minRight = A[i]; } else { minRight = Math.min(B[j], A[i]); } return (maxLeft + minRight) / 2.0; } } return 0.0; } } ================================================ FILE: src/MeetingRooms252.java ================================================ /** * Given an array of meeting time intervals consisting of start and end times * [[s1,e1],[s2,e2],...] (si < ei), determine if a person could attend all * meetings. * * Example 1: * Input: [[0,30],[5,10],[15,20]] * Output: false * * Example 2: * Input: [[7,10],[2,4]] * Output: true */ /** * Definition for an interval. * public class Interval { * int start; * int end; * Interval() { start = 0; end = 0; } * Interval(int s, int e) { start = s; end = e; } * } */ public class MeetingRooms252 { public boolean canAttendMeetings(Interval[] intervals) { Arrays.sort(intervals, (i1, i2) -> Integer.compare(i1.start, i2.start)); for (int i=1; i intervals[i].start) return false; } return true; } /** * https://leetcode.com/problems/meeting-rooms/discuss/67780/Easy-JAVA-solution-beat-98/148985 */ public boolean canAttendMeetings2(Interval[] intervals) { int len=intervals.length; if(len==0){ return true; } int[]begin=new int[len]; int[]stop=new int[len]; for(int i=0;i comparator = new Comparator() { @Override public int compare(Interval i1, Interval i2) { return Integer.compare(i1.start, i2.start); } }; Arrays.sort(intervals, comparator); Set> set = new HashSet<>(); for (Interval i: intervals) { boolean createNewList = true; for (List l: set) { Interval ii = l.get(l.size()-1); if (ii.end <= i.start) { l.add(i); createNewList = false; break; } } if (createNewList) { List newList = new ArrayList<>(); newList.add(i); set.add(newList); } } return set.size(); } /** * https://leetcode.com/problems/meeting-rooms-ii/discuss/67855/Explanation-of-%22Super-Easy-Java-Solution-Beats-98.8%22-from-@pinkfloyda */ public int minMeetingRooms2(Interval[] intervals) { int[] starts = new int[intervals.length]; int[] ends = new int[intervals.length]; for(int i=0; i() { public int compare(Interval a, Interval b) { return a.start - b.start; } }); // Use a min heap to track the minimum end time of merged intervals PriorityQueue heap = new PriorityQueue(intervals.length, new Comparator() { public int compare(Interval a, Interval b) { return a.end - b.end; } }); // start with the first meeting, put it to a meeting room heap.offer(intervals[0]); for (int i = 1; i < intervals.length; i++) { // get the meeting room that finishes earliest Interval interval = heap.poll(); if (intervals[i].start >= interval.end) { // if the current meeting starts right after // there's no need for a new room, merge the interval interval.end = intervals[i].end; } else { // otherwise, this meeting needs a new room heap.offer(intervals[i]); } // don't forget to put the meeting room back heap.offer(interval); } return heap.size(); } } ================================================ FILE: src/MergeIntervals56.java ================================================ /** * Given a collection of intervals, merge all overlapping intervals. * * For example, * Given [1,3],[2,6],[8,10],[15,18], * return [1,6],[8,10],[15,18]. */ /** * Definition for an interval. * public class Interval { * int start; * int end; * Interval() { start = 0; end = 0; } * Interval(int s, int e) { start = s; end = e; } * } */ public class MergeIntervals56 { public List merge(List intervals) { if (intervals == null || intervals.size() <= 1) return intervals; Collections.sort(intervals, new SortByLeft()); List res = new ArrayList<>(); Interval acc = intervals.get(0); int i=1; while (i < intervals.size()) { Interval curr = intervals.get(i); if (curr.start > acc.end) { res.add(acc); acc = curr; } else { acc = new Interval(acc.start, Math.max(acc.end, curr.end)); } i++; } res.add(acc); return res; } class SortByLeft implements Comparator { @Override public int compare(Interval a, Interval b) { return a.start - b.start; } } public List merge2(List intervals) { List res = new ArrayList<>(); int N = intervals.size(); if (N == 0) return res; int[] starts = new int[N]; int[] ends = new int[N]; int i = 0; for (Interval inv: intervals) { starts[i] = inv.start; ends[i] = inv.end; i++; } Arrays.sort(starts); Arrays.sort(ends); int s = 0; for (int e=1; e ends[e-1]) { res.add(new Interval(starts[s], ends[e-1])); s = e; } } res.add(new Interval(starts[s], ends[N-1])); return res; } public List merge3(List intervals) { Comparator comp = (in1, in2) -> Integer.compare(in1.start, in2.start); Collections.sort(intervals, comp); List res = new ArrayList<>(); if (intervals.size() == 0) return res; Interval tmp = intervals.get(0); for (Interval inv: intervals) { if (inv.start <= tmp.end) { tmp.start = Math.min(tmp.start, inv.start); tmp.end = Math.max(tmp.end, inv.end); } else { res.add(tmp); tmp = inv; } } res.add(tmp); return res; } } ================================================ FILE: src/MergeKSortedLists23.java ================================================ /** * Merge k sorted linked lists and return it as one sorted list. */ /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ public class MergeKSortedLists23 { /** * https://discuss.leetcode.com/topic/26095/my-simple-java-solution-use-recursion */ public static ListNode mergeKLists(ListNode[] lists){ return partion(lists,0,lists.length-1); } public static ListNode partion(ListNode[] lists,int s,int e){ if(s==e) return lists[s]; if(s queue= new PriorityQueue(lists.length,new Comparator(){ @Override public int compare(ListNode o1,ListNode o2){ if (o1.val q = new PriorityQueue((l1, l2) -> Integer.compare(l1.val, l2.val)); for (ListNode node: lists) { if (node != null) q.add(node); } while (!q.isEmpty()) { ListNode curr = q.poll(); if (curr.next != null) q.add(curr.next); curr.next = null; p.next = curr; p = p.next; } return dummy.next; } public ListNode mergeKLists5(ListNode[] lists) { if (lists == null || lists.length == 0) return null; int len = lists.length; int interval = 1; while (interval < len) { for (int i=0; i < len-interval; i+=interval*2) lists[i] = mergeTwoLists5(lists[i], lists[i + interval]); interval *= 2; } return lists[0]; } public ListNode mergeTwoLists(ListNode l1, ListNode l2) { ListNode dummy = new ListNode(0); ListNode p = dummy; while (l1 != null && l2 != null) { if (l1.val >= l2.val) { p.next = l2; l2 = l2.next; } else { p.next = l1; l1 = l1.next; } p = p.next; p.next = null; } if (l1 != null) p.next = l1; if (l2 != null) p.next = l2; return dummy.next; } public ListNode mergeKLists6(ListNode[] lists) { if (lists == null || lists.length == 0) return null; return mergeKLists(lists, 0, lists.length-1); } public ListNode mergeKLists(ListNode[] lists, int i, int j) { if (i == j) return lists[i]; else if (j - i == 1) return mergeTwoLists(lists[i], lists[j]); else { int mid = (i + j) / 2; return mergeTwoLists(mergeKLists(lists, i, mid), mergeKLists(lists, mid+1, j)); } } private ListNode mergeTwoLists(ListNode l1, ListNode l2) { ListNode prehead = new ListNode(-1); ListNode prev = prehead; while (l1 != null && l2 != null) { if (l1.val <= l2.val) { prev.next = l1; l1 = l1.next; } else { prev.next = l2; l2 = l2.next; } prev = prev.next; } prev.next = l1 == null ? l2 : l1; return prehead.next; } } ================================================ FILE: src/MergeSortedArray88.java ================================================ /** * Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as * one sorted array. * * Note: * You may assume that nums1 has enough space (size that is greater or equal to * m + n) to hold additional elements from nums2. The number of elements * initialized in nums1 and nums2 are m and n respectively. * */ public class MergeSortedArray88 { public void merge(int[] nums1, int m, int[] nums2, int n) { if (n == 0) return; int i = m-1; int j = n-1; while (i >= 0 && j >= 0) { if (nums1[i] >= nums2[j]) { nums1[i+j+1] = nums1[i]; i--; } else { nums1[i+j+1] = nums2[j]; j--; } } while (j >= 0) { nums1[j] = nums2[j]; j--; } } /** * https://leetcode.com/problems/merge-sorted-array/discuss/29505/1-Line-Solution */ public void merge2(int[] nums1, int m, int[] nums2, int n) { while (n > 0) nums1[m+n-1] = (m == 0 || nums2[n-1] > nums1[m-1]) ? nums2[--n] : nums1[--m]; } } ================================================ FILE: src/MergeTwoSortedLists21.java ================================================ /** * Merge two sorted linked lists and return it as a new list. The new list * should be made by splicing together the nodes of the first two lists. * * Example: * * Input: 1->2->4, 1->3->4 * Output: 1->1->2->3->4->4 * */ /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ public class MergeTwoSortedLists21 { public ListNode mergeTwoLists(ListNode l1, ListNode l2) { ListNode dummy = new ListNode(0); ListNode p = dummy; while (l1 != null && l2 != null) { if (l1.val >= l2.val) { p.next = l2; l2 = l2.next; } else { p.next = l1; l1 = l1.next; } p = p.next; p.next = null; } if (l1 != null) p.next = l1; if (l2 != null) p.next = l2; return dummy.next; } public ListNode mergeTwoLists2(ListNode l1, ListNode l2) { if (l1 == null) return l2; if (l2 == null) return l1; if (l1.val >= l2.val) { l2.next = mergeTwoLists2(l1, l2.next); return l2; } else { l1.next = mergeTwoLists2(l1.next, l2); return l1; } } } ================================================ FILE: src/MiddleOfTheLinkedList876.java ================================================ /** * Given a non-empty, singly linked list with head node head, return a middle * node of linked list. * * If there are two middle nodes, return the second middle node. * * Example 1: * * Input: [1,2,3,4,5] * Output: Node 3 from this list (Serialization: [3,4,5]) * The returned node has value 3. (The judge's serialization of this node is [3,4,5]). * Note that we returned a ListNode object ans, such that: * ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, and ans.next.next.next = NULL. * * Example 2: * * Input: [1,2,3,4,5,6] * Output: Node 4 from this list (Serialization: [4,5,6]) * Since the list has two middle nodes with values 3 and 4, we return the second one. * * Note: * The number of nodes in the given list will be between 1 and 100. */ /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ public class MiddleOfTheLinkedList876 { public ListNode middleNode(ListNode head) { ListNode slow = head; ListNode fast = head; while (fast != null && fast.next != null) { slow = slow.next; fast = fast.next.next; } return slow; } } ================================================ FILE: src/MinCostClimbingStairs746.java ================================================ /** * On a staircase, the i-th step has some non-negative cost cost[i] assigned * (0 indexed). * * Once you pay the cost, you can either climb one or two steps. You need to * find minimum cost to reach the top of the floor, and you can either start * from the step with index 0, or the step with index 1. * * Example 1: * Input: cost = [10, 15, 20] * Output: 15 * Explanation: Cheapest is start on cost[1], pay that cost and go to the top. * * Example 2: * Input: cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1] * Output: 6 * Explanation: Cheapest is start on cost[0], and only step on 1s, skipping cost[3]. * * Note: * cost will have a length in the range [2, 1000]. * Every cost[i] will be an integer in the range [0, 999]. */ public class MinCostClimbingStairs746 { public int minCostClimbingStairs(int[] cost) { int cost0 = 0; int cost1 = 0; for (int i=0; i<=cost.length; i++) { int newCost = Math.min(cost0, cost1) + ((i == cost.length) ? 0 : cost[i]); cost0 = cost1; cost1 = newCost; } return cost1; } /** * https://leetcode.com/problems/min-cost-climbing-stairs/solution/ */ public int minCostClimbingStairs2(int[] cost) { int f1 = 0, f2 = 0; for (int i = cost.length - 1; i >= 0; --i) { int f0 = cost[i] + Math.min(f1, f2); f2 = f1; f1 = f0; } return Math.min(f1, f2); } } ================================================ FILE: src/MinStack.java ================================================ /** * Design a stack that supports push, pop, top, and retrieving the minimum * element in constant time. * * push(x) -- Push element x onto stack. * pop() -- Removes the element on top of the stack. * top() -- Get the top element. * getMin() -- Retrieve the minimum element in the stack. * * Example: * MinStack minStack = new MinStack(); * minStack.push(-2); * minStack.push(0); * minStack.push(-3); * minStack.getMin(); --> Returns -3. * minStack.pop(); * minStack.top(); --> Returns 0. * minStack.getMin(); --> Returns -2. * */ import java.util.SortedMap; import java.util.TreeMap; class MinStack { SortedMap map = new TreeMap<>();; Stack st = new Stack<>(); /** initialize your data structure here. */ public MinStack() { } public void push(int x) { if (map.containsKey(x)) { map.put(x, map.get(x)+1); } else { map.put(x, 1); } st.push(x); } public void pop() { Integer topEle = st.peek(); int count = map.get(topEle); count--; if (count <= 0) { map.remove(topEle); } else { map.put(topEle, count); } st.pop(); } public int top() { return st.peek(); } public int getMin() { return map.firstKey(); } } /** * https://discuss.leetcode.com/topic/4953/share-my-java-solution-with-only-one-stack */ class MinStack2 { static class Element { final int value; final int min; Element(final int value, final int min) { this.value = value; this.min = min; } } final Stack stack = new Stack<>(); public void push(int x) { final int min = (stack.empty()) ? x : Math.min(stack.peek().min, x); stack.push(new Element(x, min)); } public void pop() { stack.pop(); } public int top() { return stack.peek().value; } public int getMin() { return stack.peek().min; } } /** * https://discuss.leetcode.com/topic/4953/share-my-java-solution-with-only-one-stack */ class MinStack3 { long min; Stack stack; public MinStack(){ stack=new Stack<>(); } public void push(int x) { if (stack.isEmpty()){ stack.push(0L); min=x; }else{ stack.push(x-min);//Could be negative if min value needs to change if (x0){ return (int)(top+min); }else{ return (int)(min); } } public int getMin() { return (int)min; } } /** * Your MinStack object will be instantiated and called as such: * MinStack obj = new MinStack(); * obj.push(x); * obj.pop(); * int param_3 = obj.top(); * int param_4 = obj.getMin(); */ ================================================ FILE: src/Minesweeper529.java ================================================ /** * Let's play the minesweeper game (Wikipedia, online game)! * * You are given a 2D char matrix representing the game board. 'M' represents * an unrevealed mine, 'E' represents an unrevealed empty square, 'B' * represents a revealed blank square that has no adjacent (above, below, left, * right, and all 4 diagonals) mines, digit ('1' to '8') represents how many * mines are adjacent to this revealed square, and finally 'X' represents a * revealed mine. * * Now given the next click position (row and column indices) among all the * unrevealed squares ('M' or 'E'), return the board after revealing this * position according to the following rules: * * If a mine ('M') is revealed, then the game is over - change it to 'X'. * If an empty square ('E') with no adjacent mines is revealed, then change it * to revealed blank ('B') and all of its adjacent unrevealed squares should be * revealed recursively. * If an empty square ('E') with at least one adjacent mine is revealed, then * change it to a digit ('1' to '8') representing the number of adjacent mines. * Return the board when no more squares will be revealed. * * Example 1: * Input: * * [['E', 'E', 'E', 'E', 'E'], * ['E', 'E', 'M', 'E', 'E'], * ['E', 'E', 'E', 'E', 'E'], * ['E', 'E', 'E', 'E', 'E']] * * lick : [3,0] * * Output: * * [['B', '1', 'E', '1', 'B'], * ['B', '1', 'M', '1', 'B'], * ['B', '1', '1', '1', 'B'], * ['B', 'B', 'B', 'B', 'B']] * * Explanation: * https://leetcode.com/static/images/problemset/minesweeper_example_1.png * * Example 2: * Input: * * [['B', '1', 'E', '1', 'B'], * ['B', '1', 'M', '1', 'B'], * ['B', '1', '1', '1', 'B'], * ['B', 'B', 'B', 'B', 'B']] * * Click : [1,2] * * Output: * [['B', '1', 'E', '1', 'B'], * ['B', '1', 'X', '1', 'B'], * ['B', '1', '1', '1', 'B'], * ['B', 'B', 'B', 'B', 'B']] * * Explanation: * https://leetcode.com/static/images/problemset/minesweeper_example_2.png * * Note: * he range of the input matrix's height and width is [1,50]. * The click position will only be an unrevealed square ('M' or 'E'), which * also means the input board contains at least one clickable square. * The input board won't be a stage when game is over (some mines have * been revealed). * For simplicity, not mentioned rules should be ignored in this problem. * For example, you don't need to reveal all the unrevealed mines when the game * is over, consider any cases that you will win the game or flag any squares. */ public class Minesweeper529 { private int[][] directions = new int[][]{{-1, -1}, {-1, 0}, {-1, 1}, {1, 1}, {1, 0}, {1, -1}, {0, 1}, {0, -1}}; public char[][] updateBoard(char[][] board, int[] click) { if (board == null || board.length == 0|| board[0].length == 0) return board; int M = board.length; int N = board[0].length; helper(board, click[0], click[1], M, N); return board; } public void helper(char[][] board, int i, int j, int M, int N) { if (i < 0 || i >= M || j < 0 || j >= N || board[i][j] == 'B' || isDigit(board[i][j]) || board[i][j] == 'X') return; if (board[i][j] == 'M') { board[i][j] = 'X'; return; } // board[i][j] == 'E' int numMines = numAdjacentMines(board, i, j, M, N); if (numMines == 0) { board[i][j] = 'B'; for (int[] d: directions) { helper(board, i + d[0], j + d[1], M, N); } } else { board[i][j] = Character.forDigit(numMines, 10); } } private boolean isDigit(char c) { return c >= '1' && c <= '8'; } private int numAdjacentMines(char[][] board, int i, int j, int M, int N) { int numMines = 0; for (int[] d: directions) { int ii = i + d[0]; int jj = j + d[1]; if (ii < 0 || ii >= M || jj < 0 || jj >= N) continue; if (board[ii][jj] == 'M' || board[ii][jj] == 'X') numMines++; } return numMines; } } ================================================ FILE: src/MinimumASCIIDeleteSumForTwoStrings712.java ================================================ /** * Given two strings s1, s2, find the lowest ASCII sum of deleted characters to * make two strings equal. * * Example 1: * Input: s1 = "sea", s2 = "eat" * Output: 231 * Explanation: Deleting "s" from "sea" adds the ASCII value of "s" (115) to the sum. * Deleting "t" from "eat" adds 116 to the sum. * At the end, both strings are equal, and 115 + 116 = 231 is the minimum sum possible to achieve this. * * Example 2: * Input: s1 = "delete", s2 = "leet" * Output: 403 * Explanation: Deleting "dee" from "delete" to turn the string into "let", * adds 100[d]+101[e]+101[e] to the sum. Deleting "e" from "leet" adds 101[e] to the sum. * At the end, both strings are equal to "let", and the answer is 100+101+101+101 = 403. * If instead we turned both strings into "lee" or "eet", we would get answers of 433 or 417, which are higher. * * Note: * 0 < s1.length, s2.length <= 1000. * All elements of each string will have an ASCII value in [97, 122]. */ public class MinimumASCIIDeleteSumForTwoStrings712 { public int minimumDeleteSum(String s1, String s2) { if (s1.equals(s2)) return 0; int len1 = s1.length(); int len2 = s2.length(); int[][] dp = new int[len1 + 1][len2 + 1]; for (int i=1; i<=len1; i++) dp[i][0] = (int) s1.charAt(i-1) + dp[i-1][0]; for (int j=1; j<=len2; j++) dp[0][j] = (int) s2.charAt(j-1) + dp[0][j-1]; for (int i=1; i<=len1; i++) { for (int j=1; j<=len2; j++) { if (s1.charAt(i-1) == s2.charAt(j-1)) { dp[i][j] = dp[i-1][j-1]; } else { int noI = (int) s1.charAt(i-1) + dp[i-1][j]; int noJ = (int) s2.charAt(j-1) + dp[i][j-1]; dp[i][j] = Math.min(noI, noJ); } } } return dp[len1][len2]; } } ================================================ FILE: src/MinimumAbsoluteDifferenceInBST530.java ================================================ /** * Given a binary search tree with non-negative values, find the minimum * absolute difference between values of any two nodes. * * Example: * * Input: * * 1 * \ * 3 * / * 2 * * Output: * 1 * * Explanation: * The minimum absolute difference is 1, which is the difference between 2 * and 1 (or between 2 and 3). * * Note: There are at least two nodes in this BST. */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class MinimumAbsoluteDifferenceInBST530 { public int getMinimumDifference(TreeNode root) { int[] res = new int[]{Integer.MAX_VALUE}; helper(root, res); return res[0]; } public int[] helper(TreeNode root, int[] res) { int[] bound = new int[]{root.val, root.val}; if (root.left == null && root.right == null) return bound; if (root.left != null) { int[] leftRes = helper(root.left, res); bound[0] = Math.min(bound[0], leftRes[0]); bound[1] = Math.max(bound[1], leftRes[1]); res[0] = Math.min(res[0], Math.abs(leftRes[1] - root.val)); } if (root.right != null) { int[] rightRes = helper(root.right, res); bound[0] = Math.min(bound[0], rightRes[0]); bound[1] = Math.max(bound[1], rightRes[1]); res[0] = Math.min(res[0], Math.abs(rightRes[0] - root.val)); } return bound; } } ================================================ FILE: src/MinimumDepthOfBinaryTree111.java ================================================ /** * Given a binary tree, find its minimum depth. * * The minimum depth is the number of nodes along the shortest path from the * root node down to the nearest leaf node. * * Note: A leaf is a node with no children. * * Example: * * Given binary tree [3,9,20,null,null,15,7], * * 3 * / \ * 9 20 * / \ * 15 7 * return its minimum depth = 2. * */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class MinimumDepthOfBinaryTree111 { public int minDepth(TreeNode root) { if (root == null) return 0; Queue q = new LinkedList<>(); int depth = 1; q.add(root); while (!q.isEmpty()) { int size = q.size(); for (int i=0; i(), res); return res[0]; } public void minDiffInBST(TreeNode root, LinkedList list, int[] res) { if (root.left != null) minDiffInBST(root.left, list, res); if (!list.isEmpty() && root.val - list.getLast() < res[0]) { res[0] = root.val - list.getLast(); } list.add(root.val); if (root.right != null) minDiffInBST(root.right, list, res); } public int minDiffInBST2(TreeNode root) { int[] res = new int[]{Integer.MAX_VALUE}; Integer[] pre = new Integer[]{null}; minDiffInBST2(root, new LinkedList<>(), pre, res); return res[0]; } public void minDiffInBST2(TreeNode root, LinkedList list, Integer[] pre, int[] res) { if (root.left != null) minDiffInBST2(root.left, list, pre, res); if (pre[0] != null && root.val - pre[0] < res[0]) { res[0] = root.val - pre[0]; } pre[0] = root.val; if (root.right != null) minDiffInBST2(root.right, list, pre, res); } } ================================================ FILE: src/MinimumGeneticMutation433.java ================================================ /** * A gene string can be represented by an 8-character long string, * with choices from "A", "C", "G", "T". * * Suppose we need to investigate about a mutation (mutation from "start" to "end"), * where ONE mutation is defined as ONE single character changed in the gene string. * * For example, "AACCGGTT" -> "AACCGGTA" is 1 mutation. * * Also, there is a given gene "bank", which records all the valid gene mutations. * A gene must be in the bank to make it a valid gene string. * * Now, given 3 things - start, end, bank, your task is to determine what is the * minimum number of mutations needed to mutate from "start" to "end". If there * is no such a mutation, return -1. * * Note: * * Starting point is assumed to be valid, so it might not be included in the bank. * If multiple mutations are needed, all mutations during in the sequence must be valid. * You may assume start and end string is not the same. * * Example 1: * * start: "AACCGGTT" * end: "AACCGGTA" * bank: ["AACCGGTA"] * * return: 1 * * Example 2: * * start: "AACCGGTT" * end: "AAACGGTA" * bank: ["AACCGGTA", "AACCGCTA", "AAACGGTA"] * * return: 2 * * Example 3: * * start: "AAAAACCC" * end: "AACCCCCC" * bank: ["AAAACCCC", "AAACCCCC", "AACCCCCC"] * * return: 3 */ public class MinimumGeneticMutation433 { public int minMutation(String start, String end, String[] bank) { int len = bank.length; boolean[] marked = new boolean[len]; Integer res = helper(start, end, bank, len, marked, 0, Integer.MAX_VALUE); return res.equals(Integer.MAX_VALUE) ? -1 : res; } private int helper(String start, String end, String[] bank, int len, boolean[] marked, int step, Integer res) { for (Integer i=0; i findMinHeightTrees(int n, int[][] edges) { Map> map = new HashMap<>(); for (int i=0; i()); } for (int[] e: edges) { map.get(e[0]).put(e[1], -1); map.get(e[1]).put(e[0], -1); } List res = new ArrayList<>(); int minH = Integer.MAX_VALUE; for (int p=0; p(); res.add(p); minH = newHeight; } else if (newHeight == minH) { res.add(p); } } return res; } private int search(Integer p, Integer h, Map> map, boolean[] marked) { Map connects = map.get(p); int max = 0; for (Map.Entry c: connects.entrySet()) { if (marked[c.getKey()]) { max = Math.max(max, h); continue; } if (c.getValue() != -1) { max = Math.max(max, c.getValue()); continue; } marked[c.getKey()] = true; int cValue = search(c.getKey(), h, map, marked); marked[c.getKey()] = false; c.setValue(cValue); max = Math.max(max, cValue); } return max+1; } /** * https://discuss.leetcode.com/topic/30572/share-some-thoughts */ public List findMinHeightTrees2(int n, int[][] edges) { if (n == 1) return Collections.singletonList(0); List> adj = new ArrayList<>(n); for (int i = 0; i < n; ++i) adj.add(new HashSet<>()); for (int[] edge : edges) { adj.get(edge[0]).add(edge[1]); adj.get(edge[1]).add(edge[0]); } List leaves = new ArrayList<>(); for (int i = 0; i < n; ++i) if (adj.get(i).size() == 1) leaves.add(i); while (n > 2) { n -= leaves.size(); List newLeaves = new ArrayList<>(); for (int i : leaves) { int j = adj.get(i).iterator().next(); adj.get(j).remove(i); if (adj.get(j).size() == 1) newLeaves.add(j); } leaves = newLeaves; } return leaves; } /** * https://discuss.leetcode.com/topic/30956/two-o-n-solutions */ int n; List[] e; private void bfs(int start, int[] dist, int[] pre) { boolean[] visited = new boolean[n]; Queue queue = new ArrayDeque<>(); queue.add(start); dist[start] = 0; visited[start] = true; pre[start] = -1; while (!queue.isEmpty()) { int u = queue.poll(); for (int v : e[u]) if (!visited[v]) { visited[v] = true; dist[v] = dist[u] + 1; queue.add(v); pre[v] = u; } } } public List findMinHeightTree3(int n, int[][] edges) { if (n <= 0) return new ArrayList<>(); this.n = n; e = new List[n]; for (int i = 0; i < n; i++) e[i] = new ArrayList<>(); for (int[] pair : edges) { int u = pair[0]; int v = pair[1]; e[u].add(v); e[v].add(u); } int[] d1 = new int[n]; int[] d2 = new int[n]; int[] pre = new int[n]; bfs(0, d1, pre); int u = 0; for (int i = 0; i < n; i++) if (d1[i] > d1[u]) u = i; bfs(u, d2, pre); int v = 0; for (int i = 0; i < n; i++) if (d2[i] > d2[v]) v = i; List list = new ArrayList<>(); while (v != -1) { list.add(v); v = pre[v]; } if (list.size() % 2 == 1) return Arrays.asList(list.get(list.size() / 2)); else return Arrays.asList(list.get(list.size() / 2 - 1), list.get(list.size() / 2)); } /** * https://discuss.leetcode.com/topic/30956/two-o-n-solutions */ int n; List[] e; int[] height1; int[] height2; int[] dp; private void dfs4(int u, int parent) { height1[u] = height2[u] = -Integer.MIN_VALUE / 10; for (int v : e[u]) if (v != parent) { dfs4(v, u); int tmp = height1[v] + 1; if (tmp > height1[u]) { height2[u] = height1[u]; height1[u] = tmp; } else if (tmp > height2[u]) { height2[u] = tmp; } } height1[u] = Math.max(height1[u], 0); // in case u is a leaf. } private void dfs4(int u, int parent, int acc) { dp[u] = Math.max(height1[u], acc); for (int v : e[u]) if (v != parent) { int newAcc = Math.max(acc + 1, (height1[v] + 1 == height1[u] ? height2[u] : height1[u]) + 1); dfs4(v, u, newAcc); } } public List findMinHeightTrees4(int n, int[][] edges) { if (n <= 0) return new ArrayList<>(); if (n == 1) return Arrays.asList(0); this.n = n; e = new List[n]; for (int i = 0; i < n; i++) e[i] = new ArrayList<>(); for (int[] pair : edges) { int u = pair[0]; int v = pair[1]; e[u].add(v); e[v].add(u); } height1 = new int[n]; height2 = new int[n]; dp = new int[n]; dfs4(0, -1); dfs4(0, -1, 0); int min = dp[0]; for (int i : dp) if (i < min) min = i; List ans = new ArrayList<>(); for (int i = 0; i < n; i++) if (dp[i] == min) ans.add(i); return ans; } } ================================================ FILE: src/MinimumMovesToEqualArrayElementsII462.java ================================================ /** * Given a non-empty integer array, find the minimum number of moves required * to make all array elements equal, where a move is incrementing a selected * element by 1 or decrementing a selected element by 1. * * You may assume the array's length is at most 10,000. * * Example: * * Input: * [1,2,3] * * Output: * 2 * * Explanation: * Only two moves are needed (remember each move increments or decrements one element): * * [1,2,3] => [2,2,3] => [2,2,2] */ public class MinimumMovesToEqualArrayElementsII462 { public int minMoves2(int[] nums) { Arrays.sort(nums); int m = 0; int midIndex = nums.length / 2; if (nums.length % 2 == 1) { m = nums[midIndex]; } else { m = (nums[midIndex - 1] + nums[midIndex]) /2; } int res = 0; for (int n: nums) { res += Math.abs(n - m); } return res; } } ================================================ FILE: src/MinimumPathSum64.java ================================================ /** * Given a m x n grid filled with non-negative numbers, find a path from top * left to bottom right which minimizes the sum of all numbers along its path. * * Note: You can only move either down or right at any point in time. */ public class MinimumPathSum64 { public int minPathSum(int[][] grid) { int m = grid.length; int n = grid[0].length; int[][] dp = new int[m][n]; for (int i = 0; i < m; i++) for (int j = 0; j < n; j++) dp[i][j] = Integer.MAX_VALUE; dp[0][0] = grid[0][0]; for (int i = 1; i < m; i++) dp[i][0] = grid[i][0] + dp[i - 1][0]; for (int i = 1; i < n; i++) dp[0][i] = grid[0][i] + dp[0][i - 1]; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { dp[i][j] = Math.min(dp[i-1][j], dp[i][j-1]) + grid[i][j]; } } return dp[m-1][n-1]; } /** * https://discuss.leetcode.com/topic/22732/my-solution-beats-100-java-solutions */ public int minPathSum1(int[][] grid) { if(grid.length == 0) return 0; int r = grid.length; int c = grid[0].length; for(int i=0;i0) ? grid[i][j-1] : Integer.MAX_VALUE; int topSum = (i>0) ? grid[i-1][j] : Integer.MAX_VALUE; if(i==0 && j==0) continue; grid[i][j] += Math.min(leftSum, topSum); } } return grid[r-1][c-1]; } /** * https://discuss.leetcode.com/topic/38213/my-java-solution-using-dp-with-memorization-beats-about-98-submissions */ public int minPathSum2(int[][] grid) { int[][] memo = new int[grid.length][grid[0].length]; return minPathSumHelper(grid, 0, 0, memo); } public int minPathSumHelper(int[][] grid, int row, int col, int[][] memo) { if(row == grid.length-1 && col == grid[0].length-1) return grid[row][col]; if(memo[row][col] != 0) return memo[row][col]; int rowInc = Integer.MAX_VALUE, colInc = Integer.MAX_VALUE; if(row < grid.length-1) rowInc = minPathSumHelper(grid, row+1, col, memo); if(col < grid[0].length-1) colInc = minPathSumHelper(grid, row, col+1, memo); memo[row][col] = Math.min(rowInc, colInc) + grid[row][col]; return memo[row][col]; } /** * https://discuss.leetcode.com/topic/85826/java-solution-1ms-recursive-and-4ms-iterative */ public int minPathSum3(int[][] grid) { int[][] dp = new int[grid.length][grid[0].length]; return minPathSum(grid, 0, 0, dp); } public int minPathSum(int[][] grid, int i, int j, int[][] dp) { if (i == grid.length || j == grid[0].length) { return Integer.MAX_VALUE; } if (i == grid.length - 1 && j == grid[0].length - 1) { return grid[i][j]; } if (dp[i][j] != 0) { return dp[i][j]; } int min = grid[i][j]; min += Math.min(minPathSum(grid, i, j + 1, dp), minPathSum(grid, i + 1, j, dp)); dp[i][j] = min; return min; } public int minPathSum4(int[][] grid) { int M = grid.length; if (M == 0) return 0; int N = grid[0].length; if (N == 0) return 0; for (int j=1; j= s && slow < nums.length) { min = Math.min(min, fast-slow+1); sum -= nums[slow]; slow++; } } return min == Integer.MAX_VALUE ? 0 : min; } public int minSubArrayLen2(int s, int[] nums) { if (nums == null || nums.length == 0) return 0; int minLen = Integer.MAX_VALUE; int sum = 0; int left = 0; int right = 0; while (right < nums.length) { sum += nums[right++]; while (sum >= s) { if (right - left < minLen) { minLen = right - left; } sum -= nums[left++]; } } return minLen == Integer.MAX_VALUE ? 0 : minLen; } public int minSubArrayLen3(int s, int[] nums) { if (nums == null || nums.length == 0) return 0; int lo = 1; int hi = nums.length; int minLen = Integer.MAX_VALUE; while (lo <= hi) { int mid = lo + (hi - lo) / 2; if (isValid(nums, mid, s)) { if (mid < minLen) minLen = mid; hi = mid - 1; } else { lo = mid + 1; } } return minLen == Integer.MAX_VALUE ? 0 : minLen; } private boolean isValid(int[] nums, int len, int s) { int sum = 0; for (int i=0; i= s) return true; } for (int i=len; i= s) return true; } return false; } } ================================================ FILE: src/MinimumWindowSubsequence727.java ================================================ /** * Given strings S and T, find the minimum (contiguous) substring W of S, so * that T is a subsequence of W. * * If there is no such window in S that covers all characters in T, return the * empty string "". If there are multiple such minimum-length windows, return * the one with the left-most starting index. * * Example 1: * Input: * S = "abcdebdde", T = "bde" * Output: "bcde" * * Explanation: * "bcde" is the answer because it occurs before "bdde" which has the same length. * "deb" is not a smaller window because the elements of T in the window must occur in order. * * Note: * * All the strings in the input will only contain lowercase letters. * The length of S will be in the range [1, 20000]. * The length of T will be in the range [1, 100]. * */ public class MinimumWindowSubsequence727 { public String minWindow(String S, String T) { if (S.length() == 0 || T.length() == 0) return ""; char[] schars = S.toCharArray(); char[] tchars = T.toCharArray(); int sl = schars.length; int tl = tchars.length; int[][] n = new int[tl+1][sl+1]; for (int j=0; j<=sl; j++) n[0][j] = 0; for (int i=1; i<=tl; i++) n[i][0] = -1; for (int i=1; i<=tl; i++) { for (int j=1; j<=sl; j++) { n[i][j] = Math.max( (schars[j-1] == tchars[i-1] && n[i-1][j-1] != -1) ? j : -1, n[i][j-1] ); } } int[] edges = new int[2]; int diff = Integer.MAX_VALUE; int j = 1; while (j <= sl && n[tl][j] == -1) j++; while (j <= sl) { int lastJ = j; int i = tl; while (i > 1 && j > 1) { i--; j--; j = n[i][j]; } if (i == 1 && j > 0 && diff > lastJ - j + 1) { edges[0] = j; edges[1] = lastJ; diff = lastJ - j + 1; } j = lastJ; while (j <= sl && n[tl][j] == lastJ) j++; } return (diff == Integer.MAX_VALUE) ? "" : S.substring(edges[0]-1, edges[1]); } /** * https://leetcode.com/problems/minimum-window-subsequence/solution/ */ public String minWindow2s(String S, String T) { int[][] dp = new int[2][S.length()]; for (int i = 0; i < S.length(); ++i) dp[0][i] = S.charAt(i) == T.charAt(0) ? i : -1; /*At time j when considering T[:j+1], the smallest window [s, e] where S[e] == T[j] is represented by dp[j & 1][e] = s, and the previous information of the smallest window [s, e] where S[e] == T[j-1] is stored as dp[~j & 1][e] = s. */ for (int j = 1; j < T.length(); ++j) { int last = -1; Arrays.fill(dp[j & 1], -1); //Now we would like to calculate the candidate windows //"dp[j & 1]" for T[:j+1]. 'last' is the last window seen. for (int i = 0; i < S.length(); ++i) { if (last >= 0 && S.charAt(i) == T.charAt(j)) dp[j & 1][i] = last; if (dp[~j & 1][i] >= 0) last = dp[~j & 1][i]; } } //Looking at the window data dp[~T.length & 1], //choose the smallest length window [s, e]. int start = 0, end = S.length(); for (int e = 0; e < S.length(); ++e) { int s = dp[~T.length() & 1][e]; if (s >= 0 && e - s < end - start) { start = s; end = e; } } return end < S.length() ? S.substring(start, end+1) : ""; } /** * https://leetcode.com/problems/minimum-window-subsequence/solution/ */ public String minWindow3(String S, String T) { int N = S.length(); int[] last = new int[26]; int[][] nxt = new int[N][26]; Arrays.fill(last, -1); for (int i = N - 1; i >= 0; --i) { last[S.charAt(i) - 'a'] = i; for (int k = 0; k < 26; ++k) { nxt[i][k] = last[k]; } } List windows = new ArrayList(); for (int i = 0; i < N; ++i) { if (S.charAt(i) == T.charAt(0)) windows.add(new int[]{i, i}); } for (int j = 1; j < T.length(); ++j) { int letterIndex = T.charAt(j) - 'a'; for (int[] window: windows) { if (window[1] < N-1 && nxt[window[1]+1][letterIndex] >= 0) { window[1] = nxt[window[1]+1][letterIndex]; } else { window[0] = window[1] = -1; break; } } } int[] ans = {-1, S.length()}; for (int[] window: windows) { if (window[0] == -1) break; if (window[1] - window[0] < ans[1] - ans[0]) { ans = window; } } return ans[0] >= 0 ? S.substring(ans[0], ans[1] + 1) : ""; } /** * https://leetcode.com/problems/minimum-window-subsequence/discuss/109362/Java-Super-Easy-DP-Solution-(O(mn)) */ public String minWindow4(String S, String T) { int m = T.length(), n = S.length(); int[][] dp = new int[m + 1][n + 1]; for (int j = 0; j <= n; j++) { dp[0][j] = j + 1; } for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { if (T.charAt(i - 1) == S.charAt(j - 1)) { dp[i][j] = dp[i - 1][j - 1]; } else { dp[i][j] = dp[i][j - 1]; } } } int start = 0, len = n + 1; for (int j = 1; j <= n; j++) { if (dp[m][j] != 0) { if (j - dp[m][j] + 1 < len) { start = dp[m][j] - 1; len = j - dp[m][j] + 1; } } } return len == n + 1 ? "" : S.substring(start, start + len); } public String minWindow5(String S, String T) { if (S == null || T == null || T.length() > S.length()) return ""; int lenS = S.length(); int lenT = T.length(); char[] charS = S.toCharArray(); char[] charT = T.toCharArray(); int[][] pos = new int[lenT][lenS]; for (int i=0; i=0; j--) { if (pos[lenT-1][j] == -1) break; if (j - pos[lenT-1][j] + 1 <= minSize) { start = pos[lenT-1][j]; minSize = j - pos[lenT-1][j] + 1; } } return start == -1 ? "" : S.substring(start, start + minSize); } /** * https://leetcode.com/problems/minimum-window-subsequence/discuss/109373/m-pointer-technique-Java-O(S.length()-*-T.length())-solution */ public String minWindow6(String S, String T) { int n = S.length(), m = T.length(); int l = 0, r = n; for (int i = 0; i < n; i++) { if (S.charAt(i) != T.charAt(0)) continue; // No group of mapping is found, so continue int k = i + 1; for (int j = 1; j < m; j++, k++) { // Greedy algorithm to find the greedy mapping while (k < n && S.charAt(k) != T.charAt(j)) k++; if (k == n) return (r == n ? "" : S.substring(l, r + 1)); // Link for T[j] does not exist, so return } if (k - 1 - i < r - l) { // Update the result substring if one with a smaller length is found l = i; r = k - 1; } } return (r == n ? "" : S.substring(l, r + 1)); } /** * https://leetcode.com/problems/minimum-window-subsequence/discuss/109373/m-pointer-technique-Java-O(S.length()-*-T.length())-solution */ public String minWindow7(String S, String T) { int n = S.length(), m = T.length(); int l = 0, r = n; int[] p = new int[m]; for (int i = 0; i < n; i++) { if (S.charAt(i) != T.charAt(0)) continue; // No group of mapping is found, so continue p[0] = i; // Group of mapping is found, so update the first link for (int j = 1, k = i + 1; j < m; j++, k++) { // Greedy algorithm to find the greedy mapping if (k <= p[j]) break; // Early termination, since the remaining links have been computed in previous groups while (k < n && S.charAt(k) != T.charAt(j)) k++; if (k == n) return (r == n ? "" : S.substring(l, r + 1)); // Link for T[j] does not exist, so return p[j] = k; // Else update the link for T[j] } if (p[m - 1] - p[0] < r - l) { // Update the result substring if one with a smaller length is found l = p[0]; r = p[m - 1]; } } return (r == n ? "" : S.substring(l, r + 1)); } public String minWindow8(String S, String T) { int lenS = S.length(); int lenT = T.length(); char[] charS = S.toCharArray(); char[] charT = T.toCharArray(); int left = 0; int right = 0; int flag = 0; int start = -1; int minLen = lenS + 1; while (right < lenS) { while (left <= lenS - lenT && charS[left] != charT[0]) left++; if (left > lenS - lenT) break; right = left; flag = 0; while (flag < lenT && right < lenS) { if (charS[right] == charT[flag]) { flag++; } right++; } if (flag != lenT) break; if (right - left < minLen) { minLen = right - left; start = left; } left++; right = left; } return start == -1 ? "" : S.substring(start, start + minLen); } public String minWindow9(String S, String T) { int lenS = S.length(); int lenT = T.length(); char[] charS = S.toCharArray(); char[] charT = T.toCharArray(); int left = 0; int right = 0; int flag = 0; int start = -1; int minLen = lenS + 1; while (right < lenS) { while (left <= lenS - lenT && charS[left] != charT[0]) left++; if (left > lenS - lenT) break; right = left; flag = 0; while (flag < lenT && right < lenS) { if (charS[right] == charT[flag]) { flag++; } right++; } if (flag != lenT) break; int newStart = backwards(charS, charT, left, right-1); left = Math.max(left, newStart); if (right - left < minLen) { minLen = right - left; start = left; } left++; right = left; } return start == -1 ? "" : S.substring(start, start + minLen); } private int backwards(char[] charS, char[] charT, int begin, int end) { int flagS = end; int flagT = charT.length - 1; while (true) { if (charS[flagS] == charT[flagT]) { if (flagT == 0) return flagS; flagT--; } flagS--; } } } ================================================ FILE: src/MinimumWindowSubstring76.java ================================================ /** * Given a string S and a string T, find the minimum window in S which will * contain all the characters in T in complexity O(n). * * For example, * S = "ADOBECODEBANC" * T = "ABC" * Minimum window is "BANC". * * Note: * If there is no such window in S that covers all characters in T, return the * empty string "". * * If there are multiple such windows, you are guaranteed that there will always * be only one unique minimum window in S. */ public class MinimumWindowSubstring76 { /** * https://discuss.leetcode.com/topic/12492/share-my-neat-java-solution */ public String minWindow(String S, String T) { if(S==null||S.isEmpty()||T==null||T.isEmpty()) return ""; int i=0, j=0; int[] Tmap=new int[256]; int[] Smap=new int[256]; for(int k=0; k< T.length(); k++){ Tmap[T.charAt(k)]++; } int found=0; int length=Integer.MAX_VALUE; String res=""; while(j0){ Smap[S.charAt(j)]++; if(Smap[S.charAt(j)]<=Tmap[S.charAt(j)]){ found++; } } j++; } while(found==T.length()){ if(j-i0){ Smap[S.charAt(i)]--; if(Smap[S.charAt(i)]= 1) counter++; while (counter == t.length()) { if (end - start < min) { min = end - start; ts = start; te = end; } if (map[s.charAt(start++)]++ >= 0) counter--; } } return min == Integer.MAX_VALUE? "": s.substring(ts,te); } public String minWindow3(String s, String t) { if (s == null || s.length() == 0 || t == null || t.length() == 0) return ""; int lenS = s.length(); int lenT = t.length(); int start = 0; int len = Integer.MAX_VALUE; int l = 0; int r = 0; char[] charsInS = s.toCharArray(); int[] map = new int[256]; boolean[] contains = new boolean[256]; char[] charsInT = t.toCharArray(); for (char c: charsInT) { map[c]++; contains[c] = true; } int count = 0; while (r < lenS) { if (!contains[charsInS[r]]) { r++; continue; } map[charsInS[r]]--; if (map[charsInS[r]] >= 0) { count++; } r++; while (l <= r && count == lenT) { if (r - l < len) { len = r - l; start = l; } if (contains[charsInS[l]]) { map[charsInS[l]]++; if (map[charsInS[l]] > 0) { count--; } } l++; } } return len == Integer.MAX_VALUE ? "" : s.substring(start, start + len); } } ================================================ FILE: src/MissingNumber268.java ================================================ /** * Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, * find the one that is missing from the array. * * Example 1: * Input: [3,0,1] * Output: 2 * * Example 2: * Input: [9,6,4,2,3,5,7,0,1] * Output: 8 * * Note: * Your algorithm should run in linear runtime complexity. * Could you implement it using only constant extra space complexity? */ public class MissingNumber268 { public int missingNumber(int[] nums) { int sum = 0; int N = nums.length; for (int n: nums) sum += n; return N * (N + 1) / 2 - sum; } /** * https://leetcode.com/problems/missing-number/solution/ */ public int missingNumber2(int[] nums) { int missing = nums.length; for (int i = 0; i < nums.length; i++) { missing ^= i ^ nums[i]; } return missing; } } ================================================ FILE: src/MissingRanges163.java ================================================ /** * Given a sorted integer array where the range of elements are in the * inclusive range [lower, upper], return its missing ranges. * * For example, given [0, 1, 3, 50, 75], lower = 0 and upper = 99, return * ["2", "4->49", "51->74", "76->99"]. */ public class MissingRanges163 { public List findMissingRanges(int[] nums, int lower, int upper) { List res = new ArrayList<>(); long mark = (long) lower; for (int i=0; i 0 && nums[i] == nums[i-1]) continue; long n = (long) nums[i]; if (n > mark) { String s = String.valueOf(mark); res.add((mark == n-1) ? s : s + "->" + String.valueOf(n-1)); } mark = n+1; } if (mark == upper) res.add(String.valueOf(mark)); else if (mark < upper) res.add(String.valueOf(mark) + "->" + String.valueOf(upper)); return res; } } ================================================ FILE: src/MonotoneIncreasingDigits738.java ================================================ /** * Given a non-negative integer N, find the largest number that is less than or * equal to N with monotone increasing digits. * * (Recall that an integer has monotone increasing digits if and only if each * pair of adjacent digits x and y satisfy x <= y.) * * Example 1: * Input: N = 10 * Output: 9 * * Example 2: * Input: N = 1234 * Output: 1234 * * Example 3: * Input: N = 332 * Output: 299 * Note: N is an integer in the range [0, 10^9]. */ public class MonotoneIncreasingDigits738 { public int monotoneIncreasingDigits(int N) { String ns = Integer.toString(N); int i = 0; char[] chars = ns.toCharArray(); while (i + 1 < chars.length && chars[i] <= chars[i+1]) { i++; } while (i > 0 && chars[i-1] == chars[i]) { i--; } if (i == chars.length - 1) return N; chars[i] = (char) ((int) chars[i] - 1); for (int j=i+1; j S[i]) S[--i]--; for (int j = i+1; j < S.length; ++j) S[j] = '9'; return Integer.parseInt(String.valueOf(S)); } /** * https://leetcode.com/problems/monotone-increasing-digits/discuss/144404/Simple-Java-from-back-to-front-no-extra-space-and-no-conversion-to-char */ public int monotoneIncreasingDigits3(int N) { int res = 0; int pre = Integer.MAX_VALUE; int offset = 1; while(N != 0) { int digit = N % 10; if(digit > pre) { res = digit * offset - 1; pre = digit - 1; }else { res = res + digit * offset; pre = digit; } offset *= 10; N = N / 10; } return res; } } ================================================ FILE: src/MonotonicArray896.java ================================================ /** * An array is monotonic if it is either monotone increasing or monotone decreasing. * * An array A is monotone increasing if for all i <= j, A[i] <= A[j]. An array A is * monotone decreasing if for all i <= j, A[i] >= A[j]. * * Return true if and only if the given array A is monotonic. * * Example 1: * Input: [1,2,2,3] * Output: true * * Example 2: * Input: [6,5,4,4] * Output: true * * Example 3: * Input: [1,3,2] * Output: false * * Example 4: * Input: [1,2,4,5] * Output: true * * Example 5: * Input: [1,1,1] * Output: true * * Note: * 1 <= A.length <= 50000 * -100000 <= A[i] <= 100000 */ public class MonotonicArray896 { public boolean isMonotonic(int[] A) { if (A == null || A.length <= 2) return true; int i = 1; int len = A.length; while (i < len && A[i] == A[i-1]) i++; if (i == len) return true; boolean flag = A[i] > A[i-1]; while (i < len) { if (A[i] != A[i-1] && flag != A[i] > A[i-1]) return false; i++; } return true; } /** * https://leetcode.com/problems/monotonic-array/solution/ */ public boolean isMonotonic2(int[] A) { int store = 0; for (int i = 0; i < A.length - 1; ++i) { int c = Integer.compare(A[i], A[i+1]); if (c != 0) { if (c != store && store != 0) return false; store = c; } } return true; } } ================================================ FILE: src/MostCommonWord819.java ================================================ /** * Given a paragraph and a list of banned words, return the most frequent word * that is not in the list of banned words. It is guaranteed there is at least * one word that isn't banned, and that the answer is unique. * * Words in the list of banned words are given in lowercase, and free of * punctuation. Words in the paragraph are not case sensitive. The answer * is in lowercase. * * Example: * Input: * paragraph = "Bob hit a ball, the hit BALL flew far after it was hit." * banned = ["hit"] * Output: "ball" * * Explanation: * "hit" occurs 3 times, but it is a banned word. * "ball" occurs twice (and no other word does), so it is the most frequent * non-banned word in the paragraph. * * Note that words in the paragraph are not case sensitive, * that punctuation is ignored (even if adjacent to words, such as "ball,"), * and that "hit" isn't the answer even though it occurs more because it is banned. * * Note: * * 1 <= paragraph.length <= 1000. * 1 <= banned.length <= 100. * 1 <= banned[i].length <= 10. * The answer is unique, and written in lowercase (even if its occurrences in * paragraph may have uppercase symbols, and even if it is a proper noun.) * paragraph only consists of letters, spaces, or the punctuation symbols !?',;. * Different words in paragraph are always separated by a space. * There are no hyphens or hyphenated words. * Words only consist of letters, never apostrophes or other punctuation symbols. */ public class MostCommonWord819 { public String mostCommonWord(String paragraph, String[] banned) { if (paragraph == null || paragraph.length() == 0) return ""; // update O(K) Set bannedSet = new HashSet<>(); for (String w: banned) bannedSet.add(w.toLowerCase()); // update O(N), N: number of chars Map freq = new HashMap<>(); String mcw = ""; int maxCount = -1; int left = 0; int right = 0; while (right < paragraph.length()) { while (left < paragraph.length() && !isLetter(paragraph.charAt(left))) left++; if (left >= paragraph.length()) break; right = left; while (right < paragraph.length() && isLetter(paragraph.charAt(right))) right++; String word = paragraph.substring(left, right).toLowerCase(); if (!bannedSet.contains(word)) { freq.put(word, freq.getOrDefault(word, 0) + 1); if (freq.get(word) > maxCount) { maxCount = freq.get(word); mcw = word; } } left = right; } return mcw; } private boolean isLetter(char c) { return (c - 'a' >= 0 && c - 'z' <= 0) || (c - 'A' >= 0 && c - 'Z' <= 0); } public String mostCommonWord2(String paragraph, String[] banned) { String[] splitArr = paragraph.replaceAll("[!?',;.]","").toLowerCase().split(" "); HashMap map = new HashMap<>(); List bannedList = Arrays.asList(banned); int currentMax = 0; String res = ""; for(String str: splitArr) { if(!bannedList.contains(str)) { map.put(str, map.getOrDefault(str, 0) + 1); if (map.get(str) > currentMax) { res = str; currentMax = map.get(str); } } } return res; } } ================================================ FILE: src/MostFrequentSubtreeSum508.java ================================================ /** * Given the root of a tree, you are asked to find the most frequent subtree * sum. The subtree sum of a node is defined as the sum of all the node values * formed by the subtree rooted at that node (including the node itself). So * what is the most frequent subtree sum value? If there is a tie, return all * the values with the highest frequency in any order. * * Examples 1 * Input: * * 5 * / \ * 2 -3 * return [2, -3, 4], since all the values happen only once, return all of * them in any order. * * Examples 2 * Input: * * 5 * / \ * 2 -5 * return [2], since 2 happens twice, however -5 only occur once. * * Note: You may assume the sum of values in any subtree is in the range of * 32-bit signed integer. * */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class MostFrequentSubtreeSum508 { public int[] findFrequentTreeSum(TreeNode root) { Map sums = new HashMap<>(); if (root == null) return new int[0]; int[] cache = new int[1]; cache[0] = Integer.MIN_VALUE; helper(root, sums, cache); List list = new ArrayList<>(); for (Map.Entry e: sums.entrySet()) { if (e.getValue().equals(cache[0])) { list.add(e.getKey()); } } int[] res = new int[list.size()]; for (int i=0; i sums, int[] cache) { if (n == null) return null; Integer left = helper(n.left, sums, cache); Integer right = helper(n.right, sums, cache); int sum = ((left == null) ? 0 : left) + ((right == null) ? 0 : right) + n.val; int t = sums.getOrDefault(sum, 0) + 1; cache[0] = Math.max(cache[0], t); sums.put(sum, t); return sum; } public int[] findFrequentTreeSum2(TreeNode root) { Map map = new HashMap<>(); findFrequentTreeSum(root, map); int freq = 0; Set sums = new HashSet<>(); for (Map.Entry entry: map.entrySet()) { if (entry.getValue() == freq) { sums.add(entry.getKey()); } else if (entry.getValue() > freq) { freq = entry.getValue(); sums.clear(); sums.add(entry.getKey()); } } int[] res = new int[sums.size()]; int i = 0; for (int n: sums) { res[i++] = n; } return res; } public int findFrequentTreeSum(TreeNode root, Map map) { if (root == null) return 0; int l = findFrequentTreeSum(root.left, map); int r = findFrequentTreeSum(root.right, map); int sum = l + r + root.val; map.put(sum, map.getOrDefault(sum, 0) + 1); return sum; } } ================================================ FILE: src/MostProfitAssigningWork826.java ================================================ /** * We have jobs: difficulty[i] is the difficulty of the ith job, and profit[i] * is the profit of the ith job. * * Now we have some workers. worker[i] is the ability of the ith worker, which * means that this worker can only complete a job with difficulty at most * worker[i]. * * Every worker can be assigned at most one job, but one job can be completed * multiple times. * * For example, if 3 people attempt the same job that pays $1, then the total * profit will be $3. If a worker cannot complete any job, his profit is $0. * * What is the most profit we can make? * * Example 1: * * Input: difficulty = [2,4,6,8,10], profit = [10,20,30,40,50], worker = [4,5,6,7] * Output: 100 * Explanation: Workers are assigned jobs of difficulty [4,4,6,6] and they get * profit of [20,20,30,30] seperately. * * Notes: * 1 <= difficulty.length = profit.length <= 10000 * 1 <= worker.length <= 10000 * difficulty[i], profit[i], worker[i] are in range [1, 10^5] */ public class MostProfitAssigningWork826 { public int maxProfitAssignment(int[] difficulty, int[] profit, int[] worker) { int N = difficulty.length; Job[] jobs = new Job[N]; for (int i=0; i Integer.compare(j1.difficulty, j2.difficulty)); Arrays.sort(worker); int res = 0; int max = 0; int i = 0; for (int cap: worker) { while (i < N && jobs[i].difficulty <= cap) { max = Math.max(max, jobs[i].profit); i++; } res += max; } return res; } class Job { int difficulty; int profit; Job (int d, int p) { difficulty = d; profit = p; } } } ================================================ FILE: src/MoveZeroes283.java ================================================ /** * Given an array nums, write a function to move all 0's to the end of it while * maintaining the relative order of the non-zero elements. * * For example, given nums = [0, 1, 0, 3, 12], after calling your function, * nums should be [1, 3, 12, 0, 0]. * * Note: * You must do this in-place without making a copy of the array. * Minimize the total number of operations. * */ public class MoveZeroes283 { public void moveZeroes(int[] nums) { int slow = 0; int fast = 0; while (fast < nums.length) { if (nums[fast] != 0) { nums[slow] = nums[fast]; slow++; } fast++; } while (slow < nums.length) { nums[slow] = 0; slow++; } } public void moveZeroes2(int[] nums) { int p = 0; int zeros = -1; for (int i=0; i=0) { nums[nums.length-1-zeros] = 0; zeros--; } } public void moveZeroes3(int[] nums) { for (int i = 0, p = 0; p < nums.length; p++) { if (nums[p] != 0) { swap(nums, i++, p); } } } private void swap(int[] arr, int a, int b) { int temp = arr[a]; arr[a] = arr[b]; arr[b] = temp; } } ================================================ FILE: src/MovingAverageFromDataStream346.java ================================================ /** * Given a stream of integers and a window size, calculate the moving average * of all integers in the sliding window. * * For example, * MovingAverage m = new MovingAverage(3); * m.next(1) = 1 * m.next(10) = (1 + 10) / 2 * m.next(3) = (1 + 10 + 3) / 3 * m.next(5) = (10 + 3 + 5) / 3 */ public class MovingAverageFromDataStream346 { class MovingAverage { private int size; private Queue cache; private long sum; /** Initialize your data structure here. */ public MovingAverage(int size) { this.size = size; this.cache = new LinkedList(); this.sum = 0L; } public double next(int val) { if (this.cache.size() >= this.size) { this.sum -= this.cache.remove(); } this.sum += val; this.cache.add(val); return this.sum * 1.0 / this.cache.size(); } } class MovingAverage2 { private int[] window; private int head = 0; private int len = 0 ; private int sum = 0; /** Initialize your data structure here. */ public MovingAverage2(int size) { this.window = new int[size + 1]; } public double next(int val) { int nextPos = (this.head + this.len + 1) % this.window.length; this.window[nextPos] = val; this.len++; this.sum += val; if (this.len == this.window.length) { this.head++; this.head %= this.window.length; this.len--; this.sum -= this.window[this.head]; } return this.sum * 1.0 / this.len; } } } /** * Your MovingAverage object will be instantiated and called as such: * MovingAverage obj = new MovingAverage(size); * double param_1 = obj.next(val); */ ================================================ FILE: src/MultiplyStrings43.java ================================================ /** * Given two non-negative integers num1 and num2 represented as strings, return * the product of num1 and num2, also represented as a string. * * Example 1: * Input: num1 = "2", num2 = "3" * Output: "6" * * Example 2: * Input: num1 = "123", num2 = "456" * Output: "56088" * * Note: * The length of both num1 and num2 is < 110. * Both num1 and num2 contain only digits 0-9. * Both num1 and num2 do not contain any leading zero, except the number 0 itself. * You must not use any built-in BigInteger library or convert the inputs to * integer directly. */ public class MultiplyStrings43 { public String multiply(String num1, String num2) { char[] chars1 = num1.toCharArray(); char[] chars2 = num2.toCharArray(); StringBuilder sb = new StringBuilder(); sb.append('0'); for (int j=chars2.length - 1; j>=0; j--) { StringBuilder oneMul = multiplyForOne(chars1, chars2[j]); for (int z=0; z 1 && sb.charAt(0) == '0') { sb.deleteCharAt(0); } return sb.toString(); } private StringBuilder multiplyForOne(char[] chars, char ch) { StringBuilder sb = new StringBuilder(); int carry = 0; int b = (int)(ch - '0'); for (int i = chars.length-1; i>=0; i--) { int prod = (int)(chars[i] - '0') * b + carry; carry = prod / 10; sb.insert(0, Character.forDigit(prod % 10, 10)); } if (carry != 0) sb.insert(0, Character.forDigit(carry, 10)); return sb; } private StringBuilder add(StringBuilder sb1, StringBuilder sb2) { StringBuilder sb = new StringBuilder(); int i = sb1.length()-1; int j = sb2.length()-1; int carry = 0; while (i >= 0 && j >= 0) { int prod = (int)(sb1.charAt(i--) - '0') + (int)(sb2.charAt(j--) - '0') + carry; carry = prod / 10; sb.insert(0, Character.forDigit(prod % 10, 10)); } while (i >= 0) { int prod = (int)(sb1.charAt(i--) - '0')+ carry; carry = prod / 10; sb.insert(0, Character.forDigit(prod % 10, 10)); } while (j >= 0) { int prod = (int)(sb2.charAt(j--) - '0') + carry; carry = prod / 10; sb.insert(0, Character.forDigit(prod % 10, 10)); } if (carry != 0) sb.insert(0, Character.forDigit(carry, 10)); return sb; } /** * https://leetcode.com/problems/multiply-strings/discuss/17605/Easiest-JAVA-Solution-with-Graph-Explanation */ public String multiply2(String num1, String num2) { int m = num1.length(), n = num2.length(); int[] pos = new int[m + n]; for(int i = m - 1; i >= 0; i--) { for(int j = n - 1; j >= 0; j--) { int mul = (num1.charAt(i) - '0') * (num2.charAt(j) - '0'); int p1 = i + j, p2 = i + j + 1; int sum = mul + pos[p2]; pos[p1] += sum / 10; pos[p2] = (sum) % 10; } } StringBuilder sb = new StringBuilder(); for(int p : pos) if(!(sb.length() == 0 && p == 0)) sb.append(p); return sb.length() == 0 ? "0" : sb.toString(); } } ================================================ FILE: src/MyCalendarI729.java ================================================ /** * Implement a MyCalendar class to store your events. A new event can be added * if adding the event will not cause a double booking. * * Your class will have the method, book(int start, int end). Formally, this * represents a booking on the half open interval [start, end), the range of * real numbers x such that start <= x < end. * * A double booking happens when two events have some non-empty intersection * (ie., there is some time that is common to both events.) * * For each call to the method MyCalendar.book, return true if the event can * be added to the calendar successfully without causing a double booking. * Otherwise, return false and do not add the event to the calendar. * * Your class will be called like this: * MyCalendar cal = new MyCalendar(); MyCalendar.book(start, end) * * Example 1: * MyCalendar(); * MyCalendar.book(10, 20); // returns true * MyCalendar.book(15, 25); // returns false * MyCalendar.book(20, 30); // returns true * * Explanation: * The first event can be booked. The second can't because time 15 is already * booked by another event. * The third event can be booked, as the first event takes every time less * than 20, but not including 20. * * Note: * The number of calls to MyCalendar.book per test case will be at most 1000. * In calls to MyCalendar.book(start, end), start and end are integers in the * range [0, 10^9]. */ public class MyCalendarI729 { class MyCalendar { private TreeSet intervals = new TreeSet<>((i1, i2) -> Integer.compare(i1.start, i2.start)); public MyCalendar() { } public boolean book(int start, int end) { Interval inv = new Interval(start, end); Interval ceiling = intervals.ceiling(inv); if (ceiling != null && ceiling.start < end) return false; Interval floor = intervals.floor(inv); if (floor != null && floor.end > start) return false; intervals.add(inv); return true; } class Interval { int start; int end; Interval(int s, int e) { start = s; end = e; } } } class MyCalendar2 { private TreeMap intervals = new TreeMap<>(); public MyCalendar() { } public boolean book(int start, int end) { Map.Entry ceiling = intervals.ceilingEntry(start); if (ceiling != null && ceiling.getKey() < end) return false; Map.Entry floor = intervals.floorEntry(start); if (floor != null && floor.getValue() > start) return false; intervals.put(start, end); return true; } } /** * Your MyCalendar object will be instantiated and called as such: * MyCalendar obj = new MyCalendar(); * boolean param_1 = obj.book(start,end); */ } ================================================ FILE: src/MyCalendarII731.java ================================================ /** * Implement a MyCalendarTwo class to store your events. A new event can be * added if adding the event will not cause a triple booking. * * Your class will have one method, book(int start, int end). Formally, this * represents a booking on the half open interval [start, end), the range of * real numbers x such that start <= x < end. * * A triple booking happens when three events have some non-empty intersection * (ie., there is some time that is common to all 3 events.) * * For each call to the method MyCalendar.book, return true if the event can be * added to the calendar successfully without causing a triple booking. * Otherwise, return false and do not add the event to the calendar. * * Your class will be called like this: * MyCalendar cal = new MyCalendar(); MyCalendar.book(start, end) * * Example 1: * MyCalendar(); * MyCalendar.book(10, 20); // returns true * MyCalendar.book(50, 60); // returns true * MyCalendar.book(10, 40); // returns true * MyCalendar.book(5, 15); // returns false * MyCalendar.book(5, 10); // returns true * MyCalendar.book(25, 55); // returns true * * Explanation: * The first two events can be booked. The third event can be double booked. * The fourth event (5, 15) can't be booked, because it would result in a * triple booking. * The fifth event (5, 10) can be booked, as it does not use time 10 which is * already double booked. * The sixth event (25, 55) can be booked, as the time in [25, 40) will be * double booked with the third event; * the time [40, 50) will be single booked, and the time [50, 55) will be * double booked with the second event. * * Note: * The number of calls to MyCalendar.book per test case will be at most 1000. * In calls to MyCalendar.book(start, end), start and end are integers in the * range [0, 10^9]. */ public class MyCalendarII731 { /** * https://leetcode.com/problems/my-calendar-ii/discuss/109519/JavaC++-Clean-Code-with-Explanation */ class MyCalendarTwo { private List books = new ArrayList<>(); public boolean book(int s, int e) { MyCalendar overlaps = new MyCalendar(); for (int[] b : books) if (Math.max(b[0], s) < Math.min(b[1], e)) // overlap exist if (!overlaps.book(Math.max(b[0], s), Math.min(b[1], e))) return false; // overlaps overlapped books.add(new int[]{ s, e }); return true; } private static class MyCalendar { List books = new ArrayList<>(); public boolean book(int start, int end) { for (int[] b : books) if (Math.max(b[0], start) < Math.min(b[1], end)) return false; books.add(new int[]{ start, end }); return true; } } } /** * https://leetcode.com/problems/my-calendar-ii/solution/ */ class MyCalendarTwo2 { List calendar; List overlaps; MyCalendarTwo() { calendar = new ArrayList(); overlaps = new ArrayList(); } public boolean book(int start, int end) { for (int[] iv: overlaps) { if (iv[0] < end && start < iv[1]) return false; } for (int[] iv: calendar) { if (iv[0] < end && start < iv[1]) overlaps.add(new int[]{Math.max(start, iv[0]), Math.min(end, iv[1])}); } calendar.add(new int[]{start, end}); return true; } } /** * https://leetcode.com/problems/my-calendar-ii/solution/ */ class MyCalendarTwo3 { TreeMap delta; public MyCalendarTwo() { delta = new TreeMap(); } public boolean book(int start, int end) { delta.put(start, delta.getOrDefault(start, 0) + 1); delta.put(end, delta.getOrDefault(end, 0) - 1); int active = 0; for (int d: delta.values()) { active += d; if (active >= 3) { delta.put(start, delta.get(start) - 1); delta.put(end, delta.get(end) + 1); if (delta.get(start) == 0) delta.remove(start); return false; } } return true; } } } ================================================ FILE: src/NQueens51.java ================================================ /** * The n-queens puzzle is the problem of placing n queens on an nxn chessboard * such that no two queens attack each other. * * * * * Given an integer n, return all distinct solutions to the n-queens puzzle. * * Each solution contains a distinct board configuration of the n-queens' * placement, where 'Q' and '.' both indicate a queen and an empty space * respectively. * * For example, * * There exist two distinct solutions to the 4-queens puzzle: * * [ * [".Q..", // Solution 1 * "...Q", * "Q...", * "..Q."], * * ["..Q.", // Solution 2 * "Q...", * "...Q", * ".Q.."] * ] */ import java.util.Arrays; import java.util.ArrayList; import java.util.List; import java.util.HashSet; import java.util.Set; public class NQueens51 { // so slow public List> solveNQueens(int n) { List> result = new ArrayList<>(); if (n < 0) { return result; } List> trace = new ArrayList<>(); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { Integer[] now = new Integer[]{i, j}; if (attacked(trace, now)) { if (j == n - 1) { List last = backtrack(trace, i, j, n); i = last.get(0); j = last.get(1); if (i == 0 && j == n - 1) { return result; } break; } } else { trace.add(Arrays.asList(now)); if (i == n - 1) { List first = foundOneSolution(result, trace, n); i = first.get(0); j = first.get(1); } if (i == 0 && j > n - 1) { return result; } break; } } } return result; } private List backtrack(List> trace, int inputI, int inputJ, int n) { int i = inputI; int j = inputJ; if (trace.size() == 0) { return new ArrayList(Arrays.asList(i, j)); } List last = trace.get(trace.size() - 1); trace.remove(last); if (last.get(1) < n - 1 && !attacked(trace, new Integer[]{last.get(0), last.get(1) + 1})) { last.set(1, last.get(1) + 1); trace.add(last); i = i - 1; j = 0; } else if (last.get(1) < n - 1) { int a = last.get(0); int b = last.get(1) + 2; while (b <= n - 1 && attacked(trace, new Integer[]{a, b})) { b++; } if (b > n - 1) { List back = backtrack(trace, a, n - 1, n); i = back.get(0); j = back.get(1); } else { trace.add(Arrays.asList(a, b)); i = i - 1; j = 0; } } else { List back = backtrack(trace, last.get(0), last.get(1), n); i = back.get(0); j = back.get(1); } return new ArrayList(Arrays.asList(i, j)); } private List foundOneSolution(List> result, List> trace, int n) { String[][] board = new String[n][n]; for(String[] row: board){ Arrays.fill(row, "."); } for (List queen: trace) { board[queen.get(0)][queen.get(1)] = "Q"; } List solution = new ArrayList<>(); for(String[] row: board){ solution.add(String.join("", row)); } result.add(solution); List last = trace.get(trace.size() - 1); trace.remove(last); last.set(1, last.get(1) + 1); trace.add(last); return new ArrayList(Arrays.asList(last.get(0) - 1, 0)); } private boolean attacked(List> trace, Integer[] point) { Integer x = point[0]; Integer y = point[1]; for (List qPoint: trace) { Integer qx = qPoint.get(0); Integer qy = qPoint.get(1); if (x.equals(qx) || y.equals(qy) || Math.abs(x - qx) == Math.abs(y - qy)) { return true; } } return false; } /** * https://discuss.leetcode.com/topic/8592/comparably-concise-java-code */ private void helper(int r, boolean[] cols, boolean[] d1, boolean[] d2, String[] board, List> res) { if (r == board.length) { res.add(Arrays.asList(board.clone())); } else { for (int c = 0; c < board.length; c++) { int id1 = r - c + board.length, id2 = 2*board.length - r - c - 1; if (!cols[c] && !d1[id1] && !d2[id2]) { char[] row = new char[board.length]; Arrays.fill(row, '.'); row[c] = 'Q'; board[r] = new String(row); cols[c] = true; d1[id1] = true; d2[id2] = true; helper(r+1, cols, d1, d2, board, res); cols[c] = false; d1[id1] = false; d2[id2] = false; } } } } public List> solveNQueens2(int n) { List> res = new ArrayList<>(); helper(0, new boolean[n], new boolean[2*n], new boolean[2*n], new String[n], res); return res; } public static void main(String[] args) { NQueens51 nq = new NQueens51(); System.out.println("---- 1"); System.out.println(nq.solveNQueens(1)); System.out.println("---- 4"); System.out.println(nq.solveNQueens(4)); System.out.println("---- 2"); System.out.println(nq.solveNQueens(2)); System.out.println("---- 3"); System.out.println(nq.solveNQueens(3)); System.out.println("---- 5"); System.out.println(nq.solveNQueens(5)); System.out.println("---- 6"); System.out.println(nq.solveNQueens(6)); } } ================================================ FILE: src/NQueensII52.java ================================================ /** * Follow up for N-Queens problem. * * Now, instead outputting board configurations, return the total number of * distinct solutions. */ import java.util.Arrays; import java.util.HashMap; import java.util.Map; public class NQueensII52 { private void helper(int r, boolean[] cols, boolean[] d1, boolean[] d2, int n, Map res) { if (r == n) { res.put("num", res.get("num") + 1); } else { for (int c = 0; c < n; c++) { int id1 = r - c + n, id2 = 2*n - r - c - 1; if (!cols[c] && !d1[id1] && !d2[id2]) { cols[c] = true; d1[id1] = true; d2[id2] = true; helper(r+1, cols, d1, d2, n, res); cols[c] = false; d1[id1] = false; d2[id2] = false; } } } } public int totalNQueens(int n) { Map res = new HashMap<>(); res.put("num", 0); helper(0, new boolean[n], new boolean[2*n], new boolean[2*n], n, res); return res.get("num"); } public static void main(String[] args) { NQueensII52 nq = new NQueensII52(); System.out.println("---- 1"); System.out.println(nq.totalNQueens(1)); System.out.println("---- 4"); System.out.println(nq.totalNQueens(4)); System.out.println("---- 2"); System.out.println(nq.totalNQueens(2)); System.out.println("---- 3"); System.out.println(nq.totalNQueens(3)); System.out.println("---- 5"); System.out.println(nq.totalNQueens(5)); System.out.println("---- 6"); System.out.println(nq.totalNQueens(6)); } } ================================================ FILE: src/NaryTreeLevelOrderTraversal429.java ================================================ /** * Given an n-ary tree, return the level order traversal of its nodes' values. * (ie, from left to right, level by level). * * For example, given a 3-ary tree: * https://leetcode.com/static/images/problemset/NaryTreeExample.png * * We should return its level order traversal: * * [ * [1], * [3,2,4], * [5,6] * ] * * Note: * The depth of the tree is at most 1000. * The total number of nodes is at most 5000. */ /* // Definition for a Node. class Node { public int val; public List children; public Node() {} public Node(int _val,List _children) { val = _val; children = _children; } }; */ public class NaryTreeLevelOrderTraversal429 { public List> levelOrder(Node root) { List> res = new ArrayList<>(); if (root == null) return res; Queue q = new LinkedList<>(); q.add(root); while (!q.isEmpty()) { int size = q.size(); List level = new ArrayList<>(); for (int i=0; i children; public Node() {} public Node(int _val,List _children) { val = _val; children = _children; } }; */ public class NaryTreePostorderTraversal590 { public List postorder(Node root) { List res = new ArrayList<>(); helper(root, res); return res; } private void helper(Node root, List res) { if (root == null) return; for (Node child: root.children) { helper(child, res); } res.add(root.val); } public List postorder2(Node root) { LinkedList res = new LinkedList<>(); if (root == null) return res; Stack stack = new Stack<>(); stack.push(root); while (!stack.isEmpty()) { Node curr = stack.pop(); res.addFirst(curr.val); for (Node child: curr.children) { stack.add(child); } } return res; } } ================================================ FILE: src/NestedIterator.java ================================================ /** * Given a nested list of integers, implement an iterator to flatten it. * * Each element is either an integer, or a list -- whose elements may also be * integers or other lists. * * Example 1: * Given the list [[1,1],2,[1,1]], * * By calling next repeatedly until hasNext returns false, the order of elements * returned by next should be: [1,1,2,1,1]. * * Example 2: * Given the list [1,[4,[6]]], * * By calling next repeatedly until hasNext returns false, the order of elements * returned by next should be: [1,4,6]. * */ /** * // This is the interface that allows for creating nested lists. * // You should not implement it, or speculate about its implementation * public interface NestedInteger { * * // @return true if this NestedInteger holds a single integer, rather than a nested list. * public boolean isInteger(); * * // @return the single integer that this NestedInteger holds, if it holds a single integer * // Return null if this NestedInteger holds a nested list * public Integer getInteger(); * * // @return the nested list that this NestedInteger holds, if it holds a nested list * // Return null if this NestedInteger holds a single integer * public List getList(); * } */ public class NestedIterator implements Iterator { Queue q = new LinkedList<>(); public NestedIterator(List nestedList) { flattenNestedList(nestedList); } private void flattenNestedList(List nestedList) { for (NestedInteger ni: nestedList) { if (ni.isInteger()) { q.add(ni.getInteger()); } else { flattenNestedList(ni.getList()); } } } @Override public Integer next() { return q.remove(); } @Override public boolean hasNext() { return !q.isEmpty(); } } /* public class NestedIterator implements Iterator { Stack stack = new Stack<>(); public NestedIterator(List nestedList) { for(int i = nestedList.size() - 1; i >= 0; i--) { stack.push(nestedList.get(i)); } } @Override public Integer next() { return stack.pop().getInteger(); } @Override public boolean hasNext() { while(!stack.isEmpty()) { NestedInteger curr = stack.peek(); if(curr.isInteger()) { return true; } stack.pop(); for(int i = curr.getList().size() - 1; i >= 0; i--) { stack.push(curr.getList().get(i)); } } return false; } } */ /** * Your NestedIterator object will be instantiated and called as such: * NestedIterator i = new NestedIterator(nestedList); * while (i.hasNext()) v[f()] = i.next(); */ ================================================ FILE: src/NestedListWeightSum339.java ================================================ /** * Given a nested list of integers, return the sum of all integers in the list * weighted by their depth. * * Each element is either an integer, or a list -- whose elements may also be * integers or other lists. * * Example 1: * Input: [[1,1],2,[1,1]] * Output: 10 * Explanation: Four 1's at depth 2, one 2 at depth 1. * * Example 2: * Input: [1,[4,[6]]] * Output: 27 * Explanation: One 1 at depth 1, one 4 at depth 2, and one 6 at depth 3; * 1 + 4*2 + 6*3 = 27. */ /** * // This is the interface that allows for creating nested lists. * // You should not implement it, or speculate about its implementation * public interface NestedInteger { * // Constructor initializes an empty nested list. * public NestedInteger(); * * // Constructor initializes a single integer. * public NestedInteger(int value); * * // @return true if this NestedInteger holds a single integer, rather than a nested list. * public boolean isInteger(); * * // @return the single integer that this NestedInteger holds, if it holds a single integer * // Return null if this NestedInteger holds a nested list * public Integer getInteger(); * * // Set this NestedInteger to hold a single integer. * public void setInteger(int value); * * // Set this NestedInteger to hold a nested list and adds a nested integer to it. * public void add(NestedInteger ni); * * // @return the nested list that this NestedInteger holds, if it holds a nested list * // Return null if this NestedInteger holds a single integer * public List getList(); * } */ public class NestedListWeightSum339 { public int depthSum(List nestedList) { return depthSum(nestedList, 1); } private int depthSum(List nestedList, int level) { int res = 0; for (NestedInteger ni: nestedList) { if (ni.isInteger()) { res += ni.getInteger() * level; } else { res += depthSum(ni.getList(), level + 1); } } return res; } } ================================================ FILE: src/NextClosestTime681.java ================================================ /** * Given a time represented in the format "HH:MM", form the next closest time * by reusing the current digits. There is no limit on how many times a digit * can be reused. * * You may assume the given input string is always valid. For example, "01:34", * "12:09" are all valid. "1:34", "12:9" are all invalid. * * Example 1: * * Input: "19:34" * Output: "19:39" * Explanation: The next closest time choosing from digits 1, 9, 3, 4, is 19:39, * which occurs 5 minutes later. It is not 19:33, because this occurs 23 hours * and 59 minutes later. * * Example 2: * * Input: "23:59" * Output: "22:22" * Explanation: The next closest time choosing from digits 2, 3, 5, 9, is 22:22. * It may be assumed that the returned time is next day's time since it is * smaller than the input time numerically. */ public class NextClosestTime681 { public String nextClosestTime(String time) { int hours = Integer.valueOf(time.substring(0, 2)); int mins = Integer.valueOf(time.substring(3, 5)); int allmins = hours * 60 + mins; boolean[] set = new boolean[10]; for (char c: time.toCharArray()) { if (c != ':') { set[c - '0'] = true; } } while (true) { allmins = (allmins + 1) % (24 * 60); int currHours = allmins / 60; int a = currHours / 10; if (!set[a]) continue; int b = currHours % 10; if (!set[b]) continue; int currMins = allmins % 60; int c = currMins / 10; if (!set[c]) continue; int d = currMins % 10; if (!set[d]) continue; return String.format("%d%d:%d%d", a, b, c, d); } } /** * https://leetcode.com/problems/next-closest-time/solution/ */ public String nextClosestTime2(String time) { int start = 60 * Integer.parseInt(time.substring(0, 2)); start += Integer.parseInt(time.substring(3)); int ans = start; int elapsed = 24 * 60; Set allowed = new HashSet(); for (char c: time.toCharArray()) if (c != ':') { allowed.add(c - '0'); } for (int h1: allowed) for (int h2: allowed) if (h1 * 10 + h2 < 24) { for (int m1: allowed) for (int m2: allowed) if (m1 * 10 + m2 < 60) { int cur = 60 * (h1 * 10 + h2) + (m1 * 10 + m2); int candElapsed = Math.floorMod(cur - start, 24 * 60); if (0 < candElapsed && candElapsed < elapsed) { ans = cur; elapsed = candElapsed; } } } return String.format("%02d:%02d", ans / 60, ans % 60); } } ================================================ FILE: src/NextGreaterElementI496.java ================================================ /** * You are given two arrays (without duplicates) nums1 and nums2 where nums1’s * elements are subset of nums2. Find all the next greater numbers for nums1's * elements in the corresponding places of nums2. * * The Next Greater Number of a number x in nums1 is the first greater number * to its right in nums2. If it does not exist, output -1 for this number. * * Example 1: * Input: nums1 = [4,1,2], nums2 = [1,3,4,2]. * Output: [-1,3,-1] * Explanation: * For number 4 in the first array, you cannot find the next greater number for it in the second array, so output -1. * For number 1 in the first array, the next greater number for it in the second array is 3. * For number 2 in the first array, there is no next greater number for it in the second array, so output -1. * * Example 2: * Input: nums1 = [2,4], nums2 = [1,2,3,4]. * Output: [3,-1] * Explanation: * For number 2 in the first array, the next greater number for it in the second array is 3. * For number 4 in the first array, there is no next greater number for it in the second array, so output -1. * * Note: * All elements in nums1 and nums2 are unique. * The length of both nums1 and nums2 would not exceed 1000. */ public class NextGreaterElementI496 { public int[] nextGreaterElement(int[] nums1, int[] nums2) { if (nums1 == null || nums1.length == 0) return new int[0]; int[] res = new int[nums1.length]; Map map = new HashMap<>(); Stack stack = new Stack<>(); for (int i=0; i= nums2[i]) { stack.push(nums2[i]); continue; } while (!stack.isEmpty() && stack.peek() < nums2[i]) { map.put(stack.pop(), nums2[i]); } stack.push(nums2[i]); } for (int i=0; i nums[i]) { res[i] = nums[j]; found = true; break; } j = (j+1)%len; } if (!found) { res[i] = -1; } i++; } return res; } public int[] nextGreaterElements2(int[] nums) { if (nums == null || nums.length == 0) return nums; if (nums.length == 1) return new int[]{-1}; int len = nums.length; int[] res = new int[len]; Arrays.fill(res, -1); Stack st = new Stack<>(); for (int i=0; i nums[st.peek()]) { res[st.pop()] = nums[i]; } st.push(i); } for (int i=0; i nums[st.peek()]) { int idx = st.pop(); if (res[idx] == -1) { res[idx] = nums[i]; } } st.push(i); } return res; } /** * https://leetcode.com/problems/next-greater-element-ii/solution/ */ public int[] nextGreaterElements3(int[] nums) { int[] res = new int[nums.length]; Stack stack = new Stack<>(); for (int i = 2 * nums.length - 1; i >= 0; --i) { while (!stack.empty() && nums[stack.peek()] <= nums[i % nums.length]) { stack.pop(); } res[i % nums.length] = stack.empty() ? -1 : nums[stack.peek()]; stack.push(i % nums.length); } return res; } /** * https://leetcode.com/problems/next-greater-element-ii/discuss/130338/Why-need-to-use-a-stack-for-index */ public int[] nextGreaterElements4(int[] nums) { Stack st = new Stack<>(); for (int e = nums.length -1; e >= 0; e --) { st.push(nums[e]); } int[] r = new int[nums.length]; for (int i = nums.length -1; i >= 0; i--) { while (!st.isEmpty() && st.peek() <= nums[i]) st.pop(); r[i] = st.isEmpty() ? -1 : st.peek(); st.push(nums[i]); } return r; } /** * https://leetcode.com/problems/next-greater-element-ii/discuss/98276/21ms-Java-Solution-beats-99.84-with-comments-and-explanations */ public int[] nextGreaterElements5(int[] nums) { if (nums==null||nums.length==0) return new int[0]; int maxIndex = 0; for (int i = 0; i < nums.length; i++) { if (nums[i] > nums[maxIndex]) { maxIndex = i; //find the largest element } } int[] index = new int[nums.length]; //declare an array that holds the index of next greater element index[maxIndex] = -1; //set the max element's value to -1 for (int i = (maxIndex - 1 + nums.length) % nums.length; i != maxIndex; i = (i - 1 + nums.length) % nums.length) { //the array is circular. pay attention to 'i' if (nums[i] < nums[(i + 1) % nums.length]) { index[i] = (i + 1) % nums.length; //set index[i] = (i+1)%nums.length if index[(i+1)%nums.length]>index[i] } else { int res = index[(i + 1 + nums.length) % nums.length]; //res = index of the cloest element whose value greater than nums[(i+1)%nums.length] while (res != -1 && index[res] != -1 && nums[i] >= nums[res]) { //find the closet index makes nums[index] > nums[i] res = index[res]; //if nums[i] >= nums[res], try nums[index[res]], index[res] is the index of the closest element whose value is greater than nums[res]. repeat the process until we find such an element. } if (res != -1 && nums[res] == nums[i]) { //res==-1 or index[res]==-1 means current element is another largest element, just set index[i] = -1. res = -1; } index[i] = res; } } int[] result = new int[nums.length]; // retrieve value with index recorded previously for (int i = 0; i < result.length; i++) { int temp = index[i] != -1 ? nums[index[i]] : -1; result[i] = temp; } return result; } public int[] nextGreaterElements6(int[] nums) { if (nums == null || nums.length == 0) return new int[]{}; int len = nums.length; int[] idx = new int[len]; Arrays.fill(idx, -1); for (int i=2*len-1; i>=0; i--) { int nextIdx = (i + 1) % len; while (idx[nextIdx] != -1 && nums[nextIdx] <= nums[i % len]) { nextIdx = idx[nextIdx]; } if (nums[nextIdx] > nums[i % len]) { idx[i % len] = nextIdx; } } int[] res = new int[len]; for (int i=0; i now) j++; swap(digits, i, j-1); mark = i; } pre = now; p = p / 10; i--; } if (mark == -1) return -1; Arrays.sort(digits, mark+1, len); long res = 0; long tens = 1; for (int j=len-1; j>=0; j--) { res += digits[j] * tens; tens = tens * 10; } return res > Integer.MAX_VALUE ? -1 : (int) res; } private void swap(int[] digits, int i, int j) { int temp = digits[i]; digits[i] = digits[j]; digits[j] = temp; } public int nextGreaterElement2(int n) { int[] digits = new int[10]; int k = n; int i = 9; while (k != 0) { digits[i--] = k % 10; k /= 10; } if (i == 8) return -1; int j = 8; while (j > i) { if (digits[j] < digits[j+1]) break; j--; } if (j == i) return -1; int p = 9; while (p > j) { if (digits[p] > digits[j]) break; p--; } swap(digits, j, p); Arrays.sort(digits, j+1, 10); long res = 0; long level = 1; for (int q=9; q>=0; q--) { res += digits[q] * level; level *= 10; } return res > Integer.MAX_VALUE ? -1 : (int) res; } } ================================================ FILE: src/NextPermutation31.java ================================================ /** * Implement next permutation, which rearranges numbers into the * lexicographically next greater permutation of numbers. * * If such arrangement is not possible, it must rearrange it as the lowest * possible order (ie, sorted in ascending order). * * The replacement must be in-place, do not allocate extra memory. * * Here are some examples. Inputs are in the left-hand column and its * corresponding outputs are in the right-hand column. * * 1,2,3 → 1,3,2 * 3,2,1 → 1,2,3 * 1,1,5 → 1,5,1 * */ public class NextPermutation31 { public void nextPermutation(int[] nums) { int n = nums.length - 1; while (n > 0) { if (nums[n-1] < nums[n]) break; n--; } if (n == 0) { Arrays.sort(nums); return; } int p = nums.length - 1; int minIdx = nums.length - 1; int minVal = Integer.MAX_VALUE; while (p >= n) { if (nums[p] > nums[n-1]) break; p--; } swap(nums, n-1, p); int l = n; int r = nums.length - 1; while (l < r) { swap(nums, l, r); l++; r--; } } private void swap(int[] nums, int i, int j) { int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; } } ================================================ FILE: src/NonDecreasingArray665.java ================================================ /** * Given an array with n integers, your task is to check if it could become * non-decreasing by modifying at most 1 element. * * We define an array is non-decreasing if array[i] <= array[i + 1] holds for * every i (1 <= i < n). * * Example 1: * Input: [4,2,3] * Output: True * Explanation: You could modify the first 4 to 1 to get a non-decreasing array. * * Example 2: * Input: [4,2,1] * Output: False * Explanation: You can't get a non-decreasing array by modify at most one element. * * Note: The n belongs to [1, 10,000]. */ public class NonDecreasingArray665 { public boolean checkPossibility(int[] nums) { if (nums == null || nums.length <= 2) return true; int min = nums[nums.length-1]; int n1 = 0; for (int i=nums.length-2; i>=0; i--) { if (min < nums[i]) { n1++; if (n1 == 2) break; } else { min = nums[i]; } } if (n1 < 2) return true; int max = nums[0]; int n2 = 0; for (int i=1; i nums[i]) { n2++; if (n2 == 2) return false; } else { max = nums[i]; } } return true; } /** * https://leetcode.com/problems/non-decreasing-array/discuss/106849/C++-Java-Clean-Code-6-liner-Without-Modifying-Input */ public boolean checkPossibility2(int[] a) { int modified = 0; for (int i = 1, prev = a[0]; i < a.length; i++) { if (a[i] < prev) { if (modified++ > 0) return false; if (i - 2 >= 0 && a[i - 2] > a[i]) continue; } prev = a[i]; } return true; } /** * https://leetcode.com/problems/non-decreasing-array/solution/ */ public boolean checkPossibility3(int[] a) { int p = -1; for (int i = 0; i a[i+1]) { if (p != -1) return false; p = i; } } return (p == -1 || p == 0 || p == a.length-2 || a[p-1] <= a[p+1] || a[p] <= a[p+2]); } } ================================================ FILE: src/NonOverlappingIntervals435.java ================================================ /** * Given a collection of intervals, find the minimum number of intervals you * need to remove to make the rest of the intervals non-overlapping. * * Note: * You may assume the interval's end point is always bigger than its start point. * Intervals like [1,2] and [2,3] have borders "touching" but they don't * overlap each other. * * Example 1: * Input: [ [1,2], [2,3], [3,4], [1,3] ] * Output: 1 * Explanation: [1,3] can be removed and the rest of intervals are * non-overlapping. * * Example 2: * Input: [ [1,2], [1,2], [1,2] ] * Output: 2 * Explanation: You need to remove two [1,2] to make the rest of intervals * non-overlapping. * * Example 3: * Input: [ [1,2], [2,3] ] * Output: 0 * Explanation: You don't need to remove any of the intervals since they're * already non-overlapping. */ public class NonOverlappingIntervals435 { private static Comparator comp = new Comparator() { @Override public int compare(Interval i1, Interval i2) { int diff = Integer.compare(i1.start, i2.start); if (diff != 0) return diff; return Integer.compare(i2.end-i2.start, i1.end-i1.start); } }; public int eraseOverlapIntervals(Interval[] intervals) { if (intervals == null || intervals.length == 0) return 0; Arrays.sort(intervals, comp); Interval inv = intervals[0]; int res = 0; for (int i=1; i this.rank[py]) { this.parent[py] = px; } else { this.parent[py] = px; this.rank[px]++; } } } } ================================================ FILE: src/NumberOfCornerRectangles750.java ================================================ /** * Given a grid where each entry is only 0 or 1, find the number of corner * rectangles. * * A corner rectangle is 4 distinct 1s on the grid that form an axis-aligned * rectangle. Note that only the corners need to have the value 1. Also, all * four 1s used must be distinct. * * Example 1: * Input: grid = * [[1, 0, 0, 1, 0], * [0, 0, 1, 0, 1], * [0, 0, 0, 1, 0], * [1, 0, 1, 0, 1]] * Output: 1 * Explanation: There is only one corner rectangle, with corners * grid[1][2], grid[1][4], grid[3][2], grid[3][4]. * * Example 2: * Input: grid = * [[1, 1, 1], * [1, 1, 1], * [1, 1, 1]] * Output: 9 * Explanation: There are four 2x2 rectangles, four 2x3 and 3x2 rectangles, * and one 3x3 rectangle. * * Example 3: * Input: grid = * [[1, 1, 1, 1]] * Output: 0 * Explanation: Rectangles must have four distinct corners. * * Note: * The number of rows and columns of grid will each be in the range [1, 200]. * Each grid[i][j] will be either 0 or 1. * The number of 1s in the grid will be at most 6000. */ public class NumberOfCornerRectangles750 { public int countCornerRectangles(int[][] grid) { int M = grid.length; int N = grid[0].length; int res = 0; for (int i=0; i count = new HashMap(); int ans = 0; for (int[] row: grid) { for (int c1 = 0; c1 < row.length; ++c1) if (row[c1] == 1) { for (int c2 = c1+1; c2 < row.length; ++c2) if (row[c2] == 1) { int pos = c1 * 200 + c2; int c = count.getOrDefault(pos, 0); ans += c; count.put(pos, c+1); } } } return ans; } /** * https://leetcode.com/problems/number-of-corner-rectangles/discuss/110196/short-JAVA-AC-solution-(O(m2-*-n))-with-explanation. */ public int countCornerRectangles3(int[][] grid) { int ans = 0; for (int i = 0; i < grid.length - 1; i++) { for (int j = i + 1; j < grid.length; j++) { int counter = 0; for (int k = 0; k < grid[0].length; k++) { if (grid[i][k] == 1 && grid[j][k] == 1) counter++; } if (counter > 0) ans += counter * (counter - 1) / 2; } } return ans; } /** * https://leetcode.com/problems/number-of-corner-rectangles/discuss/110200/Summary-of-three-solutions-based-on-three-different-ideas */ public int countCornerRectangles4(int[][] grid) { int m = grid.length, n = grid[0].length, res = 0; int[][] dp = new int[n][n]; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] == 0) continue; for (int q = j + 1; q < n; q++) { if (grid[i][q] == 0) continue; res += dp[j][q]++; } } } return res; } } ================================================ FILE: src/NumberOfDigitOne233.java ================================================ /** * Given an integer n, count the total number of digit 1 appearing in all * non-negative integers less than or equal to n. * * For example: * Given n = 13, * Return 6, because digit 1 occurred in the following numbers: 1, 10, 11, 12, 13. */ public class NumberOfDigitOne233 { public int countDigitOne(int n) { if (n < 1) return 0; int result = 0; int i = 1; int preK = 0; int k = n%10; int num = n/10; while (num != 0) { result += currentOne(n, k, preK, num, i); i = i*10; preK = k; k = num%10; num = num/10; } // do last once!!! result += currentOne(n, k, preK, num, i); return result; } private int currentOne(int n, int k, int preK, int num, int i) { if (k < 1) return num*i; if (k > 1) return (num+1)*i; return num*i + n%i + 1; } /** * https://discuss.leetcode.com/topic/18054/4-lines-o-log-n-c-java-python */ public int countDigitOne2(int n) { int ones = 0; for (long m = 1; m <= n; m *= 10) ones += (n/m + 8) / 10 * m + (n/m % 10 == 1 ? n%m + 1 : 0); return ones; } /** * https://discuss.leetcode.com/topic/18054/4-lines-o-log-n-c-java-python */ public int countDigitOne3(int n) { int ones = 0, m = 1, r = 1; while (n > 0) { ones += (n + 8) / 10 * m + (n % 10 == 1 ? r : 0); r += n % 10 * m; m *= 10; n /= 10; } return ones; } /** * https://discuss.leetcode.com/topic/22441/0-ms-recursive-solution */ public int countDigitOne4(int n) { if(n<1) return 0; if(n>=1 && n<10) return 1; // x: first digit int y=1, x=n; while(!(x<10)){ x/=10; y*=10; } if(x==1) return n-y+1+countDigitOne4(y-1)+countDigitOne4(n%y); else return y+x*countDigitOne4(y-1)+countDigitOne4(n%y); } } ================================================ FILE: src/NumberOfIslands200.java ================================================ /** * Given a 2d grid map of '1's (land) and '0's (water), count the number of * islands. An island is surrounded by water and is formed by connecting * adjacent lands horizontally or vertically. You may assume all four edges * of the grid are all surrounded by water. * * Example 1: * * 11110 * 11010 * 11000 * 00000 * * Answer: 1 * * Example 2: * * 11000 * 11000 * 00100 * 00011 * * Answer: 3 */ public class NumberOfIslands200 { public int numIslands(char[][] grid) { if (grid == null) return 0; int n = grid.length; if (n == 0) return 0; int m = grid[0].length; boolean[][] visited = new boolean[n][m]; int res = 0; for (int i=0; i= n || j < 0 || j >= m || grid[i][j] == '0' || visited[i][j]) return; visited[i][j] = true; numIslands(grid, visited, i-1, j, n, m); numIslands(grid, visited, i, j+1, n, m); numIslands(grid, visited, i+1, j, n, m); numIslands(grid, visited, i, j-1, n, m); } /** * https://leetcode.com/problems/number-of-islands/solution/ */ public int numIslands2(char[][] grid) { if (grid == null || grid.length == 0) { return 0; } int nr = grid.length; int nc = grid[0].length; int num_islands = 0; for (int r = 0; r < nr; ++r) { for (int c = 0; c < nc; ++c) { if (grid[r][c] == '1') { ++num_islands; dfs(grid, r, c); } } } return num_islands; } void dfs(char[][] grid, int r, int c) { int nr = grid.length; int nc = grid[0].length; if (r < 0 || c < 0 || r >= nr || c >= nc || grid[r][c] == '0') { return; } grid[r][c] = '0'; dfs(grid, r - 1, c); dfs(grid, r + 1, c); dfs(grid, r, c - 1); dfs(grid, r, c + 1); } public int numIslands3(char[][] grid) { if (grid == null) return 0; int n = grid.length; if (n == 0) return 0; int m = grid[0].length; boolean[][] visited = new boolean[n][m]; int res = 0; for (int i=0; i q = new LinkedList<>(); q.add(i * m + j); visited[i][j] = true; while (!q.isEmpty()) { int v = q.remove(); int ii = v / m; int jj = v % m; if (ii-1 >= 0 && grid[ii-1][jj] == '1' && !visited[ii-1][jj]) { visited[ii-1][jj] = true; q.add(v-m); } if (jj+1 < m && grid[ii][jj+1] == '1' && !visited[ii][jj+1]) { visited[ii][jj+1] = true; q.add(v+1); } if (ii+1 < n && grid[ii+1][jj] == '1' && !visited[ii+1][jj]) { visited[ii+1][jj] = true; q.add(v+m); } if (jj-1 >= 0 && grid[ii][jj-1] == '1' && !visited[ii][jj-1]) { visited[ii][jj-1] = true; q.add(v-1); } } } /** * https://leetcode.com/problems/number-of-islands/solution/ */ class UnionFind { int count; // # of connected components int[] parent; int[] rank; public UnionFind(char[][] grid) { // for problem 200 count = 0; int m = grid.length; int n = grid[0].length; parent = new int[m * n]; rank = new int[m * n]; for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { int val = i * n + j; if (grid[i][j] == '1') { parent[val] = val; ++count; } rank[val] = 0; } } } public int find(int i) { // path compression if (parent[i] != i) parent[i] = find(parent[i]); return parent[i]; } public void union(int x, int y) { // union with rank int rootx = find(x); int rooty = find(y); if (rootx != rooty) { if (rank[rootx] > rank[rooty]) { parent[rooty] = rootx; } else if (rank[rootx] < rank[rooty]) { parent[rootx] = rooty; } else { parent[rooty] = rootx; rank[rootx] += 1; } --count; } } public int getCount() { return count; } } public int numIslands4(char[][] grid) { if (grid == null || grid.length == 0) { return 0; } int nr = grid.length; int nc = grid[0].length; int num_islands = 0; UnionFind uf = new UnionFind(grid); for (int r = 0; r < nr; ++r) { for (int c = 0; c < nc; ++c) { if (grid[r][c] == '1') { int val = r * nc + c; grid[r][c] = '0'; if (r - 1 >= 0 && grid[r-1][c] == '1') { uf.union(val, val - nc); } if (r + 1 < nr && grid[r+1][c] == '1') { uf.union(val, val + nc); } if (c - 1 >= 0 && grid[r][c-1] == '1') { uf.union(val, val - 1); } if (c + 1 < nc && grid[r][c+1] == '1') { uf.union(val, val + 1); } } } } return uf.getCount(); } } ================================================ FILE: src/NumberOfIslandsII305.java ================================================ /** * A 2d grid map of m rows and n columns is initially filled with water. We may * perform an addLand operation which turns the water at position (row, col) * into a land. Given a list of positions to operate, count the number of * islands after each addLand operation. An island is surrounded by water and * is formed by connecting adjacent lands horizontally or vertically. You may * assume all four edges of the grid are all surrounded by water. * * Example: * Input: m = 3, n = 3, positions = [[0,0], [0,1], [1,2], [2,1]] * Output: [1,1,2,3] * * Explanation: * Initially, the 2d grid grid is filled with water. (Assume 0 represents water * and 1 represents land). * * 0 0 0 * 0 0 0 * 0 0 0 * Operation #1: addLand(0, 0) turns the water at grid[0][0] into a land. * * 1 0 0 * 0 0 0 Number of islands = 1 * 0 0 0 * Operation #2: addLand(0, 1) turns the water at grid[0][1] into a land. * * 1 1 0 * 0 0 0 Number of islands = 1 * 0 0 0 * Operation #3: addLand(1, 2) turns the water at grid[1][2] into a land. * * 1 1 0 * 0 0 1 Number of islands = 2 * 0 0 0 * Operation #4: addLand(2, 1) turns the water at grid[2][1] into a land. * * 1 1 0 * 0 0 1 Number of islands = 3 * 0 1 0 * * Follow up: * Can you do it in time complexity O(k log mn), where k is the length of the * positions? */ public class NumberOfIslandsII305 { private int[][] dirs = new int[][]{{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; // time complexity too high public List numIslands2(int m, int n, int[][] positions) { int[][] grid = new int[m][n]; List res = new ArrayList<>(); int num = 0; for (int[] pos: positions) { num += addNumIslands(grid, pos[0], pos[1], m, n); res.add(num); grid[pos[0]][pos[1]] = 1; } return res; } private int addNumIslands(int[][] grid, int i, int j, int m, int n) { int neighbors = 0; boolean[][] visited = new boolean[m][n]; for (int[] d: dirs) { if (isNeighbor(grid, i+d[0], j+d[1], visited, m, n)) neighbors++; } return neighbors == 0 ? 1 : 1 - neighbors; } private boolean isNeighbor(int[][] grid, int i, int j, boolean[][] visited, int m, int n) { if (i < 0 || j < 0 || i >= m || j >= n || grid[i][j] == 0 || visited[i][j]) return false; travese(grid, i, j, visited, m, n); return true; } private void travese(int[][] grid, int i, int j, boolean[][] visited, int m, int n) { if (i < 0 || j < 0 || i >= m || j >= n || grid[i][j] == 0 || visited[i][j]) return; visited[i][j] = true; for (int[] d: dirs) { travese(grid, i+d[0], j+d[1], visited, m, n); } } // Disjoint Set (Union-Find) public List numIslands22(int m, int n, int[][] positions) { int[][] grid = new int[m][n]; DisjointSet ds = new DisjointSet(m * n); List res = new ArrayList<>(); int num = 0; for (int[] pos: positions) { Set set = new HashSet<>(); for (int[] d: dirs) { int i = pos[0] + d[0]; int j = pos[1] + d[1]; if (i < 0 || j < 0 || i >= m || j >= n || grid[i][j] == 0) continue; int idx = posToIndex(i, j, n); set.add(ds.find(idx)); } int neighbors = set.size(); int numDiff = neighbors == 0 ? 1 : 1 - neighbors; num += numDiff; res.add(num); grid[pos[0]][pos[1]] = 1; int curr = posToIndex(pos[0], pos[1], n); for (int nb: set) { ds.union(curr, nb); } } return res; } private int posToIndex(int i, int j, int n) { return i * n + j; } class DisjointSet { private int[] parent; public DisjointSet(int n) { parent = new int[n]; for (int i=0; i rank[yy]) { parent[yy] = xx; } else { parent[xx] = yy; rank[yy]++; } } } /** * https://leetcode.com/problems/number-of-islands-ii/discuss/75470/Easiest-Java-Solution-with-Explanations */ public List numIslands23(int m, int n, int[][] positions) { List result = new ArrayList<>(); if(m <= 0 || n <= 0) return result; int count = 0; // number of islands int[] roots = new int[m * n]; // one island = one tree Arrays.fill(roots, -1); for(int[] p : positions) { int root = n * p[0] + p[1]; // assume new point is isolated island roots[root] = root; // add new island count++; for(int[] dir : dirs) { int x = p[0] + dir[0]; int y = p[1] + dir[1]; int nb = n * x + y; if(x < 0 || x >= m || y < 0 || y >= n || roots[nb] == -1) continue; int rootNb = findIsland(roots, nb); if(root != rootNb) { // if neighbor is in another island roots[root] = rootNb; // union two islands root = rootNb; // current tree root = joined tree root count--; } } result.add(count); } return result; } public int findIsland(int[] roots, int id) { while(id != roots[id]) { roots[id] = roots[roots[id]]; // only one line added id = roots[id]; } return id; } } ================================================ FILE: src/NumberOfLongestIncreasingSubsequence673.java ================================================ /** * Given an unsorted array of integers, find the number of longest increasing * subsequence. * * Example 1: * Input: [1,3,5,4,7] * Output: 2 * Explanation: The two longest increasing subsequence are * [1, 3, 4, 7] and [1, 3, 5, 7]. * * Example 2: * Input: [2,2,2,2,2] * Output: 5 * Explanation: The length of longest continuous increasing subsequence is 1, * and there are 5 subsequences' length is 1, so output 5. * * Note: Length of the given array will be not exceed 2000 and the answer is * guaranteed to be fit in 32-bit signed int. */ public class NumberOfLongestIncreasingSubsequence673 { public int findNumberOfLIS(int[] nums) { if (nums == null || nums.length == 0) return 0; int N = nums.length; int[] dp = new int[N]; int[] count = new int[N]; int res = 0; int maxLen = 1; for (int i=0; i nums[j]) { if (dp[j] + 1 > localRes) { localRes = dp[j] + 1; localCount = count[j]; } else if (dp[j] + 1 == localRes) { localCount += count[j]; } } } if (localRes > maxLen) { maxLen = localRes; res = localCount; } else if (localRes == maxLen) { res += localCount; } count[i] = localCount; dp[i] = localRes; } return res; } } ================================================ FILE: src/NumberOfMatchingSubsequences792.java ================================================ /** * Given string S and a dictionary of words words, find the number of words[i] * that is a subsequence of S. * * Example : * Input: * S = "abcde" * words = ["a", "bb", "acd", "ace"] * Output: 3 * Explanation: There are three words in words that are a subsequence of * S: "a", "acd", "ace". * * Note: * All words in words and S will only consists of lowercase letters. * The length of S will be in the range of [1, 50000]. * The length of words will be in the range of [1, 5000]. * The length of words[i] will be in the range of [1, 50]. */ public class NumberOfMatchingSubsequences792 { public int numMatchingSubseq(String S, String[] words) { int res = 0; for (String w: words) { if (isSubsequence(w, S)) res++; } return res; } private boolean isSubsequence(String s, String t) { int i = 0; int j = 0; char[] chars = s.toCharArray(); char[] chart = t.toCharArray(); while (i < chars.length && j < chart.length) { if (chars[i] == chart[j]) { i++; j++; } else { j++; } } return i == chars.length; } public int numMatchingSubseq2(String S, String[] words) { LinkedList[] map = new LinkedList[26]; for (char c = 'a'; c <= 'z'; c++) { map[c-'a'] = new LinkedList(); } for (String word : words) { map[word.charAt(0)-'a'].addLast(new Mover(word)); } int count = 0; for (char c : S.toCharArray()) { LinkedList ll = map[c-'a']; int size = ll.size(); for (int i = 0; i < size; i++) { Mover m = ll.removeFirst(); m.move(); if (m.hasEnded()) { count++; } else { map[m.currChar()-'a'].addLast(m); } } } return count; } class Mover { char[] word; int pos = 0; Mover (String w) { this.word = w.toCharArray(); } char currChar() { return this.word[pos]; } void move() { this.pos++; } boolean hasEnded() { return this.word.length == pos; } } public int numMatchingSubseq3(String S, String[] words) { Trie trie = constructTrie(words); int count = 0; for (char c : S.toCharArray()) { Trie curr = trie.children[c-'a']; trie.children[c-'a'] = null; while (curr != null) { count += curr.count; for (int nc=0; nc<26; nc++) { if (curr.children[nc] == null) continue; trie.children[nc] = add(curr.children[nc], trie.children[nc]); } curr = curr.next; } } return count; } private Trie add(Trie a, Trie b) { a.next = b; return a; } private Trie constructTrie(String[] words) { Trie trie = new Trie(); for (String word: words) { trie.add(word); } return trie; } class Trie { Trie[] children = new Trie[26]; Trie next; int count = 0; void add(String word) { add(word.toCharArray(), 0); } void add(char[] word, int i) { if (word.length == i) { this.count++; return; } int idx = word[i] - 'a'; if (this.children[idx] == null) { this.children[idx] = new Trie(); } this.children[idx].add(word, i+1); } } } ================================================ FILE: src/OddEvenLinkedList328.java ================================================ /** * Given a singly linked list, group all odd nodes together followed by the * even nodes. Please note here we are talking about the node number and not * the value in the nodes. * * You should try to do it in place. The program should run in O(1) space * complexity and O(nodes) time complexity. * * Example: * Given 1->2->3->4->5->NULL, * return 1->3->5->2->4->NULL. * * Note: * The relative order inside both the even and odd groups should remain as it was in the input. * The first node is considered odd, the second node even and so on ... * */ /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ public class OddEvenLinkedList328 { public ListNode oddEvenList(ListNode head) { if (head == null) return null; ListNode dummy = new ListNode(0); dummy.next = head; ListNode evens = new ListNode(0); ListNode e = evens; ListNode p = dummy; while (p.next != null) { p = p.next; if (p.next == null) break; e.next = new ListNode(p.next.val); e = e.next; p.next = p.next.next; } p.next = evens.next; return dummy.next; } public ListNode oddEvenList2(ListNode head) { if (head == null) return null; ListNode dummy = new ListNode(0); dummy.next = head; ListNode evens = new ListNode(0); ListNode e = evens; ListNode p = dummy; while (p.next != null) { p = p.next; if (p.next == null) break; e.next = p.next; e = e.next; p.next = p.next.next; e.next = null; } p.next = evens.next; return dummy.next; } /** * https://leetcode.com/problems/odd-even-linked-list/solution/ */ public ListNode oddEvenList3(ListNode head) { if (head == null) return null; ListNode odd = head, even = head.next, evenHead = even; while (even != null && even.next != null) { odd.next = even.next; odd = odd.next; even.next = odd.next; even = even.next; } odd.next = evenHead; return head; } } ================================================ FILE: src/OneEditDistance.java ================================================ /** * */ public class OneEditDistance { public boolean oneEditDistance(String str, String[] wordDict) { Trie trie = constructTrie(wordDict, str.length()); return helper(str.toCharArray(), 0, trie, 0); } private boolean helper(char[] str, int i, Trie trie, int edit) { if (edit > 1) return false; if (str.length == i) { if (edit == 1) { return trie.isWord; } else { for (char ch='a'; ch<='z'; ch++) { if (trie.children[ch-'a'] != null && trie.children[ch-'a'].isWord) return true; } return false; } } char curr = str[i]; for (char ch='a'; ch<='z'; ch++) { int idx = ch-'a'; if (trie.children[idx] == null) continue; if (helper(str, i+1, trie.children[idx], edit + ch == curr ? 0 : 1) || helper(str, i, trie.children[idx], edit + 1) || helper(str, i+1, trie, edit + 1)) return true; } return false; } private Trie constructTrie(String[] wordDict, int len) { Trie trie = new Trie(); for (String word: wordDict) { if (Math.abs(word.length() - len) <= 1) { trie.add(word); } } return trie; } // assume the string only contains a ~ z class Trie { Trie[] children = new Trie[26]; boolean isWord; void add(String word) { add(word.toCharArray(), 0); } void add(char[] word, int i) { if (i == word.length) { this.isWord = true; return; } int idx = word[i] - 'a'; if (this.children[idx] == null) { this.children[idx] = new Trie(); } this.children[idx].add(word, i+1); } } public boolean oneEditDistance2(String str, String[] wordDict) { for (String word: wordDict) { if (Math.abs(str.length() - word.length()) <= 1 && isOneEditDistance(s, word)) { return true; } } return false; } private boolean isOneEditDistance(String s, String w) { return isOneEditDistance(s.toCharArray(), 0, w.toCharArray(), 0, 0); } private boolean isOneEditDistance(char[] charsS, int i, char[] charsW, int j, int edit) { if (edit > 1) return false; if (i == charsS.length || j == charsW.length) { return (Math.abs(charsS.length - charsW.length) + edit) == 1; } char chs = charsS[i]; char chw = charsW[j]; return isOneEditDistance(charsS, i+1, charsW, j+1, edit + chs == chw ? 0 : 1) || isOneEditDistance(charsS, i, charsW, j+1, edit + 1) || isOneEditDistance(charsS, i+1, charsW, j, edit + 1); } public boolean oneEditDistance3(String str, String[] wordDict) { Set dictSet = new HashSet<>(); for (String word: wordDict) { char[] chars = wrod.toCharArray(); for (int i=0; i strSet = new HashSet<>(); for (int i=0; i 1) return false; if (lens > lent) { return isOneDelete(s, t); } else if (lent > lens) { return isOneDelete(t, s); } else { return isOneReplace(s, t); } } private boolean isOneReplace(String s, String t) { int diff = 0; char[] charss = s.toCharArray(); char[] charst = t.toCharArray(); for (int i=0; i 1) return false; } } return diff == 1; } private boolean isOneDelete(String longStr, String shortStr) { char[] charsl = longStr.toCharArray(); char[] charss = shortStr.toCharArray(); int l = 0; int s = 0; int diff = 0; while (s < charss.length && l < charsl.length) { if (charss[s] != charsl[l]) { diff++; if (diff > 1) return false; l++; } else { s++; l++; } } return ((l - s) == 1 && diff == 1) || (s == l && diff == 0); } public boolean isOneEditDistance2(String s, String t) { if (s == null || t == null || Math.abs(s.length() - t.length()) >= 2) return false; char[] cs = s.toCharArray(); int lenS = s.length(); char[] ct = t.toCharArray(); int lenT = t.length(); int i = 0; int j = 0; while (i < lenS && j < lenT) { if (cs[i] == ct[j]) { i++; j++; continue; } return isSame(cs, i+1, lenS, ct, j+1, lenT) || isSame(cs, i+1, lenS, ct, j, lenT) || isSame(cs, i, lenS, ct, j+1, lenT); } return Math.abs(lenS - lenT) == 1; } private boolean isSame(char[] cs, int i, int lenS, char[] ct, int j, int lenT) { if (i == lenS && j == lenT) return true; if (i == lenS || j == lenT) return false; while (i < lenS && j < lenT) { if (cs[i++] != ct[j++]) return false; } return i == lenS && j == lenT; } } ================================================ FILE: src/OnesAndZeroes474.java ================================================ /** * In the computer world, use restricted resource you have to generate maximum * benefit is what we always want to pursue. * * For now, suppose you are a dominator of m 0s and n 1s respectively. On the * other hand, there is an array with strings consisting of only 0s and 1s. * * Now your task is to find the maximum number of strings that you can form * with given m 0s and n 1s. Each 0 and 1 can be used at most once. * * Note: * The given numbers of 0s and 1s will both not exceed 100 * The size of given string array won't exceed 600. * * Example 1: * Input: Array = {"10", "0001", "111001", "1", "0"}, m = 5, n = 3 * Output: 4 * Explanation: This are totally 4 strings can be formed by the using of 5 0s and 3 1s, which are “10,”0001”,”1”,”0” * * Example 2: * Input: Array = {"10", "0", "1"}, m = 1, n = 1 * Output: 2 * Explanation: You could form "10", but then you'd have nothing left. Better form "0" and "1". */ public class OnesAndZeroes474 { /** * https://leetcode.com/problems/ones-and-zeroes/solution/ */ public int findMaxForm(String[] strs, int m, int n) { int[][][] memo = new int[strs.length][m + 1][n + 1]; return calculate(strs, 0, m, n, memo); } public int calculate(String[] strs, int i, int zeroes, int ones, int[][][] memo) { if (i == strs.length) return 0; if (memo[i][zeroes][ones] != 0) return memo[i][zeroes][ones]; int[] count = countzeroesones(strs[i]); int taken = -1; if (zeroes - count[0] >= 0 && ones - count[1] >= 0) taken = calculate(strs, i + 1, zeroes - count[0], ones - count[1], memo) + 1; int not_taken = calculate(strs, i + 1, zeroes, ones, memo); memo[i][zeroes][ones] = Math.max(taken, not_taken); return memo[i][zeroes][ones]; } public int[] countzeroesones(String s) { int[] c = new int[2]; for (int i = 0; i < s.length(); i++) { c[s.charAt(i)-'0']++; } return c; } /** * https://leetcode.com/problems/ones-and-zeroes/solution/ */ public int findMaxForm2(String[] strs, int m, int n) { int[][] dp = new int[m + 1][n + 1]; for (String s: strs) { int[] count = countzeroesones(s); for (int zeroes = m; zeroes >= count[0]; zeroes--) for (int ones = n; ones >= count[1]; ones--) dp[zeroes][ones] = Math.max(1 + dp[zeroes - count[0]][ones - count[1]], dp[zeroes][ones]); } return dp[m][n]; } } ================================================ FILE: src/OpenTheLock752.java ================================================ /** * You have a lock in front of you with 4 circular wheels. Each wheel has 10 * slots: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'. The wheels can * rotate freely and wrap around: for example we can turn '9' to be '0', or * '0' to be '9'. Each move consists of turning one wheel one slot. * * The lock initially starts at '0000', a string representing the state of the * 4 wheels. * * You are given a list of deadends dead ends, meaning if the lock displays * any of these codes, the wheels of the lock will stop turning and you will * be unable to open it. * * Given a target representing the value of the wheels that will unlock the * lock, return the minimum total number of turns required to open the lock, * or -1 if it is impossible. * * Example 1: * Input: deadends = ["0201","0101","0102","1212","2002"], target = "0202" * Output: 6 * Explanation: * A sequence of valid moves would be * "0000" -> "1000" -> "1100" -> "1200" -> "1201" -> "1202" -> "0202". * Note that a sequence like "0000" -> "0001" -> "0002" -> "0102" -> "0202" * would be invalid, because the wheels of the lock become stuck after the * display becomes the dead end "0102". * * Example 2: * Input: deadends = ["8888"], target = "0009" * Output: 1 * Explanation: * We can turn the last wheel in reverse to move from "0000" -> "0009". * * Example 3: * Input: deadends = ["8887","8889","8878","8898","8788","8988","7888","9888"], * target = "8888" * Output: -1 * Explanation: * We can't reach the target without getting stuck. * * Example 4: * Input: deadends = ["0000"], target = "8888" * Output: -1 * * Note: * The length of deadends will be in the range [1, 500]. * target will not be in the list deadends. * Every string in deadends and the string target will be a string of 4 digits * from the 10,000 possibilities '0000' to '9999'. */ public class OpenTheLock752 { private char[] digits = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; public int openLock(String[] deadends, String target) { Set set = new HashSet<>(); for (String end: deadends) set.add(end); String start = "0000"; if (set.contains(start)) return -1; Queue q = new LinkedList<>(); q.add(start); int level = 0; Set visited = new HashSet<>(); while (!q.isEmpty()) { int size = q.size(); for (int i=0; i 0. * Person's IDs may not be linear, e.g. we could have the persons 0, 1, 2 or * we could also have the persons 0, 2, 6. * * Example 1: * Input: * [[0,1,10], [2,0,5]] * Output: * 2 * * Explanation: * Person #0 gave person #1 $10. * Person #2 gave person #0 $5. * Two transactions are needed. One way to settle the debt is person #1 pays * person #0 and #2 $5 each. * * Example 2: * Input: * [[0,1,10], [1,0,1], [1,2,5], [2,0,5]] * Output: * 1 * * Explanation: * Person #0 gave person #1 $10. * Person #1 gave person #0 $1. * Person #1 gave person #2 $5. * Person #2 gave person #0 $5. * Therefore, person #1 only need to give person #0 $4, and all debt is settled. */ public class OptimalAccountBalancing465 { public int minTransfers(int[][] transactions) { Map balances = getBalances(transactions); int[] posNeg = new int[balances.size()]; int i =0; for (int b: balances.values()) { posNeg[i++] = b; } return dfs(posNeg, 0); } private int dfs(int[] posNeg, int start) { int L = posNeg.length; while (start < L && posNeg[start] == 0) start++; if (start == L) return 0; int res = Integer.MAX_VALUE; for (int i=start+1; i= 0) continue; int pre = posNeg[i]; posNeg[i] += posNeg[start]; res = Math.min(res, dfs(posNeg, start+1) + 1); posNeg[i] = pre; } return res; } private Map getBalances(int[][] transactions) { Map balances = new HashMap<>(); for (int[] tx: transactions) { balances.put(tx[0], balances.getOrDefault(tx[0], 0) - tx[2]); balances.put(tx[1], balances.getOrDefault(tx[1], 0) + tx[2]); } return balances; } } ================================================ FILE: src/OutputContestMatches544.java ================================================ /** * During the NBA playoffs, we always arrange the rather strong team to play * with the rather weak team, like make the rank 1 team play with the rank nth * team, which is a good strategy to make the contest more interesting. Now, * you're given n teams, you need to output their final contest matches in the * form of a string. * * The n teams are given in the form of positive integers from 1 to n, which * represents their initial rank. (Rank 1 is the strongest team and Rank n is * the weakest team.) We'll use parentheses('(', ')') and commas(',') to * represent the contest team pairing - parentheses('(' , ')') for pairing and * commas(',') for partition. During the pairing process in each round, you * always need to follow the strategy of making the rather strong one pair with * the rather weak one. * * Example 1: * Input: 2 * Output: (1,2) * Explanation: * Initially, we have the team 1 and the team 2, placed like: 1,2. * Then we pair the team (1,2) together with '(', ')' and ',', which is the * final answer. * * Example 2: * Input: 4 * Output: ((1,4),(2,3)) * Explanation: * In the first round, we pair the team 1 and 4, the team 2 and 3 together, as * we need to make the strong team and weak team together. * And we got (1,4),(2,3). * In the second round, the winners of (1,4) and (2,3) need to play again to * generate the final winner, so you need to add the paratheses outside them. * And we got the final answer ((1,4),(2,3)). * * Example 3: * Input: 8 * Output: (((1,8),(4,5)),((2,7),(3,6))) * Explanation: * First round: (1,8),(2,7),(3,6),(4,5) * Second round: ((1,8),(4,5)),((2,7),(3,6)) * Third round: (((1,8),(4,5)),((2,7),(3,6))) * Since the third round will generate the final winner, you need to output the * answer (((1,8),(4,5)),((2,7),(3,6))). * * Note: * The n is in range [2, 212]. * We ensure that the input n can be converted into the form 2k, where k is a * positive integer. */ class OutputContestMatches544 { // O(NlogN). Each of O(logN) rounds performs O(N) work. public String findContestMatch(int n) { String[] arr = new String[n]; for (int i=1; i<=n; i++) arr[i-1] = String.valueOf(i); while (n/2 >= 1) { int h = n/2; for (int i=1; i<=h; i++) { arr[i-1] = combine(arr[i-1], arr[n-i]); } n /= 2; } return arr[0]; } private String combine(String l, String r) { return "(" + l + "," + r + ")"; } /** * https://leetcode.com/problems/output-contest-matches/solution/ */ // O(N). We print each of O(N) characters in order. int[] team; int t; StringBuilder ans; public String findContestMatch2(int n) { team = new int[n]; t = 0; ans = new StringBuilder(); write(n, Integer.numberOfTrailingZeros(n)); return ans.toString(); } public void write(int n, int round) { if (round == 0) { int w = Integer.lowestOneBit(t); team[t] = w > 0 ? n / w + 1 - team[t - w] : 1; ans.append("" + team[t++]); } else { ans.append("("); write(n, round - 1); ans.append(","); write(n, round - 1); ans.append(")"); } } /** * https://leetcode.com/problems/output-contest-matches/discuss/101228/3-ms-Java-Recursive-clean-code */ public String findContestMatch3(int n) { StringBuilder sb = new StringBuilder(); helper(sb, 3, n, 1); return sb.toString(); } void helper(StringBuilder sb, int sum, int n, int val) { if (sum > n + 1) { sb.append(val); return; } sb.append('('); helper(sb, (sum << 1) - 1, n, val); sb.append(','); helper(sb, (sum << 1) - 1, n, sum - val); sb.append(')'); } } ================================================ FILE: src/PacificAtlanticWaterFlow417.java ================================================ /** * Given an m x n matrix of non-negative integers representing the height of * each unit cell in a continent, the "Pacific ocean" touches the left and top * edges of the matrix and the "Atlantic ocean" touches the right and bottom * edges. * * Water can only flow in four directions (up, down, left, or right) from a * cell to another one with height equal or lower. * * Find the list of grid coordinates where water can flow to both the Pacific * and Atlantic ocean. * * Note: * The order of returned grid coordinates does not matter. * Both m and n are less than 150. * * Example: * * Given the following 5x5 matrix: * * Pacific ~ ~ ~ ~ ~ * ~ 1 2 2 3 (5) * * ~ 3 2 3 (4) (4) * * ~ 2 4 (5) 3 1 * * ~ (6) (7) 1 4 5 * * ~ (5) 1 1 2 4 * * * * * * * Atlantic * * Return: * * [[0, 4], [1, 3], [1, 4], [2, 2], [3, 0], [3, 1], [4, 0]] (positions with * parentheses in above matrix). */ public class PacificAtlanticWaterFlow417 { private int[][] dirs = new int[][]{{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; public List pacificAtlantic(int[][] matrix) { if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return new ArrayList<>(); int M = matrix.length; int N = matrix[0].length; boolean[][] pacific = new boolean[M][N]; boolean[][] visited = new boolean[M][N]; Queue q = new LinkedList<>(); for (int j=0; j= 0 && y >= 0 && x < M && y < N && !visited[x][y] && matrix[x][y] >= matrix[now[0]][now[1]]) { q.add(new int[]{x, y}); pacific[x][y] = true; visited[x][y] = true; } } } boolean[][] atlantic = new boolean[M][N]; visited = new boolean[M][N]; q = new LinkedList<>(); for (int j=0; j= 0 && y >= 0 && x < M && y < N && !visited[x][y] && matrix[x][y] >= matrix[now[0]][now[1]]) { q.add(new int[]{x, y}); atlantic[x][y] = true; visited[x][y] = true; } } } List res = new ArrayList<>(); for (int i=0; i min1 && dp[i][k] < min2) { min2 = dp[i][k]; } } if (min2 == Integer.MAX_VALUE) min2 = min1; for (int k=0; k min1 && dp[k] < min2) { min2 = dp[k]; } } if (min2 == Integer.MAX_VALUE) min2 = min1; for (int k=0; k min1 && dp[k] < min2) { min2 = dp[k]; } } } int res = Integer.MAX_VALUE; for (int c: dp) { if (c < res) res = c; } return res == Integer.MAX_VALUE ? 0 : res; } public int minCostII4(int[][] costs) { if (costs == null || costs.length == 0 || costs[0].length == 0) return 0; int N = costs.length; int K = costs[0].length; int[] dp = new int[K]; int min1 = 0; int min2 = 0; for (int i=0; i min1 && dp[k] < min2) { min2 = dp[k]; } } } return min1; } public int minCostII5(int[][] costs) { if (costs == null || costs.length == 0 || costs[0].length == 0) return 0; int N = costs.length; int K = costs[0].length; int min1 = 0; int minIdx = -1; int min2 = 0; for (int i=0; i min1 && tmp < min2) { min2 = tmp; } } } return min1; } } ================================================ FILE: src/PalindromeLinkedList234.java ================================================ /** * Given a singly linked list, determine if it is a palindrome. * * Follow up: * Could you do it in O(n) time and O(1) space? */ /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ public class PalindromeLinkedList234 { public boolean isPalindrome(ListNode head) { ListNode dummy = new ListNode(0); ListNode f = head; ListNode s = head; while (s != null && f != null && f.next != null) { ListNode t = s; s = s.next; f = f.next.next; t.next = dummy.next; dummy.next = t; } if (f != null) { s = s.next; } dummy = dummy.next; while (s != null && dummy != null) { if (dummy.val != s.val) return false; s = s.next; dummy = dummy.next; } return true; } /** * https://leetcode.com/problems/palindrome-linked-list/discuss/64501/Java-easy-to-understand */ public boolean isPalindrome2(ListNode head) { ListNode fast = head, slow = head; while (fast != null && fast.next != null) { fast = fast.next.next; slow = slow.next; } if (fast != null) { // odd nodes: let right half smaller slow = slow.next; } slow = reverse(slow); fast = head; while (slow != null) { if (fast.val != slow.val) { return false; } fast = fast.next; slow = slow.next; } return true; } public ListNode reverse(ListNode head) { ListNode prev = null; while (head != null) { ListNode next = head.next; head.next = prev; prev = head; head = next; } return prev; } } ================================================ FILE: src/PalindromeNumber9.java ================================================ /** * Determine whether an integer is a palindrome. An integer is a palindrome * when it reads the same backward as forward. * * Example 1: * Input: 121 * Output: true * * Example 2: * Input: -121 * Output: false * Explanation: From left to right, it reads -121. From right to left, * it becomes 121-. Therefore it is not a palindrome. * * Example 3: * Input: 10 * Output: false * Explanation: Reads 01 from right to left. Therefore it is not a palindrome. * * Follow up: * Coud you solve it without converting the integer to a string? */ public class PalindromeNumber9 { public boolean isPalindrome(int x) { if (x < 0) return false; if (x == 0) return true; return x == reverse(x); } private int reverse(int x) { int res = 0; while (x != 0) { res *= 10; res += x % 10; x /= 10; } return res; } public int numberOfDigits(int x) { int res = 0; while (x != 0) { res++; x /= 10; } return res; } private int getDigit(int x, int pos) { return (x / (int) Math.pow(10, pos-1)) % 10; } public boolean isPalindrome2(int x) { if (x < 0) return false; if (x == 0) return true; int N = numberOfDigits(x); int hi = N; int lo = 1; while (lo < hi) { if (getDigit(x, lo++) != getDigit(x, hi--)) return false; } return true; } /** * https://leetcode.com/problems/palindrome-number/discuss/5127/9-line-accepted-Java-code-without-the-need-of-handling-overflow */ public boolean isPalindrome3(int x) { if (x<0 || (x!=0 && x%10==0)) return false; int rev = 0; while (x>rev){ rev = rev*10 + x%10; x = x/10; } return (x==rev || x==rev/10); } } ================================================ FILE: src/PalindromePairs336.java ================================================ /** * Given a list of unique words, find all pairs of distinct indices (i, j) in * the given list, so that the concatenation of the two words, i.e. * words[i] + words[j] is a palindrome. * * Example 1: * Given words = ["bat", "tab", "cat"] * Return [[0, 1], [1, 0]] * The palindromes are ["battab", "tabbat"] * * Example 2: * Given words = ["abcd", "dcba", "lls", "s", "sssll"] * Return [[0, 1], [1, 0], [3, 2], [2, 4]] * The palindromes are ["dcbaabcd", "abcddcba", "slls", "llssssll"] * */ public class PalindromePairs336 { public List> palindromePairs(String[] words) { List> res = new ArrayList<>(); for (int i=0; i pair = new ArrayList<>(2); pair.add(i); pair.add(j); res.add(pair); } if (isPalindrome(s2, s1)) { List pair = new ArrayList<>(2); pair.add(j); pair.add(i); res.add(pair); } } } return res; } private boolean isPalindrome(String s1, String s2) { int i = 0; int j = s2.length() - 1; while (i < s1.length() && j >= 0) { if (s1.charAt(i) != s2.charAt(j)) return false; i++; j--; } if (i < s1.length()) { return isPalindrome(s1, i, s1.length()-1); } if (j >= 0) { return isPalindrome(s2, 0, j); } return true; } private boolean isPalindrome(String str, int i, int j) { if (str == null || str.length() <= 1) return true; if ((j - i + 1) <= 0) return true; while (i < j) { if (str.charAt(i) != str.charAt(j)) return false; i++; j--; } return true; } private boolean isPalindrome(String str) { if (str == null || str.length() <= 1) return true; int i = 0; int j = str.length() - 1; while (i < j) { if (str.charAt(i) != str.charAt(j)) return false; i++; j--; } return true; } /** * https://leetcode.com/problems/palindrome-pairs/discuss/79199/150-ms-45-lines-JAVA-solution */ public List> palindromePairs2(String[] words) { List> ret = new ArrayList<>(); if (words == null || words.length < 2) return ret; Map map = new HashMap(); for (int i=0; i list = new ArrayList(); list.add(map.get(str2rvs)); list.add(i); ret.add(list); } } if (isPalindrome(str2)) { String str1rvs = new StringBuilder(str1).reverse().toString(); if (map.containsKey(str1rvs) && map.get(str1rvs) != i && str2.length()!=0) { List list = new ArrayList(); list.add(i); list.add(map.get(str1rvs)); ret.add(list); } } } } return ret; } /** * https://leetcode.com/problems/palindrome-pairs/discuss/79195/O(n*k2)-java-solution-with-Trie-structure-(n:-total-number-of-words-k:-average-length-of-each-word) */ private static class TrieNode { TrieNode[] next; int index; List list; TrieNode() { next = new TrieNode[26]; index = -1; list = new ArrayList<>(); } } public List> palindromePairs3(String[] words) { List> res = new ArrayList<>(); TrieNode root = new TrieNode(); for (int i = 0; i < words.length; i++) addWord(root, words[i], i); for (int i = 0; i < words.length; i++) search(words, i, root, res); return res; } private void addWord(TrieNode root, String word, int index) { for (int i = word.length() - 1; i >= 0; i--) { int j = word.charAt(i) - 'a'; if (root.next[j] == null) root.next[j] = new TrieNode(); if (isPalindrome(word, 0, i)) root.list.add(index); root = root.next[j]; } root.list.add(index); root.index = index; } private void search(String[] words, int i, TrieNode root, List> res) { for (int j = 0; j < words[i].length(); j++) { if (root.index >= 0 && root.index != i && isPalindrome(words[i], j, words[i].length() - 1)) { res.add(Arrays.asList(i, root.index)); } root = root.next[words[i].charAt(j) - 'a']; if (root == null) return; } for (int j : root.list) { if (i == j) continue; res.add(Arrays.asList(i, j)); } } } ================================================ FILE: src/PalindromePartitioning131.java ================================================ /** * Given a string s, partition s such that every substring of the partition is * a palindrome. * * Return all possible palindrome partitioning of s. * * Example: * * Input: "aab" * Output: * [ * ["aa","b"], * ["a","a","b"] * ] */ public class PalindromePartitioning131 { public List> partition(String s) { List> res = new ArrayList<>(); helper(s.toCharArray(), 0, new ArrayList<>(), res); return res; } private void helper(char[] chars, int start, List path, List> res) { if (start == chars.length) { res.add(new ArrayList<>(path)); return; } for (int j=start; j j) return true; if (i == j) return true; for (int k=0; k<=(j-i)/2; k++) { if (chars[i+k] != chars[j-k]) return false; } return true; } /** * https://leetcode.com/problems/palindrome-partitioning/discuss/41982/Java-DP-+-DFS-solution */ public List> partition2(String s) { List> res = new ArrayList<>(); boolean[][] dp = new boolean[s.length()][s.length()]; for(int i = 0; i < s.length(); i++) { for(int j = 0; j <= i; j++) { if(s.charAt(i) == s.charAt(j) && (i - j <= 2 || dp[j+1][i-1])) { dp[j][i] = true; } } } helper(res, new ArrayList<>(), dp, s, 0); return res; } private void helper(List> res, List path, boolean[][] dp, String s, int pos) { if(pos == s.length()) { res.add(new ArrayList<>(path)); return; } for(int i = pos; i < s.length(); i++) { if(dp[pos][i]) { path.add(s.substring(pos,i+1)); helper(res, path, dp, s, i+1); path.remove(path.size()-1); } } } } ================================================ FILE: src/PalindromePermutationII267.java ================================================ /** * Given a string s, return all the palindromic permutations * (without duplicates) of it. Return an empty list if no palindromic * permutation could be form. * * Example 1: * Input: "aabb" * Output: ["abba", "baab"] * * Example 2: * Input: "abc" * Output: [] */ public class PalindromePermutationII267 { public List generatePalindromes(String s) { List res = new ArrayList<>(); int[] map = new int[256]; int N = 0; for (char ch: s.toCharArray()) { map[ch]++; N++; } StringBuilder sb = new StringBuilder(); int odd = -1; for (int i=0; i<256; i++) { if (map[i] % 2 != 0) { if (odd != -1) return res; odd = i; sb.append((char) i); map[i]--; } } helper(map, 0, sb, res, N); return res; } private void helper(int[] map, int curr, StringBuilder sb, List res, int N) { if (sb.length() == N) { res.add(sb.toString()); return; } for (int i=0; i<256; i++) { if (map[i] == 0) continue; map[i] -= 2; add(sb, (char) i); helper(map, curr+1, sb, res, N); remove(sb); map[i] += 2; } } private void add(StringBuilder sb, char ch) { sb.append(ch); sb.insert(0, ch); } private void remove(StringBuilder sb) { sb.deleteCharAt(0); sb.deleteCharAt(sb.length()-1); } } ================================================ FILE: src/PalindromicSubstrings647.java ================================================ /** * Given a string, your task is to count how many palindromic substrings in this string. * * The substrings with different start indexes or end indexes are counted as * different substrings even they consist of same characters. * * Example 1: * Input: "abc" * Output: 3 * Explanation: Three palindromic strings: "a", "b", "c". * * Example 2: * Input: "aaa" * Output: 6 * Explanation: Six palindromic strings: "a", "a", "a", "aa", "aa", "aaa". * * Note: * The input string length won't exceed 1000. * */ public class PalindromicSubstrings647 { public int countSubstrings(String s) { boolean[][] dp = new boolean[s.length()][s.length()]; int res = 0; for (int l=0; l=0 && j q = new LinkedList<>(); q.offer(0); int i = 1; int acc = nums[0]; while (!q.isEmpty() && i < nums.length) { int curr = nums[i]; if (acc == half) { return true; } else if (acc < half) { q.offer(i); acc += curr; i++; } else { i = q.poll(); acc -= nums[i]; i++; if (i >= nums.length) { i = q.poll(); acc -= nums[i]; i++; } } } return false; } /** * https://discuss.leetcode.com/topic/62987/java-dynamic-programming-solution-21ms-with-explanation */ public boolean canPartition2(int[] nums) { int total = 0; for(int i : nums) total+=i; // compute the total sum of the input array if(total%2 != 0) return false; // if the array sum is not even, we cannot partition it into 2 equal subsets int max = total/2; // the maximum for a subset is total/2 int[][] results = new int[nums.length][max]; // integer matrix to store the results, so we don't have to compute it more than one time return isPartitionable(max,0,0,nums,results); } public boolean isPartitionable(int max,int curr, int index, int[] nums, int[][] results) { if(curr>max || index>nums.length-1) return false; // if we passed the max, or we reached the end of the array, return false if(curr==max) return true; // if we reached the goal (total/2) we found a possible partition if(results[index][curr]==1) return true; // if we already computed teh result for the index i with the sum current, we retrieve this result (1 for true) if(results[index][curr]==2) return false; // if we already computed teh result for the index i with the sum current, we retrieve this result (2 for false) boolean res = isPartitionable(max, curr+nums[index], index+1, nums, results) || isPartitionable(max, curr, index+1, nums, results); // else try to find the equal partiion, taking this element, or not taking it results[index][curr] = res ? 1 : 2; // store the result for this index and this current sum, to use it in dynamic programming return res; } /** * https://discuss.leetcode.com/topic/67539/0-1-knapsack-detailed-explanation */ public boolean canPartition3(int[] nums) { int sum = 0; for (int num : nums) { sum += num; } if ((sum & 1) == 1) { return false; } sum /= 2; int n = nums.length; boolean[][] dp = new boolean[n+1][sum+1]; for (int i = 0; i < dp.length; i++) { Arrays.fill(dp[i], false); } dp[0][0] = true; for (int i = 1; i < n+1; i++) { dp[i][0] = true; } for (int j = 1; j < sum+1; j++) { dp[0][j] = false; } for (int i = 1; i < n+1; i++) { for (int j = 1; j < sum+1; j++) { dp[i][j] = dp[i-1][j]; if (j >= nums[i-1]) { dp[i][j] = (dp[i][j] || dp[i-1][j-nums[i-1]]); } } } return dp[n][sum]; } /** * https://discuss.leetcode.com/topic/62312/java-solution-similar-to-backpack-problem-easy-to-understand */ public boolean canPartition4(int[] nums) { // check edge case if (nums == null || nums.length == 0) { return true; } // preprocess int volumn = 0; for (int num : nums) { volumn += num; } if (volumn % 2 != 0) { return false; } volumn /= 2; // dp def boolean[] dp = new boolean[volumn + 1]; // dp init dp[0] = true; // dp transition for (int i = 1; i <= nums.length; i++) { for (int j = volumn; j >= nums[i-1]; j--) { dp[j] = dp[j] || dp[j - nums[i-1]]; } } return dp[volumn]; } } ================================================ FILE: src/PartitionLabels763.java ================================================ /** * A string S of lowercase letters is given. We want to partition this string * into as many parts as possible so that each letter appears in at most one * part, and return a list of integers representing the size of these parts. * * Example 1: * Input: S = "ababcbacadefegdehijhklij" * Output: [9,7,8] * Explanation: * The partition is "ababcbaca", "defegde", "hijhklij". * This is a partition so that each letter appears in at most one part. * A partition like "ababcbacadefegde", "hijhklij" is incorrect, because it * splits S into less parts. * * Note: * S will have length in range [1, 500]. * S will consist of lowercase letters ('a' to 'z') only. */ public class PartitionLabels763 { public List partitionLabels(String S) { char[] chars = S.toCharArray(); List intervals = new ArrayList<>(); Map map = new HashMap<>(); int ii = 0; int i = 0; for (char c: chars) { if (map.containsKey(c)) { intervals.get(map.get(c))[1] = i; } else { map.put(c, ii++); intervals.add(new int[]{i, i}); } i++; } List res = new ArrayList<>(); int l = 0; int r = 0; for (int[] curr: intervals) { if (curr[0] <= r) { r = Math.max(curr[1], r); } else { res.add(r - l + 1); l = curr[0]; r = curr[1]; } } res.add(r - l + 1); return res; } /** * https://leetcode.com/problems/partition-labels/solution/ */ public List partitionLabels2(String S) { int[] last = new int[26]; for (int i = 0; i < S.length(); ++i) last[S.charAt(i) - 'a'] = i; int j = 0, anchor = 0; List ans = new ArrayList(); for (int i = 0; i < S.length(); ++i) { j = Math.max(j, last[S.charAt(i) - 'a']); if (i == j) { ans.add(i - anchor + 1); anchor = i + 1; } } return ans; } } ================================================ FILE: src/PartitionList86.java ================================================ /** * Given a linked list and a value x, partition it such that all nodes less * than x come before nodes greater than or equal to x. * * You should preserve the original relative order of the nodes in each of the two partitions. * * For example, * Given 1->4->3->2->5->2 and x = 3, * return 1->2->2->4->3->5. */ /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ public class PartitionList86 { public ListNode partition(ListNode head, int x) { if (head == null) { return null; } ListNode left = null; ListNode leftEnd = null; ListNode right = null; ListNode rightEnd = null; while (head != null) { if (head.val < x) { if (left == null) { left = new ListNode(head.val); } else if (leftEnd == null) { leftEnd = new ListNode(head.val); left.next = leftEnd; } else { leftEnd.next = new ListNode(head.val); leftEnd = leftEnd.next; } } else { if (right == null) { right = new ListNode(head.val); } else if (rightEnd == null) { rightEnd = new ListNode(head.val); right.next = rightEnd; } else { rightEnd.next = new ListNode(head.val); rightEnd = rightEnd.next; } } head = head.next; } if (leftEnd != null){ leftEnd.next = right; return left; } else if (left != null) { left.next = right; return left; } else { return right; } } /** * https://discuss.leetcode.com/topic/23951/java-solution-pick-out-larger-nodes-and-append-to-the-end */ public ListNode partition(ListNode head, int x) { if(head==null || head.next==null) return head; ListNode l1 = new ListNode(0); ListNode l2 = new ListNode(0); ListNode p1=l1, p2=l2; p1.next = head; while(p1.next!=null) { // keep moving larger node to list 2; if(p1.next.val>=x) { ListNode tmp = p1.next; p1.next = tmp.next; p2.next = tmp; p2 = p2.next; } else { p1 = p1.next; } } // conbine lists 1 and 2; p2.next = null; p1.next = l2.next; return l1.next; } } ================================================ FILE: src/PartitionToKEqualSumSubsets698.java ================================================ /** * Given an array of integers nums and a positive integer k, find whether it's * possible to divide this array into k non-empty subsets whose sums are all * equal. * * Example 1: * Input: nums = [4, 3, 2, 3, 5, 2, 1], k = 4 * Output: True * Explanation: It's possible to divide it into 4 subsets * (5), (1, 4), (2,3), (2,3) with equal sums. * * Note: * 1 <= k <= len(nums) <= 16. * 0 < nums[i] < 10000. */ public class PartitionToKEqualSumSubsets698 { public boolean canPartitionKSubsets(int[] nums, int k) { int sum = 0; int N = nums.length; for (int i=0; i 0 || nums[N - 1] > target) return false; boolean[] dp = new boolean[1 << N]; dp[0] = true; int[] total = new int[1 << N]; for (int state = 0; state < (1 << N); state++) { if (!dp[state]) continue; for (int i = 0; i < N; i++) { int future = state | (1 << i); if (state != future && !dp[future]) { if (nums[i] <= target - (total[state] % target)) { dp[future] = true; total[future] = total[state] + nums[i]; } else { break; } } } } return dp[(1 << N) - 1]; } /** * https://leetcode.com/problems/partition-to-k-equal-sum-subsets/solution/ */ public boolean search(int[] groups, int row, int[] nums, int target) { if (row < 0) return true; int v = nums[row--]; for (int i = 0; i < groups.length; i++) { if (groups[i] + v <= target) { groups[i] += v; if (search(groups, row, nums, target)) return true; groups[i] -= v; } if (groups[i] == 0) break; } return false; } public boolean canPartitionKSubsets3(int[] nums, int k) { int sum = Arrays.stream(nums).sum(); if (sum % k > 0) return false; int target = sum / k; Arrays.sort(nums); int row = nums.length - 1; if (nums[row] > target) return false; while (row >= 0 && nums[row] == target) { row--; k--; } return search(new int[k], row, nums, target); } } ================================================ FILE: src/PascalsTriangleII119.java ================================================ /** * Given a non-negative index k where k ≤ 33, return the kth index row of the * Pascal's triangle. * * Note that the row index starts from 0. * https://upload.wikimedia.org/wikipedia/commons/0/0d/PascalTriangleAnimated2.gif * * In Pascal's triangle, each number is the sum of the two numbers directly above it. * * Example: * Input: 3 * Output: [1,3,3,1] * * Follow up: * Could you optimize your algorithm to use only O(k) extra space? */ public class PascalsTriangleII119 { public List getRow(int rowIndex) { LinkedList res = new LinkedList<>(); res.add(1); if (rowIndex == 0) return res; res.add(1); if (rowIndex == 1) return res; int i = 2; while (i <= rowIndex) { int size = res.size(); res.add(1); int pre = res.removeFirst(); for (int j=0; j getRow2(int rowIndex) { long nCk = 1; List result = new ArrayList(); for(int i=0;i<=rowIndex;i++){ result.add((int)nCk); nCk = nCk *(rowIndex-i)/(i+1); } return result; } } ================================================ FILE: src/PatchingArray330.java ================================================ /** * Given a sorted positive integer array nums and an integer n, add/patch * elements to the array such that any number in range [1, n] inclusive can * be formed by the sum of some elements in the array. Return the minimum * number of patches required. * * Example 1: * Input: nums = [1,3], n = 6 * Output: 1 * Explanation: * Combinations of nums are [1], [3], [1,3], which form possible sums of: 1, 3, 4. * Now if we add/patch 2 to nums, the combinations are: [1], [2], [3], [1,3], [2,3], [1,2,3]. * Possible sums are 1, 2, 3, 4, 5, 6, which now covers the range [1, 6]. * So we only need 1 patch. * * Example 2: * Input: nums = [1,5,10], n = 20 * Output: 2 * Explanation: The two patches can be [2, 4]. * * Example 3: * Input: nums = [1,2,2], n = 5 * Output: 0 */ /** * https://leetcode.com/problems/patching-array/discuss/280183/Detailed-Explanation-with-Example */ public class PatchingArray330 { public int minPatches(int[] nums, int n) { long patch = 0; int count = 0; int index = 0; while (patch < n) { if (index < nums.length && patch + 1 >= nums[index]) { patch += nums[index]; index++; } else { patch += (patch + 1); count++; } } return count; } } ================================================ FILE: src/PathSum112.java ================================================ /** * Given a binary tree and a sum, determine if the tree has a root-to-leaf path * such that adding up all the values along the path equals the given sum. * * For example: * Given the below binary tree and sum = 22, * 5 * / \ * 4 8 * / / \ * 11 13 4 * / \ \ * 7 2 1 * return true, as there exist a root-to-leaf path 5->4->11->2 which sum is 22. */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class PathSum112 { public boolean hasPathSum(TreeNode root, int sum) { return sum(root, sum, 0); } private boolean sum(TreeNode root, int sum, int sumForNow) { if (root == null) { return false; } sumForNow += root.val; if (sumForNow == sum && root.left == null && root.right == null) { return true; } if (sum(root.left, sum, sumForNow)) { return true; } return sum(root.right, sum, sumForNow); } /** * https://discuss.leetcode.com/topic/3149/accepted-my-recursive-solution-in-java */ public boolean hasPathSum2(TreeNode root, int sum) { if(root == null) return false; if(root.left == null && root.right == null && sum - root.val == 0) return true; return hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val); } } ================================================ FILE: src/PathSumII113.java ================================================ /** * Given a binary tree and a sum, find all root-to-leaf paths where each path's * sum equals the given sum. * * Note: A leaf is a node with no children. * * Example: * * Given the below binary tree and sum = 22, * * 5 * / \ * 4 8 * / / \ * 11 13 4 * / \ / \ * 7 2 5 1 * Return: * * [ * [5,4,11,2], * [5,8,4,5] * ] */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class PathSumII113 { public List> pathSum(TreeNode root, int sum) { List> res = new ArrayList<>(); pathSum(root, 0, sum, new ArrayList<>(), res); return res; } private void pathSum(TreeNode root, int sumSoFar, int target, List path, List> res) { if (root == null) return; int newSum = sumSoFar + root.val; path.add(root.val); if (root.left == null && root.right == null) { if (newSum == target) res.add(new ArrayList<>(path)); path.remove(path.size() - 1); return; } pathSum(root.left, newSum, target, path, res); pathSum(root.right, newSum, target, path, res); path.remove(path.size() - 1); } } ================================================ FILE: src/PathSumIII437.java ================================================ /** * You are given a binary tree in which each node contains an integer value. * * Find the number of paths that sum to a given value. * * The path does not need to start or end at the root or a leaf, but it must go * downwards (traveling only from parent nodes to child nodes). * * The tree has no more than 1,000 nodes and the values are in the range -1,000,000 to 1,000,000. * * Example: * * * root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8 * * 10 * / \ * 5 -3 * / \ \ * 3 2 11 * / \ \ * 3 -2 1 * * Return 3. The paths that sum to 8 are: * * 1. 5 -> 3 * 2. 5 -> 2 -> 1 * 3. -3 -> 11 * */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class PathSumIII437 { public int pathSum(TreeNode root, int sum) { int[] res = new int[1]; pathSum(root, sum, res, new ArrayList<>()); return res[0]; } private void pathSum(TreeNode root, int target, int[] res, List path) { if (root == null) return; int last = path.isEmpty() ? root.val : path.get(path.size() - 1) + root.val; if (last == target) res[0]++; for (int s: path) { if (last - s == target) { res[0]++; } } path.add(last); pathSum(root.left, target, res, path); pathSum(root.right, target, res, path); path.remove(path.size() - 1); } /** * https://leetcode.com/problems/path-sum-iii/discuss/91878/17-ms-O(n)-java-Prefix-sum-method */ public int pathSum2(TreeNode root, int sum) { HashMap preSum = new HashMap(); preSum.put(0,1); return helper(root, 0, sum, preSum); } public int helper(TreeNode root, int currSum, int target, HashMap preSum) { if (root == null) { return 0; } currSum += root.val; int res = preSum.getOrDefault(currSum - target, 0); preSum.put(currSum, preSum.getOrDefault(currSum, 0) + 1); res += helper(root.left, currSum, target, preSum) + helper(root.right, currSum, target, preSum); preSum.put(currSum, preSum.get(currSum) - 1); return res; } } ================================================ FILE: src/PeekingIterator284.java ================================================ /** * Given an Iterator class interface with methods: next() and hasNext(), design * and implement a PeekingIterator that support the peek() operation -- it * essentially peek() at the element that will be returned by the next call to * next(). * * Example: * Assume that the iterator is initialized to the beginning of the list: [1,2,3]. * * Call next() gets you 1, the first element in the list. * Now you call peek() and it returns 2, the next element. Calling next() after * that still return 2. * You call next() the final time and it returns 3, the last element. * Calling hasNext() after that should return false. * * Follow up: How would you extend your design to be generic and work with all * types, not just integer? */ public class PeekingIterator284 { // Java Iterator interface reference: // https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html class PeekingIterator implements Iterator { private Integer next; private Iterator iterator; public PeekingIterator(Iterator iterator) { // initialize any member here. this.iterator = iterator; if (this.iterator.hasNext()) { this.next = this.iterator.next(); } } // Returns the next element in the iteration without advancing the iterator. public Integer peek() { return next; } // hasNext() and next() should behave the same as in the Iterator interface. // Override them if needed. @Override public Integer next() { Integer returned = next; if (iterator.hasNext()) { next = iterator.next(); } else { next = null; } return returned; } @Override public boolean hasNext() { return next != null; } } } ================================================ FILE: src/PerfectSquares279.java ================================================ /** * Given a positive integer n, find the least number of perfect square numbers * (for example, 1, 4, 9, 16, ...) which sum to n. * * For example, given n = 12, return 3 because 12 = 4 + 4 + 4; given n = 13, * return 2 because 13 = 4 + 9. * */ public class PerfectSquares279 { public int numSquares(int n) { int[] dp = new int[n+1]; dp[0] = 0; dp[1] = 1; for (int i=2; i<=n; i++) { int sq = (int) Math.sqrt(i); int curr = Integer.MAX_VALUE; for (int j=sq; j>=1; j--) { curr = Math.min(curr, dp[i-j*j]+1); } dp[i] = curr; } return dp[n]; } public static void main(String[] args) { PerfectSquares279 ps = new PerfectSquares279(); System.out.println(ps.numSquares(12)); System.out.println(ps.numSquares(13)); } } ================================================ FILE: src/PermutationInString567.java ================================================ /** * Given two strings s1 and s2, write a function to return true if s2 contains * the permutation of s1. In other words, one of the first string's * permutations is the substring of the second string. * * Example 1: * Input:s1 = "ab" s2 = "eidbaooo" * Output:True * Explanation: s2 contains one permutation of s1 ("ba"). * * Example 2: * Input:s1= "ab" s2 = "eidboaoo" * Output: False * * Note: * The input strings only contain lower case letters. * The length of both given strings is in range [1, 10,000]. */ public class PermutationInString567 { public boolean checkInclusion(String s1, String s2) { if (s1 == null || s2 == null || s1.length() > s2.length()) return false; int[] map = new int[26]; int M = 0; for (char c: s1.toCharArray()) { if (map[c - 'a'] == 0) M++; map[c - 'a']++; } char[] chars2 = s2.toCharArray(); int N2 = s2.length(); int N1 = s1.length(); int left = 0; int right = 0; while (right < N2) { char rc = chars2[right++]; map[rc - 'a']--; if (map[rc - 'a'] == 0) M--; if (M == 0) return true; if (right - left == N1) { char lc = chars2[left++]; if (map[lc - 'a'] == 0) M++; map[lc - 'a']++; } } return false; } } ================================================ FILE: src/PermutationSequence60.java ================================================ /** * The set [1,2,3,...,n] contains a total of n! unique permutations. * * By listing and labeling all of the permutations in order, we get the * following sequence for n = 3: * * "123" * "132" * "213" * "231" * "312" * "321" * * Given n and k, return the kth permutation sequence. * * Note: * Given n will be between 1 and 9 inclusive. * Given k will be between 1 and n! inclusive. * * Example 1: * Input: n = 3, k = 3 * Output: "213" * * Example 2: * Input: n = 4, k = 9 * Output: "2314" */ public class PermutationSequence60 { public String getPermutation(int n, int k) { StringBuilder sb = new StringBuilder(); int[] count = new int[1]; boolean[] used = new boolean[n]; helper(sb, n, k, count, used); return sb.toString(); } private boolean helper(StringBuilder sb, int n, int k, int[] count, boolean[] used) { if (sb.length() == n) { count[0]++; return count[0] == k; } for (int i=0; i list = new ArrayList<>(); for (int i=0; i0; i--) { int idx = k / factors[i - 1]; k = k % factors[i - 1]; int val = list.get(idx); list.remove(idx); sb.append(val); } return sb.toString(); } } ================================================ FILE: src/Permutations46.java ================================================ /** * Given a collection of distinct numbers, return all possible permutations. * * For example, * [1,2,3] have the following permutations: * [ * [1,2,3], * [1,3,2], * [2,1,3], * [2,3,1], * [3,1,2], * [3,2,1] * ] */ import java.util.Arrays; import java.util.ArrayList; import java.util.List; public class Permutations46 { public List> permute(int[] nums) { List> results = new ArrayList<>(); List result = new ArrayList<>(); boolean[] selected = new boolean[nums.length]; helper(results, result, nums, nums.length, selected); return results; } private void helper(List> results, List result, int[] nums, int length, boolean[] selected) { if (result.size() == length) { results.add(new ArrayList<>(result)); return; } for (int i = 0; i < length; i++) { if (!selected[i]) { result.add(nums[i]); selected[i] = true; helper(results, result, nums, length, selected); result.remove(result.size() - 1); selected[i] = false; } } } /** * In this way, we are not using selected, saved space, but increased time! * result.contains(nums[i]) is with time O(n); but selected[i] = true is O(1) */ public List> permute2(int[] nums) { List> results = new ArrayList<>(); List result = new ArrayList<>(); helper(results, result, nums, nums.length); return results; } private void helper(List> results, List result, int[] nums, int length) { if (result.size() == length) { results.add(new ArrayList<>(result)); return; } for (int i = 0; i < length; i++) { if (!result.contains(nums[i])) { result.add(nums[i]); helper(results, result, nums, length); result.remove(result.size() - 1); } } } /** * https://discuss.leetcode.com/topic/6377/my-ac-simple-iterative-java-python-solution */ public List> permute3(int[] num) { List> ans = new ArrayList>(); if (num.length ==0) return ans; List l0 = new ArrayList(); l0.add(num[0]); ans.add(l0); for (int i = 1; i< num.length; ++i){ List> new_ans = new ArrayList>(); for (int j = 0; j<=i; ++j){ for (List l : ans){ List new_l = new ArrayList(l); new_l.add(j,num[i]); new_ans.add(new_l); } } ans = new_ans; } return ans; } /** * https://discuss.leetcode.com/topic/23036/java-clean-code-two-recursive-solutions */ public List> permute4(int[] nums) { List> permutations = new ArrayList<>(); if (nums.length == 0) { return permutations; } collectPermutations(nums, 0, new ArrayList<>(), permutations); return permutations; } private void collectPermutations(int[] nums, int start, List permutation, List> permutations) { if (permutation.size() == nums.length) { permutations.add(permutation); return; } for (int i = 0; i <= permutation.size(); i++) { List newPermutation = new ArrayList<>(permutation); newPermutation.add(i, nums[start]); collectPermutations(nums, start + 1, newPermutation, permutations); } } /** * https://discuss.leetcode.com/topic/42417/2ms-java-solution-beats-93-i-think-it-could-be-optimized */ public List> permute5(int[] nums) { List> result = new ArrayList>(); perm(result, nums, 0, nums.length - 1); return result; } public static void perm(List> result, int[] nums, int start, int end){ if(start == end){ Integer[] ele = new Integer[nums.length]; for(int i = 0; i < nums.length; i++){ ele[i] = nums[i]; } result.add(Arrays.asList(ele)); } else{ for(int i = start; i <= end; i++){ int temp = nums[start]; nums[start] = nums[i]; nums[i] = temp; perm(result, nums, start + 1, end); temp = nums[start]; nums[start] = nums[i]; nums[i] = temp; } } } public List> permute6(int[] nums) { List> result = new ArrayList>(); perm(result, nums, 0); return result; } private static void perm(List> result, int[] nums, int start){ if (start == nums.length-1) { Integer[] ele = new Integer[nums.length]; for(int i = 0; i < nums.length; i++){ ele[i] = nums[i]; } result.add(Arrays.asList(ele)); return; } for (int i = start; i < nums.length; i++){ swap(nums, start, i); perm(result, nums, start + 1); swap(nums, start, i); } } private static void swap(int[] nums, int i, int j) { int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; } } ================================================ FILE: src/PermutationsII47.java ================================================ /** * Given a collection of numbers that might contain duplicates, return all * possible unique permutations. * * For example, * [1,1,2] have the following unique permutations: * [ * [1,1,2], * [1,2,1], * [2,1,1] * ] * */ public class PermutationsII47 { public List> permuteUnique(int[] nums) { Arrays.sort(nums); Set> result = new HashSet<>(); perm(result, nums, 0); List> res = new ArrayList<>(); for (List l: result) res.add(l); return res; } private static void perm(Set> result, int[] nums, int start){ if (start == nums.length-1) { Integer[] ele = new Integer[nums.length]; for(int i = 0; i < nums.length; i++){ ele[i] = nums[i]; } result.add(Arrays.asList(ele)); return; } int pre = nums[start]; for (int i = start; i < nums.length; i++) { if (start != i && (nums[start] == nums[i] || pre == nums[i])) continue; pre = nums[i]; swap(nums, start, i); perm(result, nums, start + 1); swap(nums, start, i); } } private static void swap(int[] nums, int i, int j) { int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; } /** * https://leetcode.com/problems/permutations-ii/discuss/18648/Share-my-Java-code-with-detailed-explanantion */ public List> permuteUnique2(int[] nums) { Arrays.sort(nums); List> result = new ArrayList<>(); perm(result, nums, 0); return result; } private static void perm(List> result, int[] nums, int start){ if (start == nums.length-1) { Integer[] ele = new Integer[nums.length]; for(int i = 0; i < nums.length; i++){ ele[i] = nums[i]; } result.add(Arrays.asList(ele)); return; } Set seen = new HashSet<>(); for (int i = start; i < nums.length; i++) { if (seen.add(nums[i])) { swap(nums, start, i); perm(result, nums, start + 1); swap(nums, start, i); } } } /** * https://leetcode.com/problems/permutations-ii/discuss/18594/Really-easy-Java-solution-much-easier-than-the-solutions-with-very-high-vote */ public List> permuteUnique3(int[] nums) { List> res = new ArrayList>(); if(nums==null || nums.length==0) return res; boolean[] used = new boolean[nums.length]; List list = new ArrayList(); Arrays.sort(nums); dfs(nums, used, list, res); return res; } public void dfs(int[] nums, boolean[] used, List list, List> res){ if(list.size()==nums.length){ res.add(new ArrayList(list)); return; } for(int i=0;i0 &&nums[i-1]==nums[i] && !used[i-1]) continue; used[i]=true; list.add(nums[i]); dfs(nums,used,list,res); used[i]=false; list.remove(list.size()-1); } } /** * https://leetcode.com/problems/permutations-ii/discuss/18601/Short-iterative-Java-solution */ public List> permuteUnique4s(int[] num) { LinkedList> res = new LinkedList<>(); res.add(new ArrayList<>()); for (int i = 0; i < num.length; i++) { Set cache = new HashSet<>(); while (res.peekFirst().size() == i) { List l = res.removeFirst(); for (int j = 0; j <= l.size(); j++) { List newL = new ArrayList<>(l.subList(0,j)); newL.add(num[i]); newL.addAll(l.subList(j,l.size())); if (cache.add(newL.toString())) res.add(newL); } } } return res; } } ================================================ FILE: src/PlusOne66.java ================================================ /** * Given a non-negative integer represented as a non-empty array of digits, * plus one to the integer. * * You may assume the integer do not contain any leading zero, except the * number 0 itself. * * The digits are stored such that the most significant digit is at the head * of the list. */ public class PlusOne66 { public int[] plusOne(int[] digits) { int[] res = new int[digits.length+1]; int c = 1; for (int i=digits.length-1; i>=0; i--) { int s = digits[i] + c; c = s / 10; res[i+1] = s % 10; } res[0] = c; return (res[0] != 0) ? res : Arrays.copyOfRange(res, 1, res.length); } /** * https://leetcode.com/problems/plus-one/discuss/24082/My-Simple-Java-Solution */ public int[] plusOne2(int[] digits) { int n = digits.length; for(int i=n-1; i>=0; i--) { if(digits[i] < 9) { digits[i]++; return digits; } digits[i] = 0; } int[] newNumber = new int [n+1]; newNumber[0] = 1; return newNumber; } } ================================================ FILE: src/PlusOneLinkedList369.java ================================================ /** * Given a non-negative integer represented as non-empty a singly linked list * of digits, plus one to the integer. * * You may assume the integer do not contain any leading zero, except the * number 0 itself. * * The digits are stored such that the most significant digit is at the head * of the list. * * Example: * Input: * 1->2->3 * * Output: * 1->2->4 */ /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ public class PlusOneLinkedList369 { public ListNode plusOne(ListNode head) { if (head == null) return null; int carry = helper(head); if (carry == 0) return head; ListNode h = new ListNode(carry); h.next = head; return h; } public int helper(ListNode head) { if (head == null) return 1; int carry = helper(head.next); int sum = carry + head.val; head.val = sum % 10; return sum / 10; } /** * https://leetcode.com/problems/plus-one-linked-list/discuss/84150/Two-Pointers-Java-Solution:-O(n)-time-O(1)-space */ public ListNode plusOne2(ListNode head) { ListNode dummy = new ListNode(0); dummy.next = head; ListNode i = dummy; ListNode j = dummy; while (j.next != null) { j = j.next; if (j.val != 9) { i = j; } } // i = index of last non-9 digit i.val++; i = i.next; while (i != null) { i.val = 0; i = i.next; } if (dummy.val == 0) return dummy.next; return dummy; } } ================================================ FILE: src/Point.java ================================================ public class Point { int x; int y; Point() { x = 0; y = 0; } Point(int a, int b) { x = a; y = b; } } ================================================ FILE: src/PopulatingNextRightPointersInEachNode116.java ================================================ /** * Given a binary tree * * struct TreeLinkNode { * TreeLinkNode *left; * TreeLinkNode *right; * TreeLinkNode *next; * } * Populate each next pointer to point to its next right node. If there is no * next right node, the next pointer should be set to NULL. * * Initially, all next pointers are set to NULL. * * Note: * You may only use constant extra space. * You may assume that it is a perfect binary tree (ie, all leaves are at the * same level, and every parent has two children). * * * For example, * Given the following perfect binary tree, * 1 * / \ * 2 3 * / \ / \ * 4 5 6 7 * After calling your function, the tree should look like: * 1 -> NULL * / \ * 2 -> 3 -> NULL * / \ / \ * 4->5->6->7 -> NULL * */ /** * Definition for binary tree with next pointer. * public class TreeLinkNode { * int val; * TreeLinkNode left, right, next; * TreeLinkNode(int x) { val = x; } * } */ public class PopulatingNextRightPointersInEachNode116 { public void connect(TreeLinkNode root) { if (root == null || (root.left == null && root.right == null)) return; LinkedList q = new LinkedList<>(); q.add(root.left); q.add(root.right); int num = 2; while (!q.isEmpty()) { TreeLinkNode pre = q.remove(); if (pre == null) return; q.add(pre.left); q.add(pre.right); int i = 0; if (q.isEmpty()) return; while (i level = new LinkedList<>(); level.add(root); connect(level); } private void connect(LinkedList level) { LinkedList newLevel = new LinkedList<>(); if (level.isEmpty()) return; while (!level.isEmpty()) { TreeLinkNode n = level.remove(); if (n == null) return; n.next = level.peek(); if (n.left != null) { newLevel.add(n.left); newLevel.add(n.right); } } connect(newLevel); } } ================================================ FILE: src/PopulatingNextRightPointersInEachNodeII117.java ================================================ /** * Follow up for problem "Populating Next Right Pointers in Each Node". * * What if the given tree could be any binary tree? Would your previous * solution still work? * * Note: * * You may only use constant extra space. * For example, * Given the following binary tree, * 1 * / \ * 2 3 * / \ \ * 4 5 7 * After calling your function, the tree should look like: * 1 -> NULL * / \ * 2 -> 3 -> NULL * / \ \ * 4-> 5 -> 7 -> NULL */ /** * Definition for binary tree with next pointer. * public class TreeLinkNode { * int val; * TreeLinkNode left, right, next; * TreeLinkNode(int x) { val = x; } * } */ public class PopulatingNextRightPointersInEachNodeII117 { public void connect(TreeLinkNode root) { if (root == null) return; LinkedList level = new LinkedList<>(); level.add(root); connect(level); } private void connect(LinkedList level) { LinkedList newLevel = new LinkedList<>(); if (level.isEmpty()) return; while (!level.isEmpty()) { TreeLinkNode n = level.remove(); if (n == null) return; n.next = level.peek(); if (n.left != null) newLevel.add(n.left); if (n.right != null) newLevel.add(n.right); } connect(newLevel); } /** * https://leetcode.com/problems/populating-next-right-pointers-in-each-node-ii/discuss/37811/Simple-solution-using-constant-space/35836 */ public void connect2(TreeLinkNode root) { TreeLinkNode tempChild = new TreeLinkNode(0); while (root != null) { TreeLinkNode currentChild = tempChild; while (root != null) { if (root.left != null) { currentChild.next = root.left; currentChild = currentChild.next; } if (root.right != null) { currentChild.next = root.right; currentChild = currentChild.next; } root = root.next; } root = tempChild.next; tempChild.next = null; } } public void connect3(TreeLinkNode root) { if (root == null) return; Queue q = new LinkedList<>(); q.add(root); while (!q.isEmpty()) { int size = q.size(); TreeLinkNode pre = q.remove(); if (pre.left != null) q.add(pre.left); if (pre.right != null) q.add(pre.right); TreeLinkNode curr = null; for (int i=1; i[] nonGraph = new Set[N+1]; for (int[] d: dislikes) { if (nonGraph[d[0]] == null) { nonGraph[d[0]] = new HashSet<>(); } if (nonGraph[d[1]] == null) { nonGraph[d[1]] = new HashSet<>(); } nonGraph[d[0]].add(d[1]); nonGraph[d[1]].add(d[0]); } int[] visited = new int[N+1]; for (int i=1; i<=N; i++) { if (visited[i] == 0) { if (!helper(i, nonGraph, N, visited, 1)) return false; } } return true; } private boolean helper(int curr, Set[] nonGraph, int N, int[] visited, int pre) { if (visited[curr] != 0) return visited[curr] == pre; visited[curr] = pre; if (nonGraph[curr] == null) return true; for (int next: nonGraph[curr]) { if (visited[next] == pre) return false; if (visited[next] == 0) { if (!helper(next, nonGraph, N, visited, -pre)) return false; } } return true; } /** * https://leetcode.com/problems/possible-bipartition/discuss/159085/java-graph */ public boolean possibleBipartition2(int N, int[][] dislikes) { Set[] nonGraph = new Set[N+1]; for (int[] d: dislikes) { if (nonGraph[d[0]] == null) { nonGraph[d[0]] = new HashSet<>(); } if (nonGraph[d[1]] == null) { nonGraph[d[1]] = new HashSet<>(); } nonGraph[d[0]].add(d[1]); nonGraph[d[1]].add(d[0]); } int[] visited = new int[N+1]; for (int i=1; i<=N; i++) { if (visited[i] == 0) { visited[i] = 1; Queue q = new LinkedList<>(); q.add(i); while (!q.isEmpty()) { int curr = q.poll(); if (nonGraph[curr] == null) continue; for (int next: nonGraph[curr]) { if (visited[next] == 0) { visited[next] = -visited[curr]; q.add(next); } else { if (visited[next] == visited[curr]) return false; } } } } } return true; } } ================================================ FILE: src/PowXN50.java ================================================ /** * Implement pow(x, n), which calculates x raised to the power n (xn). * * Example 1: * Input: 2.00000, 10 * Output: 1024.00000 * * Example 2: * Input: 2.10000, 3 * Output: 9.26100 * * Example 3: * Input: 2.00000, -2 * Output: 0.25000 * Explanation: 2-2 = 1/22 = 1/4 = 0.25 * * Note: * -100.0 < x < 100.0 * n is a 32-bit signed integer, within the range [−231, 231 − 1] */ public class PowXN50 { /** * https://leetcode.com/problems/powx-n/solution/ */ public double myPow(double x, int n) { long N = n; if (N < 0) { x = 1 / x; N = -N; } return fastPow(x, N); } private double fastPow(double x, long n) { if (n == 0) { return 1.0; } double half = fastPow(x, n / 2); if (n % 2 == 0) { return half * half; } else { return half * half * x; } } /** * https://leetcode.com/problems/powx-n/solution/ */ public double myPow2(double x, int n) { long N = n; if (N < 0) { x = 1 / x; N = -N; } double ans = 1; double current_product = x; for (long i = N; i > 0; i /= 2) { if ((i % 2) == 1) { ans = ans * current_product; } current_product = current_product * current_product; } return ans; } } ================================================ FILE: src/PowerOfTwo231.java ================================================ /** * Given an integer, write a function to determine if it is a power of two. * * Example 1: * Input: 1 * Output: true * Explanation: 2^0 = 1 * * Example 2: * Input: 16 * Output: true * Explanation: 2^4 = 16 * * Example 3: * Input: 218 * Output: false */ public class PowerOfTwo231 { public boolean isPowerOfTwo(int n) { if (n <= 0) return false; while (n > 1) { if (n % 2 != 0) return false; n /= 2; } return true; } /** * https://leetcode.com/problems/power-of-two/discuss/63974/Using-nand(n-1)-trick */ public boolean isPowerOfTwo2(int n) { if (n<=0) return false; return (n & (n-1)) == 0; } } ================================================ FILE: src/PredictTheWinner486.java ================================================ /** * Given an array of scores that are non-negative integers. Player 1 picks one * of the numbers from either end of the array followed by the player 2 and * then player 1 and so on. Each time a player picks a number, that number will * not be available for the next player. This continues until all the scores * have been chosen. The player with the maximum score wins. * * Given an array of scores, predict whether player 1 is the winner. You can * assume each player plays to maximize his score. * * Example 1: * Input: [1, 5, 2] * Output: False * Explanation: Initially, player 1 can choose between 1 and 2. * If he chooses 2 (or 1), then player 2 can choose from 1 (or 2) and 5. If * player 2 chooses 5, then player 1 will be left with 1 (or 2). * So, final score of player 1 is 1 + 2 = 3, and player 2 is 5. * Hence, player 1 will never be the winner and you need to return False. * * Example 2: * Input: [1, 5, 233, 7] * Output: True * Explanation: Player 1 first chooses 1. Then player 2 have to choose between * 5 and 7. No matter which number player 2 choose, player 1 can choose 233. * Finally, player 1 has more score (234) than player 2 (12), so you need to * return True representing player1 can win. * * Note: * 1 <= length of the array <= 20. * Any scores in the given array are non-negative integers and will not exceed * 10,000,000. * If the scores of both players are equal, then player 1 is still the winner. */ public class PredictTheWinner486 { public boolean PredictTheWinner(int[] nums) { if (nums.length <= 1) return true; int sum = 0; for (int n: nums) sum += n; int player1 = helper(nums, 0, 0, nums.length - 1, true); return player1 >= (sum - player1); } private int helper(int[] nums, int p1, int left, int right, boolean turn1) { if (left == right) return p1 + (turn1 ? nums[left] : 0); if (turn1) { p1 += nums[left]; int a = helper(nums, p1, left+1, right, false); p1 -= nums[left]; p1 += nums[right]; int b = helper(nums, p1, left, right-1, false); p1 -= nums[right]; return Math.max(a, b); } else { int a = helper(nums, p1, left+1, right, true); int b = helper(nums, p1, left, right-1, true); return Math.min(a, b); } } public boolean PredictTheWinner2(int[] nums) { if (nums.length <= 1) return true; int sum = 0; for (int n: nums) sum += n; int player1 = helper(nums, 0, nums.length - 1, true); return player1 >= (sum - player1); } private int helper(int[] nums, int left, int right, boolean turn1) { if (left == right) return turn1 ? nums[left] : 0; if (turn1) { int a = nums[left] + helper(nums, left+1, right, false); int b = nums[right] + helper(nums, left, right-1, false); return Math.max(a, b); } else { int a = helper(nums, left+1, right, true); int b = helper(nums, left, right-1, true); return Math.min(a, b); } } public boolean PredictTheWinner3(int[] nums) { if (nums.length <= 1) return true; int sum = 0; for (int n: nums) sum += n; int[][][] mem = new int[2][nums.length][nums.length]; int player1 = helper(nums, 0, nums.length - 1, true, mem); return player1 >= (sum - player1); } private int helper(int[] nums, int left, int right, boolean turn1, int[][][] mem) { if (left == right) return turn1 ? nums[left] : 0; if (turn1) { if (mem[0][left][right] > 0) return mem[0][left][right]; int a = nums[left] + helper(nums, left+1, right, false, mem); int b = nums[right] + helper(nums, left, right-1, false, mem); mem[0][left][right] = Math.max(a, b); return Math.max(a, b); } else { if (mem[1][left][right] > 0) return mem[1][left][right]; int a = helper(nums, left+1, right, true, mem); int b = helper(nums, left, right-1, true, mem); mem[1][left][right] = Math.min(a, b); return Math.min(a, b); } } /** * https://leetcode.com/problems/predict-the-winner/solution/ */ public boolean PredictTheWinner4(int[] nums) { Integer[][] memo = new Integer[nums.length][nums.length]; return winner(nums, 0, nums.length - 1, memo) >= 0; } public int winner(int[] nums, int s, int e, Integer[][] memo) { if (s == e) return nums[s]; if (memo[s][e] != null) return memo[s][e]; int a = nums[s] - winner(nums, s + 1, e, memo); int b = nums[e] - winner(nums, s, e - 1, memo); memo[s][e] = Math.max(a, b); return memo[s][e]; } /** * https://leetcode.com/problems/predict-the-winner/solution/ */ public boolean PredictTheWinner5(int[] nums) { int[][] dp = new int[nums.length + 1][nums.length]; for (int s = nums.length; s >= 0; s--) { for (int e = s + 1; e < nums.length; e++) { int a = nums[s] - dp[s + 1][e]; int b = nums[e] - dp[s][e - 1]; dp[s][e] = Math.max(a, b); } } return dp[0][nums.length - 1] >= 0; } /** * https://leetcode.com/problems/predict-the-winner/solution/ */ public boolean PredictTheWinner6(int[] nums) { int[] dp = new int[nums.length]; for (int s = nums.length; s >= 0; s--) { for (int e = s + 1; e < nums.length; e++) { int a = nums[s] - dp[e]; int b = nums[e] - dp[e - 1]; dp[e] = Math.max(a, b); } } return dp[nums.length - 1] >= 0; } } ================================================ FILE: src/ProductOfArrayExceptSelf238.java ================================================ /** * Given an array nums of n integers where n > 1, return an array output such * that output[i] is equal to the product of all the elements of nums except * nums[i]. * * Example: * Input: [1,2,3,4] * Output: [24,12,8,6] * * Note: Please solve it without division and in O(n). * * Follow up: * Could you solve it with constant space complexity? (The output array does * not count as extra space for the purpose of space complexity analysis.) */ public class ProductOfArrayExceptSelf238 { public int[] productExceptSelf(int[] nums) { if (nums == null || nums.length == 0) return new int[0]; int[] L = new int[nums.length]; int[] R = new int[nums.length]; L[0] = 1; for (int i=1; i=0; i--) R[i] = R[i+1] * nums[i+1]; int[] res = new int[nums.length]; for (int i=0; i=0; i--) { res[i] = res[i] * sum; sum = sum * nums[i]; } return res; } } ================================================ FILE: src/ProfitableSchemes879.java ================================================ /** * There are G people in a gang, and a list of various crimes they could commit. * * The i-th crime generates a profit[i] and requires group[i] gang members to * participate. * * If a gang member participates in one crime, that member can't participate in * another crime. * * Let's call a profitable scheme any subset of these crimes that generates at * least P profit, and the total number of gang members participating in that * subset of crimes is at most G. * * How many schemes can be chosen? Since the answer may be very large, return * ∂it modulo 10^9 + 7. * * Example 1: * Input: G = 5, P = 3, group = [2,2], profit = [2,3] * Output: 2 * Explanation: * To make a profit of at least 3, the gang could either commit crimes 0 and 1, * or just crime 1. * In total, there are 2 schemes. * * Example 2: * Input: G = 10, P = 5, group = [2,3,5], profit = [6,7,8] * Output: 7 * Explanation: * To make a profit of at least 5, the gang could commit any crimes, as long * as they commit one. * * There are 7 possible schemes: (0), (1), (2), (0,1), (0,2), (1,2), and (0,1,2). * * Note: * 1 <= G <= 100 * 0 <= P <= 100 * 1 <= group[i] <= 100 * 0 <= profit[i] <= 100 * 1 <= group.length = profit.length <= 100 */ public class ProfitableSchemes879 { public int profitableSchemes(int G, int P, int[] group, int[] profit) { int K = group.length; int[][][] dp = new int[K + 1][P + 1][G + 1]; dp[0][0][0] = 1; int mod = (int)1e9 + 7; for (int k=1; k<=K; k++) { int pk = profit[k-1]; int gk = group[k-1]; for (int i=0; i<=P; i++) { for (int j=0; j<=G; j++) { dp[k][i][j] = (dp[k-1][i][j] + (j < gk ? 0 : dp[k-1][Math.max(0, i-pk)][j - gk])) % mod; } } } int res = 0; for (int a: dp[K][P]) { res = (res + a) % mod; } return res; } public int profitableSchemes2(int G, int P, int[] group, int[] profit) { int K = group.length; int[][] dp = new int[P + 1][G + 1]; dp[0][0] = 1; int mod = (int)1e9 + 7; for (int k=1; k<=K; k++) { int pk = profit[k-1]; int gk = group[k-1]; int[][] tmp = new int[P + 1][G + 1]; for (int i=0; i<=P; i++) { for (int j=0; j<=G; j++) { tmp[i][j] = dp[i][j]; } } for (int i=0; i<=P; i++) { for (int j=0; j<=G; j++) { dp[i][j] = (tmp[i][j] + (j < gk ? 0 : tmp[Math.max(0, i-pk)][j - gk])) % mod; } } } int res = 0; for (int a: dp[P]) { res = (res + a) % mod; } return res; } /** * https://leetcode.com/problems/profitable-schemes/solution/ */ public int profitableSchemes3(int G, int P, int[] group, int[] profit) { int MOD = 1_000_000_007; int N = group.length; long[][][] dp = new long[2][P+1][G+1]; dp[0][0][0] = 1; for (int i = 0; i < N; ++i) { int p0 = profit[i]; // the current crime profit int g0 = group[i]; // the current crime group size long[][] cur = dp[i % 2]; long[][] cur2 = dp[(i + 1) % 2]; // Deep copy cur into cur2 for (int jp = 0; jp <= P; ++jp) for (int jg = 0; jg <= G; ++jg) cur2[jp][jg] = cur[jp][jg]; for (int p1 = 0; p1 <= P; ++p1) { // p1 : the current profit // p2 : the new profit after committing this crime int p2 = Math.min(p1 + p0, P); for (int g1 = 0; g1 <= G - g0; ++g1) { // g1 : the current group size // g2 : the new group size after committing this crime int g2 = g1 + g0; cur2[p2][g2] += cur[p1][g1]; cur2[p2][g2] %= MOD; } } } // Sum all schemes with profit P and group size 0 <= g <= G. long ans = 0; for (long x: dp[N%2][P]) ans += x; return (int) (ans % MOD); } /** * https://leetcode.com/problems/profitable-schemes/discuss/154617/C++JavaPython-DP */ public int profitableSchemes4(int G, int P, int[] group, int[] profit) { int[][] dp = new int[P + 1][G + 1]; dp[0][0] = 1; int res = 0, mod = (int)1e9 + 7; for (int k = 0; k < group.length; k++) { int g = group[k], p = profit[k]; for (int i = P; i >= 0; i--) for (int j = G - g; j >= 0; j--) dp[Math.min(i + p, P)][j + g] = (dp[Math.min(i + p, P)][j + g] + dp[i][j]) % mod; } for (int x : dp[P]) res = (res + x) % mod; return res; } /** * https://www.youtube.com/watch?v=MjOIR61txFc */ public int profitableSchemes5(int G, int P, int[] group, int[] profit) { int K = group.length; int[][] dp = new int[P + 1][G + 1]; dp[0][0] = 1; int mod = (int)1e9 + 7; for (int k=1; k<=K; k++) { int pk = profit[k-1]; int gk = group[k-1]; for (int i=P; i>=0; i--) { int ip = Math.min(P, i + pk); for (int j=G-gk; j>=0; j--) { dp[ip][j+gk] = (dp[ip][j+gk] + dp[i][j]) % mod; } } } int res = 0; for (int a: dp[P]) { res = (res + a) % mod; } return res; } } ================================================ FILE: src/ProjectionAreaOf3DShapes887.java ================================================ /** * On a N * N grid, we place some 1 * 1 * 1 cubes that are axis-aligned with the x, y, and z axes. * * Each value v = grid[i][j] represents a tower of v cubes placed on top of grid cell (i, j). * * Now we view the projection of these cubes onto the xy, yz, and zx planes. * * A projection is like a shadow, that maps our 3 dimensional figure to a 2 dimensional plane. * * Here, we are viewing the "shadow" when looking at the cubes from the top, the front, and the side. * * Return the total area of all three projections. * * Example 1: * Input: [[2]] * Output: 5 * * Example 2: * Input: [[1,2],[3,4]] * Output: 17 * Explanation: * Here are the three projections ("shadows") of the shape made with each axis-aligned plane. * https://s3-lc-upload.s3.amazonaws.com/uploads/2018/08/02/shadow.png * * Example 3: * Input: [[1,0],[0,2]] * Output: 8 * * Example 4: * Input: [[1,1,1],[1,0,1],[1,1,1]] * Output: 14 * * Example 5: * Input: [[2,2,2],[2,1,2],[2,2,2]] * Output: 21 * * Note: * 1 <= grid.length = grid[0].length <= 50 * 0 <= grid[i][j] <= 50 */ public class ProjectionAreaOf3DShapes887 { public int projectionArea(int[][] grid) { int M = grid.length; int N = grid[0].length; int top = 0; int side = 0; int[] maxFront = new int[N]; for (int i=0; i 0) top++; if (now > rowMax) rowMax = now; if (now > maxFront[j]) maxFront[j] = now; } side += rowMax; } int front = 0; for (int col: maxFront) { front += col; } return top + front + side; } } ================================================ FILE: src/QuadTreeIntersection558.java ================================================ /** * A quadtree is a tree data in which each internal node has exactly four * children: topLeft, topRight, bottomLeft and bottomRight. Quad trees are * often used to partition a two-dimensional space by recursively subdividing * it into four quadrants or regions. * * We want to store True/False information in our quad tree. The quad tree is * used to represent a N * N boolean grid. For each node, it will be * subdivided into four children nodes until the values in the region it * represents are all the same. Each node has another two boolean attributes: * isLeaf and val. isLeaf is true if and only if the node is a leaf node. * The val attribute for a leaf node contains the value of the region it * represents. * * For example, below are two quad trees A and B: * * A: * +-------+-------+ T: true * | | | F: false * | T | T | * | | | * +-------+-------+ * | | | * | F | F | * | | | * +-------+-------+ * topLeft: T * topRight: T * bottomLeft: F * bottomRight: F * * B: * +-------+---+---+ * | | F | F | * | T +---+---+ * | | T | T | * +-------+---+---+ * | | | * | T | F | * | | | * +-------+-------+ * topLeft: T * topRight: * topLeft: F * topRight: F * bottomLeft: T * bottomRight: T * bottomLeft: T * bottomRight: F * * Your task is to implement a function that will take two quadtrees and return * a quadtree that represents the logical OR (or union) of the two trees. * * A: B: C (A or B): * +-------+-------+ +-------+---+---+ +-------+-------+ * | | | | | F | F | | | | * | T | T | | T +---+---+ | T | T | * | | | | | T | T | | | | * +-------+-------+ +-------+---+---+ +-------+-------+ * | | | | | | | | | * | F | F | | T | F | | T | F | * | | | | | | | | | * +-------+-------+ +-------+-------+ +-------+-------+ * * Note: * Both A and B represent grids of size N * N. * N is guaranteed to be a power of 2. * If you want to know more about the quad tree, you can refer to its wiki. * The logic OR operation is defined as this: "A or B" is true if A is true, or * if B is true, or if both A and B are true. */ /* // Definition for a QuadTree node. class Node { public boolean val; public boolean isLeaf; public Node topLeft; public Node topRight; public Node bottomLeft; public Node bottomRight; public Node() {} public Node(boolean _val,boolean _isLeaf,Node _topLeft,Node _topRight,Node _bottomLeft,Node _bottomRight) { val = _val; isLeaf = _isLeaf; topLeft = _topLeft; topRight = _topRight; bottomLeft = _bottomLeft; bottomRight = _bottomRight; } }; */ public class QuadTreeIntersection558 { public Node intersect(Node quadTree1, Node quadTree2) { if (quadTree1 == null || quadTree2 == null) { return null; } Node res = new Node(); if (quadTree1.isLeaf && quadTree2.isLeaf) { res.isLeaf = true; res.val = quadTree1.val || quadTree2.val; return res; } res.topLeft = intersect(getTopLeft(quadTree1), getTopLeft(quadTree2)); res.topRight = intersect(getTopRight(quadTree1), getTopRight(quadTree2)); res.bottomLeft = intersect(getBottomLeft(quadTree1), getBottomLeft(quadTree2)); res.bottomRight = intersect(getBottomRight(quadTree1), getBottomRight(quadTree2)); if (allLeaves(res) && allSame(res)) { res.isLeaf = true; res.val = res.topLeft.val; return res; } return res; } private Node getTopLeft(Node n) { return n.isLeaf ? n : n.topLeft; } private Node getTopRight(Node n) { return n.isLeaf ? n : n.topRight; } private Node getBottomLeft(Node n) { return n.isLeaf ? n : n.bottomLeft; } private Node getBottomRight(Node n) { return n.isLeaf ? n : n.bottomRight; } private boolean allLeaves(Node n) { return n.topLeft.isLeaf && n.topRight.isLeaf && n.bottomLeft.isLeaf && n.bottomRight.isLeaf; } private boolean allSame(Node n) { return (n.topLeft.val == n.topRight.val) && (n.bottomLeft.val && n.bottomRight.val) && (n.topLeft.val && n.bottomLeft.val); } public Node intersect2(Node q1, Node q2) { if (q1.isLeaf) return q1.val ? q1 : q2; if (q2.isLeaf) return q2.val ? q2 : q1; q1.topLeft = intersect(q1.topLeft, q2.topLeft); q1.topRight = intersect(q1.topRight, q2.topRight); q1.bottomLeft = intersect(q1.bottomLeft, q2.bottomLeft); q1.bottomRight = intersect(q1.bottomRight, q2.bottomRight); if (allLeaves(q1) && allSame(q1)) { q1.isLeaf = true; q1.val = q1.topLeft.val; } return q1; } } ================================================ FILE: src/QueueReconstructionByHeight406.java ================================================ /** * Suppose you have a random list of people standing in a queue. Each person * is described by a pair of integers (h, k), where h is the height of the * person and k is the number of people in front of this person who have a * height greater than or equal to h. Write an algorithm to reconstruct the * queue. * * Note: * The number of people is less than 1,100. * * * Example * * Input: * [[7,0], [4,4], [7,1], [5,0], [6,1], [5,2]] * * Output: * [[5,0], [7,0], [5,2], [6,1], [4,4], [7,1]] * */ public class QueueReconstructionByHeight406 { public int[][] reconstructQueue(int[][] people) { int y = people.length; if (y == 0) return people; Arrays.sort(people, new SortRule()); LinkedList res = new LinkedList<>(); for(int[] p: people){ res.add(p[1], p); } return res.toArray(new int[people.length][]); } class SortRule implements Comparator { @Override public int compare(int[] a, int[] b) { int diff = a[0] - b[0]; if (diff < 0) return 1; else if (diff > 0) return -1; else return a[1] - b[1]; } } } ================================================ FILE: src/RandomFlipMatrix519.java ================================================ /** * You are given the number of rows n_rows and number of columns n_cols of a * 2D binary matrix where all values are initially 0. Write a function flip * which chooses a 0 value uniformly at random, changes it to 1, and then * returns the position [row.id, col.id] of that value. Also, write a function * reset which sets all values back to 0. Try to minimize the number of calls * to system's Math.random() and optimize the time and space complexity. * * Note: * 1 <= n_rows, n_cols <= 10000 * 0 <= row.id < n_rows and 0 <= col.id < n_cols * flip will not be called when the matrix has no 0 values left. * the total number of calls to flip and reset will not exceed 1000. * * Example 1: * Input: * ["Solution","flip","flip","flip","flip"] * [[2,3],[],[],[],[]] * Output: [null,[0,1],[1,2],[1,0],[1,1]] * * Example 2: * Input: * ["Solution","flip","flip","reset","flip"] * [[1,2],[],[],[],[]] * Output: [null,[0,0],[0,1],null,[0,0]] * Explanation of Input Syntax: * The input is two lists: the subroutines called and their arguments. * Solution's constructor has two arguments, n_rows and n_cols. flip and * reset have no arguments. Arguments are always wrapped with a list, even * if there aren't any. */ public class RandomFlipMatrix519 { /** * https://leetcode.com/problems/random-flip-matrix/discuss/154053/Java-AC-Solution-call-Least-times-of-Random.nextInt()-function */ class Solution { private Map map = new HashMap<>(); private int size; private int N; private int nCols; private Random rand = new Random(); public Solution(int n_rows, int n_cols) { this.N = n_rows * n_cols; this.nCols = n_cols; this.size = this.N; } public int[] flip() { int idx = rand.nextInt(this.size--); int val = map.getOrDefault(idx, idx); map.put(idx, map.getOrDefault(this.size, this.size)); return new int[]{val / this.nCols, val % this.nCols}; } public void reset() { map.clear(); this.size = this.N; } } class Solution2 { private int N; private int nCols; private Random rand = new Random(); private Set set = new HashSet<>(); public Solution(int n_rows, int n_cols) { this.N = n_rows * n_cols; this.nCols = n_cols; // this.size = this.N; } public int[] flip() { int val = rand.nextInt(this.N); while (set.contains(val)) { val = rand.nextInt(this.N); } set.add(val); return new int[]{val / this.nCols, val % this.nCols}; } public void reset() { this.set.clear(); } } /** * Your Solution object will be instantiated and called as such: * Solution obj = new Solution(n_rows, n_cols); * int[] param_1 = obj.flip(); * obj.reset(); */ } ================================================ FILE: src/RandomListNode.java ================================================ public class RandomListNode { int label; RandomListNode next, random; RandomListNode(int x) { this.label = x; } } ================================================ FILE: src/RandomPickIndex398.java ================================================ /** * Given an array of integers with possible duplicates, randomly output the * index of a given target number. You can assume that the given target number * must exist in the array. * * Note: * The array size can be very large. Solution that uses too much extra space * will not pass the judge. * * Example: * * int[] nums = new int[] {1,2,3,3,3}; * Solution solution = new Solution(nums); * * // pick(3) should return either index 2, 3, or 4 randomly. Each index * should have equal probability of returning. * solution.pick(3); * * // pick(1) should return 0. Since in the array only nums[0] is equal to 1. * solution.pick(1); */ public class RandomPickIndex398 { class Solution { private Map> map = new HashMap<>(); private Random rand = new Random(); public Solution(int[] nums) { for (int i=0; i()); } map.get(nums[i]).add(i); } } public int pick(int target) { int idx = rand.nextInt(map.get(target).size()); return map.get(target).get(idx); } } class Solution2 { private int[] nums; private Random random; public Solution2(int[] nums) { this.nums = nums; this.random = new Random(); } public int pick(int target) { int count = 0; int res = -1; for (int i = 0; i < nums.length; i++) { if (nums[i] == target) { count++; int rand = random.nextInt(count) + 1; if (rand == count) { res = i; } } } return res; } } /** * Your Solution object will be instantiated and called as such: * Solution obj = new Solution(nums); * int param_1 = obj.pick(target); */ } ================================================ FILE: src/RangeAddition370.java ================================================ /** * Assume you have an array of length n initialized with all 0's and are given * k update operations. * * Each operation is represented as a triplet: [startIndex, endIndex, inc] * which increments each element of subarray A[startIndex ... endIndex] * (startIndex and endIndex inclusive) with inc. * * Return the modified array after all k operations were executed. * * Example: * Input: length = 5, updates = [[1,3,2],[2,4,3],[0,2,-2]] * Output: [-2,0,3,5,3] * * Explanation: * * Initial state: * [0,0,0,0,0] * * After applying operation [1,3,2]: * [0,2,2,2,0] * * After applying operation [2,4,3]: * [0,2,5,5,3] * * After applying operation [0,2,-2]: * [-2,0,3,5,3] */ public class RangeAddition370 { // brute force public int[] getModifiedArray(int length, int[][] updates) { int[] res = new int[length]; for (int[] up: updates) { for (int i=up[0]; i<=up[1]; i++) { res[i] += up[2]; } } return res; } // brute force public int[] getModifiedArray2(int length, int[][] updates) { int[] res = new int[length]; for (int i=0; i= i) { res[i] += up[2]; } } } return res; } public int[] getModifiedArray3(int length, int[][] updates) { int[] res = new int[length]; int[] starts = new int[length]; int[] ends = new int[length]; for (int[] up: updates) { starts[up[0]] += up[2]; if (up[1]+1 < length) ends[up[1]+1] += up[2]; } int curr = 0; for (int i=0; i 0) { nums[update[0] - 1] -= update[2]; } } int sum = nums[length - 1]; for (int i = length - 2; i >= 0; i--) { nums[i] += sum; sum = nums[i]; } return nums; } } ================================================ FILE: src/RangeModule715.java ================================================ /** * A Range Module is a module that tracks ranges of numbers. Your task is to * design and implement the following interfaces in an efficient manner. * * - addRange(int left, int right) Adds the half-open interval [left, right), * tracking every real number in that interval. Adding an interval that * partially overlaps with currently tracked numbers should add any numbers in * the interval [left, right) that are not already tracked. * - queryRange(int left, int right) Returns true if and only if every real * number in the interval [left, right) is currently being tracked. * - removeRange(int left, int right) Stops tracking every real number * currently being tracked in the interval [left, right). * * Example 1: * addRange(10, 20): null * removeRange(14, 16): null * queryRange(10, 14): true (Every number in [10, 14) is being tracked) * queryRange(13, 15): false (Numbers like 14, 14.03, 14.17 in [13, 15) are * not being tracked) * queryRange(16, 17): true (The number 16 in [16, 17) is still being tracked, * despite the remove operation) * * Note: * A half open interval [left, right) denotes all real numbers left <= x < right. * 0 < left < right < 10^9 in all calls to addRange, queryRange, removeRange. * The total number of calls to addRange in a single test case is at most 1000. * The total number of calls to queryRange in a single test case is at most 5000. * The total number of calls to removeRange in a single test case is at most 1000. */ public class RangeModule715 { class RangeModule { private TreeMap ranges; public RangeModule() { ranges = new TreeMap<>(); } public void addRange(int left, int right) { Integer l = left; Integer r = right; Integer floor = ranges.floorKey(l); if (floor != null && l <= ranges.get(floor)) { if (r <= ranges.get(floor)) return; l = floor; r = Math.max(ranges.get(floor), r); ranges.remove(floor); } Integer higher = ranges.higherKey(l); while (higher != null && higher <= r) { r = Math.max(ranges.get(higher), r); ranges.remove(higher); higher = ranges.higherKey(l); } ranges.put(l, r); } public boolean queryRange(int left, int right) { Integer floor = ranges.floorKey(left); return floor != null && ranges.get(floor) >= right; } public void removeRange(int left, int right) { Integer l = left; Integer r = right; Map.Entry lower = ranges.lowerEntry(l); if (lower != null && l < lower.getValue()) { ranges.remove(lower.getKey()); ranges.put(lower.getKey(), l); if (lower.getValue() > r) { ranges.put(r, lower.getValue()); return; } else if (lower.getValue() == r) { return; } else { l = lower.getValue(); } } Map.Entry ceiling = ranges.ceilingEntry(l); while (ceiling != null && ceiling.getKey() <= r) { ranges.remove(ceiling.getKey()); if (ceiling.getValue() > r) { ranges.put(r, ceiling.getValue()); return; } ceiling = ranges.ceilingEntry(l); } } } class RangeModule2 { private TreeSet ranges = new TreeSet<>((r1, r2) -> Integer.compare(r1.left, r2.left)); public RangeModule() { } public void addRange(int left, int right) { Range newRange = new Range(left, right); Range floor = ranges.floor(newRange); if (floor != null && floor.right >= left) { if (floor.right >= right) return; newRange.left = floor.left; newRange.right = Math.max(floor.right, right); ranges.remove(floor); } while (true) { Range ceiling = ranges.ceiling(newRange); if (ceiling == null || ceiling.left > newRange.right) break; newRange.right = Math.max(ceiling.right, newRange.right); ranges.remove(ceiling); } ranges.add(newRange); } public boolean queryRange(int left, int right) { Range floor = ranges.floor(new Range(left, right)); if (floor == null) return false; return floor.right >= right; } public void removeRange(int left, int right) { Range toBeRemoved = new Range(left, right); Range floor = ranges.floor(toBeRemoved); if (floor != null && floor.right >= left) { int fRight = floor.right; floor.right = left; if (fRight == right) return; if (fRight > right) { Range add = new Range(right, fRight); ranges.add(add); return; } } while (true) { Range ceiling = ranges.ceiling(toBeRemoved); if (ceiling == null || ceiling.left >= toBeRemoved.right) break; ranges.remove(ceiling); if (ceiling.right > toBeRemoved.right) { ceiling.left = toBeRemoved.right; ranges.add(ceiling); break; } } } class Range { int left; int right; Range (int l, int r) { left = l; right = r; } } } /** * Your RangeModule object will be instantiated and called as such: * RangeModule obj = new RangeModule(); * obj.addRange(left,right); * boolean param_2 = obj.queryRange(left,right); * obj.removeRange(left,right); */ } ================================================ FILE: src/RangeSumQuery2DImmutable304.java ================================================ /** * Given a 2D matrix matrix, find the sum of the elements inside the rectangle * defined by its upper left corner (row1, col1) and lower right corner * (row2, col2). * * Range Sum Query 2D * https://leetcode.com/static/images/courses/range_sum_query_2d.png * * The above rectangle (with the red border) is defined by * (row1, col1) = (2, 1) and (row2, col2) = (4, 3), which contains sum = 8. * * Example: * Given matrix = [ * [3, 0, 1, 4, 2], * [5, 6, 3, 2, 1], * [1, 2, 0, 1, 5], * [4, 1, 0, 1, 7], * [1, 0, 3, 0, 5] * ] * * sumRegion(2, 1, 4, 3) -> 8 * sumRegion(1, 1, 2, 2) -> 11 * sumRegion(1, 2, 2, 4) -> 12 * * Note: * You may assume that the matrix does not change. * There are many calls to sumRegion function. * You may assume that row1 ≤ row2 and col1 ≤ col2. */ public class RangeSumQuery2DImmutable304 { class NumMatrix { private int[][] sum; public NumMatrix(int[][] matrix) { if (matrix.length == 0 || matrix[0].length == 0) return; int M = matrix.length; int N = matrix[0].length; sum = new int[M+1][N+1]; for (int i=1; i<=M; i++) { for (int j=1; j<=N; j++) { sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] + matrix[i-1][j-1]; } } } public int sumRegion(int row1, int col1, int row2, int col2) { if (sum == null) return 0; return sum[row2+1][col2+1] - sum[row2+1][col1] - sum[row1][col2+1] + sum[row1][col1]; } } class NumMatrix2 { private int[][] sums; private int M; private int N; public NumMatrix2(int[][] matrix) { if (matrix.length != 0 && matrix[0].length != 0) { this.M = matrix.length; this.N = matrix[N].length; this.sums = new int[M][N + 1]; for (int i=0; i 8 * update(3, 2, 2) * sumRegion(2, 1, 4, 3) -> 10 * * Note: * The matrix is only modifiable by the update function. * You may assume the number of calls to update and sumRegion function is * distributed evenly. * You may assume that row1 ≤ row2 and col1 ≤ col2. */ public class RangeSumQuery2DMutable308 { class NumMatrix { private Node root; public NumMatrix(int[][] matrix) { if (matrix != null && matrix.length != 0 && matrix[0].length != 0) { this.root = constructTree(matrix, 0, 0, matrix.length-1, matrix[0].length-1); } } private Node constructTree(int[][] matrix, int row1, int col1, int row2, int col2) { if (row1 > row2 || col1 > col2) return null; Node res = new Node(row1, col1, row2, col2, matrix[row1][col1]); if (row1 == row2 && col1 == col2) return res; int midRow = (row1 + row2) / 2; int midCol = (col1 + col2) / 2; Node tl = constructTree(matrix, row1, col1, midRow, midCol); Node tr = constructTree(matrix, row1, midCol+1, midRow, col2); Node bl = constructTree(matrix, midRow+1, col1, row2, midCol); Node br = constructTree(matrix, midRow+1, midCol+1, row2, col2); res.tl = tl; res.tr = tr; res.bl = bl; res.br = br; res.sum = (tl == null ? 0 : tl.sum) + (tr == null ? 0 : tr.sum) + (bl == null ? 0 : bl.sum) + (br == null ? 0 : br.sum); return res; } public void update(int row, int col, int val) { update(this.root, row, col, val); } private void update(Node root, int row, int col, int val) { if (root.row1 == root.row2 && root.row1 == row && root.col1 == root.col2 && root.col1 == col) { root.sum = val; return; } int rowMid = (root.row1 + root.row2) / 2; int colMid = (root.col1 + root.col2) / 2; Node next; if (row <= rowMid) { if (col <= colMid) { next = root.tl; } else { next = root.tr; } } else { if (col <= colMid) { next = root.bl; } else { next = root.br; } } root.sum -= next.sum; update(next, row, col, val); root.sum += next.sum; } public int sumRegion(int row1, int col1, int row2, int col2) { return sumRegion(this.root, row1, col1, row2, col2); } private int sumRegion(Node root, int row1, int col1, int row2, int col2) { if (root == null || root.row2 < row1 || root.row1 > row2 || root.col2 < col1 || root.col1 > col2) return 0; if (root.row1 >= row1 && root.row2 <= row2 && root.col1 >= col1 && root.col2 <= col2) return root.sum; return sumRegion(root.tl, row1, col1, row2, col2) + sumRegion(root.tr, row1, col1, row2, col2) + sumRegion(root.bl, row1, col1, row2, col2) + sumRegion(root.br, row1, col1, row2, col2); } class Node { Node tl; Node tr; Node bl; Node br; int sum; int row1; int col1; int row2; int col2; Node (int row1, int col1, int row2, int col2, int sum) { this.row1 = row1; this.col1 = col1; this.row2 = row2; this.col2 = col2; this.sum = sum; } } } /** * https://leetcode.com/problems/range-sum-query-2d-mutable/discuss/75870/Java-2D-Binary-Indexed-Tree-Solution-clean-and-short-17ms */ // time should be O(log(m) * log(n)) class NumMatrix2 { int[][] tree; int[][] nums; int m; int n; public NumMatrix2(int[][] matrix) { if (matrix.length == 0 || matrix[0].length == 0) return; m = matrix.length; n = matrix[0].length; tree = new int[m+1][n+1]; nums = new int[m][n]; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { update(i, j, matrix[i][j]); } } } public void update(int row, int col, int val) { if (m == 0 || n == 0) return; int delta = val - nums[row][col]; nums[row][col] = val; for (int i = row + 1; i <= m; i += i & (-i)) { for (int j = col + 1; j <= n; j += j & (-j)) { tree[i][j] += delta; } } } public int sumRegion(int row1, int col1, int row2, int col2) { if (m == 0 || n == 0) return 0; return sum(row2+1, col2+1) + sum(row1, col1) - sum(row1, col2+1) - sum(row2+1, col1); } public int sum(int row, int col) { int sum = 0; for (int i = row; i > 0; i -= i & (-i)) { for (int j = col; j > 0; j -= j & (-j)) { sum += tree[i][j]; } } return sum; } } class NumMatrix3 { private int[][] sum; private int[][] board; public NumMatrix3(int[][] matrix) { this.board = matrix; if (matrix.length != 0 && matrix[0].length != 0) { this.sum = new int[matrix.length][matrix[0].length + 1]; for (int i=0; i 1 * sumRange(2, 5) -> -1 * sumRange(0, 5) -> -3 * * Note: * You may assume that the array does not change. * There are many calls to sumRange function. */ public class RangeSumQueryImmutable303 { class NumArray { private int[] sum; public NumArray(int[] nums) { sum = new int[nums.length+1]; for (int i=1; i<=nums.length; i++) { sum[i] = sum[i-1] + nums[i-1]; } } public int sumRange(int i, int j) { return sum[j+1] - sum[i]; } } /** * Your NumArray object will be instantiated and called as such: * NumArray obj = new NumArray(nums); * int param_1 = obj.sumRange(i,j); */ } ================================================ FILE: src/RangeSumQueryMutable307.java ================================================ /** * Given an integer array nums, find the sum of the elements between indices i * and j (i ≤ j), inclusive. * * The update(i, val) function modifies nums by updating the element at * index i to val. * * Example: * Given nums = [1, 3, 5] * sumRange(0, 2) -> 9 * update(1, 2) * sumRange(0, 2) -> 8 * * Note: * * The array is only modifiable by the update function. * You may assume the number of calls to update and sumRange function is * distributed evenly. */ public class RangeSumQueryMutable307 { class NumArray { private int[] sum; private int[] nums; public NumArray(int[] nums) { this.nums = nums; sum = new int[nums.length+1]; for (int i=1; i<=nums.length; i++) { sum[i] = sum[i-1] + nums[i-1]; } } public void update(int i, int val) { int diff = val - nums[i]; for (int j=i+1; j r) return null; Node res = new Node(l, r, nums[l]); if (l == r) return res; int mid = (l + r) / 2; Node left = constructTree(nums, l, mid); Node right = constructTree(nums, mid+1, r); res.left = left; res.right = right; res.sum = left.sum + right.sum; return res; } public void update(int i, int val) { update(this.root, i, val); } public void update(Node root, int i, int val) { if (root.l == root.r && root.l == i) { root.sum = val; return; } int mid = (root.l + root.r) / 2; if (i <= mid) { update(root.left, i, val); } else { update(root.right, i, val); } root.sum = root.left.sum + root.right.sum; } public int sumRange(int i, int j) { return sumRange(this.root, i, j); } private int sumRange(Node root, int i, int j) { if (root.l == i && root.r == j) { return root.sum; } int mid = (root.l + root.r) / 2; if (mid < i) { return sumRange(root.right, i, j); } else if (mid >= j) { return sumRange(root.left, i, j); } else { return sumRange(root.left, i, mid) + sumRange(root.right, mid+1, j); } } class Node { Node left; Node right; int l; int r; int sum; Node(int l, int r, int s) { this.l = l; this.r = r; sum = s; } } } /** * https://leetcode.com/problems/range-sum-query-mutable/solution/ */ class NumArray3 { int[] tree; int n; public NumArray(int[] nums) { if (nums.length > 0) { n = nums.length; tree = new int[n * 2]; buildTree(nums); } } private void buildTree(int[] nums) { for (int i = n, j = 0; i < 2 * n; i++, j++) tree[i] = nums[j]; for (int i = n - 1; i > 0; --i) tree[i] = tree[i * 2] + tree[i * 2 + 1]; } public void update(int pos, int val) { pos += n; tree[pos] = val; while (pos > 0) { int left = pos; int right = pos; if (pos % 2 == 0) { right = pos + 1; } else { left = pos - 1; } // parent is updated after child is updated tree[pos / 2] = tree[left] + tree[right]; pos /= 2; } } public int sumRange(int l, int r) { // get leaf with value 'l' l += n; // get leaf with value 'r' r += n; int sum = 0; while (l <= r) { if ((l % 2) == 1) { sum += tree[l]; l++; } if ((r % 2) == 0) { sum += tree[r]; r--; } l /= 2; r /= 2; } return sum; } } class NumArray4 { private int[] tree; private int L; public NumArray(int[] nums) { tree = new int[nums.length * 3]; L = nums.length; constructTree(nums); } private void constructTree(int[] nums) { constructTree(nums, 0, nums.length-1, 0); } private void constructTree(int[] nums, int l, int r, int i) { if (l > r) return; if (l == r) { tree[i] = nums[l]; return; } int mid = (l + r) / 2; constructTree(nums, l, mid, left(i)); constructTree(nums, mid+1, r, right(i)); tree[i] = tree[left(i)] + tree[right(i)]; } public void update(int i, int val) { update(0, L-1, i, val, 0); } public void update(int l, int r, int i, int val, int n) { if (l == r && l == i) { tree[n] = val; return; } int mid = (l + r) / 2; if (i <= mid) { update(l, mid, i, val, left(n)); } else { update(mid + 1, r, i, val, right(n)); } tree[n] = tree[left(n)] + tree[right(n)]; } public int sumRange(int i, int j) { return sumRange(0, L-1, i, j, 0); } private int sumRange(int l, int r, int i, int j, int n) { if (l == i && r == j) { return tree[n]; } int mid = (l + r) / 2; if (mid < i) { return sumRange(mid+1, r, i, j, right(n)); } else if (mid >= j) { return sumRange(l, mid, i, j, left(n)); } else { return sumRange(l, mid, i, mid, left(n)) + sumRange(mid+1, r, mid+1, j, right(n)); } } private int left(int i) { return 2 * i + 1; } private int right(int i) { return 2 * i + 2; } } class NumArray5 { private int[] nums; private int[] tree; private int L; public NumArray(int[] nums) { this.nums = nums; this.L = nums.length; constructTree(nums); } private void constructTree(int[] nums) { this.tree = new int[nums.length + 1]; for (int i=0; i 0) { res += this.tree[idx]; idx -= idx & -idx; } return res; } } /** * Your NumArray object will be instantiated and called as such: * NumArray obj = new NumArray(nums); * obj.update(i,val); * int param_2 = obj.sumRange(i,j); */ } ================================================ FILE: src/RansomNote383.java ================================================ /** * Given an arbitrary ransom note string and another string containing letters * from all the magazines, write a function that will return true if the ransom * note can be constructed from the magazines ; otherwise, it will return false. * * Each letter in the magazine string can only be used once in your ransom note. * * Note: * You may assume that both strings contain only lowercase letters. * * canConstruct("a", "b") -> false * canConstruct("aa", "ab") -> false * canConstruct("aa", "aab") -> true */ public class RansomNote383 { public boolean canConstruct(String ransomNote, String magazine) { Map dict = new HashMap<>(); for (char c: magazine.toCharArray()) dict.put(c, dict.getOrDefault(c, 0) + 1); for (char c: ransomNote.toCharArray()) { int count = dict.getOrDefault(c, 0); if (count <= 0) return false; dict.put(c, count-1); } return true; } public boolean canConstruct2(String ransomNote, String magazine) { int[] dict = new int[26]; for (char c: magazine.toCharArray()) dict[c-'a']++; for (char c: ransomNote.toCharArray()) { dict[c-'a']--; if (dict[c-'a'] < 0) return false; } return true; } } ================================================ FILE: src/ReadNCharactersGivenRead4IICallMultipleTimes158.java ================================================ /** * The API: int read4(char *buf) reads 4 characters at a time from a file. * * The return value is the actual number of characters read. For example, it * returns 3 if there is only 3 characters left in the file. * * By using the read4 API, implement the function int read(char *buf, int n) * that reads n characters from the file. * * Note: * The read function may be called multiple times. * */ /* The read4 API is defined in the parent class Reader4. int read4(char[] buf); */ public class ReadNCharactersGivenRead4IICallMultipleTimes158 extends Reader4 { private int cacheSize = 0; private int ptr = 0; private int SIZE = 4; private char[] cache = new char[SIZE]; /** * @param buf Destination buffer * @param n Maximum number of characters to read * @return The number of characters read */ public int read(char[] buf, int n) { int count = 0; while (cacheSize > 0) { if (count >= n) { return count; } buf[count] = cache[ptr]; count++; cacheSize--; ptr = (ptr+1) % SIZE; } char[] buf4 = new char[4]; while (count < n) { int k = read4(buf4); if (k == 0) { cacheSize = 0; return count; } int add = Math.min(k, n - count); for (int i=0; i= buffCnt) buffPtr = 0; } return ptr; } /** * https://leetcode.com/problems/read-n-characters-given-read4-ii-call-multiple-times/discuss/49615/Clean-solution-in-Java */ char[] prevBuf = new char[4]; int prevSize = 0; int prevIndex = 0; public int read3(char[] buf, int n) { int counter = 0; while (counter < n) { if (prevIndex < prevSize) { buf[counter++] = prevBuf[prevIndex++]; } else { prevSize = read4(prevBuf); prevIndex = 0; if (prevSize == 0) { // no more data to consume from stream break; } } } return counter; } // private char[] cache = new char[4]; // private int ptr = 0; // private int len = 0; // /** // * @param buf Destination buffer // * @param n Maximum number of characters to read // * @return The number of characters read // */ // public int read(char[] buf, int n) { // int res = 0; // while (true) { // while (ptr < len && res < n) { // buf[res++] = cache[ptr++]; // } // if (res == n) break; // len = read4(cache); // ptr = 0; // if (len == 0) break; // } // return res; // } } ================================================ FILE: src/ReadNCharactersGivenReadFour157.java ================================================ /** * The API: int read4(char *buf) reads 4 characters at a time from a file. * * The return value is the actual number of characters read. For example, it * returns 3 if there is only 3 characters left in the file. * * By using the read4 API, implement the function int read(char *buf, int n) * that reads n characters from the file. * * Note: * The read function will only be called once for each test case. * */ /* The read4 API is defined in the parent class Reader4. int read4(char[] buf); */ public class ReadNCharactersGivenReadFour157 extends Reader4 { /** * @param buf Destination buffer * @param n Maximum number of characters to read * @return The number of characters read */ public int read(char[] buf, int n) { int count = 0; char[] buf4 = new char[4]; while (count < n) { int k = read4(buf4); if (k == 0) return count; int add = Math.min(k, n-count); for (int i=0; i map = new HashMap<>(); for (char ch: s.toCharArray()) { map.put(ch, map.getOrDefault(ch, 0) + 1); } Comparator> comp = (e1, e2) -> Integer.compare(e2.getValue(), e1.getValue()); PriorityQueue> pq = new PriorityQueue<>(1, comp); for (Map.Entry e: map.entrySet()) { pq.add(e); } StringBuilder sb = new StringBuilder(); Queue> cache = new LinkedList<>(); while (!pq.isEmpty()) { Map.Entry curr = pq.poll(); sb.append(curr.getKey()); curr.setValue(curr.getValue() - 1); cache.add(curr); // intial k-1 chars, cache not full yet if (cache.size() < k) continue; // release from cache if char is already k apart Map.Entry next = cache.poll(); //note that char with 0 count still needs to be placed in cache as a place holder if (next.getValue() > 0) { pq.add(next); } } return sb.length() == N ? sb.toString() : ""; } public String rearrangeString2(String s, int k) { if (k == 0) return s; int N = s.length(); int[] map = new int[26]; for (char ch: s.toCharArray()) { map[ch-'a']++; } Comparator comp = (c1, c2) -> Integer.compare(map[c2-'a'], map[c1-'a']); PriorityQueue pq = new PriorityQueue<>(1, comp); for (char c='a'; c<='z'; c++) { if (map[c-'a'] > 0) { pq.add(c); } } StringBuilder sb = new StringBuilder(); Queue cache = new LinkedList<>(); while (!pq.isEmpty()) { char curr = pq.poll(); sb.append(curr); map[curr-'a']--; cache.add(curr); if (cache.size() < k) continue; char next = cache.poll(); if (map[next-'a'] > 0) { pq.add(next); } } return sb.length() == N ? sb.toString() : ""; } /** * https://leetcode.com/problems/rearrange-string-k-distance-apart/discuss/83193/Java-15ms-Solution-with-Two-auxiliary-array.-O(N)-time. */ public String rearrangeString3(String str, int k) { int length = str.length(); int[] count = new int[26]; int[] nextIndex = new int[26]; char[] chars = str.toCharArray(); for (char ch: chars){ count[ch-'a']++; } StringBuilder sb = new StringBuilder(); for (int i=0; i max && index >= nextIndex[i]) { max = count[i]; idx = i; } } return idx; } /** * https://leetcode.com/problems/rearrange-string-k-distance-apart/discuss/83205/Java_solution_in_12_ms-O(N)-time-and-space */ public String rearrangeString4(String str, int k) { if (k < 2) return str; int[][] times = new int[26][2]; for(int i = 0; i < 26; i++) times[i][1] = 'a'+i; for (int i = 0; i < str.length(); i++) { times[str.charAt(i) - 'a'][0]++; } Comparator comp = (a, b) -> a[0] == b[0] ? Integer.compare(a[1], b[1]) : Integer.compare(b[0], a[0]); Arrays.sort(times, comp); int len = str.length(), maxlen = (len + k - 1)/k, count = 0, i = 0; if(times[0][0] > maxlen) return ""; char[] res = new char[len]; if((count = (len % k)) != 0){ for(i = 0; i < 26; i++){ if(times[i][0] < maxlen) break; if(i >= count) return ""; for(int j = i; j < len; j += k) res[j] = (char)times[i][1]; } } count = i; maxlen = i; for(int j = 25; j >= maxlen; j--){ for(int t = 0; t < times[j][0]; t++){ res[count] = (char)times[j][1]; count += k; if(count >= len) count = ++i; } } return new String(res); } } ================================================ FILE: src/ReconstructItinerary332.java ================================================ /** * Given a list of airline tickets represented by pairs of departure and * arrival airports [from, to], reconstruct the itinerary in order. All of the * tickets belong to a man who departs from JFK. Thus, the itinerary must * begin with JFK. * * Note: * If there are multiple valid itineraries, you should return the itinerary * that has the smallest lexical order when read as a single string. For * example, the itinerary ["JFK", "LGA"] has a smaller lexical order than * ["JFK", "LGB"]. * All airports are represented by three capital letters (IATA code). * You may assume all tickets form at least one valid itinerary. * * Example 1: * Input: [["MUC", "LHR"], ["JFK", "MUC"], ["SFO", "SJC"], ["LHR", "SFO"]] * Output: ["JFK", "MUC", "LHR", "SFO", "SJC"] * * Example 2: * Input: [["JFK","SFO"],["JFK","ATL"],["SFO","ATL"],["ATL","JFK"],["ATL","SFO"]] * Output: ["JFK","ATL","JFK","SFO","ATL","SFO"] * * Explanation: Another possible reconstruction is * ["JFK","SFO","ATL","JFK","ATL","SFO"]. * But it is larger in lexical order. */ public class ReconstructItinerary332 { public List findItinerary(String[][] tickets) { Map> graph = new HashMap<>(); for (String[] ticket: tickets) { if (!graph.containsKey(ticket[0])) { graph.put(ticket[0], new ArrayList<>()); } graph.get(ticket[0]).add(ticket[1]); } for (List nexts: graph.values()) { Collections.sort(nexts); } List res = new ArrayList<>(); res.add("JFK"); dfs(graph, tickets.length, "JFK", res, 0); return res; } private boolean dfs(Map> graph, int N, String start, List res, int level) { if (level == N) return true; List nexts = graph.get(start); if (nexts == null) return false; int size = nexts.size(); for (int i=0; i Integer.compare(a[0], b[0])); List active = new ArrayList(); int currY = events[0][0]; long ans = 0; for (int[] event: events) { int y = event[0], typ = event[1], x1 = event[2], x2 = event[3]; ans += mergeIntervals(active) * (y - currY); if (typ == OPEN) { active.add(new int[]{x1, x2}); } else { for (int i = 0; i < active.size(); ++i) { if (active.get(i)[0] == x1 && active.get(i)[1] == x2) { active.remove(i); break; } } } currY = y; } ans %= MOD; return (int) ans; } private long mergeIntervals(List active) { long query = 0; int cur = -1; Collections.sort(active, (a, b) -> Integer.compare(a[0], b[0])); for (int[] xs: active) { cur = Math.max(cur, xs[0]); query += Math.max(xs[1] - cur, 0); cur = Math.max(cur, xs[1]); } return query; } /** * https://leetcode.com/problems/rectangle-area-ii/solution/ */ public int rectangleArea2(int[][] rectangles) { int OPEN = 1, CLOSE = -1; int[][] events = new int[rectangles.length * 2][]; Set Xvals = new HashSet(); int t = 0; for (int[] rec: rectangles) { events[t++] = new int[]{rec[1], OPEN, rec[0], rec[2]}; events[t++] = new int[]{rec[3], CLOSE, rec[0], rec[2]}; Xvals.add(rec[0]); Xvals.add(rec[2]); } Arrays.sort(events, (a, b) -> Integer.compare(a[0], b[0])); Integer[] X = Xvals.toArray(new Integer[0]); Arrays.sort(X); Map Xi = new HashMap(); for (int i = 0; i < X.length; ++i) Xi.put(X[i], i); Node active = new Node(0, X.length - 1, X); long ans = 0; long cur_x_sum = 0; int cur_y = events[0][0]; for (int[] event: events) { int y = event[0], typ = event[1], x1 = event[2], x2 = event[3]; ans += cur_x_sum * (y - cur_y); cur_x_sum = active.update(Xi.get(x1), Xi.get(x2), typ); cur_y = y; } ans %= 1_000_000_007; return (int) ans; } class Node { int start, end; Integer[] X; Node left, right; int count; long total; public Node(int start, int end, Integer[] X) { this.start = start; this.end = end; this.X = X; left = null; right = null; count = 0; total = 0; } public int getRangeMid() { return start + (end - start) / 2; } public Node getLeft() { if (left == null) left = new Node(start, getRangeMid(), X); return left; } public Node getRight() { if (right == null) right = new Node(getRangeMid(), end, X); return right; } public long update(int i, int j, int val) { if (i >= j) return 0; if (start == i && end == j) { count += val; } else { getLeft().update(i, Math.min(getRangeMid(), j), val); getRight().update(Math.max(getRangeMid(), i), j, val); } if (count > 0) total = X[end] - X[start]; else total = getLeft().total + getRight().total; return total; } } } ================================================ FILE: src/RectangleOverlap863.java ================================================ /** * A rectangle is represented as a list [x1, y1, x2, y2], where (x1, y1) are * the coordinates of its bottom-left corner, and (x2, y2) are the coordinates * of its top-right corner. * * Two rectangles overlap if the area of their intersection is positive. To be * clear, two rectangles that only touch at the corner or edges do not overlap. * * Given two (axis-aligned) rectangles, return whether they overlap. * * Example 1: * Input: rec1 = [0,0,2,2], rec2 = [1,1,3,3] * Output: true * * Example 2: * Input: rec1 = [0,0,1,1], rec2 = [1,0,2,1] * Output: false * * Notes: * Both rectangles rec1 and rec2 are lists of 4 integers. * All coordinates in rectangles will be between -10^9 and 10^9. */ public class RectangleOverlap863 { public boolean isRectangleOverlap(int[] rec1, int[] rec2) { return isIntervalOverlap(rec1[0], rec1[2], rec2[0], rec2[2]) && isIntervalOverlap(rec1[1], rec1[3], rec2[1], rec2[3]); } private boolean isIntervalOverlap(int a1, int a2, int b1, int b2) { return !(a2 <= b1 || b2 <= a1); } public boolean isRectangleOverlap2(int[] rec1, int[] rec2) { return !(rec1[2] <= rec2[0] || // left rec1[3] <= rec2[1] || // bottom rec1[0] >= rec2[2] || // right rec1[1] >= rec2[3]); // top } } ================================================ FILE: src/RedundantConnection684.java ================================================ /** * In this problem, a tree is an undirected graph that is connected and has no cycles. * * The given input is a graph that started as a tree with N nodes (with distinct * values 1, 2, ..., N), with one additional edge added. The added edge has two * different vertices chosen from 1 to N, and was not an edge that already existed. * * The resulting graph is given as a 2D-array of edges. Each element of edges * is a pair [u, v] with u < v, that represents an undirected edge connecting * nodes u and v. * * Return an edge that can be removed so that the resulting graph is a tree of * N nodes. If there are multiple answers, return the answer that occurs last * in the given 2D-array. The answer edge [u, v] should be in the same format, * with u < v. * * Example 1: * Input: [[1,2], [1,3], [2,3]] * Output: [2,3] * Explanation: The given undirected graph will be like this: * 1 * / \ * 2 - 3 * * Example 2: * Input: [[1,2], [2,3], [3,4], [1,4], [1,5]] * Output: [1,4] * Explanation: The given undirected graph will be like this: * 5 - 1 - 2 * | | * 4 - 3 * * Note: * The size of the input 2D-array will be between 3 and 1000. * Every integer represented in the 2D-array will be between 1 and N, where N * is the size of the input array. * * Update (2017-09-26): * We have overhauled the problem description + test cases and specified clearly * the graph is an undirected graph. For the directed graph follow up please * see Redundant Connection II). We apologize for any inconvenience caused. * */ public class RedundantConnection684 { public int[] findRedundantConnection(int[][] edges) { Map> graph = new HashMap<>(); Set visited = new HashSet<>(); for (int[] edge: edges) { visited.clear(); Set set0 = graph.getOrDefault(edge[0], new HashSet()); Set set1 = graph.getOrDefault(edge[1], new HashSet()); if (!set0.isEmpty() && !set1.isEmpty() && dfs(graph, edge[0], edge[1], visited)) { return edge; } set0.add(edge[1]); graph.put(edge[0], set0); set1.add(edge[0]); graph.put(edge[1], set1); } return null; } private boolean dfs(Map> graph, int source, int target, Set visited) { if (!visited.contains(source)) { visited.add(source); if (source == target) return true; for (int nei: graph.get(source)) { if (dfs(graph, nei, target, visited)) return true; } } return false; } /** * https://leetcode.com/problems/redundant-connection/solution/ */ Set seen = new HashSet(); int MAX_EDGE_VAL = 1000; public int[] findRedundantConnection2(int[][] edges) { ArrayList[] graph = new ArrayList[MAX_EDGE_VAL + 1]; for (int i = 0; i <= MAX_EDGE_VAL; i++) { graph[i] = new ArrayList(); } for (int[] edge: edges) { seen.clear(); if (!graph[edge[0]].isEmpty() && !graph[edge[1]].isEmpty() && dfs(graph, edge[0], edge[1])) { return edge; } graph[edge[0]].add(edge[1]); graph[edge[1]].add(edge[0]); } throw new AssertionError(); } public boolean dfs(ArrayList[] graph, int source, int target) { if (!seen.contains(source)) { seen.add(source); if (source == target) return true; for (int nei: graph[source]) { if (dfs(graph, nei, target)) return true; } } return false; } /** * https://leetcode.com/problems/redundant-connection/solution/ */ public int[] findRedundantConnection3(int[][] edges) { DSU dsu = new DSU(MAX_EDGE_VAL + 1); for (int[] edge: edges) { if (!dsu.union(edge[0], edge[1])) return edge; } throw new AssertionError(); } /** * https://leetcode.com/problems/redundant-connection/discuss/107984/10-line-Java-solution-Union-Find */ public int[] findRedundantConnection4(int[][] edges) { int[] parent = new int[1001]; for (int i = 0; i < parent.length; i++) parent[i] = i; for (int[] edge: edges){ int f = edge[0], t = edge[1]; if (find(parent, f) == find(parent, t)) return edge; else parent[find(parent, f)] = find(parent, t); } return new int[2]; } private int find(int[] parent, int f) { if (f != parent[f]) { parent[f] = find(parent, parent[f]); } return parent[f]; } } class DSU { int[] parent; int[] rank; public DSU(int size) { parent = new int[size]; for (int i = 0; i < size; i++) parent[i] = i; rank = new int[size]; } public int find(int x) { if (parent[x] != x) parent[x] = find(parent[x]); return parent[x]; } public boolean union(int x, int y) { int xr = find(x), yr = find(y); if (xr == yr) { return false; } else if (rank[xr] < rank[yr]) { parent[xr] = yr; } else if (rank[xr] > rank[yr]) { parent[yr] = xr; } else { parent[yr] = xr; rank[xr]++; } return true; } } ================================================ FILE: src/RedundantConnectionII685.java ================================================ /** * In this problem, a rooted tree is a directed graph such that, there is * exactly one node (the root) for which all other nodes are descendants of * this node, plus every node has exactly one parent, except for the root * node which has no parents. * * The given input is a directed graph that started as a rooted tree with N * nodes (with distinct values 1, 2, ..., N), with one additional directed * edge added. The added edge has two different vertices chosen from 1 to N, * and was not an edge that already existed. * * The resulting graph is given as a 2D-array of edges. Each element of edges * is a pair [u, v] that represents a directed edge connecting nodes u and v, * where u is a parent of child v. * * Return an edge that can be removed so that the resulting graph is a rooted * tree of N nodes. If there are multiple answers, return the answer that * occurs last in the given 2D-array. * * Example 1: * Input: [[1,2], [1,3], [2,3]] * Output: [2,3] * Explanation: The given directed graph will be like this: * 1 * / \ * v v * 2-->3 * * Example 2: * Input: [[1,2], [2,3], [3,4], [4,1], [1,5]] * Output: [4,1] * Explanation: The given directed graph will be like this: * 5 <- 1 -> 2 * ^ | * | v * 4 <- 3 * * Note: * The size of the input 2D-array will be between 3 and 1000. * Every integer represented in the 2D-array will be between 1 and N, * where N is the size of the input array. */ public class RedundantConnectionII685 { public int[] findRedundantDirectedConnection(int[][] edges) { int N = edges.length; int[] res1 = null; int[] res2 = null; int[] parent = new int[N+1]; boolean twoParentsExist = false; for (int[] edge: edges) { int u = edge[0]; int v = edge[1]; if (parent[v] != 0) { res1 = new int[]{parent[v], v}; res2 = new int[]{u, v}; twoParentsExist = true; break; } parent[v] = u; } DisjointSet djs = new DisjointSet(N); for (int[] edge: edges) { int u = edge[0]; int v = edge[1]; if (twoParentsExist && ((u == res1[0] && v == res1[1]) || (u == res2[0] && v == res2[1]))) continue; int up = djs.find(u); int vp = djs.find(v); if (up == vp) { return edge; } else { djs.union(u, v); } } if (twoParentsExist && djs.find(res1[0]) == djs.find(res1[1])) { return res1; } return res2; } class DisjointSet { int[] parent; int[] rank; DisjointSet(int N) { parent = new int[N+1]; for (int i=0; i rank[yp]) { parent[yp] = xp; } else if (rank[xp] < rank[yp]) { parent[xp] = yp; } else { parent[xp] = yp; rank[yp]++; } } } /** * https://leetcode.com/problems/redundant-connection-ii/discuss/108045/C++Java-Union-Find-with-explanation-O(n) */ public int[] findRedundantDirectedConnection2(int[][] edges) { int[] can1 = {-1, -1}; int[] can2 = {-1, -1}; int[] parent = new int[edges.length + 1]; for (int i = 0; i < edges.length; i++) { if (parent[edges[i][1]] == 0) { parent[edges[i][1]] = edges[i][0]; } else { can2 = new int[] {edges[i][0], edges[i][1]}; can1 = new int[] {parent[edges[i][1]], edges[i][1]}; edges[i][1] = 0; } } for (int i = 0; i < edges.length; i++) { parent[i] = i; } for (int i = 0; i < edges.length; i++) { if (edges[i][1] == 0) { continue; } int child = edges[i][1], father = edges[i][0]; if (root(parent, father) == child) { if (can1[0] == -1) { return edges[i]; } return can1; } parent[child] = father; } return can2; } int root(int[] parent, int i) { while (i != parent[i]) { parent[i] = parent[parent[i]]; i = parent[i]; } return i; } } ================================================ FILE: src/RegularExpressionMatching10.java ================================================ /** * Implement regular expression matching with support for '.' and '*'. * * '.' Matches any single character. * '*' Matches zero or more of the preceding element. * * The matching should cover the entire input string (not partial). * * The function prototype should be: * bool isMatch(const char *s, const char *p) * * Some examples: * isMatch("aa","a") → false * isMatch("aa","aa") → true * isMatch("aaa","aa") → false * isMatch("aa", "a*") → true * isMatch("aa", ".*") → true * isMatch("ab", ".*") → true * isMatch("aab", "c*a*b") → true * */ public class RegularExpressionMatching10 { /** * https://leetcode.com/problems/regular-expression-matching/solution/ */ public boolean isMatch(String text, String pattern) { if (pattern.isEmpty()) return text.isEmpty(); boolean first_match = (!text.isEmpty() && (pattern.charAt(0) == text.charAt(0) || pattern.charAt(0) == '.')); if (pattern.length() >= 2 && pattern.charAt(1) == '*'){ return (isMatch(text, pattern.substring(2)) || (first_match && isMatch(text.substring(1), pattern))); } else { return first_match && isMatch(text.substring(1), pattern.substring(1)); } } public boolean isMatch2(String text, String pattern) { return isMatch(0, 0, text, pattern); } public boolean isMatch(int i, int j, String text, String pattern) { if (j == pattern.length()) return i == text.length(); boolean first_match = (i != text.length() && (pattern.charAt(j) == text.charAt(i) || pattern.charAt(j) == '.')); if (pattern.length() >= j+2 && pattern.charAt(j+1) == '*'){ return (isMatch(i, j+2, text, pattern) || (first_match && isMatch(i+1, j, text, pattern))); } else { return first_match && isMatch(i+1, j+1, text, pattern); } } public boolean isMatch3(String text, String pattern) { int textLen = text.length(); int pattLen = pattern.length(); boolean[][] dp = new boolean[textLen+1][pattLen+1]; dp[0][0] = true; for(int j=1; j<=pattLen; j++) { if (pattern.charAt(j-1) == '*'){ dp[0][j] = dp[0][j-2]; } } for (int i=1; i<=textLen; i++) { for(int j=1; j<=pattLen; j++) { if (j >= 2 && pattern.charAt(j-1) == '*') { boolean preMatch = (pattern.charAt(j-2) == text.charAt(i-1) || pattern.charAt(j-2) == '.'); dp[i][j] = dp[i][j-2] || (preMatch && dp[i-1][j]); } else { boolean currMatch = (pattern.charAt(j-1) == text.charAt(i-1) || pattern.charAt(j-1) == '.'); dp[i][j] = currMatch && dp[i-1][j-1]; } } } return dp[text.length()][pattern.length()]; } /** * https://leetcode.com/problems/regular-expression-matching/solution/ */ enum Result { TRUE, FALSE } Result[][] memo; public boolean isMatch4(String text, String pattern) { memo = new Result[text.length() + 1][pattern.length() + 1]; return dp(0, 0, text, pattern); } public boolean dp(int i, int j, String text, String pattern) { if (memo[i][j] != null) { return memo[i][j] == Result.TRUE; } boolean ans; if (j == pattern.length()){ ans = i == text.length(); } else{ boolean first_match = (i < text.length() && (pattern.charAt(j) == text.charAt(i) || pattern.charAt(j) == '.')); if (j + 1 < pattern.length() && pattern.charAt(j+1) == '*'){ ans = (dp(i, j+2, text, pattern) || first_match && dp(i+1, j, text, pattern)); } else { ans = first_match && dp(i+1, j+1, text, pattern); } } memo[i][j] = ans ? Result.TRUE : Result.FALSE; return ans; } public boolean isMatch5(String s, String p) { if (s == null || p == null) return false; boolean[][] dp = new boolean[s.length()+1][p.length()+1]; dp[0][0] = true; for (int j=1; j<=p.length(); j++) dp[0][j] = p.charAt(j-1) == '*' ? dp[0][j-2] : false; for (int i=1; i<=s.length(); i++) dp[i][0] = false; for (int i=1; i<=s.length(); i++) { for (int j=1; j<=p.length(); j++) { char c = p.charAt(j-1); switch (c) { case '.': dp[i][j] = dp[i-1][j-1]; break; case '*': dp[i][j] = dp[i][j-2] || ((p.charAt(j-2) == '.' || p.charAt(j-2) == s.charAt(i-1)) && dp[i-1][j]); break; default: dp[i][j] = s.charAt(i-1) == p.charAt(j-1) && dp[i-1][j-1]; } } } return dp[s.length()][p.length()]; } } ================================================ FILE: src/RemoveDuplicateLetters316.java ================================================ /** * Given a string which contains only lowercase letters, remove duplicate letters so that every * letter appear once and only once. You must make sure your result is the smallest in * lexicographical order among all possible results. * * Example: * Given "bcabc" * Return "abc" * * Given "cbacdcbc" * Return "acdb" */ public class RemoveDuplicateLetters316 { /** * https://leetcode.com/problems/remove-duplicate-letters/discuss/76766/Easy-to-understand-iterative-Java-solution */ public String removeDuplicateLetters(String s) { if (s == null || s.length() <= 1) return s; Map lastPosMap = new HashMap<>(); for (int i = 0; i < s.length(); i++) { lastPosMap.put(s.charAt(i), i); } char[] result = new char[lastPosMap.size()]; int begin = 0, end = findMinLastPos(lastPosMap); for (int i = 0; i < result.length; i++) { char minChar = 'z' + 1; for (int k = begin; k <= end; k++) { if (lastPosMap.containsKey(s.charAt(k)) && s.charAt(k) < minChar) { minChar = s.charAt(k); begin = k+1; } } result[i] = minChar; if (i == result.length-1) break; lastPosMap.remove(minChar); if (s.charAt(end) == minChar) end = findMinLastPos(lastPosMap); } return new String(result); } private int findMinLastPos(Map lastPosMap) { if (lastPosMap == null || lastPosMap.isEmpty()) return -1; int minLastPos = Integer.MAX_VALUE; for (int lastPos : lastPosMap.values()) { minLastPos = Math.min(minLastPos, lastPos); } return minLastPos; } /** * https://leetcode.com/problems/remove-duplicate-letters/discuss/76762/Java-O(n)-solution-using-stack-with-detail-explanation */ public String removeDuplicateLetters2(String s) { Stack stack = new Stack<>(); int[] count = new int[26]; char[] arr = s.toCharArray(); for(char c : arr) { count[c-'a']++; } boolean[] visited = new boolean[26]; for(char c : arr) { count[c-'a']--; if(visited[c-'a']) { continue; } while(!stack.isEmpty() && stack.peek() > c && count[stack.peek()-'a'] > 0) { visited[stack.peek()-'a'] = false; stack.pop(); } stack.push(c); visited[c-'a'] = true; } StringBuilder sb = new StringBuilder(); for(char c : stack) { sb.append(c); } return sb.toString(); } } ================================================ FILE: src/RemoveDuplicatesFromSortedArray26.java ================================================ /** * Given a sorted array, remove the duplicates in place such that each element * appear only once and return the new length. * * Do not allocate extra space for another array, you must do this in place with * constant memory. * * For example, * Given input array nums = [1,1,2], * * Your function should return length = 2, with the first two elements of nums * being 1 and 2 respectively. It doesn't matter what you leave beyond the new * length. * */ public class RemoveDuplicatesFromSortedArray26 { public int removeDuplicates(int[] nums) { if (nums.length <= 1) { return nums.length; } int slow = 0; int fast = 1; while (fast < nums.length) { if (nums[fast] != nums[slow]) { slow++; nums[slow] = nums[fast]; } fast++; } return slow+1; } /** * https://discuss.leetcode.com/topic/17252/5-lines-c-java-nicer-loops */ public int removeDuplicates2(int[] nums) { int i = nums.length > 0 ? 1 : 0; for (int n : nums) if (n > nums[i-1]) nums[i++] = n; return i; } public int removeDuplicates3(int[] nums) { if (nums == null || nums.length == 0) return 0; int len = nums.length; int i = 0; int j = 0; while (j < len) { while (j > 0 && j < len && nums[j] == nums[j-1]) j++; if (j == len) break; nums[i++] = nums[j++]; } return i; } } ================================================ FILE: src/RemoveDuplicatesFromSortedArrayII80.java ================================================ /** * Follow up for "Remove Duplicates": * What if duplicates are allowed at most twice? * * For example, * Given sorted array nums = [1,1,1,2,2,3], * * Your function should return length = 5, with the first five elements of nums * being 1, 1, 2, 2 and 3. It doesn't matter what you leave beyond the new length. * */ public class RemoveDuplicatesFromSortedArrayII80 { public int removeDuplicates(int[] nums) { int count = 1; int i = 0; for (int j=1; j nums[i - 2]) nums[i++] = n; return i; } // private int removeDuplicates(int[] nums, int k) { // int i = 0; // for (int n : nums) // if (i < k || n > nums[i-k]) // nums[i++] = n; // return i; // } } ================================================ FILE: src/RemoveDuplicatesFromSortedList83.java ================================================ /** * Given a sorted linked list, delete all duplicates such that each element * appear only once. * * Example 1: * Input: 1->1->2 * Output: 1->2 * * Example 2: * Input: 1->1->2->3->3 * Output: 1->2->3 */ /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ public class RemoveDuplicatesFromSortedList83 { public ListNode deleteDuplicates(ListNode head) { if (head == null || head.next == null) return head; ListNode fast = head.next; ListNode slow = head; slow.next = null; while (fast != null) { if (fast.val == slow.val) { fast = fast.next; } else { slow.next = fast; fast = fast.next; slow = slow.next; slow.next = null; } } return head; } /** * https://leetcode.com/problems/remove-duplicates-from-sorted-list/solution/ */ public ListNode deleteDuplicates2(ListNode head) { ListNode current = head; while (current != null && current.next != null) { if (current.next.val == current.val) { current.next = current.next.next; } else { current = current.next; } } return head; } /** * https://leetcode.com/problems/remove-duplicates-from-sorted-list/discuss/28625/3-Line-JAVA-recursive-solution */ public ListNode deleteDuplicates3(ListNode head) { if (head == null || head.next == null) return head; head.next = deleteDuplicates3(head.next); return head.val == head.next.val ? head.next : head; } } ================================================ FILE: src/RemoveDuplicatesFromSortedListII82.java ================================================ /** * Given a sorted linked list, delete all nodes that have duplicate numbers, * leaving only distinct numbers from the original list. * * For example, * Given 1->2->3->3->4->4->5, return 1->2->5. * Given 1->1->1->2->3, return 2->3. * */ /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ public class RemoveDuplicatesFromSortedListII82 { public ListNode deleteDuplicates(ListNode head) { ListNode dummy = new ListNode(0); dummy.next = head; ListNode p = dummy; boolean isDuplicate = false; int dup = 0; while (p.next != null && p.next.next != null) { if (isDuplicate) { do { p.next = p.next.next; } while (p.next != null && p.next.val == dup); isDuplicate = false; } else { if (p.next.val != p.next.next.val) { p = p.next; } else { isDuplicate = true; dup = p.next.val; } } } return dummy.next; } /** * https://discuss.leetcode.com/topic/3890/my-accepted-java-code */ public ListNode deleteDuplicates2(ListNode head) { if(head==null) return null; ListNode FakeHead=new ListNode(0); FakeHead.next=head; ListNode pre=FakeHead; ListNode cur=head; while(cur!=null){ while(cur.next!=null&&cur.val==cur.next.val){ cur=cur.next; } if(pre.next==cur){ pre=pre.next; } else{ pre.next=cur.next; } cur=cur.next; } return FakeHead.next; } /** * https://discuss.leetcode.com/topic/5206/my-recursive-java-solution */ public ListNode deleteDuplicates3(ListNode head) { if (head == null) return null; if (head.next != null && head.val == head.next.val) { while (head.next != null && head.val == head.next.val) { head = head.next; } return deleteDuplicates3(head.next); } else { head.next = deleteDuplicates3(head.next); } return head; } /** * https://discuss.leetcode.com/topic/24470/java-simple-and-clean-code-with-comment */ public ListNode deleteDuplicates4(ListNode head) { //use two pointers, slow - track the node before the dup nodes, // fast - to find the last node of dups. ListNode dummy = new ListNode(0), fast = head, slow = dummy; slow.next = fast; while(fast != null) { while (fast.next != null && fast.val == fast.next.val) { fast = fast.next; //while loop to find the last node of the dups. } if (slow.next != fast) { //duplicates detected. slow.next = fast.next; //remove the dups. fast = slow.next; //reposition the fast pointer. } else { //no dup, move down both pointer. slow = slow.next; fast = fast.next; } } return dummy.next; } } ================================================ FILE: src/RemoveInvalidParentheses301.java ================================================ /** * Remove the minimum number of invalid parentheses in order to make the input * string valid. Return all possible results. * * Note: The input string may contain letters other than the parentheses ( and ). * * Examples: * "()())()" -> ["()()()", "(())()"] * "(a)())()" -> ["(a)()()", "(a())()"] * ")(" -> [""] */ /** * A review of all solutions (BFS and DFS) * https://leetcode.com/problems/remove-invalid-parentheses/discuss/75038/Evolve-from-intuitive-solution-to-optimal-a-review-of-all-solutions * * There are three challenges: * - Remove minimum parenthesis * - The result is valid * - Without duplicates. * */ public class RemoveInvalidParentheses301 { public List removeInvalidParentheses(String s) { Set results = new HashSet<>(); int L = s.length(); if (L == 0) return Arrays.asList(""); Stack st = new Stack<>(); StringBuilder sb = new StringBuilder(""); int maxLength = helper(s, 0, st, sb, L, results); return setToList(results, maxLength); } private int helper(String s, int level, Stack st, StringBuilder sb, int L, Set results) { int maxLength = 0; if (level == L) { if (st.size() == 0) { maxLength = Math.max(maxLength, sb.length()); results.add(sb.toString()); } return maxLength; } char c = s.charAt(level); int localMax = 0; if (c >= 'a' && c <= 'z') { sb.append(c); localMax = helper(s, level+1, st, sb, L, results); maxLength = Math.max(maxLength, localMax); sb.deleteCharAt(sb.length()-1); } else if (c == '(') { st.push('('); sb.append('('); localMax = helper(s, level+1, st, sb, L, results); maxLength = Math.max(maxLength, localMax); st.pop(); sb.deleteCharAt(sb.length()-1); localMax = helper(s, level+1, st, sb, L, results); maxLength = Math.max(maxLength, localMax); } else if (c == ')' && !st.empty() && st.peek() == '(') { st.pop(); sb.append(c); localMax = helper(s, level+1, st, sb, L, results); maxLength = Math.max(maxLength, localMax); st.push('('); sb.deleteCharAt(sb.length()-1); localMax = helper(s, level+1, st, sb, L, results); maxLength = Math.max(maxLength, localMax); } else { localMax = helper(s, level+1, st, sb, L, results); maxLength = Math.max(maxLength, localMax); } return maxLength; } private List setToList(Set set, int maxLength) { List results = new ArrayList<>(); for (String s: set) { if (s.length() == maxLength) { results.add(s); } } return results; } /** * https://discuss.leetcode.com/topic/34875/easy-short-concise-and-fast-java-dfs-3-ms-solution */ public List removeInvalidParentheses2(String s) { List ans = new ArrayList<>(); remove(s, ans, 0, 0, new char[]{'(', ')'}); return ans; } public void remove(String s, List ans, int last_i, int last_j, char[] par) { for (int stack = 0, i = last_i; i < s.length(); ++i) { if (s.charAt(i) == par[0]) stack++; if (s.charAt(i) == par[1]) stack--; if (stack >= 0) continue; for (int j = last_j; j <= i; ++j) if (s.charAt(j) == par[1] && (j == last_j || s.charAt(j - 1) != par[1])) remove(s.substring(0, j) + s.substring(j + 1, s.length()), ans, i, j, par); return; } String reversed = new StringBuilder(s).reverse().toString(); if (par[0] == '(') // finished left to right remove(reversed, ans, 0, 0, new char[]{')', '('}); else // finished right to left ans.add(reversed); } /** * https://discuss.leetcode.com/topic/28827/share-my-java-bfs-solution */ public List removeInvalidParentheses3(String s) { List res = new ArrayList<>(); // sanity check if (s == null) return res; Set visited = new HashSet<>(); Queue queue = new LinkedList<>(); // initialize queue.add(s); visited.add(s); boolean found = false; while (!queue.isEmpty()) { s = queue.poll(); if (isValid(s)) { // found an answer, add to the result res.add(s); found = true; } if (found) continue; // generate all possible states for (int i = 0; i < s.length(); i++) { // we only try to remove left or right paren if (s.charAt(i) != '(' && s.charAt(i) != ')') continue; String t = s.substring(0, i) + s.substring(i + 1); if (!visited.contains(t)) { // for each state, if it's not visited, add it to the queue queue.add(t); visited.add(t); } } } return res; } // helper function checks if string s contains valid parantheses boolean isValid(String s) { int count = 0; for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c == '(') count++; if (c == ')' && count-- == 0) return false; } return count == 0; } /** * https://discuss.leetcode.com/topic/30743/easiest-9ms-java-solution */ public List removeInvalidParentheses4(String s) { int rmL = 0, rmR = 0; for (int i = 0; i < s.length(); i++) { if (s.charAt(i) == '(') { rmL++; } else if (s.charAt(i) == ')') { if (rmL != 0) { rmL--; } else { rmR++; } } } Set res = new HashSet<>(); dfs(s, 0, res, new StringBuilder(), rmL, rmR, 0); return new ArrayList(res); } public void dfs(String s, int i, Set res, StringBuilder sb, int rmL, int rmR, int open) { if (rmL < 0 || rmR < 0 || open < 0) { return; } if (i == s.length()) { if (rmL == 0 && rmR == 0 && open == 0) { res.add(sb.toString()); } return; } char c = s.charAt(i); int len = sb.length(); if (c == '(') { dfs(s, i + 1, res, sb, rmL - 1, rmR, open); // not use ( dfs(s, i + 1, res, sb.append(c), rmL, rmR, open + 1); // use ( } else if (c == ')') { dfs(s, i + 1, res, sb, rmL, rmR - 1, open); // not use ) dfs(s, i + 1, res, sb.append(c), rmL, rmR, open - 1); // use ) } else { dfs(s, i + 1, res, sb.append(c), rmL, rmR, open); } sb.setLength(len); } /** * https://leetcode.com/problems/remove-invalid-parentheses/discuss/75095/Java-optimized-DFS-solution-3-ms */ public List removeInvalidParentheses5(String s) { int count = 0, openN = 0, closeN = 0; // calculate the total numbers of opening and closing parentheses // that need to be removed in the final solution for (char c : s.toCharArray()) { if (c == '(') { count++; } else if (c == ')') { if (count == 0) closeN++; else count--; } } openN = count; count = 0; if (openN == 0 && closeN == 0) return Arrays.asList(s); List result = new ArrayList<>(); StringBuilder sb = new StringBuilder(); dfs(s.toCharArray(), 0, count, openN, closeN, result, sb); return result; } private void dfs(char[] s, int p, int count, int openN, int closeN, List result, StringBuilder sb) { if (count < 0) return; // the parentheses is invalid if (p == s.length) { if (openN == 0 && closeN == 0) { // the minimum number of invalid parentheses have been removed result.add(sb.toString()); } return; } if (s[p] != '(' && s[p] != ')') { sb.append(s[p]); dfs(s, p + 1, count, openN, closeN, result, sb); sb.deleteCharAt(sb.length() - 1); } else if (s[p] == '(') { int i = 1; while (p + i < s.length && s[p + i] == '(') i++; // use while loop to avoid duplicate result in DFS, instead of using HashSet sb.append(s, p, i); dfs(s, p + i, count + i, openN, closeN, result, sb); sb.delete(sb.length() - i, sb.length()); if (openN > 0) { // remove the current opening parenthesis dfs(s, p + 1, count, openN - 1, closeN, result, sb); } } else { int i = 1; while (p + i < s.length && s[p + i] == ')') i++; // use while loop to avoid duplicate result in DFS, instead of using HashSet sb.append(s, p, i); dfs(s, p + i, count - i, openN, closeN, result, sb); sb.delete(sb.length() - i, sb.length()); if (closeN > 0) { // remove the current closing parenthesis dfs(s, p + 1, count, openN, closeN - 1, result, sb); } } } } ================================================ FILE: src/RemoveLinkedListElements203.java ================================================ /** * Remove all elements from a linked list of integers that have value val. * * Example: * Input: 1->2->6->3->4->5->6, val = 6 * Output: 1->2->3->4->5 */ /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ public class RemoveLinkedListElements203 { public ListNode removeElements(ListNode head, int val) { ListNode dummy = new ListNode(0); dummy.next = head; ListNode p = dummy; while (p.next != null) { if (p.next.val == val) { p.next = p.next.next; } else { p = p.next; } } return dummy.next; } public ListNode removeElements2(ListNode head, int val) { if (head == null) return null; head.next = removeElements2(head.next, val); return head.val == val ? head.next : head; } } ================================================ FILE: src/RemoveNthNodeFromEndOfList19.java ================================================ /** * Given a linked list, remove the nth node from the end of list and return its head. * * For example, * * Given linked list: 1->2->3->4->5, and n = 2. * * After removing the second node from the end, the linked list becomes 1->2->3->5. * Note: * Given n will always be valid. * Try to do this in one pass. * */ /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ public class RemoveNthNodeFromEndOfList19 { public ListNode removeNthFromEnd(ListNode head, int n) { if (head == null) return null; int k = 1; ListNode q = head; while (q.next != null) { k++; q = q.next; } if (n == k) return head.next; ListNode dummy = new ListNode(0); ListNode p = head; dummy.next = p; int i = 1; while (i < k-n) { p = p.next; i++; } p.next = p.next.next; return dummy.next; } public ListNode removeNthFromEnd2(ListNode head, int n) { if (head == null) return null; ListNode dummy = new ListNode(0); dummy.next = head; ListNode f = dummy; ListNode s = dummy; int i = 0; while (i < n) { f = f.next; i++; } while (f.next != null) { f = f.next; s = s.next; } s.next = s.next.next; return dummy.next; } public ListNode removeNthFromEnd3(ListNode head, int n) { int l = 0; ListNode p = head; while (p != null) { p = p.next; l++; } if (l < n) return head; if (l == n) { head = head.next; return head; } int k = l-n; int i = 1; p = head; while (i < k) { p = p.next; i++; } p.next = p.next.next; return head; } public ListNode removeNthFromEnd4(ListNode head, int n) { if (head == null) return null; int m = 1; ListNode f = head; ListNode s = head; while (f.next != null && f.next.next != null) { s = s.next; f = f.next.next; m++; } int len = f.next == null ? (m*2-1) : m*2; if (len < n) return head; if (len == n) { head = head.next; return head; } int k = len-n; if (m <= k) { while (m < k) { s = s.next; m++; } s.next = s.next.next; } else { int i=1; f = head; while (i < k) { f = f.next; i++; } f.next = f.next.next; } return head; } /** * https://leetcode.com/problems/remove-nth-node-from-end-of-list/solution/ */ public ListNode removeNthFromEnd5(ListNode head, int n) { ListNode dummy = new ListNode(0); dummy.next = head; int length = 0; ListNode first = head; while (first != null) { length++; first = first.next; } length -= n; first = dummy; while (length > 0) { length--; first = first.next; } first.next = first.next.next; return dummy.next; } public ListNode removeNthFromEnd6(ListNode head, int n) { ListNode dummy = new ListNode(0); dummy.next = head; ListNode first = dummy; ListNode second = dummy; // Advances first pointer so that the gap between first and second is n nodes apart for (int i = 1; i <= n + 1; i++) { first = first.next; } // Move first to the end, maintaining the gap while (first != null) { first = first.next; second = second.next; } second.next = second.next.next; return dummy.next; } } ================================================ FILE: src/ReorderList143.java ================================================ /** * Given a singly linked list L: L0?L1?…?Ln-1?Ln, * reorder it to: L0?Ln?L1?Ln-1?L2?Ln-2?… * * You must do this in-place without altering the nodes' values. * * For example, * Given {1,2,3,4}, reorder it to {1,4,2,3}. */ /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ public class ReorderList143 { public void reorderList(ListNode head) { if (head == null || head.next == null || head.next.next == null) return; ListNode fast = head; ListNode slow = head; Stack st = new Stack<>(); while (fast.next != null && fast.next.next != null) { st.push(slow); slow = slow.next; fast = fast.next.next; } ListNode dummy = new ListNode(0); ListNode half = new ListNode(0); if (fast.next == null) { half = slow.next; dummy.next = slow; dummy.next.next = null; } else if (fast.next.next == null) { half = slow.next.next; dummy.next = slow; dummy.next.next.next = null; } while (half != null) { ListNode newNode = half; half = half.next; newNode.next = dummy.next; dummy.next = newNode; newNode = st.pop(); newNode.next = dummy.next; dummy.next = newNode; } head = dummy.next; } /** * https://discuss.leetcode.com/topic/13869/java-solution-with-3-steps */ public void reorderList2(ListNode head) { if(head==null||head.next==null) return; //Find the middle of the list ListNode p1=head; ListNode p2=head; while(p2.next!=null&&p2.next.next!=null){ p1=p1.next; p2=p2.next.next; } //Reverse the half after middle 1->2->3->4->5->6 to 1->2->3->6->5->4 ListNode preMiddle=p1; ListNode preCurrent=p1.next; while(preCurrent.next!=null){ ListNode current=preCurrent.next; preCurrent.next=current.next; current.next=preMiddle.next; preMiddle.next=current; } //Start reorder one by one 1->2->3->6->5->4 to 1->6->2->5->3->4 p1=head; p2=preMiddle.next; while(p1!=preMiddle){ preMiddle.next=p2.next; p2.next=p1.next; p1.next=p2; p1=p2.next; p2=preMiddle.next; } } /** * https://discuss.leetcode.com/topic/18092/java-solution-with-3-steps */ public void reorderList3(ListNode head) { if (head == null || head.next == null) return; // step 1. cut the list to two halves // prev will be the tail of 1st half // slow will be the head of 2nd half ListNode prev = null, slow = head, fast = head, l1 = head; while (fast != null && fast.next != null) { prev = slow; slow = slow.next; fast = fast.next.next; } prev.next = null; // step 2. reverse the 2nd half ListNode l2 = reverse(slow); // step 3. merge the two halves merge(l1, l2); } ListNode reverse(ListNode head) { ListNode prev = null, curr = head, next = null; while (curr != null) { next = curr.next; curr.next = prev; prev = curr; curr = next; } return prev; } void merge(ListNode l1, ListNode l2) { while (l1 != null) { ListNode n1 = l1.next, n2 = l2.next; l1.next = l2; if (n1 == null) break; l2.next = n1; l1 = n1; l2 = n2; } } } ================================================ FILE: src/ReorganizeString767.java ================================================ /** * Given a string S, check if the letters can be rearranged so that two * characters that are adjacent to each other are not the same. * * If possible, output any possible result. If not possible, return the * empty string. * * Example 1: * Input: S = "aab" * Output: "aba" * * Example 2: * Input: S = "aaab" * Output: "" * * Note: * S will consist of lowercase letters and have length in range [1, 500]. */ public class ReorganizeString767 { public String reorganizeString(String S) { int[] hash = new int[26]; for(char c : S.toCharArray()) hash[c-'a']++; int max = 0; for(int i = 0; i<26; ++i){ if(hash[i] > hash[max]) max = i; } if(hash[max] > (S.length()+1)/2) return ""; char[] res = new char[S.length()]; int ptr = 0; while(hash[max]-- > 0){ res[ptr] = (char)(max + 'a'); ptr += 2; } for(int i = 0; i<26; ++i){ while(hash[i]-- > 0){ if(ptr >= S.length()) ptr = 1; res[ptr] = (char)(i + 'a'); ptr += 2; } } return new String(res); } /** * https://leetcode.com/problems/reorganize-string/solution/ */ public String reorganizeString2(String S) { int N = S.length(); int[] count = new int[26]; for (char c: S.toCharArray()) count[c-'a']++; PriorityQueue pq = new PriorityQueue((a, b) -> a.count == b.count ? a.letter - b.letter : b.count - a.count); for (int i = 0; i < 26; ++i) if (count[i] > 0) { if (count[i] > (N + 1) / 2) return ""; pq.add(new MultiChar(count[i], (char) ('a' + i))); } StringBuilder ans = new StringBuilder(); while (pq.size() >= 2) { MultiChar mc1 = pq.poll(); MultiChar mc2 = pq.poll(); /*This code turns out to be superfluous, but explains what is happening if (ans.length() == 0 || mc1.letter != ans.charAt(ans.length() - 1)) { ans.append(mc1.letter); ans.append(mc2.letter); } else { ans.append(mc2.letter); ans.append(mc1.letter); }*/ ans.append(mc1.letter); ans.append(mc2.letter); if (--mc1.count > 0) pq.add(mc1); if (--mc2.count > 0) pq.add(mc2); } if (pq.size() > 0) ans.append(pq.poll().letter); return ans.toString(); } class MultiChar { int count; char letter; MultiChar(int ct, char ch) { count = ct; letter = ch; } } // use 358. Rearrange String k Distance Apart public String reorganizeString3(String S) { return rearrangeString(S, 2); } public String rearrangeString(String str, int k) { int length = str.length(); int[] count = new int[26]; int[] nextIndex = new int[26]; char[] chars = str.toCharArray(); for (char ch: chars){ count[ch-'a']++; } StringBuilder sb = new StringBuilder(); for (int i=0; i max && index >= nextIndex[i]) { max = count[i]; idx = i; } } return idx; } /** * https://leetcode.com/problems/reorganize-string/discuss/113451/7-ms-Java-O(n)-Solution.-no-Sorting */ public String reorganizeString4(String S) { int n = S.length(); int[] cnt = new int[128]; char mc = 'a'; for (char c : S.toCharArray()) { cnt[c]++; mc = (cnt[c] > cnt[mc]) ? c : mc; } if (cnt[mc] == 1) { return S; } if (n - cnt[mc] <= cnt[mc] - 2) { return ""; } StringBuilder[] sb = new StringBuilder[cnt[mc]]; for (int i = 0; i < sb.length; i ++) { sb[i] = new StringBuilder(); sb[i].append(mc); } int k = 0; for (char c = 'a'; c <= 'z'; c++) { while (c != mc && cnt[c] > 0) { sb[k++].append(c); cnt[c]--; k %= sb.length; } } for (int i = 1; i < sb.length; i++) { sb[0].append(sb[i]); } return sb[0].toString(); } } ================================================ FILE: src/RepeatedDNASequences187.java ================================================ /** * All DNA is composed of a series of nucleotides abbreviated as A, C, G, and T, * for example: "ACGAATTCCG". When studying DNA, it is sometimes useful to * identify repeated sequences within the DNA. * * Write a function to find all the 10-letter-long sequences (substrings) that * occur more than once in a DNA molecule. * * Example: * Input: s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT" * Output: ["AAAAACCCCC", "CCCCCAAAAA"] */ public class RepeatedDNASequences187 { public List findRepeatedDnaSequences(String s) { List res = new ArrayList<>(); Map map = new HashMap<>(); int N = s.length(); for (int i=0; i<=N-10; i++) { String sub = s.substring(i, i+10); if (map.containsKey(sub)) { if (!map.get(sub)) { map.put(sub, true); res.add(sub); } } else { map.put(sub, false); } } return res; } } ================================================ FILE: src/RepeatedStringMatch686.java ================================================ /** * Given two strings A and B, find the minimum number of times A has to be * repeated such that B is a substring of it. If no such solution, return -1. * * For example, with A = "abcd" and B = "cdabcdab". * * Return 3, because by repeating A three times (“abcdabcdabcd”), B is a * substring of it; and B is not a substring of A repeated two times ("abcdabcd"). * * Note: * The length of A and B will be between 1 and 10000. */ public class RepeatedStringMatch686 { public int repeatedStringMatch(String A, String B) { int lenA = A.length(); int lenB = B.length(); for (int i=0; i= 0) return q; if (S.append(A).indexOf(B) >= 0) return q+1; return -1; } } ================================================ FILE: src/RepeatedSubstringPattern459.java ================================================ /** * Given a non-empty string check if it can be constructed by taking a * substring of it and appending multiple copies of the substring together. * You may assume the given string consists of lowercase English letters only * and its length will not exceed 10000. * * Example 1: * Input: "abab" * Output: True * Explanation: It's the substring "ab" twice. * * Example 2: * Input: "aba" * Output: False * * Example 3: * Input: "abcabcabcabc" * Output: True * Explanation: It's the substring "abc" four times. (And the substring "abcabc" twice.) */ public class RepeatedSubstringPattern459 { /** * https://leetcode.com/problems/repeated-substring-pattern/discuss/94352/Java-Simple-Solution-with-Explanation */ public boolean repeatedSubstringPattern(String s) { if(s==null || s.length()<=1) return false; for(int i=1;i<=s.length()/2;i++){ if(s.length()%i!=0) continue; String sub = s.substring(0,i); if(dfs(s,sub,i)) return true; } return false; } private boolean dfs(String s,String sub,int i){ if(i==s.length()) return true; if(!s.startsWith(sub,i)) return false; return dfs(s,sub,i+sub.length()); } /** * https://leetcode.com/problems/repeated-substring-pattern/discuss/94344/Simple-Java-solution-2-lines */ public boolean repeatedSubstringPattern2(String str) { String s = str + str; return s.substring(1, s.length() - 1).contains(str); } /** * https://leetcode.com/problems/repeated-substring-pattern/discuss/94340/Java-and-O(n) */ public boolean repeatedSubstringPattern3(String str) { //This is the kmp issue int[] prefix = kmp(str); int len = prefix[str.length()-1]; int n = str.length(); return (len > 0 && n%(n-len) == 0); } private int[] kmp(String s){ int len = s.length(); int[] res = new int[len]; char[] ch = s.toCharArray(); int i = 0, j = 1; res[0] = 0; while(i < ch.length && j < ch.length){ if(ch[j] == ch[i]){ res[j] = i+1; i++; j++; }else{ if(i == 0){ res[j] = 0; j++; }else{ i = res[i-1]; } } } return res; } } ================================================ FILE: src/ReplaceWords648.java ================================================ /** * In English, we have a concept called root, which can be followed by some * other words to form another longer word - let's call this word successor. * For example, the root an, followed by other, which can form another word * another. * * Now, given a dictionary consisting of many roots and a sentence. You need * to replace all the successor in the sentence with the root forming it. If * a successor has many roots can form it, replace it with the root with the * shortest length. * * You need to output the sentence after the replacement. * * Example 1: * Input: dict = ["cat", "bat", "rat"] * sentence = "the cattle was rattled by the battery" * Output: "the cat was rat by the bat" * * Note: * The input will only have lower-case letters. * 1 <= dict words number <= 1000 * 1 <= sentence words number <= 1000 * 1 <= root length <= 100 * 1 <= sentence words length <= 1000 */ public class ReplaceWords648 { public String replaceWords(List dict, String sentence) { String[] words = sentence.split("\\s+"); StringBuilder sb = new StringBuilder(); for (int i=0; i roots, String sentence) { Set rootset = new HashSet(); for (String root: roots) rootset.add(root); StringBuilder ans = new StringBuilder(); for (String word: sentence.split("\\s+")) { String prefix = ""; for (int i = 1; i <= word.length(); ++i) { prefix = word.substring(0, i); if (rootset.contains(prefix)) break; } if (ans.length() > 0) ans.append(" "); ans.append(prefix); } return ans.toString(); } public String replaceWords3(List roots, String sentence) { Trie trie = constructTrie(roots); String[] words = sentence.split("\\s+"); for (int i=0; i roots) { Trie root = new Trie(); for (String word: roots) { root.add(word); } return root; } class Trie { Trie[] children = new Trie[26]; String word; public void add(String word) { add(word.toCharArray(), 0); } private void add(char[] chars, int i) { if (i >= chars.length) { this.word = new String(chars); return; } if (children[chars[i]-'a'] == null) { children[chars[i]-'a'] = new Trie(); } children[chars[i]-'a'].add(chars, i+1); } public String search(String word) { String found = search(word.toCharArray(), 0); if (found == null) return word; return found; } private String search(char[] chars, int i) { if (i >= chars.length) { return word; } if (word != null) return word; if (children[chars[i]-'a'] == null) return word; return children[chars[i]-'a'].search(chars, i+1); } } } ================================================ FILE: src/RestoreIPAddresses93.java ================================================ /** * Given a string containing only digits, restore it by returning all possible * valid IP address combinations. * * For example: * Given "25525511135", * * return ["255.255.11.135", "255.255.111.35"]. (Order does not matter) */ import java.util.List; import java.util.ArrayList; import java.util.Stack; public class RestoreIPAddresses93 { public List restoreIpAddresses(String s) { List results = new ArrayList<>(); int L = s.length(); if (L < 4) return results; Stack st = new Stack<>(); helper(s, results, st, 0, L); return results; } private void helper(String s, List results, Stack st, int start, int L) { if (st.size() == 3 && (start + 3) < L) return; if (st.size() == 4) { if (start == L) results.add(String.join(".", st)); return; } for (int i = 1; i<=3 && start+i<=L; i++) { String current = s.substring(start, start+i); if (!isValid(current)) continue; st.push(current); helper(s, results, st, start+i, L); st.pop(); } } private boolean isValid(String current) { // starts with "0" but not "0" if (current.charAt(0)=='0' && current.length() > 1) return false; // larger than 255 if (Integer.valueOf(current) > 255) return false; return true; } /** * https://discuss.leetcode.com/topic/3919/my-code-in-java */ public List restoreIpAddresses2(String s) { List res = new ArrayList(); int len = s.length(); for(int i = 1; i<4 && i3 || s.length()==0 || (s.charAt(0)=='0' && s.length()>1) || Integer.parseInt(s)>255) return false; return true; } } ================================================ FILE: src/ReverseLinkedList206.java ================================================ /** * Reverse a singly linked list. * * Hint: * A linked list can be reversed either iteratively or recursively. * Could you implement both? * */ /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ public class ReverseLinkedList206 { public ListNode reverseList(ListNode head) { if (head == null || head.next == null) return head; ListNode dummy = new ListNode(0); ListNode tail = null; while (head != null) { ListNode t = head; head = head.next; tail = dummy.next; dummy.next = t; dummy.next.next = tail; } return dummy.next; } public ListNode reverseList2(ListNode head) { if (head == null || head.next == null) return head; ListNode dummy = new ListNode(0); helper(head, dummy); return dummy.next; } private void helper(ListNode head, ListNode dummy) { if (head == null) return; ListNode curr = head; head = head.next; ListNode tail = dummy.next; dummy.next = curr; dummy.next.next = tail; helper(head, dummy); } public ListNode reverseList3(ListNode head) { return helper2(head, null); } private ListNode helper2(ListNode head, ListNode h) { if (head == null) return h; ListNode tail = head.next; head.next = h; return helper2(tail, head); } /** * https://leetcode.com/problems/reverse-linked-list/solution/ */ public ListNode reverseList4(ListNode head) { ListNode prev = null; ListNode curr = head; while (curr != null) { ListNode nextTemp = curr.next; curr.next = prev; prev = curr; curr = nextTemp; } return prev; } public ListNode reverseList5(ListNode head) { if (head == null || head.next == null) return head; ListNode p = reverseList(head.next); head.next.next = head; head.next = null; return p; } } ================================================ FILE: src/ReverseLinkedListII92.java ================================================ /** * Reverse a linked list from position m to n. Do it in-place and in one-pass. * * For example: * Given 1->2->3->4->5->NULL, m = 2 and n = 4, * * return 1->4->3->2->5->NULL. * * Note: * Given m, n satisfy the following condition: * 1 ? m ? n ? length of list. */ /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ public class ReverseLinkedListII92 { public ListNode reverseBetween(ListNode head, int m, int n) { if (head == null || head.next == null || m == n) return head; ListNode dummy = new ListNode(0); dummy.next = head; ListNode p = dummy; int i = 0; while (i < m-1) { p = p.next; i++; } ListNode before = p; p = p.next; i++; ListNode start = new ListNode(0); start.next = p; while (i < n) { ListNode r = p.next; p.next = p.next.next; r.next = start.next; start.next = r; i++; } before.next = start.next; return dummy.next; } /** * https://discuss.leetcode.com/topic/8976/simple-java-solution-with-clear-explanation */ public ListNode reverseBetween2(ListNode head, int m, int n) { if(head == null) return null; ListNode dummy = new ListNode(0); // create a dummy node to mark the head of this list dummy.next = head; ListNode pre = dummy; // make a pointer pre as a marker for the node before reversing for(int i = 0; i pre = 1, start = 2, then = 3 // dummy-> 1 -> 2 -> 3 -> 4 -> 5 for(int i=0; i1 - 3 - 2 - 4 - 5; pre = 1, start = 2, then = 4 // second reversing: dummy->1 - 4 - 3 - 2 - 5; pre = 1, start = 2, then = 5 (finish) return dummy.next; } public ListNode reverseBetween3(ListNode head, int m, int n) { int i = 1; ListNode dummy = new ListNode(0); ListNode p = dummy; ListNode h = head; while (i < m) { p.next = h; h = h.next; p = p.next; p.next = null; i++; } ListNode tail = h; while (i <= n) { ListNode in = h; h = h.next; in.next = p.next; p.next = in; i++; } while (h != null) { tail.next = h; h = h.next; tail = tail.next; tail.next = null; } return dummy.next; } } ================================================ FILE: src/ReverseNodesInKGroup25.java ================================================ /** * Given a linked list, reverse the nodes of a linked list k at a time and * return its modified list. * * k is a positive integer and is less than or equal to the length of the linked * list. If the number of nodes is not a multiple of k then left-out nodes in * the end should remain as it is. * * You may not alter the values in the nodes, only nodes itself may be changed. * * Only constant memory is allowed. * * For example, * Given this linked list: 1->2->3->4->5 * * For k = 2, you should return: 2->1->4->3->5 * * For k = 3, you should return: 3->2->1->4->5 */ /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ public class ReverseNodesInKGroup25 { public ListNode reverseKGroup(ListNode head, int k) { if (k == 0 || k == 1) { return head; } if (head == null) { return null; } ListNode now = head; int i = 1; ListNode r = new ListNode(0); ListNode last = r; ListNode tempHead = null; ListNode tempTail = null; while (now != null) { ListNode temp = new ListNode(now.val); if (i == 1) { tempHead = temp; tempHead.next = null; tempTail = temp; tempTail.next = null; i++; } else if (i == k) { temp.next = tempHead; tempHead = temp; last.next = tempHead; last = tempTail; tempHead = null; tempTail = null; i = 1; } else { temp.next = tempHead; tempHead = temp; i++; } now = now.next; } ListNode tailHead = null; while (tempHead != null) { ListNode temp = new ListNode(tempHead.val); temp.next = tailHead; tailHead = temp; last.next = tailHead; tempHead = tempHead.next; } return r.next; } /** * https://discuss.leetcode.com/topic/7126/short-but-recursive-java-code-with-comments/27 */ public ListNode reverseKGroup2(ListNode head, int k) { ListNode curr = head; int count = 0; while (curr != null && count != k) { // find the k+1 node curr = curr.next; count++; } if (count == k) { // if k+1 node is found curr = reverseKGroup(curr, k); // reverse list with k+1 node as head // head - head-pointer to direct part, // curr - head-pointer to reversed part; while (count-- > 0) { // reverse current k-group: ListNode tmp = head.next; // tmp - next head in direct part head.next = curr; // preappending "direct" head to the reversed list curr = head; // move head of reversed part to a new node head = tmp; // move "direct" head to the next node in direct part } head = curr; } return head; } /** * https://discuss.leetcode.com/topic/7126/short-but-recursive-java-code-with-comments/27 */ public ListNode reverseKGroup3(ListNode head, int k) { int n = 0; for (ListNode i = head; i != null; n++, i = i.next); ListNode dmy = new ListNode(0); dmy.next = head; for(ListNode prev = dmy, tail = head; n >= k; n -= k) { for (int i = 1; i < k; i++) { ListNode next = tail.next.next; tail.next.next = prev.next; prev.next = tail.next; tail.next = next; } prev = tail; tail = tail.next; } return dmy.next; } /** * https://leetcode.com/problems/reverse-nodes-in-k-group/#/solutions */ public ListNode reverseKGroup4(ListNode head, int k) { ListNode begin; if (head==null || head.next ==null || k==1) return head; ListNode dummyhead = new ListNode(-1); dummyhead.next = head; begin = dummyhead; int i=0; while (head != null){ i++; if (i%k == 0){ begin = reverse(begin, head.next); head = begin.next; } else { head = head.next; } } return dummyhead.next; } public ListNode reverse(ListNode begin, ListNode end){ ListNode curr = begin.next; ListNode next, first; ListNode prev = begin; first = curr; while (curr!=end){ next = curr.next; curr.next = prev; prev = curr; curr = next; } begin.next = prev; first.next = curr; return first; } } ================================================ FILE: src/ReverseString344.java ================================================ /** * Write a function that takes a string as input and returns the string reversed. * * Example: * Given s = "hello", return "olleh". */ public class ReverseString344 { public String reverseString(String s) { if (s == null || s.length() <= 1) return s; char[] chars = s.toCharArray(); int i = 0; int j = s.length()-1; while (i < j) swap(chars, i++, j--); return String.valueOf(chars); } private void swap(char[] chars, int i, int j) { char t = chars[i]; chars[i] = chars[j]; chars[j] = t; } /** * https://leetcode.com/problems/reverse-string/discuss/80937/JAVA-Simple-and-Clean-with-Explanations-6-Solutions */ public String reverseString2(String s) { char[] word = s.toCharArray(); int i = 0; int j = s.length() - 1; while (i < j) { word[i] = (char) (word[i] ^ word[j]); word[j] = (char) (word[i] ^ word[j]); word[i] = (char) (word[i] ^ word[j]); i++; j--; } return new String(word); } /** * https://leetcode.com/problems/reverse-string/discuss/80937/JAVA-Simple-and-Clean-with-Explanations-6-Solutions */ public String reverseString3(String s) { return new StringBuilder(s).reverse().toString(); } } ================================================ FILE: src/ReverseStringII541.java ================================================ /** * Given a string and an integer k, you need to reverse the first k characters * for every 2k characters counting from the start of the string. If there are * less than k characters left, reverse all of them. If there are less than 2k * but greater than or equal to k characters, then reverse the first k * characters and left the other as original. * * Example: * Input: s = "abcdefg", k = 2 * Output: "bacdfeg" * * Restrictions: * The string consists of lower English letters only. * Length of the given string and k will in the range [1, 10000] * */ public class ReverseStringII541 { public String reverseStr(String s, int k) { if (s == null || s.length() == 0) return s; char[] chars = s.toCharArray(); for (int i=0; i<=s.length()/k; i++) { if (i % 2 == 0) { reverse(chars, i * k, Math.min((i+1)*k - 1, s.length()-1)); } } return new String(chars); } private void reverse(char[] chars, int left, int right) { int i = 0; while (i < (right-left+1)/2) { swap(chars, left+i, right-i); i++; } } private void swap(char[] chars, int i, int j) { char temp = chars[i]; chars[i] = chars[j]; chars[j] = temp; } } ================================================ FILE: src/ReverseVowelsOfAString345.java ================================================ /** * Write a function that takes a string as input and reverse only the * vowels of a string. * * Example 1: * Given s = "hello", return "holle". * * Example 2: * Given s = "leetcode", return "leotcede". * * Note: * The vowels does not include the letter "y". */ public class ReverseVowelsOfAString345 { private Set vowels = new HashSet<>(Arrays.asList('a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U')); public String reverseVowels(String s) { if (s == null || s.length() <= 1) return s; char[] chars = s.toCharArray(); int i = 0; int j = chars.length - 1; while (i < j) { while (i < j && !vowels.contains(chars[i])) i++; while (i < j && !vowels.contains(chars[j])) j--; if (i >= j) break; swap(chars, i, j); i++; j--; } return new String(chars); } private void swap(char[] chars, int i, int j) { char tmp = chars[i]; chars[i] = chars[j]; chars[j] = tmp; } } ================================================ FILE: src/ReverseWordsInAString151.java ================================================ /** * Given an input string, reverse the string word by word. * * Example: * * Input: "the sky is blue", * Output: "blue is sky the". * * Note: * * A word is defined as a sequence of non-space characters. * Input string may contain leading or trailing spaces. However, your reversed * string should not contain leading or trailing spaces. * You need to reduce multiple spaces between two words to a single space in * the reversed string. */ public class ReverseWordsInAString151 { public String reverseWords(String s) { if (s == null) return s; String[] words = s.replaceAll("^\\s+", "").split("\\s+", 0); int i = 0; while (i < words.length/2) { swap(words, i, words.length-i-1); i++; } return String.join(" ", words); } private void swap(String[] words, int i, int j) { String temp = words[i]; words[i] = words[j]; words[j] = temp; } /** * https://leetcode.com/problems/reverse-words-in-a-string/discuss/47781/Java-3-line-builtin-solution */ public String reverseWords2(String s) { String[] words = s.trim().split(" +"); Collections.reverse(Arrays.asList(words)); return String.join(" ", words); } public String reverseWords3(String s) { if (s == null || s.length() == 0){ return s; } String[] array = s.split(" "); StringBuilder res = new StringBuilder(); for (int i = array.length - 1; i >= 0; i--){ if(array[i].length() != 0){ if (res.length() > 0){ res.append(" "); } res.append(array[i]); } } return res.toString(); } /** * https://leetcode.com/problems/reverse-words-in-a-string/discuss/47720/Clean-Java-two-pointers-solution-(no-trim(-)-no-split(-)-no-StringBuilder) */ public String reverseWords4(String s) { if (s == null) return null; char[] a = s.toCharArray(); int n = a.length; // step 1. reverse the whole string reverse(a, 0, n - 1); // step 2. reverse each word reverseWords(a, n); // step 3. clean up spaces return cleanSpaces(a, n); } void reverseWords(char[] a, int n) { int i = 0, j = 0; while (i < n) { while (i < j || i < n && a[i] == ' ') i++; // skip spaces while (j < i || j < n && a[j] != ' ') j++; // skip non spaces reverse(a, i, j - 1); // reverse the word } } // trim leading, trailing and multiple spaces String cleanSpaces(char[] a, int n) { int i = 0, j = 0; while (j < n) { while (j < n && a[j] == ' ') j++; // skip spaces while (j < n && a[j] != ' ') a[i++] = a[j++]; // keep non spaces while (j < n && a[j] == ' ') j++; // skip spaces if (j < n) a[i++] = ' '; // keep only one space } return new String(a).substring(0, i); } // reverse a[] from a[i] to a[j] private void reverse(char[] a, int i, int j) { while (i < j) { char t = a[i]; a[i++] = a[j]; a[j--] = t; } } public String reverseWords5(String s) { if (s == null || s.length() == 0) return s; char[] chars = s.trim().toCharArray(); int N = chars.length; char[] res = new char[N]; int right = N - 1; int left = 0; while (right >= 0) { while (right >= 0 && chars[right] == ' ') { right--; } if (right < 0) break; int end = right; while (right >= 0 && chars[right] != ' ') { right--; } int i = right + 1; while (i <= end) { res[left++] = chars[i++]; } if (right < 0) break; res[left++] = ' '; } return new String(res, 0, left); } } ================================================ FILE: src/ReverseWordsInAStringII186.java ================================================ /** * Given an input string , reverse the string word by word. * * Example: * * Input: ["t","h","e"," ","s","k","y"," ","i","s"," ","b","l","u","e"] * Output: ["b","l","u","e"," ","i","s"," ","s","k","y"," ","t","h","e"] * * Note: * * A word is defined as a sequence of non-space characters. * The input string does not contain leading or trailing spaces. * The words are always separated by a single space. * Follow up: Could you do it in-place without allocating extra space? * */ public class ReverseWordsInAStringII186 { public void reverseWords(char[] str) { int i = 0; while (i < str.length/2) { swap(str, i, str.length-i-1); i++; } i = 0; while (i < str.length) { int j = i; while (j < str.length && str[j] != ' ') j++; int k = 0; while (k < (j-i)/2) { swap(str, i+k, j-k-1); k++; } i = j+1; } } private void swap(char[] str, int i, int j) { char temp = str[i]; str[i] = str[j]; str[j] = temp; } public void reverseWords2(char[] str) { if (str == null || str.length <= 2) return; int len = str.length; int i = 0; int j = len - 1; int preI = i; int preJ = j; while (i <= j) { if (str[i] == ' ') { reverseOneWord(str, j+1, preJ); preJ = j-1; } if (str[j] == ' ') { reverseOneWord(str, preI, i-1); preI = i + 1; } swap(str, i++, j--); } if (preI < preJ) { reverseOneWord(str, preI, preJ); } } private void reverseOneWord(char[] str, int i, int j) { while (i < j) { swap(str, i++, j--); } } } ================================================ FILE: src/ReverseWordsInAStringIII557.java ================================================ /** * Given a string, you need to reverse the order of characters in each word * within a sentence while still preserving whitespace and initial word order. * * Example 1: * Input: "Let's take LeetCode contest" * Output: "s'teL ekat edoCteeL tsetnoc" * Note: In the string, each word is separated by single space and there will * not be any extra space in the string. */ public class ReverseWordsInAStringIII557 { public String reverseWords(String s) { char[] chars = s.toCharArray(); int i = 0; int j = 0; while (i < s.length()) { j = i; while (j < s.length() && chars[j] != ' ') { j++; } for (int k=0; k<(j-i)/2; k++) { swap(chars, i+k, j-k-1); } i = j+1; } return new String(chars); } private void swap(char[] chars, int i, int j) { char temp = chars[i]; chars[i] = chars[j]; chars[j] = temp; } } ================================================ FILE: src/RobotRoomCleaner.java ================================================ /** * Given a robot cleaner in a room modeled as a grid. * * Each cell in the grid can be empty or blocked. * * The robot cleaner with 4 given APIs can move forward, turn left or turn * right. Each turn it made is 90 degrees. * * When it tries to move into a blocked cell, its bumper sensor detects the * obstacle and it stays on the current cell. * * Design an algorithm to clean the entire room using only the 4 given APIs * shown below. * * interface Robot { * // returns true if next cell is open and robot moves into the cell. * // returns false if next cell is obstacle and robot stays on the current cell. * boolean move(); * * // Robot will stay on the same cell after calling turnLeft/turnRight. * // Each turn will be 90 degrees. * void turnLeft(); * void turnRight(); * * // Clean the current cell. * void clean(); * } * * Example: * Input: * room = [ * [1,1,1,1,1,0,1,1], * [1,1,1,1,1,0,1,1], * [1,0,1,1,1,1,1,1], * [0,0,0,1,0,0,0,0], * [1,1,1,1,1,1,1,1] * ], * row = 1, * col = 3 * * Explanation: * All grids in the room are marked by either 0 or 1. * 0 means the cell is blocked, while 1 means the cell is accessible. * The robot initially starts at the position of row=1, col=3. * From the top left corner, its position is one row below and three columns right. * * Notes: * - The input is only given to initialize the room and the robot's position * internally. You must solve this problem "blindfolded". In other words, * you must control the robot using only the mentioned 4 APIs, without knowing * the room layout and the initial robot's position. * - The robot's initial position will always be in an accessible cell. * - The initial direction of the robot will be facing up. * - All accessible cells are connected, which means the all cells marked as 1 * will be accessible by the robot. * - Assume all four edges of the grid are all surrounded by wall. */ /** * // This is the robot's control interface. * // You should not implement it, or speculate about its implementation * interface Robot { * // Returns true if the cell in front is open and robot moves into the cell. * // Returns false if the cell in front is blocked and robot stays in the current cell. * public boolean move(); * * // Robot will stay in the same cell after calling turnLeft/turnRight. * // Each turn will be 90 degrees. * public void turnLeft(); * public void turnRight(); * * // Clean the current cell. * public void clean(); * } */ public class RobotRoomCleaner { public void cleanRoom(Robot robot) { cleanRoom(robot, new HashMap>(), new int[2], 0, true); } public void cleanRoom(Robot robot, Map> map, int[] pos, int dir, boolean in) { robot.clean(); if (!map.containsKey(pos[0])) { map.put(pos[0], new HashSet<>()); } map.get(pos[0]).add(pos[1]); int[] nxt = next(pos, dir); if (!contains(map, nxt) && robot.move()) { cleanRoom(robot, map, nxt, dir, false); } dir = (dir + 1) % 4; robot.turnLeft(); nxt = next(pos, dir); if (!contains(map, nxt) && robot.move()) { cleanRoom(robot, map, nxt, dir, false); } dir = (dir + 1) % 4; robot.turnLeft(); nxt = next(pos, dir); if (in && !contains(map, nxt) && robot.move()) { cleanRoom(robot, map, nxt, dir, false); } dir = (dir + 1) % 4; robot.turnLeft(); nxt = next(pos, dir); if (!contains(map, nxt) && robot.move()) { cleanRoom(robot, map, nxt, dir, false); } robot.turnRight(); robot.move(); robot.turnLeft(); robot.turnLeft(); } private boolean contains(Map> map, int[] pos) { return map.containsKey(pos[0]) && map.get(pos[0]).contains(pos[1]); } private int[] next(int[] now, int dir) { if (dir == 0) { return up(now); } else if (dir == 1) { return left(now); } else if (dir == 2) { return down(now); } else { return right(now); } } private int[] up(int[] now) { return new int[]{now[0]-1, now[1]}; } private int[] left(int[] now) { return new int[]{now[0], now[1]-1}; } private int[] down(int[] now) { return new int[]{now[0]+1, now[1]}; } private int[] right(int[] now) { return new int[]{now[0], now[1]+1}; } public void cleanRoom2(Robot robot) { dfs(robot, new HashMap<>(), new int[2], 0); } private void dfs(Robot robot, Map> visited, int[] pos, int dir) { // System.out.println(pos[0] + ", " + pos[1] + ": " + dir); if (visited.containsKey(pos[0]) && visited.get(pos[0]).contains(pos[1])) { robot.turnRight(); robot.turnRight(); robot.move(); return; } if (!visited.containsKey(pos[0])) visited.put(pos[0], new HashSet<>()); visited.get(pos[0]).add(pos[1]); robot.clean(); if (robot.move()) { dfs(robot, visited, nextPos(pos, dir), dir); } else { robot.turnRight(); robot.turnRight(); } robot.turnRight(); dir = nextDir(dir, 3); if (robot.move()) { dfs(robot, visited, nextPos(pos, dir), dir); } else { robot.turnRight(); robot.turnRight(); } dir = nextDir(dir, 2); if (robot.move()) { dfs(robot, visited, nextPos(pos, dir), dir); robot.turnLeft(); } else { robot.turnRight(); } dir = nextDir(dir, 1); if (robot.move()) { dfs(robot, visited, nextPos(pos, dir), dir); robot.turnRight(); robot.turnRight(); } robot.move(); } private int nextDir(int dir, int move) { return (dir + move) % 4; } private int[] nextPos(int[] pos, int dir) { if (dir == 0) { return new int[]{pos[0], pos[1]+1}; } else if (dir == 1) { return new int[]{pos[0]+1, pos[1]}; } else if (dir == 2) { return new int[]{pos[0], pos[1]-1}; } else { return new int[]{pos[0]-1, pos[1]}; } } } ================================================ FILE: src/RomanToInteger13.java ================================================ /** * Roman numerals are represented by seven different symbols: I, V, X, L, C, D and M. * * Symbol Value * I 1 * V 5 * X 10 * L 50 * C 100 * D 500 * M 1000 * For example, two is written as II in Roman numeral, just two one's added * together. Twelve is written as, XII, which is simply X + II. The number * twenty seven is written as XXVII, which is XX + V + II. * * Roman numerals are usually written largest to smallest from left to right. * However, the numeral for four is not IIII. Instead, the number four is * written as IV. Because the one is before the five we subtract it making four. * The same principle applies to the number nine, which is written as IX. There * are six instances where subtraction is used: * * I can be placed before V (5) and X (10) to make 4 and 9. * X can be placed before L (50) and C (100) to make 40 and 90. * C can be placed before D (500) and M (1000) to make 400 and 900. * Given a roman numeral, convert it to an integer. Input is guaranteed to be * within the range from 1 to 3999. * * Example 1: * Input: "III" * Output: 3 * * Example 2: * Input: "IV" * Output: 4 * * Example 3: * Input: "IX" * Output: 9 * * Example 4: * Input: "LVIII" * Output: 58 * Explanation: C = 100, L = 50, XXX = 30 and III = 3. * * Example 5: * Input: "MCMXCIV" * Output: 1994 * Explanation: M = 1000, CM = 900, XC = 90 and IV = 4. */ public class RomanToInteger13 { public int romanToInt(String s) { int res = 0; int i = 0; while (i < s.length()) { char c = s.charAt(i); switch (c) { case 'I': if (i+1 < s.length()) { char next = s.charAt(i+1); if (next == 'V') { res += 4; i += 2; } else if (next == 'X') { res += 9; i += 2; } else { res += 1; i++; } } else { res += 1; i++; } break; case 'V': res += 5; i++; break; case 'X': if (i+1 < s.length()) { char next = s.charAt(i+1); if (next == 'L') { res += 40; i += 2; } else if (next == 'C') { res += 90; i += 2; } else { res += 10; i++; } } else { res += 10; i++; } break; case 'L': res += 50; i++; break; case 'C': if (i+1 < s.length()) { char next = s.charAt(i+1); if (next == 'D') { res += 400; i += 2; } else if (next == 'M') { res += 900; i += 2; } else { res += 100; i++; } } else { res += 100; i++; } break; case 'D': res += 500; i++; break; case 'M': res += 1000; i++; break; default: return 0; } } return res; } /** * https://leetcode.com/problems/roman-to-integer/discuss/6509/7ms-solution-in-Java.-easy-to-understand */ public int romanToInt2(String s) { int nums[]=new int[s.length()]; for(int i=0;i res) { res = rot; } } return res; } } ================================================ FILE: src/RotateImage48.java ================================================ /** * You are given an n x n 2D matrix representing an image. * * Rotate the image by 90 degrees (clockwise). * * Note: * You have to rotate the image in-place, which means you have to modify the * input 2D matrix directly. DO NOT allocate another 2D matrix and do the rotation. * * Example 1: * * Given input matrix = * [ * [1,2,3], * [4,5,6], * [7,8,9] * ], * * rotate the input matrix in-place such that it becomes: * [ * [7,4,1], * [8,5,2], * [9,6,3] * ] * * * Example 2: * * Given input matrix = * [ * [ 5, 1, 9,11], * [ 2, 4, 8,10], * [13, 3, 6, 7], * [15,14,12,16] * ], * * rotate the input matrix in-place such that it becomes: * [ * [15,13, 2, 5], * [14, 3, 4, 1], * [12, 6, 8, 9], * [16, 7,10,11] * ] * */ public class RotateImage48 { public void rotate(int[][] matrix) { if (matrix == null || matrix.length == 0 || matrix.length == 1) return; int len = matrix.length; int mid = (len-1)/2; for (int i=0; i<=mid; i++) { if (i > len-i-2) continue; int last = Math.max(len-i-2, i); for (int j=i; j<=last; j++) { int forth = matrix[j][len-i-1]; int first = matrix[i][j]; matrix[j][len-i-1] = first; int second = matrix[len-j-1][i]; matrix[i][j] = second; int third = matrix[len-i-1][len-j-1]; matrix[len-j-1][i] = third; matrix[len-i-1][len-j-1] = forth; } } } /** * https://leetcode.com/problems/rotate-image/discuss/18879/AC-Java-in-place-solution-with-explanation-Easy-to-understand. */ public void rotate2(int[][] matrix) { for(int i = 0; i2->3->4->5->NULL and k = 2, * return 4->5->1->2->3->NULL. */ /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ public class RotateList61 { public ListNode rotateRight(ListNode head, int k) { if (head == null || k == 0) return head; ListNode first = head; ListNode second = head; int i = 0; while (i < k && first.next != null) { first = first.next; i++; } if (first.next == null && i < k) { return rotateRight(head, k%(i+1)); } while (first.next != null) { first = first.next; second = second.next; } ListNode returned = second.next; first.next = head; second.next = null; return returned; } /** * https://discuss.leetcode.com/topic/2861/share-my-java-solution-with-explanation */ public ListNode rotateRight2(ListNode head, int n) { if (head==null||head.next==null) return head; ListNode dummy=new ListNode(0); dummy.next=head; ListNode fast=dummy,slow=dummy; int i; for (i=0;fast.next!=null;i++)//Get the total length fast=fast.next; for (int j=i-n%i;j>0;j--) //Get the i-n%i th node slow=slow.next; fast.next=dummy.next; //Do the rotation dummy.next=slow.next; slow.next=null; return dummy.next; } /** * https://discuss.leetcode.com/topic/26364/clean-java-solution-with-brief-explanation */ public ListNode rotateRight3(ListNode head, int k) { if (head == null) return head; ListNode copyHead = head; int len = 1; while (copyHead.next != null) { copyHead = copyHead.next; len++; } copyHead.next = head; for (int i = len - k % len; i > 1; i--) head = head.next; copyHead = head.next; head.next = null; return copyHead; } } ================================================ FILE: src/RussianDollEnvelopes354.java ================================================ /** * You have a number of envelopes with widths and heights given as a pair of * integers (w, h). One envelope can fit into another if and only if both the * width and height of one envelope is greater than the width and height of * the other envelope. * * What is the maximum number of envelopes can you Russian doll? (put one inside other) * * Note: * Rotation is not allowed. * * Example: * Input: [[5,4],[6,4],[6,7],[2,3]] * Output: 3 * Explanation: The maximum number of envelopes you can Russian doll * is 3 ([2,3] => [5,4] => [6,7]). */ public class RussianDollEnvelopes354 { public int maxEnvelopes(int[][] envelopes) { if (envelopes == null || envelopes.length == 0) return 0; Comparator comp = new Comparator() { @Override public int compare(int[] e1, int[] e2) { int wDiff = Integer.compare(e2[0], e1[0]); if (wDiff != 0) return wDiff; return -Integer.compare(e2[1], e1[1]); } }; Arrays.sort(envelopes, comp); int N = envelopes.length; int[] dp = new int[N]; int res = 1; for (int i=0; i dp[i]) { dp[i] = dp[j] + 1; } } if (dp[i] > res) res = dp[i]; } return res; } private boolean isLarger(int[] e1, int[] e2) { return e1[0] > e2[0] && e1[1] > e2[1]; } public int maxEnvelopes2(int[][] envelopes) { if (envelopes == null || envelopes.length == 0) return 0; Comparator comp = new Comparator() { @Override public int compare(int[] e1, int[] e2) { int wDiff = Integer.compare(e1[0], e2[0]); if (wDiff != 0) return wDiff; return Integer.compare(e2[1], e1[1]); } }; Arrays.sort(envelopes, comp); int N = envelopes.length; int[] dp = new int[N]; int res = 0; for (int i=0; i stack_p = new Stack <> (); Stack stack_q = new Stack <> (); if (p != null) stack_p.push( p ) ; if (q != null) stack_q.push( q ) ; while (!stack_p.isEmpty() && !stack_q.isEmpty()) { TreeNode pn = stack_p.pop() ; TreeNode qn = stack_q.pop() ; if (pn.val != qn.val) return false ; if (pn.right != null) stack_p.push(pn.right) ; if (qn.right != null) stack_q.push(qn.right) ; if (stack_p.size() != stack_q.size()) return false ; if (pn.left != null) stack_p.push(pn.left) ; if (qn.left != null) stack_q.push(qn.left) ; if (stack_p.size() != stack_q.size()) return false ; } return stack_p.size() == stack_q.size() ; } } ================================================ FILE: src/SearchA2DMatrix74.java ================================================ /** * Write an efficient algorithm that searches for a value in an m x n matrix. * This matrix has the following properties: * * Integers in each row are sorted from left to right. * The first integer of each row is greater than the last integer of the previous row. * * Example 1: * Input: * matrix = [ * [1, 3, 5, 7], * [10, 11, 16, 20], * [23, 30, 34, 50] * ] * target = 3 * Output: true * * Example 2: * Input: * matrix = [ * [1, 3, 5, 7], * [10, 11, 16, 20], * [23, 30, 34, 50] * ] * target = 13 * Output: false */ public class SearchA2DMatrix74 { public boolean searchMatrix(int[][] matrix, int target) { if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return false; int start = 0; int end = matrix.length - 1; while (start < end) { int mid = start + (end - start + 1) / 2; if (matrix[mid][0] == target) return true; if (matrix[mid][0] < target) { start = mid; } else { end = mid - 1;; } } int row = start; start = 0; end = matrix[0].length - 1; while (start < end) { int mid = start + (end - start) / 2; if (matrix[row][mid] == target) return true; if (matrix[row][mid] > target) { end = mid - 1; } else { start = mid + 1; } } return matrix[row][start] == target; } public boolean searchMatrix2(int[][] matrix, int target) { if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return false; int start = 0; int end = matrix.length - 1; while (start + 1 < end) { int mid = start + (end - start) / 2; if (matrix[mid][0] == target) return true; if (matrix[mid][0] < target) { start = mid; } else { end = mid - 1;; } } int row = target >= matrix[end][0] ? end : start; start = 0; end = matrix[0].length - 1; while (start < end) { int mid = start + (end - start) / 2; if (matrix[row][mid] == target) return true; if (matrix[row][mid] > target) { end = mid - 1; } else { start = mid + 1; } } return matrix[row][start] == target; } public boolean searchMatrix3(int[][] matrix, int target) { if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return false; int M = matrix.length; int N = matrix[0].length; int start = 0; int end = M * N - 1; while (start < end) { int mid = start + (end - start) / 2; int midVal = matrix[mid / N][mid % N]; if (midVal == target) return true; if (midVal < target) { start = mid + 1; } else { end = mid - 1; } } return matrix[start / N][start % N] == target; } } ================================================ FILE: src/SearchA2DMatrixII240.java ================================================ /** * Write an efficient algorithm that searches for a value in an m x n matrix. * This matrix has the following properties: * * Integers in each row are sorted in ascending from left to right. * Integers in each column are sorted in ascending from top to bottom. * * For example, * * Consider the following matrix: * * [ * [1, 4, 7, 11, 15], * [2, 5, 8, 12, 19], * [3, 6, 9, 16, 22], * [10, 13, 14, 17, 24], * [18, 21, 23, 26, 30] * ] * * Given target = 5, return true. * Given target = 20, return false. * */ public class SearchA2DMatrixII240 { public boolean searchMatrix(int[][] matrix, int target) { for (int i=0; i target) break; } } return false; } public boolean searchMatrix2(int[][] matrix, int target) { int ye = matrix.length-1; if (ye == -1) return false; int xe = matrix[0].length-1; if (xe == -1) return false; return searchMatrix(matrix, target, 0, xe, 0, ye); } public boolean searchMatrix(int[][] matrix, int target, int xs, int xe, int ys, int ye) { if (xs < 0 || ys < 0 || xs > xe || ys > ye) return false; int midx = (xe - xs)/2 + xs; int midy = (ye - ys)/2 + ys; int now = matrix[midy][midx]; if (now == target) { return true; } if (now > target) { return searchMatrix(matrix, target, xs, xe, ys, midy-1) || searchMatrix(matrix, target, xs, midx-1, midy, ye); } return searchMatrix(matrix, target, midx+1, xe, ys, ye) || searchMatrix(matrix, target, xs, midx, midy+1, ye); } /** * https://discuss.leetcode.com/topic/20064/my-concise-o-m-n-java-solution */ public boolean searchMatrix3(int[][] matrix, int target) { if(matrix == null || matrix.length < 1 || matrix[0].length <1) { return false; } int col = matrix[0].length-1; int row = 0; while(col >= 0 && row <= matrix.length-1) { if(target == matrix[row][col]) { return true; } else if(target < matrix[row][col]) { col--; } else if(target > matrix[row][col]) { row++; } } return false; } public boolean searchMatrix4(int[][] matrix, int target) { if (matrix == null) return false; if (matrix.length == 0 || matrix[0].length == 0) return false; return searchMatrix(0, 0, matrix.length-1, matrix[0].length-1, matrix, target); } public boolean searchMatrix(int loi, int loj, int hii, int hij, int[][] matrix, int target) { if (loi > hii || loj > hij) return false; if (matrix[loi][loj] > target|| matrix[hii][hij] < target) return false; int midi = (loi + hii) / 2; int midj = (loj + hij) / 2; if (matrix[midi][midj] == target) return true; if (searchMatrix(loi, midj+1, midi, hij, matrix, target) || searchMatrix(midi+1, loj, hii, midj, matrix, target)) return true; if (matrix[midi][midj] > target) return searchMatrix(loi, loj, midi, midj, matrix, target); return searchMatrix(midi+1, midj+1, hii, hij, matrix, target); } } ================================================ FILE: src/SearchForARange34.java ================================================ /** * Given an array of integers sorted in ascending order, find the starting and * ending position of a given target value. * * Your algorithm's runtime complexity must be in the order of O(log n). * * If the target is not found in the array, return [-1, -1]. * * For example, * Given [5, 7, 7, 8, 8, 10] and target value 8, * return [3, 4]. */ public class SearchForARange34 { public int[] searchRange(int[] nums, int target) { int start = 0; int end = nums.length - 1; while (start <= end) { if (nums[start] < target) { start++; } else if (nums[end] > target) { end--; } else { break; } } if (start > nums.length - 1 || end < 0 || start > end) { return new int[]{-1, -1}; } return new int[]{start, end}; } public int[] searchRange2(int[] nums, int target) { int start = 0; int end = nums.length - 1; int mid = (end - start) >> 1 + start; while (start <= end) { if (nums[mid] < target) { start = mid + 1; } else if (nums[mid] > target) { end = mid - 1; } else { break; } mid = (end - start) / 2 + start; } while (start <= end) { if (nums[start] < target) { start++; } else if (nums[end] > target) { end--; } else { break; } } if (start > nums.length - 1 || end < 0 || start > end) { return new int[]{-1, -1}; } return new int[]{start, end}; } /** * https://discuss.leetcode.com/topic/6327/a-very-simple-java-solution-with-only-one-binary-search-algorithm */ public int[] searchRange3(int[] A, int target) { int start = Solution.firstGreaterEqual(A, target); if (start == A.length || A[start] != target) { return new int[]{-1, -1}; } return new int[]{start, Solution.firstGreaterEqual(A, target + 1) - 1}; } //find the first number that is greater than or equal to target. //could return A.length if target is greater than A[A.length-1]. //actually this is the same as lower_bound in C++ STL. private static int firstGreaterEqual(int[] A, int target) { int low = 0, high = A.length; while (low < high) { int mid = low + ((high - low) >> 1); //low <= mid < high if (A[mid] < target) { low = mid + 1; } else { //should not be mid-1 when A[mid]==target. //could be mid even if A[mid]>target because mid range[1]) range[0] = -1; return range; } public void searchRange(int[] A, int target, int left, int right, int[] range) { if (left > right) return; int mid = left + (right - left) / 2; if (A[mid] == target) { if (mid < range[0]) { range[0] = mid; searchRange(A, target, left, mid - 1, range); } if (mid > range[1]) { range[1] = mid; searchRange(A, target, mid + 1, right, range); } } else if (A[mid] < target) { searchRange(A, target, mid + 1, right, range); } else { searchRange(A, target, left, mid - 1, range); } } public int[] searchRange5(int[] nums, int target) { if (nums == null || nums.length == 0) return new int[]{-1, -1}; return searchRange(nums, target, 0, nums.length-1); } public int[] searchRange(int[] nums, int target, int lo, int hi) { if (lo > hi) return new int[]{-1, -1}; int mid = (lo + hi) / 2; if (nums[mid] > target) { return searchRange(nums, target, lo, mid-1); } else if (nums[mid] < target) { return searchRange(nums, target, mid+1, hi); } else { int[] res = new int[]{mid, mid}; int[] left = searchRange(nums, target, lo, mid-1); int[] right = searchRange(nums, target, mid+1, hi); if (left[0] != -1) res[0] = left[0]; if (right[1] != -1) res[1] = right[1]; return res; } } /** * https://leetcode.com/problems/search-for-a-range/solution/ */ // returns leftmost (or rightmost) index at which `target` should be // inserted in sorted array `nums` via binary search. private int extremeInsertionIndex(int[] nums, int target, boolean left) { int lo = 0; int hi = nums.length; while (lo < hi) { int mid = (lo+hi)/2; if (nums[mid] > target || (left && target == nums[mid])) { hi = mid; } else { lo = mid+1; } } return lo; } public int[] searchRange6(int[] nums, int target) { int[] targetRange = {-1, -1}; int leftIdx = extremeInsertionIndex(nums, target, true); // assert that `leftIdx` is within the array bounds and that `target` // is actually in `nums`. if (leftIdx == nums.length || nums[leftIdx] != target) { return targetRange; } targetRange[0] = leftIdx; targetRange[1] = extremeInsertionIndex(nums, target, false)-1; return targetRange; } } ================================================ FILE: src/SearchInASortedArrayOfUnknownSize702.java ================================================ /** * Given an integer array sorted in ascending order, write a function to search * target in nums. If target exists, then return its index, otherwise * return -1. However, the array size is unknown to you. You may only access * the array using an ArrayReader interface, where ArrayReader.get(k) returns * the element of the array at index k (0-indexed). * * You may assume all integers in the array are less than 10000, and if you * access the array out of bounds, ArrayReader.get will return 2147483647. * * Example 1: * Input: array = [-1,0,3,5,9,12], target = 9 * Output: 4 * Explanation: 9 exists in nums and its index is 4 * * Example 2: * Input: array = [-1,0,3,5,9,12], target = 2 * Output: -1 * Explanation: 2 does not exist in nums so return -1 * * Note: * You may assume that all elements in the array are unique. * The value of each element in the array will be in the range [-9999, 9999]. */ public class SearchInASortedArrayOfUnknownSize702 { public int search(ArrayReader reader, int target) { return search(reader, target, 0, 10000); } private int search(ArrayReader reader, int target, int i, int j) { if (i >= j) return reader.get(i) == target ? i : -1; int mid = (i + j) / 2; int val = reader.get(mid); if (val == target) return mid; if (val > target) { return search(reader, target, i, mid-1); } else { return search(reader, target, mid+1, j); } } /** * https://leetcode.com/problems/search-in-a-sorted-array-of-unknown-size/discuss/151685/Shortest-and-cleanest-Java-solution-so-far... */ public int search2(ArrayReader reader, int target) { int hi = 1; while (reader.get(hi) < target) { hi = hi << 1; } int low = hi >> 1; while (low <= hi) { int mid = low+(hi-low)/2; if (reader.get(mid) > target) { hi = mid-1; } else if (reader.get(mid) < target) { low = mid+1; } else { return mid; } } return -1; } public int search3(ArrayReader reader, int target) { int lo = 0; int hi = 20000; while (lo < hi) { int mid = lo + (hi - lo) / 2; int midVal = reader.get(mid); if (midVal == target) return mid; if (midVal == Integer.MAX_VALUE || midVal > target) { hi = mid - 1; } else { lo = mid + 1; } } return reader.get(lo) == target ? lo : -1; } } ================================================ FILE: src/SearchInRotatedSortedArray33.java ================================================ /** * Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. * * (i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2). * * You are given a target value to search. If found in the array return its index, otherwise return -1. * * You may assume no duplicate exists in the array. */ public class SearchInRotatedSortedArray33 { public int search(int[] nums, int target) { int L = nums.length; if (L == 0) return -1; return searchHelper(nums, target, 0, L-1); } private int searchHelper(int[] nums, int target, int s, int e) { if (s > e) return -1; int mid = (e-s)/2 + s; if (nums[mid] == target) { return mid; } if (nums[s] < nums[e] && (nums[s] > target || nums[e] < target)) { return -1; } if (nums[s] > nums[e] && target < nums[s] && nums[e] < target) { return -1; } int left = searchHelper(nums, target, s, mid-1); if (left != -1) return left; return searchHelper(nums, target, mid+1, e); } /** * https://discuss.leetcode.com/topic/7711/revised-binary-search */ public int search2(int[] A, int target) { int lo = 0; int hi = A.length - 1; if (hi == -1) return -1; while (lo < hi) { int mid = (lo + hi) / 2; if (A[mid] == target) return mid; if (A[lo] <= A[mid]) { if (target >= A[lo] && target < A[mid]) { hi = mid - 1; } else { lo = mid + 1; } } else { if (target > A[mid] && target <= A[hi]) { lo = mid + 1; } else { hi = mid - 1; } } } return A[lo] == target ? lo : -1; } public int search3(int[] nums, int target) { int L = nums.length; if (L == 0) return -1; return searchHelper2(nums, target, 0, L-1); } private int searchHelper2(int[] nums, int target, int s, int e) { if (s > e) return -1; int mid = (e+s)/2; if (nums[mid] == target) { return mid; } if (nums[s] <= nums[mid]) { if (target >= nums[s] && target <= nums[mid]) { return searchHelper2(nums, target, s, mid-1); } else { return searchHelper2(nums, target, mid+1, e); } } if (target >= nums[mid] && target <= nums[e]) { return searchHelper2(nums, target, mid+1, e); } return searchHelper2(nums, target, s, mid-1); } } ================================================ FILE: src/SearchInRotatedSortedArrayII81.java ================================================ /** * Would this affect the run-time complexity? How and why? * * Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. * * (i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2). * * Write a function to determine if a given target is in the array. * * The array may contain duplicates. * * Follow up for "Search in Rotated Sorted Array": * What if duplicates are allowed? */ public class SearchInRotatedSortedArrayII81 { public boolean search(int[] nums, int target) { System.out.println(Arrays.toString(nums)); int L = nums.length; if (L == 0) return false; int mid = L/2; if (nums[mid] == target) { return true; } return (search(Arrays.copyOfRange(nums, 0, mid), target) || search(Arrays.copyOfRange(nums, mid+1, L), target)); } // now, let's truncate it, and do not use array copy // public boolean search(int[] nums, int target) { // int L = nums.length; // if (L == 0) return false; // // if (nums[0] < nums[L-1] && (nums[0] > target || nums[L-1] < target)) { // return false; // } // // if (nums[0] > nums[L-1] && target < nums[0] && nums[L-1] < target) { // return false; // } // // int mid = L/2; // if (nums[mid] == target) { // return true; // } // // return (search(Arrays.copyOfRange(nums, 0, mid), target) || // search(Arrays.copyOfRange(nums, mid+1, L), target)); // } //now, let's truncate it, and do not use array copy public boolean search2(int[] nums, int target) { int L = nums.length; if (L == 0) return false; return searchHelper(nums, target, 0, L-1); } private boolean searchHelper(int[] nums, int target, int s, int e) { if (s > e) return false; int mid = (e-s)/2 + s; if (nums[mid] == target) { return true; } if (nums[s] < nums[e] && (nums[s] > target || nums[e] < target)) { return false; } if (nums[s] > nums[e] && target < nums[s] && nums[e] < target) { return false; } return (searchHelper(nums, target, s, mid-1) || searchHelper(nums, target, mid+1, e)); } /** * https://discuss.leetcode.com/topic/25487/neat-java-solution-using-binary-search */ public boolean search3(int[] nums, int target) { int start = 0, end = nums.length - 1; //check each num so we will check start == end //We always get a sorted part and a half part //we can check sorted part to decide where to go next while(start <= end){ int mid = start + (end - start)/2; if(nums[mid] == target) return true; //if left part is sorted if(nums[start] < nums[mid]){ if(target < nums[start] || target > nums[mid]){ //target is in rotated part start = mid + 1; }else{ end = mid - 1; } }else if(nums[start] > nums[mid]){ //right part is sorted //target is in rotated part if(target < nums[mid] || target > nums[end]){ end = mid -1; }else{ start = mid + 1; } }else{ //duplicates, we know nums[mid] != target, so nums[start] != target //based on current information, we can only move left pointer to skip one cell //thus in the worest case, we would have target: 2, and array like 11111111, then //the running time would be O(n) start ++; } } return false; } public boolean search4(int[] nums, int target) { int L = nums.length; if (L == 0) return false; return searchHelper2(nums, target, 0, L-1); } private boolean searchHelper2(int[] nums, int target, int s, int e) { if (s > e) return false; int mid = (e+s)/2; if (nums[mid] == target) { return true; } if (nums[s] < nums[mid]) { if (target >= nums[s] && target <= nums[mid]) { return searchHelper2(nums, target, s, mid-1); } else { return searchHelper2(nums, target, mid+1, e); } } else if (nums[s] > nums[mid]) { if (target >= nums[mid] && target <= nums[e]) { return searchHelper2(nums, target, mid+1, e); } else { return searchHelper2(nums, target, s, mid-1); } } else { return searchHelper2(nums, target, s+1, e); } } /** * https://leetcode.com/problems/search-in-rotated-sorted-array-ii/discuss/28212/When-there-are-duplicates-the-worst-case-is-O(n).-Could-we-do-better */ public boolean search5(int A[], int key) { int l = 0, r = A.length - 1; while (l <= r) { int m = l + (r - l)/2; if (A[m] == key) return true; //return m in Search in Rotated Array I if (A[l] < A[m]) { //left half is sorted if (A[l] <= key && key < A[m]) r = m - 1; else l = m + 1; } else if (A[l] > A[m]) { //right half is sorted if (A[m] < key && key <= A[r]) l = m + 1; else r = m - 1; } else l++; } return false; } public boolean search6(int[] nums, int target) { if (nums == null || nums.length == 0) return false; int start = 0; int end = nums.length - 1; while (start < end) { int mid = start + (end - start) / 2; int midVal = nums[mid]; if (midVal == target) return true; if (midVal > nums[start]) { if (target >= nums[start] && target < midVal) { end = mid -1; } else { start = mid + 1; } } else if (midVal < nums[end]) { if (target > midVal && target <= nums[end]) { start = mid + 1; } else { end= mid - 1; } } else { if (midVal == nums[start]) { start++; } if (midVal == nums[end]) { end--; } } } return nums[start] == target; } } ================================================ FILE: src/SearchInsertPosition35.java ================================================ /** * Given a sorted array and a target value, return the index if the target is * found. If not, return the index where it would be if it were inserted in * order. * * You may assume no duplicates in the array. * * Here are few examples. * [1,3,5,6], 5 → 2 * [1,3,5,6], 2 → 1 * [1,3,5,6], 7 → 4 * [1,3,5,6], 0 → 0 */ public class SearchInsertPosition35 { public int searchInsert(int[] nums, int target) { for (int i = 0; i < nums.length; i++) { if (nums[i] >= target) { return i; } } return nums.length; } /** * https://discuss.leetcode.com/topic/7874/my-8-line-java-solution */ public int searchInsert2(int[] A, int target) { int low = 0, high = A.length-1; while(low <= high){ int mid = (low + high) / 2; if(A[mid] == target) return mid; else if(A[mid] > target) high = mid-1; else low = mid+1; } return low; } public int searchInsert3(int[] nums, int target) { if (nums.length == 0) return 0; if (target > nums[nums.length-1]) return nums.length; int l = 0; int r = nums.length-1; while (l < r) { int mid = (r - l) / 2 + l; if (nums[mid] == target) return mid; else if (nums[mid] < target) { l = mid + 1; } else { r = mid; } } return l; } } ================================================ FILE: src/SecondMinimumNodeInABinaryTree671.java ================================================ /** * Given a non-empty special binary tree consisting of nodes with the * non-negative value, where each node in this tree has exactly two or zero * sub-node. If the node has two sub-nodes, then this node's value is the * smaller value among its two sub-nodes. * * Given such a binary tree, you need to output the second minimum value in the * set made of all the nodes' value in the whole tree. * * If no such second minimum value exists, output -1 instead. * * Example 1: * Input: * 2 * / \ * 2 5 * / \ * 5 7 * * Output: 5 * Explanation: The smallest value is 2, the second smallest value is 5. * * Example 2: * Input: * 2 * / \ * 2 2 * * Output: -1 * Explanation: The smallest value is 2, but there isn't any second smallest * value. */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class SecondMinimumNodeInABinaryTree671 { public int findSecondMinimumValue(TreeNode root) { if (root == null) return -1; int[] cache = new int[]{-1, -1}; dfs(root, cache, root.val); if (cache[0] == -1 || cache[1] == -1) return -1; return Math.max(Math.max(cache[0], -1), cache[1]); } private void dfs(TreeNode root, int[] cache, int min) { if (root == null) return; int val = root.val; if (cache[0] != val && cache[1] != val) { if (cache[0] == -1) { cache[0] = val; } else if (cache[1] == -1) { cache[1] = val; } else { if (cache[0] > val) { cache[0] = val; } else if (cache[1] > val) { cache[1] = val; } } } if (val > min) return; dfs(root.left, cache, min); dfs(root.right, cache, min); } } ================================================ FILE: src/SentenceScreenFitting418.java ================================================ /** * Given a rows x cols screen and a sentence represented by a list of non-empty * words, find how many times the given sentence can be fitted on the screen. * * Note: * A word cannot be split into two lines. * The order of words in the sentence must remain unchanged. * Two consecutive words in a line must be separated by a single space. * Total words in the sentence won't exceed 100. * Length of each word is greater than 0 and won't exceed 10. * 1 ≤ rows, cols ≤ 20,000. * * Example 1: * Input: * rows = 2, cols = 8, sentence = ["hello", "world"] * Output: 1 * Explanation: * hello--- * world--- * The character '-' signifies an empty space on the screen. * * Example 2: * Input: * rows = 3, cols = 6, sentence = ["a", "bcd", "e"] * Output: 2 * Explanation: * a-bcd- * e-a--- * bcd-e- * The character '-' signifies an empty space on the screen. * * Example 3: * Input: * rows = 4, cols = 5, sentence = ["I", "had", "apple", "pie"] * Output: 1 * Explanation: * I-had * apple * pie-I * had-- * The character '-' signifies an empty space on the screen. */ public class SentenceScreenFitting418 { /** * https://leetcode.com/problems/sentence-screen-fitting/discuss/90845/21ms-18-lines-Java-solution */ public int wordsTyping(String[] sentence, int rows, int cols) { String s = String.join(" ", sentence) + " "; int start = 0, l = s.length(); for (int i = 0; i < rows; i++) { start += cols; if (s.charAt(start % l) == ' ') { start++; } else { while (start > 0 && s.charAt((start-1) % l) != ' ') { start--; } } } return start / s.length(); } /** * https://leetcode.com/problems/sentence-screen-fitting/discuss/90846/JAVA-optimized-solution-17ms */ public int wordsTyping2(String[] sentence, int rows, int cols) { int[] nextIndex = new int[sentence.length]; int[] times = new int[sentence.length]; for(int i=0;i 0) len -= sentence[i - 1].length() + 1; // calculate the start of next line. // it's OK the index is beyond the length of array so that // we can use it to count how many words one row has. while(len + sentence[prev % n].length() <= cols) len += sentence[prev++ % n].length() + 1; dp[i] = prev; } int count = 0; for(int i = 0, k = 0; i < rows; ++i) { // count how many words one row has and move to start of next row. // It's better to check if d[k] == k but I find there is no test case on it. // if(dp[k] == k) return 0; count += dp[k] - k; k = dp[k] % n; } // divide by the number of words in sentence return count / n; } public int wordsTyping4(String[] sentence, int rows, int cols) { char[] words = (String.join(" ", sentence) + " ").toCharArray(); int len = words.length; int[] marks = new int[len]; int j = 0; for (int i=0; i> similarity = new HashMap<>(); for (String[] pair: pairs) { if (!similarity.containsKey(pair[0])) similarity.put(pair[0], new HashSet<>()); if (!similarity.containsKey(pair[1])) similarity.put(pair[1], new HashSet<>()); similarity.get(pair[0]).add(pair[1]); similarity.get(pair[1]).add(pair[0]); } int len = words1.length; for (int i=0; i parent = new HashMap<>(); Map rank = new HashMap<>(); public DisjointSet(String[][] pairs) { for (String[] pair: pairs) { if (!parent.containsKey(pair[0])) { parent.put(pair[0], pair[0]); rank.put(pair[0], 0); } if (!parent.containsKey(pair[1])) { parent.put(pair[1], pair[1]); rank.put(pair[1], 0); } union(pair[0], pair[1]); } } public String find(String word) { if (parent.containsKey(word) && !parent.get(word).equals(word)) { parent.put(word, find(parent.get(word))); } return parent.get(word); } public void union(String w1, String w2) { String p1 = find(w1); String p2 = find(w2); int r1 = rank.get(p1); int r2 = rank.get(p2); if (r1 > r2) { parent.put(p2, p1); } else if (r1 < r2) { parent.put(p1, p2); } else { parent.put(p1, p2); rank.put(p2, r2+1); } } } /** * https://leetcode.com/problems/sentence-similarity-ii/solution/ */ public boolean areSentencesSimilarTwo2(String[] words1, String[] words2, String[][] pairs) { if (words1.length != words2.length) return false; Map index = new HashMap(); int count = 0; DSU dsu = new DSU(2 * pairs.length); for (String[] pair: pairs) { for (String p: pair) if (!index.containsKey(p)) { index.put(p, count++); } dsu.union(index.get(pair[0]), index.get(pair[1])); } for (int i = 0; i < words1.length; ++i) { String w1 = words1[i], w2 = words2[i]; if (w1.equals(w2)) continue; if (!index.containsKey(w1) || !index.containsKey(w2) || dsu.find(index.get(w1)) != dsu.find(index.get(w2))) return false; } return true; } class DSU { int[] parent; public DSU(int N) { parent = new int[N]; for (int i = 0; i < N; ++i) parent[i] = i; } public int find(int x) { if (parent[x] != x) parent[x] = find(parent[x]); return parent[x]; } public void union(int x, int y) { parent[find(x)] = find(y); } } } ================================================ FILE: src/SerializeAndDeserializeBST449.java ================================================ /** * Serialization is the process of converting a data structure or object into a * sequence of bits so that it can be stored in a file or memory buffer, or * transmitted across a network connection link to be reconstructed later in * the same or another computer environment. * * Design an algorithm to serialize and deserialize a binary search tree. There * is no restriction on how your serialization/deserialization algorithm should * work. You just need to ensure that a binary search tree can be serialized to * a string and this string can be deserialized to the original tree structure. * * The encoded string should be as compact as possible. * * Note: Do not use class member/global/static variables to store states. Your * serialize and deserialize algorithms should be stateless. */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class SerializeAndDeserializeBST449 { // Level-Order, BFS, Iteratively class Codec { // Encodes a tree to a single string. public String serialize(TreeNode root) { Queue q = new LinkedList<>(); StringBuilder sb = new StringBuilder(); q.add(root); while (!q.isEmpty()) { TreeNode curr = q.poll(); if (curr == null) { sb.append("#,"); } else { sb.append(curr.val + ","); q.add(curr.left); q.add(curr.right); } } return sb.substring(0, sb.length()-1).toString(); } // Decodes your encoded data to tree. public TreeNode deserialize(String data) { String[] strs = data.split(","); TreeNode root = strs[0].equals("#") ? null : new TreeNode(Integer.valueOf(strs[0])); Queue q = new LinkedList<>(); q.add(root); int i = 1; while (i<=strs.length-2) { TreeNode p = q.poll(); if (p != null) { TreeNode left = strs[i].equals("#") ? null : new TreeNode(Integer.valueOf(strs[i])); TreeNode right = strs[i+1].equals("#") ? null : new TreeNode(Integer.valueOf(strs[i+1])); p.left = left; p.right = right; q.add(left); q.add(right); i += 2; } } return root; } } // Pre-Order, DFS, Resursively class Codec2 { // Encodes a tree to a single string. public String serialize2(TreeNode root) { if (root == null) return ""; StringBuilder sb = new StringBuilder(); serialize(root, sb); return sb.substring(0, sb.length()-1).toString(); } private void serialize(TreeNode root, StringBuilder sb) { if (root == null) return; sb.append(root.val + ","); serialize(root.left, sb); serialize(root.right, sb); } // Decodes your encoded data to tree. public TreeNode deserialize2(String data) { String[] strs = data.split(","); if (strs.length == 0 || strs[0].equals("")) return null; return deserialize(strs, 0, strs.length-1); } private TreeNode deserialize(String[] strs, int lo, int hi) { if (lo > hi) return null; if (lo == hi) return new TreeNode(Integer.valueOf(strs[lo])); int rootVal = Integer.valueOf(strs[lo]); TreeNode root = new TreeNode(Integer.valueOf(strs[lo])); int rightIdx = rightStart(strs, lo+1, hi, rootVal); root.left = deserialize(strs, lo+1, rightIdx-1); root.right = deserialize(strs, rightIdx, hi); return root; } private int rightStart(String[] strs, int lo, int hi, int rootVal) { for (int i=lo; i<=hi; i++) { if (Integer.valueOf(strs[i]) > rootVal) return i; } return hi+1; } } // https://leetcode.com/problems/serialize-and-deserialize-bst/discuss/93175/Java-PreOrder-+-Queue-solution // Pre-Order, DFS, Iteratively class Codec3 { private static final String SEP = ","; private static final String NULL = "null"; // Encodes a tree to a single string. public String serialize(TreeNode root) { StringBuilder sb = new StringBuilder(); if (root == null) return NULL; //traverse it recursively if you want to, I am doing it iteratively here Stack st = new Stack<>(); st.push(root); while (!st.empty()) { root = st.pop(); sb.append(root.val).append(SEP); if (root.right != null) st.push(root.right); if (root.left != null) st.push(root.left); } return sb.toString(); } // Decodes your encoded data to tree. // pre-order traversal public TreeNode deserialize(String data) { if (data.equals(NULL)) return null; String[] strs = data.split(SEP); Queue q = new LinkedList<>(); for (String e : strs) { q.offer(Integer.parseInt(e)); } return getNode(q); } // some notes: // 5 // 3 6 // 2 7 private TreeNode getNode(Queue q) { //q: 5,3,2,6,7 if (q.isEmpty()) return null; TreeNode root = new TreeNode(q.poll());//root (5) Queue samllerQueue = new LinkedList<>(); while (!q.isEmpty() && q.peek() < root.val) { samllerQueue.offer(q.poll()); } //smallerQueue : 3,2 storing elements smaller than 5 (root) root.left = getNode(samllerQueue); //q: 6,7 storing elements bigger than 5 (root) root.right = getNode(q); return root; } } // https://leetcode.com/problems/serialize-and-deserialize-bst/discuss/93170/pre-or-post-order-with-only-keeping-one-bound(beat-98-and-95) // Pre-Order, DFS, Resursively class Codec4 { // Encodes a tree to a single string. public String serialize(TreeNode root) { if (root == null) { return null; } StringBuilder sb = new StringBuilder(); serialize(root, sb); return sb.toString(); } private void serialize(TreeNode root, StringBuilder sb) { if (root == null) { return; } sb.append(root.val).append(" "); serialize(root.left, sb); serialize(root.right, sb); } // Decodes your encoded data to tree. public TreeNode deserialize(String data) { if (data == null || data.length() == 0) { return null; } String[] nodes = data.split(" "); int[] index = new int[] {0}; return deserialize(nodes, index, Integer.MAX_VALUE); } private TreeNode deserialize(String[] nodes, int[] index, int max) { if (index[0] >= nodes.length || Integer.valueOf(nodes[index[0]]) >= max) { return null; } TreeNode root = new TreeNode(Integer.valueOf(nodes[index[0]++])); root.left = deserialize(nodes, index, root.val); root.right = deserialize(nodes, index, max); return root; } } // https://leetcode.com/problems/serialize-and-deserialize-bst/discuss/93170/pre-or-post-order-with-only-keeping-one-bound(beat-98-and-95) // Post-Order, DFS, Resursively class Codec5 { // Encodes a tree to a single string. public String serialize(TreeNode root) { if (root == null) { return null; } StringBuilder sb = new StringBuilder(); serialize(root, sb); return sb.toString(); } private void serialize(TreeNode root, StringBuilder sb) { if (root == null) { return; } serialize(root.left, sb); serialize(root.right, sb); sb.append(Integer.valueOf(root.val)).append(" "); } // Decodes your encoded data to tree. public TreeNode deserialize(String data) { if (data == null || data.length() == 0) { return null; } String[] nodes = data.split(" "); int[] index = new int[] {nodes.length - 1}; return deserialize(nodes, index, Integer.MIN_VALUE); } private TreeNode deserialize(String[] nodes, int[] index, int min) { if (index[0] < 0 || Integer.valueOf(nodes[index[0]]) <= min) { return null; } TreeNode root = new TreeNode(Integer.valueOf(nodes[index[0]--])); root.right = deserialize(nodes, index, root.val); root.left = deserialize(nodes, index, min); return root; } } // Your Codec object will be instantiated and called as such: // Codec codec = new Codec(); // codec.deserialize(codec.serialize(root)); } ================================================ FILE: src/SerializeAndDeserializeBinaryTree297.java ================================================ /** * Serialization is the process of converting a data structure or object into a * sequence of bits so that it can be stored in a file or memory buffer, or * transmitted across a network connection link to be reconstructed later in the * same or another computer environment. * * Design an algorithm to serialize and deserialize a binary tree. There is no * restriction on how your serialization/deserialization algorithm should work. * You just need to ensure that a binary tree can be serialized to a string and * this string can be deserialized to the original tree structure. * * For example, you may serialize the following tree * * 1 * / \ * 2 3 * / \ * 4 5 * as "[1,2,3,null,null,4,5]", just the same as how LeetCode OJ serializes a * binary tree (https://leetcode.com/faq/#binary-tree). You do not necessarily * need to follow this format, so please be creative and come up with different * approaches yourself. * * Note: Do not use class member/global/static variables to store states. Your * serialize and deserialize algorithms should be stateless. * */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class SerializeAndDeserializeBinaryTree297 { class Codec { // Encodes a tree to a single string. public String serialize(TreeNode root) { if (root == null) return "[]"; StringBuilder sb = new StringBuilder(); sb.append('['); Queue q = new LinkedList<>(); q.add(root); int nulls = 0; while (!q.isEmpty()) { TreeNode n = q.remove(); if (n == null) { nulls++; sb.append("null,"); } else { nulls = 0; sb.append(n.val + ","); q.add(n.left); q.add(n.right); } } while (nulls > 0) { sb.delete(sb.length()-5, sb.length()); nulls--; } sb.setCharAt(sb.length()-1, ']'); return sb.toString(); } // Decodes your encoded data to tree. public TreeNode deserialize(String data) { String[] nums = data.substring(1, data.length()-1).split(","); if (nums.length <= 0 || nums[0].equals("")) return null; TreeNode res = new TreeNode(Integer.valueOf(nums[0])); Queue q = new LinkedList<>(); q.add(res); int i = 1; while (i < nums.length) { int add = 1; TreeNode parent = q.remove(); TreeNode left = null; if (!nums[i].equals("null")) { left = new TreeNode(Integer.valueOf(nums[i])); q.add(left); } TreeNode right = null; if (i+1 < nums.length) { add++; if (!nums[i+1].equals("null")) { right = new TreeNode(Integer.valueOf(nums[i+1])); q.add(right); } } parent.left = left; parent.right = right; i += add; } return res; } } } // Your Codec object will be instantiated and called as such: // Codec codec = new Codec(); // codec.deserialize(codec.serialize(root)); // // preorder, DFS // public class Codec { // // // Encodes a tree to a single string. // public String serialize(TreeNode root) { // StringBuilder sb = new StringBuilder(); // serialize(root, sb); // System.out.println(sb.toString()); // return sb.toString(); // } // // private void serialize(TreeNode root, StringBuilder sb) { // if (root == null) { // sb.append('N').append(','); // } else { // sb.append(root.val).append(','); // serialize(root.left, sb); // serialize(root.right, sb); // } // } // // // Decodes your encoded data to tree. // public TreeNode deserialize(String data) { // return deserialize(data.split(","), new int[]{0}); // } // // public TreeNode deserialize(String[] data, int[] is) { // if (is[0] >= data.length) return null; // String val = data[is[0]]; // is[0]++; // if (val.equals("N")) { // return null; // } else { // TreeNode node = new TreeNode(Integer.valueOf(val)); // node.left = deserialize(data, is); // node.right = deserialize(data, is); // return node; // } // } // } ================================================ FILE: src/SetMatrixZeroes73.java ================================================ /** * Given a m x n matrix, if an element is 0, set its entire row and column * to 0. Do it in place. * * Follow up: * Did you use extra space? * A straight forward solution using O(mn) space is probably a bad idea. * A simple improvement uses O(m + n) space, but still not the best solution. * Could you devise a constant space solution? */ public class SetMatrixZeroes73 { public void setZeroes(int[][] matrix) { boolean[] rows = new boolean[matrix.length]; boolean[] cols = new boolean[matrix[0].length]; for (int i=0; i edge = findOneIslandEdge(A, visited); int res = 0; while (!edge.isEmpty()) { int len = edge.size(); for (int i=0; i= 0 && ii < m && jj >= 0 && jj < n && !visited[ii][jj]) { if (A[ii][jj] == 0) { edge.add(new int[]{ii, jj}); visited[ii][jj] = true; } else { return res; } } } } res++; } return res; } private Queue findOneIslandEdge(int[][] A, boolean[][] visited) { int m = A.length; int n = A[0].length; for (int i=0; i collectEdge(int[][] A, int si, int sj, boolean[][] visited) { Queue edge = new LinkedList<>(); Queue q = new LinkedList<>(); int m = A.length; int n = A[0].length; visited[si][sj] = true; q.add(new int[]{si, sj}); while (!q.isEmpty()) { int[] curr = q.remove(); boolean isEdge = false; for (int k=0; k<4; k++) { int ii = curr[0] + DIR[k][0]; int jj = curr[1] + DIR[k][1]; if (ii >= 0 && ii < m && jj >= 0 && jj < n && !visited[ii][jj]) { if (A[ii][jj] == 0) { isEdge = true; } else { q.add(new int[]{ii, jj}); visited[ii][jj] = true; } } } if (isEdge) { edge.add(curr); } } return edge; } } ================================================ FILE: src/ShortestCompletingWord748.java ================================================ /** * Find the minimum length word from a given dictionary words, which has all * the letters from the string licensePlate. Such a word is said to complete * the given string licensePlate * * Here, for letters we ignore case. For example, "P" on the licensePlate still * matches "p" on the word. * * It is guaranteed an answer exists. If there are multiple answers, return the * one that occurs first in the array. * * The license plate might have the same letter occurring multiple times. For * example, given a licensePlate of "PP", the word "pair" does not complete the * licensePlate, but the word "supper" does. * * Example 1: * Input: licensePlate = "1s3 PSt", words = ["step", "steps", "stripe", "stepple"] * Output: "steps" * Explanation: The smallest length word that contains the letters "S", "P", * "S", and "T". * Note that the answer is not "step", because the letter "s" must occur in the * word twice. Also note that we ignored case for the purposes of comparin * whether a letter exists in the word. * * Example 2: * Input: licensePlate = "1s3 456", words = ["looks", "pest", "stew", "show"] * Output: "pest" * Explanation: There are 3 smallest length words that contains the letters "s". * We return the one that occurred first. * * Note: * licensePlate will be a string with length in range [1, 7]. * licensePlate will contain digits, spaces, or letters (uppercase or lowercase). * words will have a length in the range [10, 1000]. * Every words[i] will consist of lowercase letters, and have length in range [1, 15]. */ class ShortestCompletingWord748 { public String shortestCompletingWord(String licensePlate, String[] words) { int[] charMap = new int[26]; for (char c: licensePlate.toCharArray()) { if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { char lowerC = Character.toLowerCase(c); charMap[lowerC - 'a'] += 1; } } String res = ""; int len = Integer.MAX_VALUE; for (String word: words) { int[] map = new int[26]; for (char c: word.toCharArray()) map[c - 'a'] += 1; boolean match = true; for (int i=0; i<26; i++) { if (map[i] < charMap[i]) { match = false; break; } } if (match && word.length() < len) { res = word; len = word.length(); } } return res; } } ================================================ FILE: src/ShortestDistanceFromAllBuildings317.java ================================================ /** * You want to build a house on an empty land which reaches all buildings in * the shortest amount of distance. You can only move up, down, left and right. * You are given a 2D grid of values 0, 1 or 2, where: * * Each 0 marks an empty land which you can pass by freely. * Each 1 marks a building which you cannot pass through. * Each 2 marks an obstacle which you cannot pass through. * * Example: * * Input: [[1,0,2,0,1],[0,0,0,0,0],[0,0,1,0,0]] * * 1 - 0 - 2 - 0 - 1 * | | | | | * 0 - 0 - 0 - 0 - 0 * | | | | | * 0 - 0 - 1 - 0 - 0 * * Output: 7 * * Explanation: Given three buildings at (0,0), (0,4), (2,2), and an obstacle * at (0,2), the point (1,2) is an ideal empty land to build a house, as * the total travel distance of 3+3+1=7 is minimal. So return 7. * * Note: * There will be at least one building. If it is not possible to build such * house according to the above rules, return -1. */ public class ShortestDistanceFromAllBuildings317 { private int[][] dirs = new int[][]{{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; public int shortestDistance(int[][] grid) { if (grid == null) return -1; int m = grid.length; int n = grid[0].length; if (m == 0 || n == 0 || (m == 1 && n == 1)) return -1; int numBuildings = 0; int[][] reached = new int[m][n]; int[][] allDists = new int[m][n]; for (int i=0; i= m || j >= n || (grid[i][j] == 1 && d != 0) || grid[i][j] == 2) return; if (visited[i][j] && dist[i][j] <= d) return; if (!visited[i][j]) { reached[i][j]++; } else { allDists[i][j] -= dist[i][j]; } allDists[i][j] += d; dist[i][j] = d; visited[i][j] = true; for (int[] dir: dirs) { dfs(grid, dist, allDists, visited, reached, d+1, i+dir[0], j+dir[1], m, n); } } public int shortestDistance2(int[][] grid) { if (grid == null) return -1; int m = grid.length; int n = grid[0].length; if (m == 0 || n == 0 || (m == 1 && n == 1)) return -1; int numBuildings = 0; int[][] reached = new int[m][n]; int[][] allDists = new int[m][n]; for (int i=0; i q = new LinkedList<>(); for (int[] dir: dirs) { int i = x + dir[0]; int j = y + dir[1]; if (i < 0 || j < 0 || i >= m || j >= n || grid[i][j] == 1 || grid[i][j] == 2) continue; q.add(new Point(i, j)); added[i][j] = true; } int d = 0; while (!q.isEmpty()) { d++; int size = q.size(); for (int k=0; k= m || jj >= n || grid[ii][jj] == 1 || grid[ii][jj] == 2 || added[ii][jj]) continue; q.add(new Point(ii, jj)); added[ii][jj] = true; } } } } class Point { int x; int y; Point(int i, int j) { x = i; y = j; } } } ================================================ FILE: src/ShortestPalindrome214.java ================================================ /** * Given a string s, you are allowed to convert it to a palindrome by adding * characters in front of it. Find and return the shortest palindrome you can * find by performing this transformation. * * Example 1: * Input: "aacecaaa" * Output: "aaacecaaa" * * Example 2: * Input: "abcd" * Output: "dcbabcd" */ public class ShortestPalindrome214 { public String shortestPalindrome(String s) { int len = s.length(); if (len <= 1) return s; String res = null; char[] chars = s.toCharArray(); for (int r=len-1; r>=0; r--) { if (shortestPalindrome(chars, 0, r)) { StringBuilder sb = new StringBuilder(); for (int i=len-1; i>r; i--) { sb.append(chars[i]); } sb.append(chars); return sb.toString(); } } return ""; } private boolean shortestPalindrome(char[] chars, int left, int right) { while (left < right) { if (chars[left] != chars[right]) return false; left++; right--; } return true; } public String shortestPalindrome2(String s) { int len = s.length(); if (len <= 1) return s; String rev = new StringBuilder(s).reverse().toString(); char[] chars = (s + "#" + rev).toCharArray(); int[] prefix = prefix(chars); return rev.substring(0, len - prefix[prefix.length - 1]) + s; } private int[] prefix(char[] chars) { int len = chars.length; int[] res = new int[len]; res[0] = 0; for (int i=1; i 0 && chars[i] != chars[j]) { j = res[j-1]; } if (chars[i] == chars[j]) { j++; } res[i] = j; } return res; } } ================================================ FILE: src/ShortestPathToGetAllKeys864.java ================================================ /** * We are given a 2-dimensional grid. "." is an empty cell, "#" is a wall, "@" * is the starting point, ("a", "b", ...) are keys, and ("A", "B", ...) are * locks. * * We start at the starting point, and one move consists of walking one space * in one of the 4 cardinal directions. We cannot walk outside the grid, or * walk into a wall. If we walk over a key, we pick it up. We can't walk over * a lock unless we have the corresponding key. * * For some 1 <= K <= 6, there is exactly one lowercase and one uppercase * letter of the first K letters of the English alphabet in the grid. This * means that there is exactly one key for each lock, and one lock for each * key; and also that the letters used to represent the keys and locks were * chosen in the same order as the English alphabet. * * Return the lowest number of moves to acquire all keys. * If it's impossible, return -1. * * Example 1: * Input: ["@.a.#","###.#","b.A.B"] * Output: 8 * * Example 2: * Input: ["@..aA","..B#.","....b"] * Output: 6 * * Note: * 1 <= grid.length <= 30 * 1 <= grid[0].length <= 30 * grid[i][j] contains only '.', '#', '@', 'a'-'f' and 'A'-'F' * The number of keys is in [1, 6]. * Each key has a different letter and opens exactly one lock. */ public class ShortestPathToGetAllKeys864 { private int[][] directions = new int[][]{{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; public int shortestPathAllKeys(String[] grid) { int M = grid.length; int N = grid[0].length(); char[][] maze = new char[M][N]; int numKeys = 0; int[] start = new int[2]; for (int i=0; i= 'a' && row[j] <= 'f') { numKeys++; } } } int[] res = new int[]{Integer.MAX_VALUE}; Set keySet = new HashSet<>(); helper(maze, start, numKeys, keySet, 0, M, N, res); return res[0] == Integer.MAX_VALUE ? -1 : res[0]; } public void helper(char[][] maze, int[] start, int numKeys, Set keySet, int steps, int M, int N, int[] res) { if (numKeys == keySet.size()) { res[0] = Math.min(res[0], steps); return; } boolean[][] visited = new boolean[M][N]; Queue q = new LinkedList<>(); q.add(start); visited[start[0]][start[1]] = true; Set newKeys = new HashSet<>(); int level = 1; while (!q.isEmpty() && steps + level < res[0]) { int size = q.size(); for (int i=0; i= M || y >= N) continue; char next = maze[x][y]; if (next == '#' || visited[x][y]) continue; if (next == '@' || next == '.') { q.add(new int[]{x, y}); visited[x][y] = true; } else if (next >= 'a' && next <= 'f') { if (!keySet.contains(next)) { newKeys.add(new int[]{x, y, level}); } else { q.add(new int[]{x, y}); visited[x][y] = true; } } else if (next >= 'A' && next <= 'F') { if (keySet.contains(Character.toLowerCase(next))) { q.add(new int[]{x, y}); visited[x][y] = true; } } } } level++; } if (!newKeys.isEmpty()) { for (int[] newKey: newKeys) { int[] newKeyPos = new int[]{newKey[0], newKey[1]}; char key = maze[newKey[0]][newKey[1]]; keySet.add(key); helper(maze, newKeyPos, numKeys, keySet, steps + newKey[2], M, N, res); keySet.remove(key); } } } } ================================================ FILE: src/ShortestSubarrayWithSumAtLeastK862.java ================================================ /** * Return the length of the shortest, non-empty, contiguous subarray of A with * sum at least K. * * If there is no non-empty subarray with sum at least K, return -1. * * Example 1: * Input: A = [1], K = 1 * Output: 1 * * Example 2: * Input: A = [1,2], K = 4 * Output: -1 * * Example 3: * Input: A = [2,-1,2], K = 3 * Output: 3 * * Note: * 1 <= A.length <= 50000 * -10 ^ 5 <= A[i] <= 10 ^ 5 * 1 <= K <= 10 ^ 9 */ public class ShortestSubarrayWithSumAtLeastK862 { public int shortestSubarray(int[] A, int K) { int res = Integer.MAX_VALUE; int sum = 0; Map map = new HashMap<>(); List list = new ArrayList<>(); list.add(0); map.put(0, -1); for (int i=0; i= 0) { int val = list.get(idx); if (sum - val >= K && i - map.get(val) < res) { res = i - map.get(val); } } while (!list.isEmpty() && list.get(list.size() - 1) >= sum) { int val = list.remove(list.size()-1); } list.add(sum); map.put(sum, i); } return res == Integer.MAX_VALUE ? -1 : res; } public int shortestSubarray2(int[] A, int K) { int res = Integer.MAX_VALUE; int sum = 0; Map map = new HashMap<>(); LinkedList list = new LinkedList<>(); list.add(0); map.put(0, -1); for (int i=0; i= K) { int val = list.removeFirst(); if (i - map.get(val) < res) { res = i - map.get(val); } map.remove(val); } while (!list.isEmpty() && list.getLast() >= sum) { int val = list.removeLast(); map.remove(val); } list.add(sum); map.put(sum, i); } return res == Integer.MAX_VALUE ? -1 : res; } /** * https://leetcode.com/problems/shortest-subarray-with-sum-at-least-k/solution/ */ public int shortestSubarray3(int[] A, int K) { int N = A.length; long[] P = new long[N+1]; for (int i = 0; i < N; ++i) P[i+1] = P[i] + (long) A[i]; // Want smallest y-x with P[y] - P[x] >= K int ans = N+1; // N+1 is impossible Deque monoq = new LinkedList(); //opt(y) candidates, as indices of P for (int y = 0; y < P.length; ++y) { // Want opt(y) = largest x with P[x] <= P[y] - K; while (!monoq.isEmpty() && P[y] <= P[monoq.getLast()]) monoq.removeLast(); while (!monoq.isEmpty() && P[y] >= P[monoq.getFirst()] + K) ans = Math.min(ans, y - monoq.removeFirst()); monoq.addLast(y); } return ans < N+1 ? ans : -1; } } ================================================ FILE: src/ShortestWordDistance243.java ================================================ /** * Given a list of words and two words word1 and word2, return the shortest * distance between these two words in the list. * * Example: * Assume that words = ["practice", "makes", "perfect", "coding", "makes"]. * * Input: word1 = “coding”, word2 = “practice” * Output: 3 * * Input: word1 = "makes", word2 = "coding" * Output: 1 * * Note: * You may assume that word1 does not equal to word2, and word1 and word2 are * both in the list. */ public class ShortestWordDistance243 { public int shortestDistance(String[] words, String word1, String word2) { int last1 = -1; int last2 = -1; int res = Integer.MAX_VALUE; for (int i=0; i0; i--) { int idx = rand.nextInt(i+1); swap(randomed, idx, i); } return randomed; } private void swap(int[] arr, int i, int j) { int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } } /** * Your Solution object will be instantiated and called as such: * Solution obj = new Solution(nums); * int[] param_1 = obj.reset(); * int[] param_2 = obj.shuffle(); */ } ================================================ FILE: src/SimplifyPath71.java ================================================ /** * Given an absolute path for a file (Unix-style), simplify it. * * For example, * path = "/home/", => "/home" * path = "/a/./b/../../c/", => "/c" * * Corner Cases: * - Did you consider the case where path = "/../"? * In this case, you should return "/". * - Another corner case is the path might contain multiple slashes '/' together, such as "/home//foo/". * In this case, you should ignore redundant slashes and return "/home/foo". */ public class SimplifyPath71 { public String simplifyPath(String path) { String[] parts = path.split("/", -1); List result = new ArrayList<>(); for (String p: parts) { if (p.equals(".") || p.equals("")) { continue; } if (p.equals("..")) { if (result.size() > 0) { result.remove(result.size() - 1); } continue; } result.add(p); } return "/" + String.join("/", result.toArray(new String[result.size()])); } /** * https://discuss.leetcode.com/topic/7675/java-10-lines-solution-with-stack */ public String simplifyPath2(String path) { Deque stack = new LinkedList<>(); Set skip = new HashSet<>(Arrays.asList("..",".","")); for (String dir : path.split("/")) { if (dir.equals("..") && !stack.isEmpty()) stack.pop(); else if (!skip.contains(dir)) stack.push(dir); } String res = ""; for (String dir : stack) res = "/" + dir + res; return res.isEmpty() ? "/" : res; } } ================================================ FILE: src/SingleElementInASortedArray540.java ================================================ /** * Given a sorted array consisting of only integers where every element appears * twice except for one element which appears once. Find this single element * that appears only once. * * Example 1: * Input: [1,1,2,3,3,4,4,8,8] * Output: 2 * * Example 2: * Input: [3,3,7,7,10,11,11] * Output: 10 * * Note: Your solution should run in O(log n) time and O(1) space. */ public class SingleElementInASortedArray540 { public int singleNonDuplicate(int[] nums) { if (nums.length == 1) return nums[0]; return singleNonDuplicate(nums, 0, nums.length-1); } private int singleNonDuplicate(int[] nums, int lo, int hi) { if (lo == hi) return nums[lo]; int mid = (lo + hi) / 2; boolean b = (mid - lo) % 2 == 0; if (nums[mid] != nums[mid-1] && nums[mid] != nums[mid+1]) { return nums[mid]; } if (nums[mid] != nums[mid-1]) { if (b) { return singleNonDuplicate(nums, mid, hi); } else { return singleNonDuplicate(nums, lo, mid-1); } } if (b) { return singleNonDuplicate(nums, lo, mid); } else { return singleNonDuplicate(nums, mid+1, hi); } } private int singleNonDuplicate2(int[] nums, int lo, int hi) { if (lo == hi) return nums[lo]; int mid = (lo + hi) / 2; boolean b = (mid - lo) % 2 == 0; if (nums[mid] != nums[mid-1] && nums[mid] != nums[mid+1]) { return nums[mid]; } if ((nums[mid] == nums[mid-1]) == b) { if (nums[mid] != nums[mid-1]) mid--; return singleNonDuplicate2(nums, lo, mid); } if (nums[mid] == nums[mid-1]) mid++; return singleNonDuplicate2(nums, mid, hi); } private int singleNonDuplicate3(int[] nums, int lo, int hi) { if (lo == hi) return nums[lo]; int mid = (lo + hi) / 2; if (nums[mid] != nums[mid-1] && nums[mid] != nums[mid+1]) return nums[mid]; if (mid % 2 == 1) mid--; if (nums[mid] != nums[mid+1]) return singleNonDuplicate3(nums, lo, mid); return singleNonDuplicate3(nums, mid+2, hi); } /** * https://leetcode.com/problems/single-element-in-a-sorted-array/discuss/100754/Java-Binary-Search-short-(7l)-O(log(n))-w-explanations */ public static int singleNonDuplicate2(int[] nums) { int start = 0, end = nums.length - 1; while (start < end) { // We want the first element of the middle pair, // which should be at an even index if the left part is sorted. // Example: // Index: 0 1 2 3 4 5 6 // Array: 1 1 3 3 4 8 8 // ^ int mid = (start + end) / 2; if (mid % 2 == 1) mid--; // We didn't find a pair. The single element must be on the left. // (pipes mean start & end) // Example: |0 1 1 3 3 6 6| // ^ ^ // Next: |0 1 1|3 3 6 6 if (nums[mid] != nums[mid + 1]) end = mid; // We found a pair. The single element must be on the right. // Example: |1 1 3 3 5 6 6| // ^ ^ // Next: 1 1 3 3|5 6 6| else start = mid + 2; } // 'start' should always be at the beginning of a pair. // When 'start > end', start must be the single element. return nums[start]; } } ================================================ FILE: src/SingleNumber136.java ================================================ /** * Given an array of integers, every element appears twice except for one. * Find that single one. * * Note: * Your algorithm should have a linear runtime complexity. Could you implement * it without using extra memory? */ public class SingleNumber136 { public int singleNumber(int[] nums) { Arrays.sort(nums); for (int i=0; i 0 && n == nums[i-1]) || (i < nums.length-1 && n == nums[i+1])) continue; return nums[i]; } return -1; } public int singleNumber2(int[] nums) { Set set = new HashSet<>(); for (int i=0; i> i) & 1; } result |= (sum % 3) << i; } return result; } } ================================================ FILE: src/SlidingWindowMaximum239.java ================================================ /** * Given an array nums, there is a sliding window of size k which is moving * from the very left of the array to the very right. You can only see the k * numbers in the window. Each time the sliding window moves right by one * position. Return the max sliding window. * * Example: * * Input: nums = [1,3,-1,-3,5,3,6,7], and k = 3 * Output: [3,3,5,5,6,7] * Explanation: * * Window position Max * --------------- ----- * [1 3 -1] -3 5 3 6 7 3 * 1 [3 -1 -3] 5 3 6 7 3 * 1 3 [-1 -3 5] 3 6 7 5 * 1 3 -1 [-3 5 3] 6 7 5 * 1 3 -1 -3 [5 3 6] 7 6 * 1 3 -1 -3 5 [3 6 7] 7 * * Note: * You may assume k is always valid, 1 ≤ k ≤ input array's size for * non-empty array. * * Follow up: * Could you solve it in linear time? */ public class SlidingWindowMaximum239 { public int[] maxSlidingWindow(int[] nums, int k) { if (nums == null || nums.length == 0) return new int[0]; PriorityQueue pq = new PriorityQueue<>(k, (i1, i2) -> Integer.compare(i2, i1)); for (int i=0; i ll = new LinkedList(); for (int i=0; i window = new ArrayList<>(); for (int j = 0; j < k; j++) { window.add(nums[j]); } Collections.sort(window); if ((k & 1) == 0) { int lenNew = len - 2 * mid + 1; double[] returned = new double[lenNew]; for (int i = 0; i < lenNew - 1; i++) { returned[i] = findMedianFromEven(window, mid); int idx = window.indexOf(nums[i]); int newValue = nums[i + k]; updateWindow(window, newValue, idx, k); } returned[lenNew - 1] = findMedianFromEven(window, mid); return returned; } else { int lenNew = len - 2 * mid; double[] returned = new double[lenNew]; for (int i = 0; i < lenNew - 1; i++) { returned[i] = findMedianFromOdd(window, mid); int idx = window.indexOf(nums[i]); int newValue = nums[i + k]; updateWindow(window, newValue, idx, k); } returned[lenNew - 1] = findMedianFromOdd(window, mid); return returned; } } private double findMedianFromEven(List window, int mid) { return ((long)window.get(mid - 1) + (long)window.get(mid)) / 2.0; } private double findMedianFromOdd(List window, int mid) { return window.get(mid); } private void updateWindow(List window, int newValue, int idx, int k) { while(0 <= idx && idx < k) { if (idx > 0 && window.get(idx - 1) > newValue) { window.set(idx, window.get(idx - 1)); idx -= 1; } else if (idx < k - 1 && window.get(idx + 1) < newValue) { window.set(idx, window.get(idx + 1)); idx += 1; } else { window.set(idx, newValue); return; } } window.set(idx, newValue); } public double[] medianSlidingWindow2(int[] nums, int k) { Comparator comp = new Comparator(){ public int compare(Pair p1, Pair p2) { int diff = Integer.compare(p1.value, p2.value); if (diff != 0) return diff; return Integer.compare(p1.index, p2.index); } }; TreeSet left = new TreeSet<>(comp); TreeSet right = new TreeSet<>(comp); boolean isOdd = k % 2 == 1; for (int i=0; i left, TreeSet right) { Pair p = new Pair(index, value); if (right.size() != 0 && value > right.first().value) { right.add(p); } else { left.add(p); } balance(left, right); } private void balance(TreeSet left, TreeSet right) { while (left.size() > right.size() + 1) { Pair topLeft = left.pollLast(); right.add(topLeft); } while (left.size() < right.size()) { Pair bottomRight = right.pollFirst(); left.add(bottomRight); } } class Pair { int index; int value; Pair(int i, int v) { index = i; value = v; } } public double[] medianSlidingWindow3(int[] nums, int k) { Comparator comp = (i1, i2) -> Integer.compare(i2, i1); PriorityQueue left = new PriorityQueue<>(comp); PriorityQueue right = new PriorityQueue<>(); for (int i=0; i right.size() + 1) { right.add(left.poll()); } } int N = nums.length; double[] res = new double[N-k+1]; for (int i=k; i<=N; i++) { if (left.size() == right.size() + 1) { res[i-k] = left.peek() * 1.0; } else { res[i-k] = ((long)left.peek() + (long)right.peek()) / 2.0; } if (i == N) break; int toPop = nums[i-k]; int toAdd = nums[i]; if (toAdd <= left.peek()) { left.add(toAdd); } else { right.add(toAdd); } if (left.peek() >= toPop) { left.remove(toPop); } else { right.remove(toPop); } if (left.size() < right.size()) { left.add(right.poll()); } else if (left.size() > right.size() + 1) { right.add(left.poll()); } } return res; } public static void main(String[] args) { SlidingWindowMedian480 swm = new SlidingWindowMedian480(); int [] nums = {1, 3, -1, -3, 5, 3, 6, 7}; int [] twos = {2147483647, 2147483647}; System.out.println(Arrays.toString(swm.medianSlidingWindow(nums, 3))); System.out.println(Arrays.toString(swm.medianSlidingWindow(nums, 4))); System.out.println(Arrays.toString(swm.medianSlidingWindow(twos, 2))); } } ================================================ FILE: src/SmallestRange632.java ================================================ /** * You have k lists of sorted integers in ascending order. Find the smallest * range that includes at least one number from each of the k lists. * * We define the range [a,b] is smaller than range [c,d] if b-a < d-c or a < c if b-a == d-c. * * Example 1: * Input:[[4,10,15,24,26], [0,9,12,20], [5,18,22,30]] * Output: [20,24] * Explanation: * List 1: [4, 10, 15, 24,26], 24 is in range [20,24]. * List 2: [0, 9, 12, 20], 20 is in range [20,24]. * List 3: [5, 18, 22, 30], 22 is in range [20,24]. * * Note: * - The given list may contain duplicates, so ascending order means >= here. * - 1 <= k <= 3500 * - 105 <= value of elements <= 105. * - For Java users, please note that the input type has been changed to * List>. And after you reset the code template, you'll see * this point. * */ public class SmallestRange632 { /** * https://leetcode.com/problems/smallest-range/solution/ */ public int[] smallestRange(List> nums) { int minx = 0, miny = Integer.MAX_VALUE, max = Integer.MIN_VALUE; int[] next = new int[nums.size()]; boolean flag = true; PriorityQueue min_queue = new PriorityQueue<>((i, j) -> nums.get(i).get(next[i]) - nums.get(j).get(next[j])); for (int i = 0; i < nums.size(); i++) { min_queue.offer(i); max = Math.max(max, nums.get(i).get(0)); } for (int i = 0; i < nums.size() && flag; i++) { for (int j = 0; j < nums.get(i).size() && flag; j++) { int min_i = min_queue.poll(); if (miny - minx > max - nums.get(min_i).get(next[min_i])) { minx = nums.get(min_i).get(next[min_i]); miny = max; } next[min_i]++; if (next[min_i] == nums.get(min_i).size()) { flag = false; break; } min_queue.offer(min_i); max = Math.max(max, nums.get(min_i).get(next[min_i])); } } return new int[] {minx, miny}; } /** * https://discuss.leetcode.com/topic/94445/java-code-using-priorityqueue-similar-to-merge-k-array */ public int[] smallestRange2(List> nums) { PriorityQueue pq = new PriorityQueue(new Comparator() { public int compare(Element a, Element b) { return a.val - b.val; } }); int min = Integer.MAX_VALUE, max = Integer.MIN_VALUE; for (int i = 0; i < nums.size(); i++) { int value = nums.get(i).get(0); Element e = new Element(i, 0, value); pq.offer(e); max = Math.max(max, value); } int range = Integer.MAX_VALUE; int start = -1, end = -1; while (pq.size() == nums.size()) { Element curr = pq.poll(); if (max - curr.val < range) { range = max - curr.val; start = curr.val; end = max; } if (curr.idx + 1 < nums.get(curr.row).size()) { curr.idx = curr.idx + 1; curr.val = nums.get(curr.row).get(curr.idx); pq.offer(curr); if (curr.val > max) { max = curr.val; } } } return new int[] { start, end }; } class Element { int val; int idx; int row; public Element(int r, int i, int v) { val = v; idx = i; row = r; } } // Time Limit Exceeded public int[] smallestRange3(List> nums) { int minx = 0, miny = Integer.MAX_VALUE; int[] next = new int[nums.size()]; while (true) { int min_i = 0, max_i = 0; for (int k = 0; k < nums.size(); k++) { if (nums.get(min_i).get(next[min_i]) > nums.get(k).get(next[k])) min_i = k; if (nums.get(max_i).get(next[max_i]) < nums.get(k).get(next[k])) max_i = k; } if (miny - minx > nums.get(max_i).get(next[max_i]) - nums.get(min_i).get(next[min_i])) { miny = nums.get(max_i).get(next[max_i]); minx = nums.get(min_i).get(next[min_i]); } next[min_i]++; if (next[min_i] == nums.get(min_i).size()) break; } return new int[] {minx, miny}; } /** * https://leetcode.com/problems/smallest-range/solution/ */ public int[] smallestRange4(List> nums) { int minx = 0, miny = Integer.MAX_VALUE, max = Integer.MIN_VALUE; int[] next = new int[nums.size()]; PriorityQueue q = new PriorityQueue( (i, j) -> nums.get(i).get(next[i]) - nums.get(j).get(next[j]) ); for (int i = 0; i < nums.size(); i++) { q.offer(i); max = Math.max(max, nums.get(i).get(0)); } while (true) { int min_i = q.poll(); if (miny - minx > max - nums.get(min_i).get(next[min_i])) { miny = max; minx = nums.get(min_i).get(next[min_i]); } next[min_i]++; if (next[min_i] == nums.get(min_i).size()) { // flag = false; break; } q.offer(min_i); max = Math.max(max, nums.get(min_i).get(next[min_i])); } return new int[] {minx, miny}; } } ================================================ FILE: src/SolveTheEquation640.java ================================================ /** * Solve a given equation and return the value of x in the form of string * "x=#value". The equation contains only '+', '-' operation, the variable x * and its coefficient. * * If there is no solution for the equation, return "No solution". * * If there are infinite solutions for the equation, return "Infinite solutions". * * If there is exactly one solution for the equation, we ensure that the value * of x is an integer. * * Example 1: * Input: "x+5-3+x=6+x-2" * Output: "x=2" * * Example 2: * Input: "x=x" * Output: "Infinite solutions" * * Example 3: * Input: "2x=x" * Output: "x=0" * * Example 4: * Input: "2x+3x-6x=x+2" * Output: "x=-1" * * Example 5: * Input: "x=x+2" * Output: "No solution" */ public class SolveTheEquation640 { public String solveEquation(String equation) { char[] chars = equation.toCharArray(); int N = chars.length; int a = 0; int b = 0; int curr = 0; int sign = 1; int i = 0; while (chars[i] != '=') { if (Character.isDigit(chars[i])) { curr = curr * 10 + (int)(chars[i] - '0'); if (chars[i+1] == '=') { i += 2; break; } } else if (chars[i] == '+') { b += sign * curr; curr = 0; sign = 1; } else if (chars[i] == '-') { b += sign * curr; curr = 0; sign = -1; } else { if (i == 0 || chars[i-1] != '0') { a += sign * (curr == 0 ? 1 : curr); } curr = 0; i++; if (chars[i] != '=') { sign = chars[i] == '+' ? 1 : -1; } else { sign = 0; i++; break; } } i++; } if (sign != 0) { b += sign * curr; } curr = 0; sign = 1; while (i < N) { if (Character.isDigit(chars[i])) { curr = curr * 10 + (int)(chars[i] - '0'); } else if (chars[i] == '+') { b -= sign * curr; curr = 0; sign = 1; } else if (chars[i] == '-') { b -= sign * curr; curr = 0; sign = -1; } else { if (i == 0 || chars[i-1] != '0') { a -= sign * (curr == 0 ? 1 : curr); } curr = 0; i++; if (i != N) { sign = chars[i] == '+' ? 1 : -1; } } i++; } b -= sign * curr; if (a == 0) { return b == 0 ? "Infinite solutions" : "No solution"; } else { return "x=" + (- b / a); } } /** * https://leetcode.com/problems/solve-the-equation/discuss/105311/Concise-Java-Solution */ public String solveEquation2(String equation) { int[] res = evaluateExpression(equation.split("=")[0]); int[] res2 = evaluateExpression(equation.split("=")[1]); res[0] -= res2[0]; res[1] = res2[1] - res[1]; if (res[0] == 0 && res[1] == 0) return "Infinite solutions"; if (res[0] == 0) return "No solution"; return "x=" + res[1]/res[0]; } public int[] evaluateExpression(String exp) { String[] tokens = exp.split("(?=[-+])"); int[] res = new int[2]; for (String token : tokens) { if (token.equals("+x") || token.equals("x")) res[0] += 1; else if (token.equals("-x")) res[0] -= 1; else if (token.contains("x")) res[0] += Integer.parseInt(token.substring(0, token.indexOf("x"))); else res[1] += Integer.parseInt(token); } return res; } } ================================================ FILE: src/SortArrayByParityII922.java ================================================ /** * Given an array A of non-negative integers, half of the integers in A are odd, and half of the integers are even. * * Sort the array so that whenever A[i] is odd, i is odd; and whenever A[i] is even, i is even. * * You may return any answer array that satisfies this condition. * * Example 1: * Input: [4,2,5,7] * Output: [4,5,2,7] * * Explanation: [4,7,2,5], [2,5,4,7], [2,7,4,5] would also have been accepted. * * Note: * 2 <= A.length <= 20000 * A.length % 2 == 0 * 0 <= A[i] <= 1000 */ public class SortArrayByParityII922 { public int[] sortArrayByParityII(int[] A) { int i = 0; int j = 1; int k = 0; int len = A.length; int[] B = new int[len]; while (k < len) { if (isOdd(A[k])) { B[j] = A[k]; j += 2; } else { B[i] = A[k]; i += 2; } k++; } return B; } private boolean isOdd(int num) { return (num & 1) == 1; } } ================================================ FILE: src/SortCharactersByFrequency451.java ================================================ /** * Given a string, sort it in decreasing order based on the frequency of characters. * * Example 1: * * Input: * "tree" * * Output: * "eert" * * Explanation: * 'e' appears twice while 'r' and 't' both appear once. * So 'e' must appear before both 'r' and 't'. Therefore "eetr" is also a valid answer. * * * Example 2: * * Input: * "cccaaa" * * Output: * "cccaaa" * * Explanation: * Both 'c' and 'a' appear three times, so "aaaccc" is also a valid answer. * Note that "cacaca" is incorrect, as the same characters must be together. * * * Example 3: * * Input: * "Aabb" * * Output: * "bbAa" * * Explanation: * "bbaA" is also a valid answer, but "Aabb" is incorrect. * Note that 'A' and 'a' are treated as two different characters. */ public class SortCharactersByFrequency451 { public String frequencySort(String s) { int[] map = new int[256]; for (char c: s.toCharArray()) map[c]++; List[] bucket = new List[s.length() + 1]; for (int i=0; i<256; i++) { int freq = map[i]; if (freq != 0) { if (bucket[freq] == null) bucket[freq] = new LinkedList<>(); bucket[freq].add((char) i); } } StringBuilder sb = new StringBuilder(); for (int i=bucket.length-1; i>=0; i--) { List list = bucket[i]; if (list != null) { for (Character c: list) { char[] chars = new char[i]; Arrays.fill(chars, c); sb.append(chars); } } } return sb.toString(); } } ================================================ FILE: src/SortColors75.java ================================================ /** * Given an array with n objects colored red, white or blue, sort them so that * objects of the same color are adjacent, with the colors in the order red, * white and blue. * * Here, we will use the integers 0, 1, and 2 to represent the color red, white, * and blue respectively. * * Note: * You are not suppose to use the library's sort function for this problem. * * Follow up: * A rather straight forward solution is a two-pass algorithm using counting sort. * First, iterate the array counting number of 0's, 1's, and 2's, then overwrite * array with total number of 0's, then 1's and followed by 2's. * * Could you come up with an one-pass algorithm using only constant space? */ import java.util.Arrays; public class SortColors75 { public void sortColors(int[] nums) { int L = nums.length; if (L == 0 || L == 1) { return; } helper(0, L - 1, nums); } private void helper(int left, int right, int[] nums) { if (left == right) { return; } int mid = (left + right) / 2; helper(left, mid, nums); helper(mid + 1, right, nums); merge(left, mid, right, nums); } private void merge(int left, int mid, int right, int[] nums) { int l = 0; int r = 0; int i = left; int[] la = Arrays.copyOfRange(nums, left, mid+1); int[] ra = Arrays.copyOfRange(nums, mid+1, right+1); while (l <= mid - left && r <= right - mid - 1) { if (la[l] <= ra[r]) { nums[i] = la[l]; l++; } else { nums[i] = ra[r]; r++; } i++; } while (l <= mid - left) { nums[i] = la[l]; l++; i++; } } /** * https://discuss.leetcode.com/topic/6968/four-different-solutions */ // two pass O(m+n) space public void sortColors2(int A[]) { int num0 = 0, num1 = 0, num2 = 0; for(int i = 0; i < A.length; i++) { if (A[i] == 0) ++num0; else if (A[i] == 1) ++num1; else if (A[i] == 2) ++num2; } for(int i = 0; i < num0; ++i) A[i] = 0; for(int i = 0; i < num1; ++i) A[num0+i] = 1; for(int i = 0; i < num2; ++i) A[num0+num1+i] = 2; } // one pass in place solution public void sortColors3(int A[]) { int n0 = -1, n1 = -1, n2 = -1; for (int i = 0; i < A.length; ++i) { if (A[i] == 0) { A[++n2] = 2; A[++n1] = 1; A[++n0] = 0; } else if (A[i] == 1) { A[++n2] = 2; A[++n1] = 1; } else if (A[i] == 2) { A[++n2] = 2; } } } // one pass in place solution public void sortColors4(int A[]) { int j = 0, k = A.length - 1; for (int i = 0; i <= k; ++i){ if (A[i] == 0 && i != j) swap(A, i--, j++); else if (A[i] == 2 && i != k) swap(A, i--, k--); } } // one pass in place solution public void sortColors5(int A[], int n) { int j = 0, k = n-1; for (int i=0; i <= k; i++) { if (A[i] == 0) swap(A, i, j++); else if (A[i] == 2) swap(A, i--, k--); } } // bucket sort public void sortColors6(int[] nums) { int[] buckets = new int[3]; for (int i=0; i= 0 ? n - 1 : 0; while (i <= j) { int ii = result(nums[i], a, b, c); int jj = result(nums[j], a, b, c); if (a >= 0) { if (ii >= jj) { res[index] = ii; i++; } else { res[index] = jj; j--; } index--; } else { if (ii >= jj) { res[index] = jj; j--; } else { res[index] = ii; i++; } index++; } } return res; } private int result(int x, int a, int b, int c) { return a * x * x + b * x + c; } public int[] sortTransformedArray2(int[] nums, int a, int b, int c) { PriorityQueue pq = new PriorityQueue<>(); for (int x: nums) { pq.add(transfer(x, a, b, c)); } int[] res = new int[nums.length]; int i = 0; while (!pq.isEmpty()) { res[i++] = pq.poll(); } return res; } private int transfer(int x, int a, int b, int c) { return a * x * x + b * x + c; } } ================================================ FILE: src/SparseMatrixMultiplication311.java ================================================ /** * Given two sparse matrices A and B, return the result of AB. * * You may assume that A's column number is equal to B's row number. * * Example: * * A = [ * [ 1, 0, 0], * [-1, 0, 3] * ] * * B = [ * [ 7, 0, 0 ], * [ 0, 0, 0 ], * [ 0, 0, 1 ] * ] * * * | 1 0 0 | | 7 0 0 | | 7 0 0 | * AB = | -1 0 3 | x | 0 0 0 | = | -7 0 3 | * | 0 0 1 | * */ public class SparseMatrixMultiplication311 { // brutal force // public int[][] multiply(int[][] A, int[][] B) { // int ax = A.length; // int by = B[0].length; // int len = B.length; // int[][] res = new int[ax][by]; // // for (int i=0; i spiralOrder(int[][] matrix) { List res = new ArrayList<>(); if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return res; helper(matrix, 0, 0, matrix.length - 1, matrix[0].length - 1, res); return res; } private void helper(int[][] matrix, int x0, int y0, int x1, int y1, List res) { if (x0 > x1 || y0 > y1) return; if (x0 == x1) { for (int i=y0; i<=y1; i++) res.add(matrix[x0][i]); return; } if (y0 == y1) { for (int i=x0; i<=x1; i++) res.add(matrix[i][y0]); return; } for (int i=y0; iy0; i--) res.add(matrix[x1][i]); for (int i=x1; i>x0; i--) res.add(matrix[i][y0]); helper(matrix, x0 + 1, y0 + 1, x1 - 1, y1 - 1, res); } /** * https://leetcode.com/problems/spiral-matrix/solution/ */ public List < Integer > spiralOrder2(int[][] matrix) { List ans = new ArrayList(); if (matrix.length == 0) return ans; int r1 = 0, r2 = matrix.length - 1; int c1 = 0, c2 = matrix[0].length - 1; while (r1 <= r2 && c1 <= c2) { for (int c = c1; c <= c2; c++) ans.add(matrix[r1][c]); for (int r = r1 + 1; r <= r2; r++) ans.add(matrix[r][c2]); if (r1 < r2 && c1 < c2) { for (int c = c2 - 1; c > c1; c--) ans.add(matrix[r2][c]); for (int r = r2; r > r1; r--) ans.add(matrix[r][c1]); } r1++; r2--; c1++; c2--; } return ans; } /** * https://leetcode.com/problems/spiral-matrix/solution/ */ public List spiralOrder3(int[][] matrix) { List ans = new ArrayList(); if (matrix.length == 0) return ans; int R = matrix.length, C = matrix[0].length; boolean[][] seen = new boolean[R][C]; int[] dr = {0, 1, 0, -1}; int[] dc = {1, 0, -1, 0}; int r = 0, c = 0, di = 0; for (int i = 0; i < R * C; i++) { ans.add(matrix[r][c]); seen[r][c] = true; int cr = r + dr[di]; int cc = c + dc[di]; if (0 <= cr && cr < R && 0 <= cc && cc < C && !seen[cr][cc]){ r = cr; c = cc; } else { di = (di + 1) % 4; r += dr[di]; c += dc[di]; } } return ans; } public List spiralOrder4(int[][] matrix) { List res = new ArrayList<>(); if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return res; int M = matrix.length; int N = matrix[0].length; int mid = Math.min((M+1)/2, (N+1)/2); for (int c=0; c c) for (int j=N-c-2; j>=c; j--) res.add(matrix[M-c-1][j]); if (N-c-1 > c) for (int i=M-c-2; i>=c+1; i--) res.add(matrix[i][c]); } return res; } } ================================================ FILE: src/SpiralMatrixII59.java ================================================ /** * Given a positive integer n, generate a square matrix filled with elements * from 1 to n2 in spiral order. * * Example: * * Input: 3 * Output: * [ * [ 1, 2, 3 ], * [ 8, 9, 4 ], * [ 7, 6, 5 ] * ] */ public class SpiralMatrixII59 { private int[][] directions = new int[][]{{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; public int[][] generateMatrix(int n) { int[][] res = new int[n][n]; int i = 1; int d = 0; int x = 0; int y = 0; int END = n * n; while (i <= END) { res[x][y] = i; int nx = x + directions[d][0]; int ny = y + directions[d][1]; if (nx < 0 || ny < 0 || nx >= n || ny >= n || res[nx][ny] != 0) { d = (d + 1) % 4; nx = x + directions[d][0]; ny = y + directions[d][1]; } x = nx; y = ny; i++; } return res; } public int[][] generateMatrix2(int n) { if (n == 0) return new int[0][0]; int[][] matrix = new int[n][n]; boolean[][] filled = new boolean[n][n]; int[] dx = new int[]{0, 1, 0, -1}; int[] dy = new int[]{1, 0, -1, 0}; int x = 0; int y = 0; int d = 0; for (int i=1; i<=n*n; i++) { matrix[x][y] = i; filled[x][y] = true; int xx = x + dx[d]; int yy = y + dy[d]; if (xx >= 0 && xx < n && yy >= 0 && yy < n && !filled[xx][yy]) { x = xx; y = yy; } else { d = (d + 1) % 4; x += dx[d]; y += dy[d]; } } return matrix; } } ================================================ FILE: src/SplitArrayIntoConsecutiveSubsequences659.java ================================================ /** * You are given an integer array sorted in ascending order (may contain * duplicates), you need to split them into several subsequences, where each * subsequences consist of at least 3 consecutive integers. Return whether you * can make such a split. * * Example 1: * Input: [1,2,3,3,4,5] * Output: True * Explanation: * You can split them into two consecutive subsequences : * 1, 2, 3 * 3, 4, 5 * * Example 2: * Input: [1,2,3,3,4,4,5,5] * Output: True * Explanation: * You can split them into two consecutive subsequences : * 1, 2, 3, 4, 5 * 3, 4, 5 * * Example 3: * Input: [1,2,3,4,4,5] * Output: False * * Note: * The length of the input is in range of [1, 10000] * */ public class SplitArrayIntoConsecutiveSubsequences659 { // too slow // public boolean isPossible(int[] nums) { // if (nums == null || nums.length < 3) return false; // Map sizes = new HashMap<>(); // Map lasts = new HashMap<>(); // for (int i=0; i freq = new HashMap<>(), appendfreq = new HashMap<>(); for (int i : nums) freq.put(i, freq.getOrDefault(i,0) + 1); for (int i : nums) { if (freq.get(i) == 0) continue; else if (appendfreq.getOrDefault(i,0) > 0) { appendfreq.put(i, appendfreq.get(i) - 1); appendfreq.put(i+1, appendfreq.getOrDefault(i+1,0) + 1); } else if (freq.getOrDefault(i+1,0) > 0 && freq.getOrDefault(i+2,0) > 0) { freq.put(i+1, freq.get(i+1) - 1); freq.put(i+2, freq.get(i+2) - 1); appendfreq.put(i+3, appendfreq.getOrDefault(i+3,0) + 1); } else return false; freq.put(i, freq.get(i) - 1); } return true; } /** * https://leetcode.com/problems/split-array-into-consecutive-subsequences/discuss/106495/Java-O(n)-time-and-O(1)-space-solution-greedily-extending-shorter-subsequence */ public boolean isPossible2(int[] nums) { int pre = Integer.MIN_VALUE, p1 = 0, p2 = 0, p3 = 0; int cur = 0, cnt = 0, c1 = 0, c2 = 0, c3 = 0; for (int i = 0; i < nums.length; pre = cur, p1 = c1, p2 = c2, p3 = c3) { for (cur = nums[i], cnt = 0; i < nums.length && cur == nums[i]; cnt++, i++); if (cur != pre + 1) { if (p1 != 0 || p2 != 0) return false; c1 = cnt; c2 = 0; c3 = 0; } else { if (cnt < p1 + p2) return false; c1 = Math.max(0, cnt - (p1 + p2 + p3)); c2 = p1; c3 = p2 + Math.min(p3, cnt - (p1 + p2)); } } return (p1 == 0 && p2 == 0); } public boolean isPossible3(int[] nums) { int pre = Integer.MIN_VALUE; int p1 = 0; int p2 = 0; int p3 = 0; int i = 0; while (i < nums.length) { int cur = nums[i]; int count = 0; while (i < nums.length && nums[i] == cur) { i++; count++; } int c1 = 0; int c2 = 0; int c3 = 0; if (cur == pre + 1) { if (count < p1 + p2) return false; c1 = Math.max(0, count - (p1 + p2 + p3)); c2 = p1; c3 = p2 + Math.min(p3, count - (p1 + p2)); } else { if (p1 != 0 || p2 != 0) return false; c1 = count; c2 = 0; c3 = 0; } pre = cur; p1 = c1; p2 = c2; p3 = c3; } return (p1 == 0 && p2 == 0); } } ================================================ FILE: src/SplitArrayIntoFibonacciSequence842.java ================================================ /** * Given a string S of digits, such as S = "123456579", we can split it into a * Fibonacci-like sequence [123, 456, 579]. * * Formally, a Fibonacci-like sequence is a list F of non-negative integers such that: * 0 <= F[i] <= 2^31 - 1, (that is, each integer fits a 32-bit signed integer type); * F.length >= 3; * and F[i] + F[i+1] = F[i+2] for all 0 <= i < F.length - 2. * * Also, note that when splitting the string into pieces, each piece must not * have extra leading zeroes, except if the piece is the number 0 itself. * * Return any Fibonacci-like sequence split from S, or return [] if it cannot be done. * * Example 1: * Input: "123456579" * Output: [123,456,579] * * Example 2: * Input: "11235813" * Output: [1,1,2,3,5,8,13] * * Example 3: * Input: "112358130" * Output: [] * Explanation: The task is impossible. * * Example 4: * Input: "0123" * Output: [] * Explanation: Leading zeroes are not allowed, so "01", "2", "3" is not valid. * * Example 5: * Input: "1101111" * Output: [110, 1, 111] * Explanation: The output [11, 0, 11, 11] would also be accepted. * * Note: * 1 <= S.length <= 200 * S contains only digits. */ public class SplitArrayIntoFibonacciSequence842 { public List splitIntoFibonacci(String S) { int N = S.length(); List res = new ArrayList<>(); if (N <= 2) return res; for (int i=0; i(); try { int a = Integer.parseInt(S.substring(0, i+1)); if (S.charAt(0) == '0' && a != 0) return new ArrayList<>(); res.add(a); for (int j=i+1; j(); } } return new ArrayList<>(); } public boolean helper(List res, int a, int b, int k, int N, String S) { int x = a; int y = b; int idx = k; int next = x + y; while (idx < N) { String n = Integer.toString(next); if (!S.startsWith(n, idx)) return false; res.add(next); x = y; y = next; next = x + y; idx += n.length(); } return true; } } ================================================ FILE: src/SplitArrayLargestSum410.java ================================================ /** * Given an array which consists of non-negative integers and an integer m, you * can split the array into m non-empty continuous subarrays. Write an * algorithm to minimize the largest sum among these m subarrays. * * Note: * If n is the length of array, assume the following constraints are satisfied: * 1 ≤ n ≤ 1000 * 1 ≤ m ≤ min(50, n) * * Examples: * Input: * nums = [7,2,5,10,8] * m = 2 * * Output: * 18 * * Explanation: * There are four ways to split nums into two subarrays. * The best way is to split it into [7,2,5] and [10,8], * where the largest sum among the two subarrays is only 18. */ public class SplitArrayLargestSum410 { // DP 1 public int splitArray(int[] nums, int m) { int n = nums.length; int[] sum = new int[n+1]; for (int j=1; j<=n; j++) sum[j] += sum[j-1] + nums[j-1]; int[][] dp = new int[m][n]; for (int j=0; j m) { l = mid + 1; } else { r = mid; } } return (int) l; } private int count(int[] nums, int m, long mid) { int res = 0; long sum = 0; for (int n: nums) { sum += n; if (sum > mid) { res++; sum = n; } } return res+1; } } ================================================ FILE: src/SqrtX69.java ================================================ /** * Implement int sqrt(int x). * * Compute and return the square root of x. */ public class SqrtX69 { public int mySqrt(int x) { return (int)Math.sqrt(x); } /** * https://discuss.leetcode.com/topic/8680/a-binary-search-solution */ public int mySqrt2(int x) { if (x == 0) return 0; int left = 1, right = Integer.MAX_VALUE; while (true) { int mid = left + (right - left)/2; if (mid > x/mid) { right = mid - 1; } else { if (mid + 1 > x/(mid + 1)) return mid; left = mid + 1; } } } /** * https://discuss.leetcode.com/topic/24532/3-4-short-lines-integer-newton-every-language */ public int mySqrt3(int x) { long r = x; while (r*r > x) r = (r + x/r) / 2; return (int) r; } /** * https://discuss.leetcode.com/topic/2671/share-my-o-log-n-solution-using-bit-manipulation/26 */ public int mySqrt(int x) { if(x==0) return 0; int h=0; while((long)(1<=0){ // find the remaining bits if((long)(res | (1< j) return sumA > sumL; if (A) { return stoneGame(piles, i+1, j, true, sumA+piles[i], sumL) || stoneGame(piles, i, j-1, true, sumA, sumL+piles[j]); } return stoneGame(piles, i+1, j, true, sumA+piles[i], sumL) && stoneGame(piles, i, j-1, true, sumA, sumL+piles[j]); } /** * :D */ public boolean stoneGame2(int[] piles) { return true; } } ================================================ FILE: src/StringCompression443.java ================================================ /** * Given an array of characters, compress it in-place. * * The length after compression must always be smaller than or equal to the original array. * * Every element of the array should be a character (not int) of length 1. * * After you are done modifying the input array in-place, return the new length of the array. * * Follow up: * Could you solve it using only O(1) extra space? * * Example 1: * Input: * ["a","a","b","b","c","c","c"] * Output: * Return 6, and the first 6 characters of the input array should be: ["a","2","b","2","c","3"] * Explanation: * "aa" is replaced by "a2". "bb" is replaced by "b2". "ccc" is replaced by "c3". * * * Example 2: * Input: * ["a"] * Output: * Return 1, and the first 1 characters of the input array should be: ["a"] * Explanation: * Nothing is replaced. * * * Example 3: * Input: * ["a","b","b","b","b","b","b","b","b","b","b","b","b"] * Output: * Return 4, and the first 4 characters of the input array should be: ["a","b","1","2"]. * Explanation: * Since the character "a" does not repeat, it is not compressed. "bbbbbbbbbbbb" is replaced by "b12". * Notice each digit has it's own entry in the array. * * Note: * All characters have an ASCII value in [35, 126]. * 1 <= len(chars) <= 1000. */ public class StringCompression443 { public int compress(char[] chars) { if (chars == null || chars.length <= 0) return 0; if (chars.length == 1) return 1; int i = 1; int j = 1; int count = 1; char pre = chars[0]; while (j < chars.length) { if (chars[j] == pre) { count++; j++; } else { if (count != 1) { char[] nums = Integer.toString(count).toCharArray(); for (char n: nums) { chars[i++] = n; } } pre = chars[j]; count = 1; j++; chars[i] = pre; i++; } } if (count != 1) { char[] nums = Integer.toString(count).toCharArray(); for (char n: nums) { chars[i++] = n; } } return i; } /** * https://leetcode.com/problems/string-compression/solution/ */ public int compress2(char[] chars) { int anchor = 0, write = 0; for (int read = 0; read < chars.length; read++) { if (read + 1 == chars.length || chars[read + 1] != chars[read]) { chars[write++] = chars[anchor]; if (read > anchor) { for (char c: ("" + (read - anchor + 1)).toCharArray()) { chars[write++] = c; } } anchor = read + 1; } } return write; } } ================================================ FILE: src/StringToInteger8.java ================================================ /** * Implement atoi to convert a string to an integer. * * Hint: Carefully consider all possible input cases. If you want a challenge, * please do not see below and ask yourself what are the possible input cases. * * Notes: It is intended for this problem to be specified vaguely (ie, no given * input specs). You are responsible to gather all the input requirements up front. * * Requirements for atoi: * The function first discards as many whitespace characters as necessary until * the first non-whitespace character is found. Then, starting from this * character, takes an optional initial plus or minus sign followed by as many * numerical digits as possible, and interprets them as a numerical value. * * The string can contain additional characters after those that form the * integral number, which are ignored and have no effect on the behavior of * this function. * * If the first sequence of non-whitespace characters in str is not a valid * integral number, or if no such sequence exists because either str is empty * or it contains only whitespace characters, no conversion is performed. * * If no valid conversion could be performed, a zero value is returned. If the * correct value is out of the range of representable values, * INT_MAX (2147483647) or INT_MIN (-2147483648) is returned. * */ public class StringToInteger8 { public int myAtoi(String str) { if (str == null || str.length() == 0) return 0; long res = 0; // Initialize result int sign = 1; // Initialize sign as positive int i = 0; // Initialize index of first digit int L = str.length(); while (i < L && str.charAt(i) == ' ') { i++; } // If number is negative, then update sign boolean hasSign = false; while (i < L) { char c = str.charAt(i); if (c == '-') { if (hasSign) { return 0; } else { sign = -1; i++; // Also update index of first digit hasSign = true; } } else if (c == '+') { if (hasSign) { return 0; } else { i++; // Also update index of first digit hasSign = true; } } else if (c == '0') { i++; // Also update index of first digit } else { break; } } // Iterate through all digits of input string and update result for (; i < L; ++i) { if (isNumericChar(str.charAt(i)) == false) break; res = res * 10 + str.charAt(i) - '0'; if (res > Integer.MAX_VALUE) break; } long r = sign*res; if (r > Integer.MAX_VALUE) { return Integer.MAX_VALUE; } else if (r < Integer.MIN_VALUE) { return Integer.MIN_VALUE; } return (int)r; } // A utility function to check whether x is numeric private boolean isNumericChar(char x) { return (x >= '0' && x <= '9') ? true : false; } } ================================================ FILE: src/StrobogrammaticNumber246.java ================================================ /** * A strobogrammatic number is a number that looks the same when rotated 180 * degrees (looked at upside down). * * Write a function to determine if a number is strobogrammatic. The number * is represented as a string. * * Example 1: * Input: "69" * Output: true * * Example 2: * Input: "88" * Output: true * * Example 3: * Input: "962" * Output: false */ public class StrobogrammaticNumber246 { public boolean isStrobogrammatic(String num) { if (num == null || num.length() == 0) return true; boolean[][] map = new boolean[10][10]; map[0][0] = true; map[1][1] = true; map[8][8] = true; map[6][9] = true; map[9][6] = true; int len = num.length(); int l = 0; int r = len-1; char[] chars = num.toCharArray(); while (l <= r) { if (!map[chars[l++]-'0'][chars[r--]-'0']) return false; } return true; } } ================================================ FILE: src/StrobogrammaticNumberII247.java ================================================ /** * A strobogrammatic number is a number that looks the same when rotated 180 * degrees (looked at upside down). * * Find all strobogrammatic numbers that are of length = n. * * Example: * Input: n = 2 * Output: ["11","69","88","96"] */ public class StrobogrammaticNumberII247 { private char[] sames = new char[]{'0', '1', '8'}; private char six = '6'; private char nine = '9'; public List findStrobogrammatic(int n) { List res = new ArrayList<>(); if (n == 0) { res.add(""); return res; } char[] chars = new char[n]; findStrobogrammatic(chars, 0, n-1, res); return res; } public void findStrobogrammatic(char[] chars, int left, int right, List res) { if (left > right) { res.add(new String(chars)); return; } if (left == right) { for (char c: sames) { chars[left] = c; res.add(new String(chars)); } return; } for (char c: sames) { if (c == '0' && left == 0) continue; chars[left] = c; chars[right] = c; findStrobogrammatic(chars, left+1, right-1, res); } chars[left] = six; chars[right] = nine; findStrobogrammatic(chars, left+1, right-1, res); chars[left] = nine; chars[right] = six; findStrobogrammatic(chars, left+1, right-1, res); } } ================================================ FILE: src/SubarrayProductLessThanK713.java ================================================ /** * Your are given an array of positive integers nums. * * Count and print the number of (contiguous) subarrays where the product of * all the elements in the subarray is less than k. * * Example 1: * Input: nums = [10, 5, 2, 6], k = 100 * Output: 8 * Explanation: The 8 subarrays that have product less than 100 are: * [10], [5], [2], [6], [10, 5], [5, 2], [2, 6], [5, 2, 6]. * * Note that [10, 5, 2] is not included as the product of 100 is not * strictly less than k. * * Note: * 0 < nums.length <= 50000. * 0 < nums[i] < 1000. * 0 <= k < 10^6. */ public class SubarrayProductLessThanK713 { public int numSubarrayProductLessThanK(int[] nums, int k) { if (nums == null || nums.length == 0 || k == 0) return 0; int left = 0; int right = 0; int prod = 1; int len = nums.length; int res = 0; while (right < len) { prod *= nums[right]; while (prod >= k && left <= right) { prod /= nums[left++]; } res += right - left + 1; right++; } return res; } public int numSubarrayProductLessThanK2(int[] nums, int k) { if (nums == null || nums.length == 0 || k == 0) return 0; int prod = 1; int left = 0; int right = 0; int res = 0; while (right < nums.length) { prod *= nums[right]; while (left <= right && prod >= k) { res += right - left; prod /= nums[left++]; } right++; } while (left < nums.length) { res += right - left; left++; } return res; } } ================================================ FILE: src/SubarraySumEqualsK560.java ================================================ /** * Given an array of integers and an integer k, you need to find the total * number of continuous subarrays whose sum equals to k. * * Example 1: * Input:nums = [1,1,1], k = 2 * Output: 2 * * Note: * The length of the array is in range [1, 20,000]. * The range of numbers in the array is [-1000, 1000] and the range of the * integer k is [-1e7, 1e7]. * */ public class SubarraySumEqualsK560 { public int subarraySum(int[] nums, int k) { int n = nums.length; int res = 0; int[] dp = new int[n]; for (int j=0; j=0; i--) { int curr = (i == j) ? nums[j] : dp[i] + nums[j]; dp[i] = curr; if (curr == k) res++; } } return res; } /** * https://leetcode.com/problems/subarray-sum-equals-k/solution/ */ public int subarraySum2(int[] nums, int k) { int count = 0; int[] sum = new int[nums.length + 1]; sum[0] = 0; for (int i = 1; i <= nums.length; i++) sum[i] = sum[i - 1] + nums[i - 1]; for (int start = 0; start < nums.length; start++) { for (int end = start + 1; end <= nums.length; end++) { if (sum[end] - sum[start] == k) count++; } } return count; } /** * https://leetcode.com/problems/subarray-sum-equals-k/solution/ */ public int subarraySum3(int[] nums, int k) { int count = 0; for (int start = 0; start < nums.length; start++) { int sum=0; for (int end = start; end < nums.length; end++) { sum+=nums[end]; if (sum == k) count++; } } return count; } /** * https://leetcode.com/problems/subarray-sum-equals-k/solution/ */ public int subarraySum4(int[] nums, int k) { int count = 0, sum = 0; HashMap < Integer, Integer > map = new HashMap < > (); map.put(0, 1); for (int i = 0; i < nums.length; i++) { sum += nums[i]; if (map.containsKey(sum - k)) count += map.get(sum - k); map.put(sum, map.getOrDefault(sum, 0) + 1); } return count; } public int subarraySum5(int[] nums, int k) { Map> map = new HashMap<>(); int sum = 0; for (int i=0; i()); } map.get(sum).add(i); } int res = 0; sum = 0; for (int i=0; i= i) res++; } } sum += nums[i]; } return res; } } ================================================ FILE: src/Subsequence.java ================================================ /** * */ import java.util.*; public class Subsequence { public List subsequences(String target, String[] dict) { List res = new ArrayList<>(); for (String word: dict) { if (target.length() <= word.length() && isSubsequence(target, word)) { res.add(word); } } return res; } public boolean isSubsequence(String s, String t) { int i = 0; int j = 0; char[] chars = s.toCharArray(); char[] chart = t.toCharArray(); while (i < chars.length && j < chart.length) { if (chars[i] == chart[j]) { i++; j++; } else { j++; } } return i == chars.length; } public static void main(String[] args) { Insertables ins = new Insertables(); System.out.println(ins.insertables("google", new String[]{"goooooogle", "ddgoogle", "abcd", "googles"})); } } ================================================ FILE: src/Subsets78.java ================================================ /** * Given a set of distinct integers, nums, return all possible subsets. * * Note: The solution set must not contain duplicate subsets. * * For example, * If nums = [1,2,3], a solution is: * * [ * [3], * [1], * [2], * [1,2,3], * [1,3], * [2,3], * [1,2], * [] * ] */ import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; public class Subsets78 { /** * https://discuss.leetcode.com/topic/46159/a-general-approach-to-backtracking-questions-in-java-subsets-permutations-combination-sum-palindrome-partitioning */ public List> subsets(int[] nums) { List> list = new ArrayList<>(); backtrack(list, new ArrayList<>(), nums, 0); return list; } private void backtrack(List> list , List tempList, int [] nums, int start){ list.add(new ArrayList<>(tempList)); for(int i = start; i < nums.length; i++){ tempList.add(nums[i]); backtrack(list, tempList, nums, i + 1); tempList.remove(tempList.size() - 1); } } public List> subsets2(int[] nums) { List> res = new ArrayList<>(); if (nums == null) return res; res.add(new ArrayList()); for (Integer n: nums) { int size = res.size(); for (int i=0; i newList = new ArrayList(res.get(i)); newList.add(n); res.add(newList); } } return res; } public static void main(String[] args) { Subsets78 ss = new Subsets78(); System.out.println(ss.subsets(new int[]{1, 2, 3, 4})); System.out.println(ss.subsets(new int[]{1, 2, 3})); } } ================================================ FILE: src/SubsetsII90.java ================================================ /** * Given a collection of integers that might contain duplicates, nums, return all possible subsets (the power set). * * Note: The solution set must not contain duplicate subsets. * * For example, * If nums = [1,2,2], a solution is: * * [ * [2], * [1], * [1,2,2], * [2,2], * [1,2], * [] * ] */ public class SubsetsII90 { public List> subsetsWithDup(int[] nums) { Set> res = new HashSet<>(); Map co = new HashMap<>(); helper(0, nums, co, res); return new ArrayList>(res); } public void helper(int pos, int[] nums, Map co, Set> res) { if (pos >= nums.length) { res.add(mapToList(co)); return; } res.add(mapToList(co)); helper(pos+1, nums, co, res); co.put(nums[pos], co.getOrDefault(nums[pos], 0) + 1); helper(pos+1, nums, co, res); co.put(nums[pos], co.get(nums[pos]) - 1); } public List mapToList(Map co) { List l = new ArrayList(); for (Map.Entry e: co.entrySet()) { for (int i=0; i> subsetsWithDup2(int[] nums) { Arrays.sort(nums); Set> res = new HashSet<>(); List each = new ArrayList<>(); helper2(0, nums, each, res); return new ArrayList>(res); } public void helper2(int pos, int[] nums, List each, Set> res) { if (pos >= nums.length) { res.add(new ArrayList(each)); return; } res.add(new ArrayList(each)); helper(pos+1, nums, each, res); each.add(nums[pos]); helper(pos+1, nums, each, res); each.remove(each.size()-1); } public List> subsetsWithDup3(int[] nums) { Arrays.sort(nums); List> res = new ArrayList<>(); helper3(0, nums, new ArrayList<>(), res); return res; } public void helper3(int pos, int[] nums, List each, List> res) { if (pos <= nums.length) res.add(new ArrayList(each)); for(int i=pos; i < nums.length; i++){ if(i > pos && nums[i] == nums[i-1]) continue; each.add(nums[i]); helper(i+1, nums, each, res); each.remove(each.size()-1); } } } ================================================ FILE: src/SubtreeOfAnotherTree572.java ================================================ /** * Given two non-empty binary trees s and t, check whether tree t has exactly * the same structure and node values with a subtree of s. A subtree of s is a * tree consists of a node in s and all of this node's descendants. The tree s * could also be considered as a subtree of itself. * * Example 1: * Given tree s: * * 3 * / \ * 4 5 * / \ * 1 2 * Given tree t: * 4 * / \ * 1 2 * Return true, because t has the same structure and node values with a subtree of s. * * Example 2: * Given tree s: * * 3 * / \ * 4 5 * / \ * 1 2 * / * 0 * Given tree t: * 4 * / \ * 1 2 * Return false. * */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class SubtreeOfAnotherTree572 { public boolean isSubtree(TreeNode s, TreeNode t) { if (s == null) return false; if (isSame(s, t)) return true; return isSubtree(s.left, t) || isSubtree(s.right, t); } public boolean isSame(TreeNode s, TreeNode t) { if (s == null) return t == null; if (t == null) return s == null; if (s.val != t.val) return false; return isSame(s.left, t.left) && isSame(s.right, t.right); } /** * https://leetcode.com/problems/subtree-of-another-tree/discuss/102760/Easy-O(n)-java-solution-using-preorder-traversal */ public boolean isSubtree2(TreeNode s, TreeNode t) { String spreorder = generatepreorderString(s); String tpreorder = generatepreorderString(t); return spreorder.contains(tpreorder) ; } public String generatepreorderString(TreeNode s){ StringBuilder sb = new StringBuilder(); Stack stacktree = new Stack(); stacktree.push(s); while(!stacktree.isEmpty()){ TreeNode popelem = stacktree.pop(); if(popelem==null) sb.append(",#"); // Appending # inorder to handle same values but not subtree cases else sb.append(","+popelem.val); if(popelem!=null){ stacktree.push(popelem.right); stacktree.push(popelem.left); } } return sb.toString(); } /** * https://leetcode.com/problems/subtree-of-another-tree/discuss/102736/Java-Concise-O(n+m)-Time-O(n+m)-Space */ public boolean isSubtree3(TreeNode s, TreeNode t) { return serialize(s).contains(serialize(t)); // Java uses a naive contains algorithm so to ensure linear time, // replace with KMP algorithm } public String serialize(TreeNode root) { StringBuilder res = new StringBuilder(); serialize(root, res); return res.toString(); } private void serialize(TreeNode cur, StringBuilder res) { if (cur == null) {res.append(",#"); return;} res.append("," + cur.val); serialize(cur.left, res); serialize(cur.right, res); } } ================================================ FILE: src/SudokuSolver37.java ================================================ /** * Write a program to solve a Sudoku puzzle by filling the empty cells. * * Empty cells are indicated by the character '.'. * * You may assume that there will be only one unique solution. */ import java.util.Arrays; import java.util.Map; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.Stack; public class SudokuSolver37 { public void solveSudoku(char[][] board) { int L = board.length; Map> rows = new HashMap<>(); Map> cols = new HashMap<>(); Map> cells = new HashMap<>(); for (int l = 0; l < L; l++) { rows.put(l, new HashSet()); cols.put(l, new HashSet()); cells.put(l, new HashSet()); } for (int i = 0; i < L; i++) { Set r = rows.get(i); for (int j = 0; j < L; j++) { char c = board[i][j]; if (c != '.') { Set co = cols.get(j); Set ce = cells.get((i/3) * 3 + j/3); r.add(c); co.add(c); ce.add(c); } } } Stack> st = new Stack<>(); int x = 0; int y = 0; while (x < L) { // System.out.println(x + ", " + y); if (board[x][y] == '.') { boolean found = false; for (int n = 49; n<=57; n++) { char c = (char)n; if (!rows.get(x).contains(c) && !cols.get(y).contains(c) && !cells.get(cellPos(x, y)).contains(c)) { board[x][y] = c; // System.out.println(x + ", " + y + ", get: " + c); rows.get(x).add(c); cols.get(y).add(c); cells.get(cellPos(x, y)).add(c); st.push(Arrays.asList(x, y)); found = true; break; } } if (!found) { char newChar = (char)58; while ((int)newChar > 57) { List p = st.peek(); x = p.get(0); y = p.get(1); char old = board[x][y]; // System.out.println(x + ", " + y + ", old: " + old); while (old == '9') { rows.get(x).remove(old); cols.get(y).remove(old); cells.get(cellPos(x, y)).remove(old); st.pop(); board[x][y] = '.'; p = st.peek(); x = p.get(0); y = p.get(1); old = board[x][y]; // System.out.println(x + ", " + y + ", old: " + old); } rows.get(x).remove(old); cols.get(y).remove(old); cells.get(cellPos(x, y)).remove(old); newChar = (char)(old + 1); // System.out.println(x + ", " + y + ", new: " + newChar); while ((rows.get(x).contains(newChar) || cols.get(y).contains(newChar) || cells.get(cellPos(x, y)).contains(newChar)) && (int)newChar <= 57) { newChar = (char)(newChar + 1); // System.out.println(x + ", " + y + ", new: " + newChar); } if ((int)newChar > 57) { st.pop(); board[x][y] = '.'; } } board[x][y] = newChar; rows.get(x).add(newChar); cols.get(y).add(newChar); cells.get(cellPos(x, y)).add(newChar); // System.out.println(x + ", " + y + ", new: " + newChar); } } if (y < L-1) { y++; } else { y = 0; x++; } } } private int cellPos(int x, int y) { return (x/3) * 3 + y/3; } /** * https://leetcode.com/submissions/detail/105414901/ */ public void solveSudoku2(char[][] board) { if(board == null || board.length == 0) return; solve(board); } public boolean solve(char[][] board){ for(int i = 0; i < board.length; i++){ for(int j = 0; j < board[0].length; j++){ if(board[i][j] == '.'){ for(char c = '1'; c <= '9'; c++){//trial. Try 1 through 9 if(isValid(board, i, j, c)){ board[i][j] = c; //Put c for this cell if(solve(board)) return true; //If it's the solution return true else board[i][j] = '.'; //Otherwise go back } } return false; } } } return true; } private boolean isValid(char[][] board, int row, int col, char c){ for(int i = 0; i < 9; i++) { if(board[i][col] != '.' && board[i][col] == c) return false; //check row if(board[row][i] != '.' && board[row][i] == c) return false; //check column if(board[3 * (row / 3) + i / 3][ 3 * (col / 3) + i % 3] != '.' && board[3 * (row / 3) + i / 3][3 * (col / 3) + i % 3] == c) return false; //check 3*3 block } return true; } public static void main(String[] args) { SudokuSolver37 ss = new SudokuSolver37(); char[][] board = new char[][]{ {'.', '.', '9', '7', '4', '8', '.', '.', '.'}, {'7', '.', '.', '.', '.', '.', '.', '.', '.'}, {'.', '2', '.', '1', '.', '9', '.', '.', '.'}, {'.', '.', '7', '.', '.', '.', '2', '4', '.'}, {'.', '6', '4', '.', '1', '.', '5', '9', '.'}, {'.', '9', '8', '.', '.', '.', '3', '.', '.'}, {'.', '.', '.', '8', '.', '3', '.', '2', '.'}, {'.', '.', '.', '.', '.', '.', '.', '.', '6'}, {'.', '.', '.', '2', '7', '5', '9', '.', '.'}, }; for (int i=0; i<9; i++) { System.out.println(Arrays.toString(board[i])); } System.out.println("\n"); ss.solveSudoku(board); for (int j=0; j<9; j++) { System.out.println(Arrays.toString(board[j])); } } } ================================================ FILE: src/SumOfSquareNumbers633.java ================================================ /** * Given a non-negative integer c, your task is to decide whether there're two * integers a and b such that a2 + b2 = c. * * Example 1: * Input: 5 * Output: True * Explanation: 1 * 1 + 2 * 2 = 5 * * Example 2: * Input: 3 * Output: False */ public class SumOfSquareNumbers633 { public boolean judgeSquareSum(int c) { if (c < 0) return false; int n = (int) Math.sqrt(c); for (int i=0; i<=n; i++) { int re = c - i * i; int sq = (int) Math.sqrt(re); if (sq * sq == re) return true; } return false; } } ================================================ FILE: src/SumRootToLeafNumbers129.java ================================================ /** * Given a binary tree containing digits from 0-9 only, each root-to-leaf path * could represent a number. * * An example is the root-to-leaf path 1->2->3 which represents the number 123. * * Find the total sum of all root-to-leaf numbers. * * For example, * * 1 * / \ * 2 3 * The root-to-leaf path 1->2 represents the number 12. * The root-to-leaf path 1->3 represents the number 13. * * Return the sum = 12 + 13 = 25. * * */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class SumRootToLeafNumbers129 { public int sumNumbers(TreeNode root) { if (root == null) { return 0; } return helper(root, new ArrayList(), 0); } public int helper(TreeNode node, List path, int sum) { if (node == null) { return sum; } path.add(node.val); if (node.left == null && node.right == null) { int newSum = 0; for (int i = 0; i < path.size(); i++) { newSum += path.get(i) * (int) Math.pow(10, (path.size() - 1 - i)); } path.remove(path.size() - 1); return sum + newSum; } sum = helper(node.left, path, sum); sum = helper(node.right, path, sum); path.remove(path.size() - 1); return sum; } /** * https://discuss.leetcode.com/topic/6731/short-java-solution-recursion/17 */ public int sumNumbers(TreeNode root) { return sum(root, 0); } public int sum(TreeNode n, int s){ if (n == null) return 0; if (n.right == null && n.left == null) return s*10 + n.val; return sum(n.left, s*10 + n.val) + sum(n.right, s*10 + n.val); } } ================================================ FILE: src/SummaryRanges228.java ================================================ /** * Given a sorted integer array without duplicates, return the summary of * its ranges. * * Example 1: * Input: [0,1,2,4,5,7] * Output: ["0->2","4->5","7"] * Explanation: 0,1,2 form a continuous range; 4,5 form a continuous range. * * Example 2: * Input: [0,2,3,4,6,8,9] * Output: ["0","2->4","6","8->9"] * Explanation: 2,3,4 form a continuous range; 8,9 form a continuous range. */ public class SummaryRanges228 { public List summaryRanges(int[] arr) { List res = new ArrayList<>(); if (arr == null || arr.length == 0) return res; if (arr.length == 1) { res.add(Integer.toString(arr[0])); return res; } int len = arr.length; int i = 0; int j = 1; while (j <= len) { if (j == len || arr[j] - arr[j-1] != 1) { if (j-1 <= i) { res.add(Integer.toString(arr[i])); } else { res.add(arr[i] + "->" + arr[j-1]); } i = j; } j++; } return res; } } ================================================ FILE: src/SuperUglyNumber313.java ================================================ /** * Write a program to find the nth super ugly number. * * Super ugly numbers are positive numbers whose all prime factors are in the * given prime list primes of size k. * * Example: * Input: n = 12, primes = [2,7,13,19] * Output: 32 * Explanation: [1,2,4,7,8,13,14,16,19,26,28,32] is the sequence of the first 12 * super ugly numbers given primes = [2,7,13,19] of size 4. * * Note: * 1 is a super ugly number for any given primes. * The given numbers in primes are in ascending order. * 0 < k ≤ 100, 0 < n ≤ 106, 0 < primes[i] < 1000. * The nth super ugly number is guaranteed to fit in a 32-bit signed integer. */ public class SuperUglyNumber313 { public int nthSuperUglyNumber(int n, int[] primes) { if (n <= 0) return -1; int[] dp = new int[n]; dp[0] = 1; int[] pointers = new int[primes.length]; for (int i=1; i board.length-1 || j < 0 || j > board[0].length-1 || board[i][j] != 'O') { return; } board[i][j] = '*'; if (j < board[0].length - 2) markBoundary(board, i, j+1); if (i < board.length - 2) markBoundary(board, i+1, j); if (j > 1) markBoundary(board, i, j-1); if (i > 1) markBoundary(board, i-1, j); } private void markBoundary2(char[][] board, int i, int j) { board[i][j] = '*'; int[] dx = {-1, 0, 0, 1}; int[] dy = {0, -1, 1, 0}; for (int k = 0; k < dx.length; k++) { int x = dx[k] + i; int y = dy[k] + j; if (x > 0 && x < board.length - 1 && y > 0 && y < board[0].length - 1 && board[x][y] == 'O') { markBoundary2(board, x, y); } } } /** * https://discuss.leetcode.com/topic/35191/java-easy-version-to-understand/4 */ public static void solve2(char[][] board) { if (board == null || board.length == 0) return; int rows = board.length, columns = board[0].length; int[][] direction = { { -1, 0 }, { 1, 0 }, { 0, 1 }, { 0, -1 } }; for (int i = 0; i < rows; i++) for (int j = 0; j < columns; j++) { if ((i == 0 || i == rows - 1 || j == 0 || j == columns - 1) && board[i][j] == 'O') { Queue queue = new LinkedList<>(); board[i][j] = 'B'; queue.offer(new Point(i, j)); while (!queue.isEmpty()) { Point point = queue.poll(); for (int k = 0; k < 4; k++) { int x = direction[k][0] + point.x; int y = direction[k][1] + point.y; if (x >= 0 && x < rows && y >= 0 && y < columns && board[x][y] == 'O') { board[x][y] = 'B'; queue.offer(new Point(x, y)); } } } } } for (int i = 0; i < rows; i++) for (int j = 0; j < columns; j++) { if (board[i][j] == 'B') board[i][j] = 'O'; else if (board[i][j] == 'O') board[i][j] = 'X'; } } } ================================================ FILE: src/SwapAdjacentInLRString777.java ================================================ /** * In a string composed of 'L', 'R', and 'X' characters, like "RXXLRXRXL", a * move consists of either replacing one occurrence of "XL" with "LX", or * replacing one occurrence of "RX" with "XR". Given the starting string start * and the ending string end, return True if and only if there exists a * sequence of moves to transform one string to the other. * * Example: * Input: start = "RXXLRXRXL", end = "XRLXXRRLX" * Output: True * * Explanation: * We can transform start to end following these steps: * RXXLRXRXL -> * XRXLRXRXL -> * XRLXRXRXL -> * XRLXXRRXL -> * XRLXXRRLX * * Note: * 1 <= len(start) = len(end) <= 10000. * Both start and end will only consist of characters in {'L', 'R', 'X'}. */ public class SwapAdjacentInLRString777 { public boolean canTransform(String start, String end) { int len = start.length(); char[] starts = start.toCharArray(); char[] ends = end.toCharArray(); int ps = 0; int pe = 0; while (ps < len) { while (ps < len && starts[ps] == 'X') { ps++; } if (ps == len) break; while (pe < len && ends[pe] == 'X') { pe++; } if (pe == len) return false; if (starts[ps] == 'R') { if (ends[pe] != 'R' || pe < ps) return false; } else { // starts[ps] == 'L' if (ends[pe] != 'L' || pe > ps) return false; } ps++; pe++; } while (pe < len) { if (ends[pe++] != 'X') return false; } return true; } /** * https://leetcode.com/problems/swap-adjacent-in-lr-string/discuss/114737/Simple-Java-Solution */ public boolean canTransform2(String start, String end) { int r = 0; int l = 0; for (int i = 0; i < start.length(); i++){ if (start.charAt(i) == 'L') l++; if (start.charAt(i) == 'R') r++; if (end.charAt(i) == 'L') l--; if (end.charAt(i) == 'R') r--; if (l > 0 || r < 0 || (r > 0 && l != 0)) { return false; } } return l == 0 && r == 0; } } ================================================ FILE: src/SymmetricTree101.java ================================================ /** * Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). * * For example, this binary tree [1,2,2,3,4,4,3] is symmetric: * * 1 * / \ * 2 2 * / \ / \ * 3 4 4 3 * * But the following [1,2,2,null,3,null,3] is not: * 1 * / \ * 2 2 * \ \ * 3 3 * * Note: * Bonus points if you could solve it both recursively and iteratively. * */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class SymmetricTree101 { public boolean isSymmetric(TreeNode root) { if (root == null || (root.left == null && root.right == null)) return true; LinkedList queue = new LinkedList<>(); queue.add(root.left); queue.add(root.right); int i = 1; while (!queue.isEmpty()) { Stack st = new Stack<>(); i = queue.size() >> 1; int k = 0; while (k stack = new Stack(); TreeNode left, right; if (root.left != null) { if (root.right == null) return false; stack.push(root.left); stack.push(root.right); } else if (root.right != null) { return false; } while (!stack.empty()) { if (stack.size()%2 != 0) return false; right = stack.pop(); left = stack.pop(); if(right.val != left.val) return false; if (left.left != null) { if(right.right == null) return false; stack.push(left.left); stack.push(right.right); } else if(right.right != null){ return false; } if (left.right != null) { if(right.left == null) return false; stack.push(left.right); stack.push(right.left); } else if(right.left != null) { return false; } } return true; } /** * https://discuss.leetcode.com/topic/5941/recursive-and-non-recursive-solutions-in-java */ public boolean isSymmetric3(TreeNode root) { return root==null || isSymmetricHelp(root.left, root.right); } private boolean isSymmetricHelp(TreeNode left, TreeNode right){ if(left==null || right==null) return left==right; if(left.val!=right.val) return false; return isSymmetricHelp(left.left, right.right) && isSymmetricHelp(left.right, right.left); } } ================================================ FILE: src/TargetSum494.java ================================================ /** * You are given a list of non-negative integers, a1, a2, ..., an, and a * target, S. Now you have 2 symbols + and -. For each integer, you should * choose one from + and - as its new symbol. * * Find out how many ways to assign symbols to make sum of integers equal to * target S. * * Example 1: * Input: nums is [1, 1, 1, 1, 1], S is 3. * Output: 5 * * Explanation: * -1+1+1+1+1 = 3 * +1-1+1+1+1 = 3 * +1+1-1+1+1 = 3 * +1+1+1-1+1 = 3 * +1+1+1+1-1 = 3 * * There are 5 ways to assign symbols to make the sum of nums be target 3. * * Note: * The length of the given array is positive and will not exceed 20. * The sum of elements in the given array will not exceed 1000. * Your output answer is guaranteed to be fitted in a 32-bit integer. */ public class TargetSum494 { public int findTargetSumWays(int[] nums, int S) { if (S > 1000 || S < -1000) return 0; int N = nums.length; int[][] dp = new int[N+1][2001]; dp[0][1000] = 1; for (int i=1; i<=N; i++) { int n = nums[i-1]; for (int j=0; j<2001; j++) { dp[i][j] = (j+n < 2001 ? dp[i-1][j+n] : 0) + (j-n >=0 ? dp[i-1][j-n] : 0); } } return dp[N][S + 1000]; } public int findTargetSumWays2(int[] nums, int S) { if (S > 1000 || S < -1000) return 0; int N = nums.length; int[] dp = new int[2001]; dp[1000] = 1; for (int i=1; i<=N; i++) { int n = nums[i-1]; int[] tmp = new int[2001]; for (int j=0; j<2001; j++) tmp[j] = dp[j]; for (int j=0; j<2001; j++) { dp[j] = (j+n < 2001 ? tmp[j+n] : 0) + (j-n >=0 ? tmp[j-n] : 0); } } return dp[S + 1000]; } /** * https://leetcode.com/problems/target-sum/solution/ */ public int findTargetSumWays3(int[] nums, int S) { int[][] dp = new int[nums.length][2001]; dp[0][nums[0] + 1000] = 1; dp[0][-nums[0] + 1000] += 1; for (int i = 1; i < nums.length; i++) { for (int sum = -1000; sum <= 1000; sum++) { if (dp[i - 1][sum + 1000] > 0) { dp[i][sum + nums[i] + 1000] += dp[i - 1][sum + 1000]; dp[i][sum - nums[i] + 1000] += dp[i - 1][sum + 1000]; } } } return S > 1000 ? 0 : dp[nums.length - 1][S + 1000]; } /** * https://leetcode.com/problems/target-sum/solution/ */ public int findTargetSumWays4(int[] nums, int S) { int[] dp = new int[2001]; dp[nums[0] + 1000] = 1; dp[-nums[0] + 1000] += 1; for (int i = 1; i < nums.length; i++) { int[] next = new int[2001]; for (int sum = -1000; sum <= 1000; sum++) { if (dp[sum + 1000] > 0) { next[sum + nums[i] + 1000] += dp[sum + 1000]; next[sum - nums[i] + 1000] += dp[sum + 1000]; } } dp = next; } return S > 1000 ? 0 : dp[S + 1000]; } } ================================================ FILE: src/TaskScheduler621.java ================================================ /** * Given a char array representing tasks CPU need to do. It contains capital * letters A to Z where different letters represent different tasks.Tasks could * be done without original order. Each task could be done in one interval. * For each interval, CPU could finish one task or just be idle. * * However, there is a non-negative cooling interval n that means between two * same tasks, there must be at least n intervals that CPU are doing different * tasks or just be idle. * * You need to return the least number of intervals the CPU will take to finish * all the given tasks. * * Example 1: * Input: tasks = ["A","A","A","B","B","B"], n = 2 * Output: 8 * * Explanation: A -> B -> idle -> A -> B -> idle -> A -> B. * Note: * The number of tasks is in the range [1, 10000]. * The integer n is in the range [0, 100]. * */ /** * Note that the names of the tasks are irrelevant for obtaining the solution * of the given problem. The time taken for the tasks to be finished is only * dependent on the number of instances of each task and not on the names of * tasks. */ public class TaskScheduler621 { /** * https://leetcode.com/problems/task-scheduler/solution/ */ public int leastInterval(char[] tasks, int n) { int[] map = new int[26]; for (char c: tasks) map[c - 'A']++; Arrays.sort(map); int maxVal = map[25] - 1; int idles = maxVal * n; for (int i = 24; i >= 0 && map[i] > 0; i--) { idles -= Math.min(map[i], maxVal); } return idles > 0 ? idles + tasks.length : tasks.length; } /** * https://discuss.leetcode.com/topic/92852/concise-java-solution-o-n-time-o-26-space */ public int leastInterval2(char[] tasks, int n) { int[] c = new int[26]; for(char t : tasks){ c[t - 'A']++; } Arrays.sort(c); int i = 25; while(i >= 0 && c[i] == c[25]) i--; return Math.max(tasks.length, (c[25] - 1) * (n + 1) + 25 - i); } /** * https://leetcode.com/problems/task-scheduler/solution/ */ public int leastInterval3(char[] tasks, int n) { int[] map = new int[26]; for (char c: tasks) map[c - 'A']++; Arrays.sort(map); int time = 0; while (map[25] > 0) { int i = 0; while (i <= n) { if (map[25] == 0) break; if (i < 26 && map[25 - i] > 0) map[25 - i]--; time++; i++; } Arrays.sort(map); } return time; } public int leastInterval4(char[] tasks, int n) { int N = tasks.length; int[] count = new int[26]; int max = -1; int maxCount = -1; for (char ch: tasks) { count[ch-'A']++; if (count[ch-'A'] == max) { maxCount++; } else if (count[ch-'A'] > max) { max = count[ch-'A']; maxCount = 1; } } return Math.max((n+1) * (max-1) + maxCount, N); } /** * https://leetcode.com/problems/task-scheduler/discuss/104500/Java-O(n)-time-O(1)-space-1-pass-no-sorting-solution-with-detailed-explanation */ public int leastInterval5(char[] tasks, int n) { int[] counter = new int[26]; int max = 0; int maxCount = 0; for(char task : tasks) { counter[task - 'A']++; if(max == counter[task - 'A']) { maxCount++; } else if(max < counter[task - 'A']) { max = counter[task - 'A']; maxCount = 1; } } int partCount = max - 1; int partLength = n - (maxCount - 1); int emptySlots = partCount * partLength; int availableTasks = tasks.length - max * maxCount; int idles = Math.max(0, emptySlots - availableTasks); return tasks.length + idles; } } ================================================ FILE: src/TextJustification68.java ================================================ /** * Given an array of words and a width maxWidth, format the text such that each * line has exactly maxWidth characters and is fully (left and right) justified. * * You should pack your words in a greedy approach; that is, pack as many words * as you can in each line. Pad extra spaces ' ' when necessary so that each * line has exactly maxWidth characters. * * Extra spaces between words should be distributed as evenly as possible. If * the number of spaces on a line do not divide evenly between words, the empty * slots on the left will be assigned more spaces than the slots on the right. * * For the last line of text, it should be left justified and no extra space is * inserted between words. * * Note: * A word is defined as a character sequence consisting of non-space characters only. * Each word's length is guaranteed to be greater than 0 and not exceed maxWidth. * The input array words contains at least one word. * * Example 1: * Input: * words = ["This", "is", "an", "example", "of", "text", "justification."] * maxWidth = 16 * Output: * [ * "This is an", * "example of text", * "justification. " * ] * * Example 2: * Input: * words = ["What","must","be","acknowledgment","shall","be"] * maxWidth = 16 * Output: * [ * "What must be", * "acknowledgment ", * "shall be " * ] * Explanation: Note that the last line is "shall be " instead of "shall be", * because the last line must be left-justified instead of fully-justified. * Note that the second line is also left-justified becase it contains only one word. * * Example 3: * Input: * words = ["Science","is","what","we","understand","well","enough","to", * "explain","to","a","computer.","Art","is","everything","else","we","do"] * maxWidth = 20 * Output: * [ * "Science is what we", * "understand well", * "enough to explain to", * "a computer. Art is", * "everything else we", * "do " * ] */ import java.util.*; public class TextJustification68 { public List fullJustify(String[] words, int maxWidth) { List res = new ArrayList<>(); int i = 0; int N = words.length; while (i < N) { int spaceLeft = maxWidth; int wordsLen = 0; List line = new ArrayList<>(); while (i < N) { if (words[i].length() > spaceLeft) break; line.add(words[i]); wordsLen += words[i].length(); spaceLeft -= words[i].length() + 1; i++; } StringBuilder sb = new StringBuilder(); if (i == N || line.size() == 1) { res.add(leftJustify(line, maxWidth)); } else { res.add(middleJustify(line, maxWidth, wordsLen)); } } return res; } private String leftJustify(List line, int maxWidth) { StringBuilder sb = new StringBuilder(); for (String w: line) { sb.append(w); if (sb.length() < maxWidth) sb.append(' '); } while (sb.length() < maxWidth) { sb.append(' '); } return sb.toString(); } private String middleJustify(List line, int maxWidth, int wordsLen) { StringBuilder sb = new StringBuilder(); int n = line.size(); int spaces = maxWidth - wordsLen; int interval = spaces / (n-1); int rest = spaces - interval * (n-1); for (int k=0; k 0 && sb.length() < maxWidth) { sb.append(' '); p--; } if (rest > 0 && sb.length() < maxWidth) { sb.append(' '); rest--; } } return sb.toString(); } } ================================================ FILE: src/TheMaze490.java ================================================ /** * There is a ball in a maze with empty spaces and walls. The ball can go * through empty spaces by rolling up, down, left or right, but it won't stop * rolling until hitting a wall. When the ball stops, it could choose the next * direction. * * Given the ball's start position, the destination and the maze, determine * whether the ball could stop at the destination. * * The maze is represented by a binary 2D array. 1 means the wall and 0 means * the empty space. You may assume that the borders of the maze are all walls. * The start and destination coordinates are represented by row and column * indexes. * * Example 1 * * Input 1: a maze represented by a 2D array * * 0 0 1 0 0 * 0 0 0 0 0 * 0 0 0 1 0 * 1 1 0 1 1 * 0 0 0 0 0 * * Input 2: start coordinate (rowStart, colStart) = (0, 4) * Input 3: destination coordinate (rowDest, colDest) = (4, 4) * * Output: true * Explanation: One possible way is : left -> down -> left -> down -> right -> down -> right. * https://leetcode.com/static/images/problemset/maze_1_example_1.png * * Example 2 * * Input 1: a maze represented by a 2D array * * 0 0 1 0 0 * 0 0 0 0 0 * 0 0 0 1 0 * 1 1 0 1 1 * 0 0 0 0 0 * * Input 2: start coordinate (rowStart, colStart) = (0, 4) * Input 3: destination coordinate (rowDest, colDest) = (3, 2) * * Output: false * Explanation: There is no way for the ball to stop at the destination. * https://leetcode.com/static/images/problemset/maze_1_example_2.png * * Note: * There is only one ball and one destination in the maze. * Both the ball and the destination exist on an empty space, and they will not * be at the same position initially. * The given maze does not contain border (like the red rectangle in the example * pictures), but you could assume the border of the maze are all walls. * The maze contains at least 2 empty spaces, and both the width and height of * the maze won't exceed 100. */ public class TheMaze490 { private boolean[][] visited; public boolean hasPath(int[][] maze, int[] start, int[] destination) { visited = new boolean[maze.length][maze[0].length]; if (hasPath(maze, start, destination, Direction.Left) || hasPath(maze, start, destination, Direction.Right) || hasPath(maze, start, destination, Direction.Top) || hasPath(maze, start, destination, Direction.Down)) return true; return false; } public boolean hasPath(int[][] maze, int[] start, int[] destination, Direction d) { visited[start[0]][start[1]] = true; int[] now = new int[]{start[0], start[1]}; Direction origin = d; while (true) { if (d == Direction.Left) { int nextLeft = now[1] - 1; if (nextLeft < 0 || maze[now[0]][nextLeft] == 1) break; now[1] = nextLeft; // System.out.println(tuple(now)); origin = Direction.Right; } else if (d == Direction.Right) { int nextRight = now[1] + 1; if (nextRight >= maze[0].length || maze[now[0]][nextRight] == 1) break; now[1] = nextRight; origin = Direction.Left; } else if (d == Direction.Top) { int nextTop = now[0] - 1; if (nextTop < 0 || maze[nextTop][now[1]] == 1) break; now[0] = nextTop; origin = Direction.Down; } else { int nextDown = now[0] + 1; if (nextDown >= maze.length || maze[nextDown][now[1]] == 1) break; now[0] = nextDown; origin = Direction.Top; } } if (now[0] == destination[0] && now[1] == destination[1]) return true; if (visited[now[0]][now[1]]) return false; for (Direction nextDir: Direction.values()) { if (nextDir != origin && hasPath(maze, now, destination, nextDir)) return true; } visited[start[0]][start[1]] = false; return false; } public enum Direction { Left, Right, Top, Down } public boolean hasPath2(int[][] maze, int[] start, int[] destination) { int M = maze.length; int N = maze[0].length; return roll(maze, start[0], start[1], destination[0], destination[1], M, N, new boolean[M][N]); } private boolean roll(int[][] maze, int i, int j, int di, int dj, int M, int N, boolean[][] visited) { // if (i < 0 || j < 0 || i >= M || j >= N) return false; if (visited[i][j]) return false; if (i == di && j == dj) return true; visited[i][j] = true; // top int x = i - 1; int y = j; while (x >= 0 && maze[x][y] == 0) x--; if (roll(maze, x+1, y, di, dj, M, N, visited)) { return true; } // bottom x = i + 1; y = j; while (x < M && maze[x][y] == 0) x++; if (roll(maze, x-1, y, di, dj, M, N, visited)) { return true; } // left x = i; y = j - 1; while (y >= 0 && maze[x][y] == 0) y--; if (roll(maze, x, y+1, di, dj, M, N, visited)) { return true; } // right x = i; y = j + 1; while (y < N && maze[x][y] == 0) y++; if (roll(maze, x, y-1, di, dj, M, N, visited)) { return true; } return false; } public boolean hasPath3(int[][] maze, int[] start, int[] destination) { if (maze == null || maze.length == 0 || maze[0].length == 0 || start == null || destination == null) return false; if (start[0] == destination[0] && start[1] == destination[1]) return true; int M = maze.length; int N = maze[0].length; boolean[][] visited = new boolean[M][N]; Queue q = new LinkedList<>(); q.add(start); visited[start[0]][start[1]] = true; while (!q.isEmpty()) { int[] curr = q.poll(); if (curr[0] == destination[0] && curr[1] == destination[1]) return true; addNextSteps(maze, q, visited, curr, M, N); } return false; } private void addNextSteps(int[][] maze, Queue q, boolean[][] visited, int[] curr, int M, int N) { int i = curr[0]; while (i >= 0 && maze[i][curr[1]] == 0) { i--; } if (!visited[i+1][curr[1]]) { q.add(new int[]{i+1, curr[1]}); visited[i+1][curr[1]] = true; } i = curr[0]; while (i < M && maze[i][curr[1]] == 0) { i++; } if (!visited[i-1][curr[1]]) { q.add(new int[]{i-1, curr[1]}); visited[i-1][curr[1]] = true; } i = curr[1]; while (i >= 0 && maze[curr[0]][i] == 0) { i--; } if (!visited[curr[0]][i+1]) { q.add(new int[]{curr[0], i+1}); visited[curr[0]][i+1] = true; } i = curr[1]; while (i < N && maze[curr[0]][i] == 0) { i++; } if (!visited[curr[0]][i-1]) { q.add(new int[]{curr[0], i-1}); visited[curr[0]][i-1] = true; } } private int[][] DIRECTIONS = new int[][]{{0,1}, {0,-1}, {1,0}, {-1,0}}; public boolean hasPath4(int[][] maze, int[] start, int[] destination) { int M = maze.length; int N = maze[0].length; boolean[][] visited = new boolean[M][N]; Queue q = new LinkedList<>(); q.add(start); visited[start[0]][start[1]] = true; while (!q.isEmpty()) { int[] curr = q.poll(); for (int[] dir: DIRECTIONS) { int x = curr[0]+dir[0]; int y = curr[1]+dir[1]; while (x >= 0 && x < M && y >= 0 && y < N && maze[x][y] == 0) { x += dir[0]; y += dir[1]; } x -= dir[0]; y -= dir[1]; if (x == destination[0] && y == destination[1]) return true; if (!visited[x][y]) { q.add(new int[]{x, y}); visited[x][y] = true; } } } return false; } } ================================================ FILE: src/TheMazeII505.java ================================================ /** * There is a ball in a maze with empty spaces and walls. The ball can go * through empty spaces by rolling up, down, left or right, but it won't stop * rolling until hitting a wall. When the ball stops, it could choose the next * direction. * * Given the ball's start position, the destination and the maze, find the * shortest distance for the ball to stop at the destination. The distance is * defined by the number of empty spaces traveled by the ball from the start * position (excluded) to the destination (included). If the ball cannot stop * at the destination, return -1. * * The maze is represented by a binary 2D array. 1 means the wall and 0 means * the empty space. You may assume that the borders of the maze are all walls. * The start and destination coordinates are represented by row and column * indexes. * * Example 1 * * Input 1: a maze represented by a 2D array * * 0 0 1 0 0 * 0 0 0 0 0 * 0 0 0 1 0 * 1 1 0 1 1 * 0 0 0 0 0 * * Input 2: start coordinate (rowStart, colStart) = (0, 4) * Input 3: destination coordinate (rowDest, colDest) = (4, 4) * * Output: 12 * Explanation: One shortest way is : left -> down -> left -> down -> right -> down -> right. * The total distance is 1 + 1 + 3 + 1 + 2 + 2 + 2 = 12. * https://leetcode.com/static/images/problemset/maze_1_example_1.png * * * Example 2 * * Input 1: a maze represented by a 2D array * * 0 0 1 0 0 * 0 0 0 0 0 * 0 0 0 1 0 * 1 1 0 1 1 * 0 0 0 0 0 * * Input 2: start coordinate (rowStart, colStart) = (0, 4) * Input 3: destination coordinate (rowDest, colDest) = (3, 2) * * Output: -1 * Explanation: There is no way for the ball to stop at the destination. * https://leetcode.com/static/images/problemset/maze_1_example_2.png * * Note: * There is only one ball and one destination in the maze. * Both the ball and the destination exist on an empty space, and they will not * be at the same position initially. * The given maze does not contain border (like the red rectangle in the * example pictures), but you could assume the border of the maze are all walls. * The maze contains at least 2 empty spaces, and both the width and height of * the maze won't exceed 100. */ public class TheMazeII505 { private int[][] DIRECTIONS = new int[][]{{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; public int shortestDistance(int[][] maze, int[] start, int[] destination) { int M = maze.length; int N = maze[0].length; if (isSame(start, destination)) return 0; int[][] visited = new int[M][N]; for (int[] row: visited) { Arrays.fill(row, -1); } Queue q = new LinkedList<>(); q.add(new Point(start, 0)); visited[start[0]][start[1]] = 0; int min = Integer.MAX_VALUE; while (!q.isEmpty()) { int size = q.size(); Point curr = q.poll(); if (isSame(curr.pos, destination)) { min = Math.min(min, curr.dist); continue; } for (int[] d: DIRECTIONS) { int x = curr.pos[0] + d[0]; int y = curr.pos[1] + d[1]; int more = 1; while (x >= 0 && y >= 0 && x < M && y < N && maze[x][y] == 0) { x += d[0]; y += d[1]; more++; } x -= d[0]; y -= d[1]; more--; int[] newPos = new int[]{x, y}; if (visited[x][y] == -1 || visited[x][y] > curr.dist + more) { q.add(new Point(newPos, curr.dist + more)); visited[x][y] = curr.dist + more; } } } return min == Integer.MAX_VALUE ? -1 : min; } private boolean isSame(int[] a, int[] b) { return a[0] == b[0] && a[1] == b[1]; } class Point { int[] pos; int dist; Point(int[] p, int d) { pos = p; dist = d; } } /** * https://leetcode.com/problems/the-maze-ii/discuss/98418/Simple-Java-Solution-BFS */ public int shortestDistance2(int[][] maze, int[] start, int[] destination) { Queue q = new LinkedList<>(); int m = maze.length, n = maze[0].length; int[][] dist = new int[m][n]; for (int i = 0; i < m; i++) { Arrays.fill(dist[i], Integer.MAX_VALUE); } int[] dx = new int[] {-1, 0, 1, 0}; int[] dy = new int[] { 0, 1, 0, -1}; q.offer(start); dist[start[0]][start[1]] = 0; while (!q.isEmpty()) { int[] p = q.poll(); for (int i = 0; i < 4; i++) { int x = p[0] + dx[i], y = p[1] + dy[i]; int cnt = 1; while (x >=0 && x < m && y >= 0 && y < n && maze[x][y] != 1) { x += dx[i]; y += dy[i]; cnt++; } x -= dx[i]; y -= dy[i]; cnt--; if (dist[p[0]][p[1]] + cnt < dist[x][y]) { dist[x][y] = dist[p[0]][p[1]] + cnt; q.offer(new int[] {x, y}); } } } return dist[destination[0]][destination[1]] == Integer.MAX_VALUE ? -1 : dist[destination[0]][destination[1]]; } public int shortestDistance3(int[][] maze, int[] start, int[] destination) { int M = maze.length; int N = maze[0].length; int[][] memo = new int[M][N]; for (int[] row: memo) Arrays.fill(row, Integer.MAX_VALUE); memo[start[0]][start[1]] = 0; roll(maze, start[0], start[1], memo, M, N); return memo[destination[0]][destination[1]] == Integer.MAX_VALUE ? -1 : memo[destination[0]][destination[1]]; } private void roll(int[][] maze, int i, int j, int[][] memo, int M, int N) { // top int t = i - 1; int rt = 1; while (t >= 0 && maze[t][j] == 0) { t--; rt++; } t++; rt--; if (memo[i][j] + rt < memo[t][j]) { memo[t][j] = memo[i][j] + rt; roll(maze, t, j, memo, M, N); } // bottom int b = i + 1; int rb = 1; while (b < M && maze[b][j] == 0) { b++; rb++; } b--; rb--; if (memo[i][j] + rb < memo[b][j]) { memo[b][j] = memo[i][j] + rb; roll(maze, b, j, memo, M, N); } // left int l = j - 1; int rl = 1; while (l >= 0 && maze[i][l] == 0) { l--; rl++; } l++; rl--; if (memo[i][j] + rl < memo[i][l]) { memo[i][l] = memo[i][j] + rl; roll(maze, i, l, memo, M, N); } // right int r = j + 1; int rr = 1; while (r < N && maze[i][r] == 0) { r++; rr++; } r--; rr--; if (memo[i][j] + rr < memo[i][r]) { memo[i][r] = memo[i][j] + rr; roll(maze, i, r, memo, M, N); } } /** * https://leetcode.com/problems/the-maze-ii/solution/ */ public int shortestDistance4(int[][] maze, int[] start, int[] dest) { int[][] distance = new int[maze.length][maze[0].length]; for (int[] row: distance) Arrays.fill(row, Integer.MAX_VALUE); distance[start[0]][start[1]] = 0; dfs(maze, start, distance); return distance[dest[0]][dest[1]] == Integer.MAX_VALUE ? -1 : distance[dest[0]][dest[1]]; } public void dfs(int[][] maze, int[] start, int[][] distance) { int[][] dirs={{0,1}, {0,-1}, {-1,0}, {1,0}}; for (int[] dir: dirs) { int x = start[0] + dir[0]; int y = start[1] + dir[1]; int count = 0; while (x >= 0 && y >= 0 && x < maze.length && y < maze[0].length && maze[x][y] == 0) { x += dir[0]; y += dir[1]; count++; } if (distance[start[0]][start[1]] + count < distance[x - dir[0]][y - dir[1]]) { distance[x - dir[0]][y - dir[1]] = distance[start[0]][start[1]] + count; dfs(maze, new int[]{x - dir[0],y - dir[1]}, distance); } } } /** * https://leetcode.com/problems/the-maze-ii/solution/ */ public int shortestDistance5(int[][] maze, int[] start, int[] destination) { int M = maze.length; int N = maze[0].length; int[][] distances = new int[M][N]; for (int[] row: distances) Arrays.fill(row, Integer.MAX_VALUE); distances[start[0]][start[1]] = 0; boolean[][] visited = new boolean[M][N]; roll(maze, distances, visited, M, N); int res = distances[destination[0]][destination[1]]; return res == Integer.MAX_VALUE ? -1 : res; } private void roll(int[][] maze, int[][] distances, boolean[][] visited, int M, int N) { while (true) { int[] m = minDistance(distances, visited, M, N); if (m == null) return; visited[m[0]][m[1]] = true; for (int[] dir: DIRECTIONS) { int x = m[0] + dir[0]; int y = m[1] + dir[1]; int dis = 0; while (x >= 0 && y >= 0 && x < M && y < N && maze[x][y] == 0) { x += dir[0]; y += dir[1]; dis++; } x -= dir[0]; y -= dir[1]; int d = distances[m[0]][m[1]] + dis; if (d < distances[x][y]) { distances[x][y] = d; } } } } private int[] minDistance(int[][] distances, boolean[][] visited, int M, int N) { int[] res = null; int min = Integer.MAX_VALUE; for (int i=0; i pq = new PriorityQueue<>((a, b) -> a[2] - b[2]); pq.add(new int[]{start[0], start[1], 0}); while (!pq.isEmpty()) { int[] md = pq.poll(); if (distances[md[0]][md[1]] < md[2]) continue; for (int[] dir: DIRECTIONS) { int x = md[0] + dir[0]; int y = md[1] + dir[1]; int dis = 0; while (x >= 0 && y >= 0 && x < M && y < N && maze[x][y] == 0) { x += dir[0]; y += dir[1]; dis++; } x -= dir[0]; y -= dir[1]; int d = distances[md[0]][md[1]] + dis; if (d < distances[x][y]) { distances[x][y] = d; pq.add(new int[]{x, y, d}); } } } } } ================================================ FILE: src/TheMazeIII499.java ================================================ /** * There is a ball in a maze with empty spaces and walls. The ball can go * through empty spaces by rolling up (u), down (d), left (l) or right (r), * but it won't stop rolling until hitting a wall. When the ball stops, it * could choose the next direction. There is also a hole in this maze. The * ball will drop into the hole if it rolls on to the hole. * * Given the ball position, the hole position and the maze, find out how the * ball could drop into the hole by moving the shortest distance. The distance * is defined by the number of empty spaces traveled by the ball from the start * position (excluded) to the hole (included). Output the moving directions * by using 'u', 'd', 'l' and 'r'. Since there could be several different * shortest ways, you should output the lexicographically smallest way. If * the ball cannot reach the hole, output "impossible". * * The maze is represented by a binary 2D array. 1 means the wall and 0 means * the empty space. You may assume that the borders of the maze are all walls. * The ball and the hole coordinates are represented by row and column indexes. * * Example 1: * Input 1: a maze represented by a 2D array * 0 0 0 0 0 * 1 1 0 0 1 * 0 0 0 0 0 * 0 1 0 0 1 * 0 1 0 0 0 * * Input 2: ball coordinate (rowBall, colBall) = (4, 3) * Input 3: hole coordinate (rowHole, colHole) = (0, 1) * * Output: "lul" * * Explanation: There are two shortest ways for the ball to drop into the hole. * The first way is left -> up -> left, represented by "lul". * The second way is up -> left, represented by 'ul'. * Both ways have shortest distance 6, but the first way is lexicographically * smaller because 'l' < 'u'. So the output is "lul". * * Example 2: * Input 1: a maze represented by a 2D array * 0 0 0 0 0 * 1 1 0 0 1 * 0 0 0 0 0 * 0 1 0 0 1 * 0 1 0 0 0 * * Input 2: ball coordinate (rowBall, colBall) = (4, 3) * Input 3: hole coordinate (rowHole, colHole) = (3, 0) * * Output: "impossible" * * Explanation: The ball cannot reach the hole. * * Note: * There is only one ball and one hole in the maze. * Both the ball and hole exist on an empty space, and they will not be at the * same position initially. * The given maze does not contain border (like the red rectangle in the * example pictures), but you could assume the border of the maze are all walls. * The maze contains at least 2 empty spaces, and the width and the height * of the maze won't exceed 30. */ public class TheMazeIII499 { private int[][] DIRECTIONS = new int[][]{{1,0}, {0,-1}, {0,1}, {-1,0}}; private char[] LETTERS = new char[]{'d', 'l', 'r', 'u'}; public String findShortestWay(int[][] maze, int[] ball, int[] hole) { int M = maze.length; int N = maze[0].length; int[][] distance = new int[M][N]; for (int[] row: distance) Arrays.fill(row, Integer.MAX_VALUE); distance[ball[0]][ball[1]] = 0; StringBuilder sb = new StringBuilder(); String[] res = new String[1]; int[] dis = new int[]{Integer.MAX_VALUE}; roll(maze, ball[0], ball[1], hole[0], hole[1], distance, sb, M, N, res, dis); return res[0] == null ? "impossible" : res[0]; } private void roll(int[][] maze, int i, int j, int hi, int hj, int[][] distance, StringBuilder sb, int M, int N, String[] res, int[] dis) { int len = sb.length(); for (int k=0; k<4; k++) { int[] dir = DIRECTIONS[k]; char ch = LETTERS[k]; sb.append(ch); int x = i + dir[0]; int y = j + dir[1]; int count = 0; while (x >= 0 && y >= 0 && x < M && y < N && maze[x][y] == 0) { if (x == hi && y == hj) break; x += dir[0]; y += dir[1]; count++; } int d = distance[i][j] + count; if (x == hi && y == hj) { if (d < dis[0]) { dis[0] = d; res[0] = sb.toString(); } else if (d == dis[0]) { String tmp = sb.toString(); if (res[0] == null || tmp.compareTo(res[0]) < 0) { res[0] = tmp; } } sb.setLength(len); continue; } x -= dir[0]; y -= dir[1]; if (d < distance[x][y]) { distance[x][y] = d; roll(maze, x, y, hi, hj, distance, sb, M, N, res, dis); } sb.setLength(len); } } } ================================================ FILE: src/TheSkylineProblem218.java ================================================ /** * A city's skyline is the outer contour of the silhouette formed by all the * buildings in that city when viewed from a distance. Now suppose you are * given the locations and height of all the buildings as shown on a cityscape * photo (Figure A), write a program to output the skyline formed by these * buildings collectively (Figure B). * * https://leetcode.com/static/images/problemset/skyline2.jpg * * The geometric information of each building is represented by a triplet of * integers [Li, Ri, Hi], where Li and Ri are the x coordinates of the left * and right edge of the ith building, respectively, and Hi is its height. It * is guaranteed that 0 ≤ Li, Ri ≤ INT_MAX, 0 < Hi ≤ INT_MAX, and Ri - Li > 0. * You may assume all buildings are perfect rectangles grounded on an * absolutely flat surface at height 0. * * For instance, the dimensions of all buildings in Figure A are recorded as: * [ [2 9 10], [3 7 15], [5 12 12], [15 20 10], [19 24 8] ] . * * The output is a list of "key points" (red dots in Figure B) in the format * of [ [x1,y1], [x2, y2], [x3, y3], ... ] that uniquely defines a skyline. A * key point is the left endpoint of a horizontal line segment. Note that the * last key point, where the rightmost building ends, is merely used to mark * the termination of the skyline, and always has zero height. Also, the * ground in between any two adjacent buildings should be considered part of * the skyline contour. * * For instance, the skyline in Figure B should be represented as: * [ [2 10], [3 15], [7 12], [12 0], [15 10], [20 8], [24, 0] ]. * * Notes: * * The number of buildings in any input list is guaranteed to be in the range [0, 10000]. * The input list is already sorted in ascending order by the left x position Li. * The output list must be sorted by the x position. * There must be no consecutive horizontal lines of equal height in the output * skyline. For instance, [...[2 3], [4 5], [7 5], [11 5], [12 7]...] is not * acceptable; the three lines of height 5 should be merged into one in the * final output as such: [...[2 3], [4 5], [12 7], ...] */ public class TheSkylineProblem218 { private static int L = 0; private static int R = 1; public List getSkyline(int[][] buildings) { List res = new ArrayList<>(); int N = buildings.length; if (N == 0) return res; // xi, hi, L/R int[][] verts = new int[N * 2][3]; int t = 0; for (int[] b: buildings) { verts[t++] = new int[]{b[0], b[2], L}; verts[t++] = new int[]{b[1], b[2], R}; } Comparator comp1 = new Comparator() { @Override public int compare(int[] v1, int[] v2) { int xd = Integer.compare(v1[0], v2[0]); if (xd != 0) return xd; if (v1[2] == L && v2[2] == L) { return Integer.compare(v2[1], v1[1]); } else if (v1[2] == R && v2[2] == R) { return Integer.compare(v1[1], v2[1]); } else { return Integer.compare(v1[2], v2[2]); } } }; Arrays.sort(verts, comp1); Comparator comp2 = (h1, h2) -> Integer.compare(h2, h1); PriorityQueue pq = new PriorityQueue<>(comp2); for (int[] vi: verts) { int xi = vi[0]; int hi = vi[1]; int Di = vi[2]; if (Di == L) { // L if (pq.isEmpty() || pq.peek() < hi) { res.add(new int[]{xi, hi}); } pq.add(hi); } else { // R pq.remove(hi); if (pq.isEmpty() || pq.peek() < hi) { int y = pq.isEmpty() ? 0 : pq.peek(); res.add(new int[]{xi, y}); } } } return res; } /** * https://leetcode.com/problems/the-skyline-problem/discuss/61192/Once-for-all-explanation-with-clean-Java-code(O(n2)time-O(n)-space) */ public List getSkyline2(int[][] buildings) { List result = new ArrayList<>(); List height = new ArrayList<>(); for(int[] b:buildings) { // start point has negative height value height.add(new int[]{b[0], -b[2]}); // end point has normal height value height.add(new int[]{b[1], b[2]}); } // sort $height, based on the first value, if necessary, use the second to // break ties Collections.sort(height, (a, b) -> { if(a[0] != b[0]) return a[0] - b[0]; return a[1] - b[1]; }); // Use a maxHeap to store possible heights Queue pq = new PriorityQueue<>((a, b) -> (b - a)); // Provide a initial value to make it more consistent pq.offer(0); // Before starting, the previous max height is 0; int prev = 0; // visit all points in order for(int[] h:height) { if(h[1] < 0) { // a start point, add height pq.offer(-h[1]); } else { // a end point, remove height pq.remove(h[1]); } int cur = pq.peek(); // current max height; // compare current max height with previous max height, update result and // previous max height if necessary if(prev != cur) { result.add(new int[]{h[0], cur}); prev = cur; } } return result; } /** * https://leetcode.com/problems/the-skyline-problem/discuss/61281/Java-divide-and-conquer-solution-beats-96 */ public List getSkyline3(int[][] buildings) { return merge(buildings, 0, buildings.length-1); } private LinkedList merge(int[][] buildings, int lo, int hi) { LinkedList res = new LinkedList<>(); if(lo > hi) { return res; } else if(lo == hi) { res.add(new int[]{buildings[lo][0], buildings[lo][2]}); res.add(new int[]{buildings[lo][1], 0}); return res; } int mid = lo+(hi-lo)/2; LinkedList left = merge(buildings, lo, mid); LinkedList right = merge(buildings, mid+1, hi); int leftH = 0, rightH = 0; while(!left.isEmpty() || !right.isEmpty()) { long x1 = left.isEmpty()? Long.MAX_VALUE: left.peekFirst()[0]; long x2 = right.isEmpty()? Long.MAX_VALUE: right.peekFirst()[0]; int x = 0; if(x1 < x2) { int[] temp = left.pollFirst(); x = temp[0]; leftH = temp[1]; } else if(x1 > x2) { int[] temp = right.pollFirst(); x = temp[0]; rightH = temp[1]; } else { x = left.peekFirst()[0]; leftH = left.pollFirst()[1]; rightH = right.pollFirst()[1]; } int h = Math.max(leftH, rightH); if(res.isEmpty() || h != res.peekLast()[1]) { res.add(new int[]{x, h}); } } return res; } } ================================================ FILE: src/ThirdMaximumNumber414.java ================================================ /** * Given a non-empty array of integers, return the third maximum number in this * array. If it does not exist, return the maximum number. * The time complexity must be in O(n). * * Example 1: * Input: [3, 2, 1] * Output: 1 * Explanation: The third maximum is 1. * * Example 2: * Input: [1, 2] * Output: 2 * Explanation: The third maximum does not exist, so the maximum (2) is * returned instead. * * Example 3: * Input: [2, 2, 3, 1] * Output: 1 * Explanation: Note that the third maximum here means the third maximum * distinct number. Both numbers with value 2 are both considered as * second maximum. * */ public class ThirdMaximumNumber414 { public static int thirdMax(int[] arr) { // non-empty array, no need for checking empty Stack st = new Stack<>(); for (int i: arr) { Stack temp = new Stack<>(); while (!st.empty() && st.peek() <= i) { temp.push(st.pop()); } st.push(i); while (!temp.empty() && st.size() < 3) { int t = temp.pop(); if (!st.empty() && st.peek() == t) continue; st.push(t); } while (st.size() > 3) { st.pop(); } } if (st.size() == 3) return st.peek(); while (st.size() > 1) { st.pop(); } return st.peek(); } public static int thirdMax2(int[] arr) { PriorityQueue q = new PriorityQueue(); // non empty array q.add(arr[0]); for (int i=1; i= 3 && q.peek() >= num) continue; if (q.contains(num)) continue; if (q.size() >= 3) q.poll(); q.add(num); } // exits if (q.size() == 3) return q.peek(); // not exits while (q.size() > 1) q.poll(); return q.peek(); } /** * https://leetcode.com/problems/third-maximum-number/discuss/90190/Java-PriorityQueue-O(n)-+-O(1) */ public int thirdMax3(int[] nums) { PriorityQueue pq = new PriorityQueue<>(); Set set = new HashSet<>(); for (int i : nums) { if (!set.contains(i)) { pq.offer(i); set.add(i); if (pq.size() > 3) { set.remove(pq.poll()); } } } if (pq.size() < 3) { while (pq.size() > 1) { pq.poll(); } } return pq.peek(); } /** * https://leetcode.com/problems/third-maximum-number/discuss/90202/Java-neat-and-easy-understand-solution-O(n)-time-O(1)-space */ public int thirdMax4(int[] nums) { Integer max1 = null; Integer max2 = null; Integer max3 = null; for (Integer n : nums) { if (n.equals(max1) || n.equals(max2) || n.equals(max3)) continue; if (max1 == null || n > max1) { max3 = max2; max2 = max1; max1 = n; } else if (max2 == null || n > max2) { max3 = max2; max2 = n; } else if (max3 == null || n > max3) { max3 = n; } } return max3 == null ? max1 : max3; } // public static int thirdMax4(int[] arr) { // int[] temp = new int[3]; // Arrays.fill(temp, Integer.MIN_VALUE); // int c = 0; // for (int i: arr) { // int minIdx = -1; // int min = Integer.MAX_VALUE; // boolean dup = false; // for (int k=0; k<3; k++) { // if (temp[k] == i) { // dup = true; // break; // } // if (min > i) { // min = i; // minIdx = k; // } // } // if (!dup && minIdx != -1) { // c++; // temp[minIdx] = i; // } // } // if (c >= 3) { // return Math.min(Math.min(temp[0], temp[1]), temp[2]); // } else { // return Math.max(Math.max(temp[0], temp[1]), temp[2]); // } // } } ================================================ FILE: src/ThreeSum15.java ================================================ /** * Given an array S of n integers, are there elements a, b, c in S such that * a + b + c = 0? Find all unique triplets in the array which gives the sum * of zero. * * Note: The solution set must not contain duplicate triplets. * * For example, given array S = [-1, 0, 1, 2, -1, -4], * * A solution set is: * [ * [-1, 0, 1], * [-1, -1, 2] * ] */ import java.util.Arrays; import java.util.List; import java.util.LinkedList; public class ThreeSum15 { /** * https://discuss.leetcode.com/topic/8125/concise-o-n-2-java-solution */ public List> threeSum(int[] nums) { List> res = new ArrayList<>(); if (nums == null || nums.length < 3) return res; Arrays.sort(nums); if (nums[0] > 0 || nums[nums.length-1] < 0) return res; for (int i=0; i 0 && nums[i] == nums[i-1]) continue; int l = i+1; int r = nums.length-1; int left = 0 - nums[i]; while (l < r) { if (nums[l] + nums[r] == left) { res.add(Arrays.asList(nums[i], nums[l], nums[r])); while (l < r && nums[l] == nums[l+1]) l++; while (l < r && nums[r] == nums[r-1]) r--; l++; r--; } else if (nums[l] + nums[r] > left) { r--; } else { l++; } } } return res; } public static void main(String[] args) { ThreeSum15 ts = new ThreeSum15(); System.out.println(ts.threeSum(new int[]{-1, 0, 1, 2, -1, -4})); System.out.println(ts.threeSum(new int[]{0, 0, 0})); System.out.println(ts.threeSum(new int[]{0, 0, 0, 0})); System.out.println(ts.threeSum(new int[]{-4, -2, -2, -2, 0, 1, 2, 2, 2, 3, 3, 4, 4, 6, 6})); System.out.println(ts.threeSum(new int[]{0, 0, 0, 1, 1})); System.out.println(ts.threeSum(new int[]{-1, -1, 0, 0, 0})); } } ================================================ FILE: src/ThreeSumClosest16.java ================================================ /** * Given an array S of n integers, find three integers in S such that the sum * is closest to a given number, target. Return the sum of the three integers. * You may assume that each input would have exactly one solution. * * For example, given array S = {-1 2 1 -4}, and target = 1. * * The sum that is closest to the target is 2. (-1 + 2 + 1 = 2). */ import java.util.Arrays; import java.util.ArrayList; import java.util.List; import java.util.HashSet; import java.util.Set; public class ThreeSumClosest16 { public int threeSumClosest(int[] nums, int target) { Arrays.sort(nums); Integer sumClosest = Integer.MAX_VALUE; Integer diffClosest = Integer.MAX_VALUE; for (int i = 0; i < nums.length - 2; i++) { if (i == 0 || (i > 0 && nums[i] != nums[i-1])) { int low = i + 1; int high = nums.length - 1; while (low < high) { int tempSum = nums[i] + nums[low] + nums[high]; if (tempSum == target) { return tempSum; } boolean update = diffClosest > Math.abs(tempSum - target); sumClosest = update ? tempSum : sumClosest; diffClosest = update ? Math.abs(tempSum - target) : diffClosest; if (tempSum < target) { low++; } else { high--; } } } } return sumClosest; } /** * https://discuss.leetcode.com/topic/5192/java-solution-with-o-n2-for-reference/19 */ public int threeSumClosest2(int[] num, int target) { int result = num[0] + num[1] + num[num.length - 1]; Arrays.sort(num); for (int i = 0; i < num.length - 2; i++) { if (i > 0 && num[i] == num[i-1]) continue; int start = i + 1, end = num.length - 1; while (start < end) { int sum = num[i] + num[start] + num[end]; if (sum > target) { end--; } else { start++; } if (Math.abs(sum - target) < Math.abs(result - target)) { result = sum; } } } return result; } public static void main(String[] args) { ThreeSumClosest16 tsc = new ThreeSumClosest16(); System.out.println(tsc.threeSumClosest(new int[]{-1, 2, 1, -4}, 1)); System.out.println(tsc.threeSumClosest(new int[]{-1, 0, 1, 1, 55}, 3)); } } ================================================ FILE: src/ThreeSumSmaller259.java ================================================ /** * Given an array of n integers nums and a target, find the number of index * triplets i, j, k with 0 <= i < j < k < n that satisfy the condition * nums[i] + nums[j] + nums[k] < target. * * For example, given nums = [-2, 0, 1, 3], and target = 2. * * Return 2. Because there are two triplets which sums are less than 2: * * [-2, 0, 1] * [-2, 0, 3] * * Follow up: * Could you solve it in O(n2) runtime? */ public class ThreeSumSmaller259 { public int threeSumSmaller(int[] nums, int target) { if (nums == null || nums.length < 3) return 0; int res = 0; Arrays.sort(nums); for (int i=0; i= target) break; res++; } } } return res; } /** * https://leetcode.com/problems/3sum-smaller/solution/ */ public int threeSumSmaller2(int[] nums, int target) { Arrays.sort(nums); int sum = 0; for (int i = 0; i < nums.length - 2; i++) { sum += twoSumSmaller(nums, i + 1, target - nums[i]); } return sum; } private int twoSumSmaller(int[] nums, int startIndex, int target) { int sum = 0; int left = startIndex; int right = nums.length - 1; while (left < right) { if (nums[left] + nums[right] < target) { sum += right - left; left++; } else { right--; } } return sum; } /** * https://leetcode.com/problems/3sum-smaller/solution/ */ public int threeSumSmaller3(int[] nums, int target) { Arrays.sort(nums); int sum = 0; for (int i = 0; i < nums.length - 2; i++) { sum += twoSumSmaller(nums, i + 1, target - nums[i]); } return sum; } private int twoSumSmaller(int[] nums, int startIndex, int target) { int sum = 0; for (int i = startIndex; i < nums.length - 1; i++) { int j = binarySearch(nums, i, target - nums[i]); sum += j - i; } return sum; } private int binarySearch(int[] nums, int startIndex, int target) { int left = startIndex; int right = nums.length - 1; while (left < right) { int mid = (left + right + 1) / 2; if (nums[mid] < target) { left = mid; } else { right = mid - 1; } } return left; } } ================================================ FILE: src/ToLowerCase709.java ================================================ /** * mplement function ToLowerCase() that has a string parameter str, and returns * the same string in lowercase. * * Example 1: * Input: "Hello" * Output: "hello" * * Example 2: * Input: "here" * Output: "here" * * Example 3: * Input: "LOVELY" * Output: "lovely" */ public class ToLowerCase709 { public String toLowerCase(String str) { return str.toLowerCase(); } /** * https://leetcode.com/problems/to-lower-case/discuss/148993/Java-no-library-methods */ public String toLowerCase2(String str) { char[] a = str.toCharArray(); for (int i = 0; i < a.length; i++) if ('A' <= a[i] && a[i] <= 'Z') a[i] = (char) (a[i] - 'A' + 'a'); return new String(a); } } ================================================ FILE: src/TopKFrequentElements347.java ================================================ /** * Given a non-empty array of integers, return the k most frequent elements. * * * For example, * Given [1,1,1,2,2,3] and k = 2, return [1,2]. * * Note: * You may assume k is always valid, 1 ? k ? number of unique elements. * Your algorithm's time complexity must be better than O(n log n), where * n is the array's size. */ public class TopKFrequentElements347 { public List topKFrequent(int[] nums, int k) { Map map = new HashMap<>(); for (int n : nums) { map.put(n, (map.getOrDefault(n, 0)) + 1); } Iterator> ite = sortByValue(map).entrySet().iterator(); List results = new ArrayList<>(); int i = 0; while(i me = (Map.Entry)ite.next(); results.add(me.getKey()); i++; } return results; } private Map sortByValue(Map unsortMap) { List> list = new LinkedList>(unsortMap.entrySet()); Collections.sort(list, new Comparator>() { public int compare(Map.Entry o1, Map.Entry o2) { return (o2.getValue()).compareTo(o1.getValue()); } }); Map sortedMap = new LinkedHashMap(); for (Map.Entry entry : list) { sortedMap.put(entry.getKey(), entry.getValue()); } return sortedMap; } /** * https://discuss.leetcode.com/topic/48158/3-java-solution-using-array-maxheap-treemap */ public List topKFrequent2(int[] nums, int k) { Map map = new HashMap<>(); for(int n: nums){ map.put(n, map.getOrDefault(n,0)+1); } // corner case: if there is only one number in nums, we need the bucket has index 1. List[] bucket = new List[nums.length+1]; for(int n:map.keySet()){ int freq = map.get(n); if(bucket[freq]==null) bucket[freq] = new LinkedList<>(); bucket[freq].add(n); } List res = new LinkedList<>(); for(int i=bucket.length-1; i>0 && k>0; --i){ if(bucket[i]!=null){ List list = bucket[i]; res.addAll(list); k-= list.size(); } } return res; } /** * https://discuss.leetcode.com/topic/48158/3-java-solution-using-array-maxheap-treemap */ public List topKFrequent3(int[] nums, int k) { Map map = new HashMap<>(); for(int n: nums){ map.put(n, map.getOrDefault(n,0)+1); } PriorityQueue> maxHeap = new PriorityQueue<>((a,b)->(b.getValue()-a.getValue())); for(Map.Entry entry: map.entrySet()){ maxHeap.add(entry); } List res = new ArrayList<>(); while(res.size() entry = maxHeap.poll(); res.add(entry.getKey()); } return res; } /** * https://discuss.leetcode.com/topic/48158/3-java-solution-using-array-maxheap-treemap */ public List topKFrequent4(int[] nums, int k) { Map map = new HashMap<>(); for(int n: nums){ map.put(n, map.getOrDefault(n,0)+1); } TreeMap> freqMap = new TreeMap<>(); for(int num : map.keySet()){ int freq = map.get(num); if(!freqMap.containsKey(freq)){ freqMap.put(freq, new LinkedList<>()); } freqMap.get(freq).add(num); } List res = new ArrayList<>(); while(res.size()> entry = freqMap.pollLastEntry(); res.addAll(entry.getValue()); } return res; } } ================================================ FILE: src/TopKFrequentWords692.java ================================================ /** * Given a non-empty list of words, return the k most frequent elements. * * Your answer should be sorted by frequency from highest to lowest. If two * words have the same frequency, then the word with the lower alphabetical * order comes first. * * Example 1: * Input: ["i", "love", "leetcode", "i", "love", "coding"], k = 2 * Output: ["i", "love"] * Explanation: "i" and "love" are the two most frequent words. * Note that "i" comes before "love" due to a lower alphabetical order. * * Example 2: * Input: ["the", "day", "is", "sunny", "the", "the", "the", "sunny", "is", "is"], k = 4 * Output: ["the", "is", "sunny", "day"] * Explanation: "the", "is", "sunny" and "day" are the four most frequent words, * with the number of occurrence being 4, 3, 2 and 1 respectively. * * Note: * You may assume k is always valid, 1 ≤ k ≤ number of unique elements. * Input words contain only lowercase letters. * * Follow up: * Try to solve it in O(n log k) time and O(n) extra space. * */ public class TopKFrequentWords692 { public List topKFrequent(String[] words, int k) { Map counts = new HashMap<>(); for (String w: words) { counts.put(w, counts.getOrDefault(w, 0) + 1); } return sortByValue(counts, k); } private List sortByValue(Map unsortMap, int k) { List> list = new LinkedList>(unsortMap.entrySet()); Collections.sort(list, new Comparator>() { public int compare(Map.Entry o1, Map.Entry o2) { if (o1.getValue().equals(o2.getValue())) { return o1.getKey().compareTo(o2.getKey()); } else { return o2.getValue().compareTo(o1.getValue()); } } }); List topK = new ArrayList<>(); int i = 0; while (i < k) { topK.add(list.get(i).getKey()); i++; } return topK; } public List topKFrequent2(String[] words, int k) { Map counts = new HashMap<>(); for (String w: words) { counts.put(w, counts.getOrDefault(w, 0) + 1); } Map> freqs = new HashMap<>(); for (Map.Entry c: counts.entrySet()) { List l = freqs.getOrDefault(c.getValue(), new ArrayList<>()); l.add(c.getKey()); freqs.put(c.getValue(), l); } List>> buckets = sortByKey(freqs); List topK = new ArrayList<>(); int i = 0; int j = 0; while (j < buckets.size() && i < k) { List curr = buckets.get(j).getValue(); Collections.sort(curr); int p = 0; while (p < curr.size() && i < k) { topK.add(curr.get(p)); p++; i++; } j++; } return topK; } private List>> sortByKey(Map> unsortMap) { List>> list = new LinkedList>>(unsortMap.entrySet()); Collections.sort(list, new Comparator>>() { public int compare(Map.Entry> o1, Map.Entry> o2) { return o2.getKey().compareTo(o1.getKey()); } }); return list; } /** * https://discuss.leetcode.com/topic/107751/my-simple-java-solution-using-hashmap-priorityqueue-o-nlogk-time-o-n-space */ public List topKFrequent3(String[] words, int k) { List result = new LinkedList<>(); Map map = new HashMap<>(); for(int i=0; i> pq = new PriorityQueue<>( (a,b) -> a.getValue()==b.getValue() ? b.getKey().compareTo(a.getKey()) : a.getValue()-b.getValue() ); for(Map.Entry entry: map.entrySet()) { pq.offer(entry); if(pq.size()>k) pq.poll(); } while(!pq.isEmpty()) result.add(0, pq.poll().getKey()); return result; } /** * https://discuss.leetcode.com/topic/108675/java-hashmap-maxheap-o-nlogn */ public List topKFrequent4(String[] words, int k) { HashMap map = new HashMap<>(); for (String s : words) map.put(s, map.getOrDefault(s,0) + 1); // Frequent hashmap PriorityQueue> maxHeap = new PriorityQueue<>(k, (a,b) -> a.getValue()==b.getValue() ? a.getKey().compareTo(b.getKey()) : b.getValue()-a.getValue()); // if same frequency, then sort alphabetical . for (Map.Entry entry : map.entrySet() ) maxHeap.add(entry); List res = new ArrayList<>(); while (res.size() < k) res.add(maxHeap.poll().getKey()); //add top k return res; } /** * https://discuss.leetcode.com/topic/107069/java-o-n-solution-using-hashmap-bucketsort-and-trie-22ms-beat-81 */ public List topKFrequent5(String[] words, int k) { // calculate frequency of each word Map freqMap = new HashMap<>(); for(String word : words) { freqMap.put(word, freqMap.getOrDefault(word, 0) + 1); } // build the buckets TrieNode[] count = new TrieNode[words.length + 1]; for(String word : freqMap.keySet()) { int freq = freqMap.get(word); if(count[freq] == null) { count[freq] = new TrieNode(); } addWord(count[freq], word); } // get k frequent words List list = new LinkedList<>(); for(int f = count.length - 1; f >= 1 && list.size() < k; f--) { if(count[f] == null) continue; getWords(count[f], list, k); } return list; } private void getWords(TrieNode node, List list, int k) { if(node == null) return; if(node.word != null) { list.add(node.word); } if(list.size() == k) return; for(int i = 0; i < 26; i++) { if(node.next[i] != null) { getWords(node.next[i], list, k); } } } private boolean addWord(TrieNode root, String word) { TrieNode curr = root; for(char c : word.toCharArray()) { if(curr.next[c - 'a'] == null) { curr.next[c - 'a'] = new TrieNode(); } curr = curr.next[c - 'a']; } curr.word = word; return true; } class TrieNode { TrieNode[] next; String word; TrieNode() { this.next = new TrieNode[26]; this.word = null; } } } ================================================ FILE: src/TotalHammingDistance477.java ================================================ /** * The Hamming distance (https://en.wikipedia.org/wiki/Hamming_distance) between * two integers is the number of positions at which the corresponding bits are different. * * Now your job is to find the total Hamming distance between all pairs of the given numbers. * * Example: * Input: 4, 14, 2 * * Output: 6 * * Explanation: In binary representation, the 4 is 0100, 14 is 1110, and 2 is * 0010 (just showing the four bits relevant in this case). So the answer will * be: HammingDistance(4, 14) + HammingDistance(4, 2) + HammingDistance(14, 2) * = 2 + 2 + 2 = 6. * * Note: * Elements of the given array are in the range of 0 to 10^9 * Length of the array will not exceed 10^4. */ public class TotalHammingDistance477 { /** * https://discuss.leetcode.com/topic/72092/java-o-n-time-o-1-space */ public int totalHammingDistance2(int[] nums) { int total = 0, n = nums.length; for (int j=0;j<32;j++) { int bitCount = 0; for (int i=0;i> j) & 1; total += bitCount*(n - bitCount); } return total; } /** * https://discuss.leetcode.com/topic/72104/java-solution-with-explanation */ public int totalHammingDistance2(int[] nums) { int n = 31; int len = nums.length; int[] countOfOnes = new int[n]; for (int i = 0; i < len; i++) { for (int j = 0; j < n; j++) { countOfOnes[j] += (nums[i] >> j) & 1; } } int sum = 0; for (int count: countOfOnes) { sum += count * (len - count); } return sum; } } ================================================ FILE: src/TrappingRainWater42.java ================================================ /** * Given n non-negative integers representing an elevation map where the width * of each bar is 1, compute how much water it is able to trap after raining. * * For example, * Given [0,1,0,2,1,0,1,3,2,1,2,1], return 6. * * http://www.leetcode.com/static/images/problemset/rainwatertrap.png * * The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. * In this case, 6 units of rain water (blue section) are being trapped. */ public class TrappingRainWater42 { /** * https://leetcode.com/problems/trapping-rain-water/solution/ */ // brute force public int trap(int[] height) { int res = 0; for (int i=1; i= 0; j--) l = Math.max(l, height[j]); for (int j = i; j < height.length; j++) r = Math.max(r, height[j]); res += Math.min(l, r) - height[i]; } return res; } public int trap2(int[] height) { if (height.length <= 2) { return 0; } Stack st = new Stack<>(); st.push(0); int p = 1; int sum = 0; while(p < height.length) { while(!st.empty() && height[p] > height[st.peek()]) { Integer now = st.pop(); if (st.empty()) { break; } sum += (Math.min(height[p], height[st.peek()]) - height[now]) * (p-st.peek()-1); } st.push(p++); } return sum; } /** * https://discuss.leetcode.com/topic/3016/share-my-short-solution */ public int trap3(int[] A){ int a=0; int b=A.length-1; int max=0; int leftmax=0; int rightmax=0; while(a<=b){ leftmax=Math.max(leftmax,A[a]); rightmax=Math.max(rightmax,A[b]); if(leftmax=0; i--) r[i] = Math.max(r[i+1], height[i]); for (int i=1; i st = new Stack<>(); while (l < height.length) { if (height[l] > height[l-1] && !st.isEmpty()) { int top = st.pop(); res += (l-top-1) * (Math.min(height[l], height[top]) - height[l-1]); } if (l <= height.length-3 && height[l] > height[l+1]) { st.add(l); } l++; } return res; } } ================================================ FILE: src/TrappingRainWaterII407.java ================================================ /** * Given an m x n matrix of positive integers representing the height of each * unit cell in a 2D elevation map, compute the volume of water it is able to * trap after raining. * * Note: * Both m and n are less than 110. The height of each unit cell is greater than * 0 and is less than 20,000. * * Example: * * Given the following 3x6 height map: * [ * [1,4,3,1,3,2], * [3,2,1,3,2,4], * [2,3,3,2,3,1] * ] * * Return 4. * * https://leetcode.com/static/images/problemset/rainwater_empty.png * * The above image represents the elevation map * [[1,4,3,1,3,2],[3,2,1,3,2,4],[2,3,3,2,3,1]] before the rain. * * https://leetcode.com/static/images/problemset/rainwater_fill.png * * After the rain, water is trapped between the blocks. The total volume of * water trapped is 4. */ public class TrappingRainWaterII407 { public int trapRainWater(int[][] heightMap) { if (heightMap == null || heightMap.length < 3 || heightMap[0].length < 3) return 0; int M = heightMap.length; int N = heightMap[0].length; boolean[][] visited = new boolean[M][N]; // lambda function is much slower than anonymous Comparator class, // due to first-time initialization overhead of lambda expressions PriorityQueue pq = new PriorityQueue<>(1, new Comparator(){ public int compare(Pair a, Pair b) { return a.value - b.value; } }); for (int j=0; j= M || y >= N || visited[x][y]) continue; if (max > heightMap[x][y]) res += max - heightMap[x][y]; pq.offer(new Pair(x, y, heightMap[x][y])); visited[x][y] = true; } } return res; } class Pair { int x; int y; int value; Pair(int i, int j, int v) { x = i; y = j; value = v; } } /** * https://leetcode.com/problems/trapping-rain-water-ii/discuss/89477/Java-solution-beating-100 */ private static class Cell implements Comparable { private int row; private int col; private int value; public Cell(int r, int c, int v) { this.row = r; this.col = c; this.value = v; } @Override public int compareTo(Cell other) { return value - other.value; } } private int water; private boolean[][] visited1; public int trapRainWater2(int[][] heightMap) { if (heightMap.length == 0) return 0; PriorityQueue walls = new PriorityQueue(); water = 0; visited1 = new boolean[heightMap.length][heightMap[0].length]; int rows = heightMap.length, cols = heightMap[0].length; //build wall; for (int c = 0; c < cols; c++) { walls.add(new Cell(0, c, heightMap[0][c])); walls.add(new Cell(rows - 1, c, heightMap[rows - 1][c])); visited1[0][c] = true; visited1[rows - 1][c] = true; } for (int r = 1; r < rows - 1; r++) { walls.add(new Cell(r, 0, heightMap[r][0])); walls.add(new Cell(r, cols - 1, heightMap[r][cols - 1])); visited1[r][0] = true; visited1[r][cols - 1] = true; } //end build wall; while(walls.size() > 0) { Cell min = walls.poll(); visit(heightMap, min, walls); } return water; } private void visit(int[][] height, Cell start, PriorityQueue walls) { fill(height, start.row + 1, start.col, walls, start.value); fill(height, start.row - 1, start.col, walls, start.value); fill(height, start.row, start.col + 1, walls, start.value); fill(height, start.row, start.col - 1, walls, start.value); } private void fill(int[][] height, int row, int col, PriorityQueue walls, int min) { if (row < 0 || col < 0) return; else if (row >= height.length || col >= height[0].length) return; else if (visited1[row][col]) return; else if (height[row][col] >= min) { walls.add(new Cell(row, col, height[row][col])); visited1[row][col] = true; return; } else { water += min - height[row][col]; visited1[row][col] = true; fill(height, row + 1, col, walls, min); fill(height, row - 1, col, walls, min); fill(height, row, col + 1, walls, min); fill(height, row, col - 1, walls, min); } } } ================================================ FILE: src/TreeLinkNode.java ================================================ /** * Definition for binary tree with next pointer. */ public class TreeLinkNode { int val; TreeLinkNode left, right, next; TreeLinkNode(int x) { val = x; } } ================================================ FILE: src/TreeNode.java ================================================ /** * Definition for a binary tree node. */ public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int x) { val = x; } } ================================================ FILE: src/TreeToForestByErasingNodes.java ================================================ /** * */ public class TreeToForestByErasingNodes { // shouldBeErased is predefined public List treeToForest(Node root) { List res = new ArrayList<>(); dfs(root, true, res); return res; } private Node dfs(Node curr, boolean parentIsErasable, List res) { if (curr == null) return null; boolean currIsErasable = shouldBeErased(curr); if (parentIsErasable && !currIsErasable) res.add(curr); curr.left = dfs(curr.left, currIsErasable, res); curr.right = dfs(curr.right, currIsErasable, res); return currIsErasable ? null : curr; } class Node { Node left; Node right; } } ================================================ FILE: src/Triangle120.java ================================================ /** * Given a triangle, find the minimum path sum from top to bottom. Each step * you may move to adjacent numbers on the row below. * * For example, given the following triangle * * [ * [2], * [3,4], * [6,5,7], * [4,1,8,3] * ] * The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11). * * Note: * Bonus point if you are able to do this using only O(n) extra space, where * n is the total number of rows in the triangle. */ public class Triangle120 { public int minimumTotal(List> triangle) { if (triangle == null || triangle.size() == 0) return 0; int size = triangle.size(); List sums = triangle.get(size - 1); int i = size - 2; while (i >= 0) { List curr = triangle.get(i); int level = curr.size(); for (int j=0; j> triangle) { int[] A = new int[triangle.size()+1]; for(int i=triangle.size()-1;i>=0;i--){ for(int j=0;j= L). You might * need to change the root of the tree, so the result should return the new * root of the trimmed binary search tree. * * Example 1: * Input: * 1 * / \ * 0 2 * * L = 1 * R = 2 * * Output: * 1 * \ * 2 * * Example 2: * Input: * 3 * / \ * 0 4 * \ * 2 * / * 1 * * L = 1 * R = 3 * * Output: * 3 * / * 2 * / * 1 */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class TrimABinarySearchTree669 { public TreeNode trimBST(TreeNode root, int L, int R) { if (root == null) return null; if (root.val < L) return trimBST(root.right, L, R); if (root.val > R) return trimBST(root.left, L, R); root.left = trimBST(root.left, L, R); root.right = trimBST(root.right, L, R); return root; } } ================================================ FILE: src/TwoSum1.java ================================================ /** * Given an array of integers, return indices of the two numbers such that * they add up to a specific target. * * You may assume that each input would have exactly one solution, and * you may not use the same element twice. * * Example: * Given nums = [2, 7, 11, 15], target = 9, * * Because nums[0] + nums[1] = 2 + 7 = 9, * return [0, 1]. */ import java.util.HashMap; import java.util.Map; public class TwoSum1 { public int[] twoSum(int[] nums, int target) { Map foundSet = new HashMap<>(); int[] returns = new int[2]; for (int i = 0; i < nums.length; i++) { Integer now = nums[i]; Integer lookingfor = target - now; if (foundSet.containsKey(lookingfor)) { returns[0] = foundSet.get(lookingfor); returns[1] = i; return returns; } else { foundSet.put(now, i); } } return returns; } public static void main(String[] args) { TwoSum1 ts = new TwoSum1(); System.out.println(ts.twoSum(new int[]{2, 7, 11, 15}, 9)); System.out.println(ts.twoSum(new int[]{1, 2, 3}, 5)); } } ================================================ FILE: src/TwoSumIIInputArrayIsSorted167.java ================================================ /** * Given an array of integers that is already sorted in ascending order, find * two numbers such that they add up to a specific target number. * * The function twoSum should return indices of the two numbers such that they * add up to the target, where index1 must be less than index2. * * Note: * Your returned answers (both index1 and index2) are not zero-based. * You may assume that each input would have exactly one solution and you may * not use the same element twice. * * Example: * Input: numbers = [2,7,11,15], target = 9 * Output: [1,2] * Explanation: The sum of 2 and 7 is 9. Therefore index1 = 1, index2 = 2. */ public class TwoSumIIInputArrayIsSorted167 { public int[] twoSum(int[] numbers, int target) { if (numbers == null || numbers.length < 2) return new int[2]; int len = numbers.length; for (int i=0; i<=len-2; i++) { int idx = binarySearch(numbers, target-numbers[i], i+1, len-1); if (idx != -1) { return new int[]{i+1, idx+1}; } } return new int[2]; } private int binarySearch(int[] numbers, int target, int l, int r) { if (l > r) return -1; if (l == r) return numbers[l] == target ? l : -1; int mid = (l + r) / 2; if (numbers[mid] == target) return mid; if (numbers[mid] > target) { return binarySearch(numbers, target, l, mid-1); } else { return binarySearch(numbers, target, mid+1, r); } } // using Arrays.binarySearch public int[] twoSum2(int[] numbers, int target) { if (numbers == null || numbers.length < 2) return new int[2]; int len = numbers.length; for (int i=0; i<=len-2; i++) { int idx = Arrays.binarySearch(numbers, i+1, len, target - numbers[i]); if (idx >= 0) { return new int[]{i+1, idx+1}; } } return new int[2]; } } ================================================ FILE: src/TwoSumIVInputIsABST653.java ================================================ /** * Given a Binary Search Tree and a target number, return true if there exist * two elements in the BST such that their sum is equal to the given target. * * Example 1: * Input: * 5 * / \ * 3 6 * / \ \ * 2 4 7 * * Target = 9 * Output: True * * Example 2: * Input: * 5 * / \ * 3 6 * / \ \ * 2 4 7 * * Target = 28 * Output: False */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class TwoSumIVInputIsABST653 { public boolean findTarget(TreeNode root, int k) { List list = treeToList(root); for (int i=0; i remain) break; } } return false; } public boolean findTarget2(TreeNode root, int k) { List list = treeToList(root); if (list.size() <= 1) return false; int l = 0; int r = list.size() - 1; while (l < r) { int sum = list.get(l) + list.get(r); if (sum == k) return true; if (sum < k) { l++; } else { r--; } } return false; } private List treeToList(TreeNode root) { List res = new ArrayList<>(); dfs(root, res); return res; } private void dfs(TreeNode root, List res) { if (root == null) return; dfs(root.left, res); res.add(root.val); dfs(root.right, res); } public boolean findTarget3(TreeNode root, int k) { return dfs(root, new HashSet(), k); } private boolean dfs(TreeNode root, Set set, int k) { if (root == null) return false; if (set.contains(k - root.val)) return true; set.add(root.val); return dfs(root.left, set, k) || dfs(root.right, set, k); } /** * https://leetcode.com/problems/two-sum-iv-input-is-a-bst/solution/ */ public boolean findTarget4(TreeNode root, int k) { Set < Integer > set = new HashSet(); Queue < TreeNode > queue = new LinkedList(); queue.add(root); while (!queue.isEmpty()) { if (queue.peek() != null) { TreeNode node = queue.remove(); if (set.contains(k - node.val)) return true; set.add(node.val); queue.add(node.right); queue.add(node.left); } else queue.remove(); } return false; } } ================================================ FILE: src/UTF8Validation393.java ================================================ /** * A character in UTF8 can be from 1 to 4 bytes long, subjected to the following rules: * * For 1-byte character, the first bit is a 0, followed by its unicode code. * For n-bytes character, the first n-bits are all one's, the n+1 bit is 0, * followed by n-1 bytes with most significant 2 bits being 10. * This is how the UTF-8 encoding would work: * * Char. number range | UTF-8 octet sequence * (hexadecimal) | (binary) * --------------------+--------------------------------------------- * 0000 0000-0000 007F | 0xxxxxxx * 0000 0080-0000 07FF | 110xxxxx 10xxxxxx * 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx * 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx * Given an array of integers representing the data, return whether it is a valid utf-8 encoding. * * Note: * The input is an array of integers. Only the least significant 8 bits of each * integer is used to store the data. This means each integer represents only 1 byte of data. * * Example 1: * data = [197, 130, 1], which represents the octet sequence: 11000101 10000010 00000001. * * Return true. * It is a valid utf-8 encoding for a 2-bytes character followed by a 1-byte character. * * Example 2: * data = [235, 140, 4], which represented the octet sequence: 11101011 10001100 00000100. * * Return false. * * The first 3 bits are all one's and the 4th bit is 0 means it is a 3-bytes character. * The next byte is a continuation byte which starts with 10 and that's correct. * But the second continuation byte does not start with 10, so it is invalid. */ public class UTF8Validation393 { public boolean validUtf8(int[] data) { int L = data.length; if (L == 0) return false; for (int k = 0; k 4 || k+n > L) return false; for (int i = 1; i> pos) & 1; } /** * https://discuss.leetcode.com/topic/58338/bit-manipulation-java-6ms */ public boolean validUtf82(int[] data) { if(data==null || data.length==0) return false; boolean isValid = true; for(int i=0;i255) return false; // 1 after 8th digit, 100000000 int numberOfBytes = 0; if((data[i] & 128) == 0) { // 0xxxxxxx, 1 byte, 128(10000000) numberOfBytes = 1; } else if((data[i] & 224) == 192) { // 110xxxxx, 2 bytes, 224(11100000), 192(11000000) numberOfBytes = 2; } else if((data[i] & 240) == 224) { // 1110xxxx, 3 bytes, 240(11110000), 224(11100000) numberOfBytes = 3; } else if((data[i] & 248) == 240) { // 11110xxx, 4 bytes, 248(11111000), 240(11110000) numberOfBytes = 4; } else { return false; } for(int j=1;j=data.length) return false; if((data[i+j] & 192) != 128) return false; // 192(11000000), 128(10000000) } i=i+numberOfBytes-1; } return isValid; } } ================================================ FILE: src/UglyNumber263.java ================================================ /** * Write a program to check whether a given number is an ugly number. * * Ugly numbers are positive numbers whose prime factors only include 2, 3, 5. * * Example 1: * Input: 6 * Output: true * Explanation: 6 = 2 × 3 * * Example 2: * Input: 8 * Output: true * Explanation: 8 = 2 × 2 × 2 * * Example 3: * Input: 14 * Output: false * Explanation: 14 is not ugly since it includes another prime factor 7. * * Note: * 1 is typically treated as an ugly number. * Input is within the 32-bit signed integer range: [−231, 231 − 1]. */ public class UglyNumber263 { public boolean isUgly(int num) { if (num == 1) return true; if (num <= 0) return false; int n = num; if (num % 2 == 0) num /= 2; if (num % 3 == 0) num /= 3; if (num % 5 == 0) num /= 5; if (num == n) return false; return isUgly(num); } public boolean isUgly2(int num) { if (num <= 0) return false; while (num % 2 == 0) num /= 2; while (num % 3 == 0) num /= 3; while (num % 5 == 0) num /= 5; return num == 1; } } ================================================ FILE: src/UglyNumberII264.java ================================================ /** * Write a program to find the n-th ugly number. * * Ugly numbers are positive numbers whose prime factors only include 2, 3, 5. * * Example: * Input: n = 10 * Output: 12 * Explanation: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 is the sequence of the first 10 ugly numbers. * * Note: * 1 is typically treated as an ugly number. * n does not exceed 1690. */ /** * https://www.geeksforgeeks.org/ugly-numbers/ */ public class UglyNumberII264 { public int nthUglyNumber(int n) { if (n < 1) return 0; if (n == 1) return 1; Set set = new HashSet<>(); Comparator comp = (a1, a2) -> Long.compare(a1[0] * a1[1], a2[0] * a2[1]); PriorityQueue pq = new PriorityQueue<>(1, comp); set.add(1L); pq.add(new long[]{(long)1, (long)2}); while (true) { long[] curr = pq.poll(); long newAdd = curr[0] * curr[1]; if (move(curr)) { pq.add(curr); } if (!set.contains(newAdd)) { pq.add(new long[]{newAdd, 2L}); set.add(newAdd); } if (set.size() == n) { return (int) newAdd; } } } private boolean move(long[] p) { if (p[1] == 5) return false; if (p[1] == 2) { p[1] = 3L; } else { p[1] = 5L; } return true; } /** * https://leetcode.com/problems/ugly-number-ii/discuss/69362/O(n)-Java-solution */ public int nthUglyNumber2(int n) { int[] ugly = new int[n]; ugly[0] = 1; int index2 = 0, index3 = 0, index5 = 0; int factor2 = 2, factor3 = 3, factor5 = 5; for(int i=1;i q = new PriorityQueue(); q.add(1l); for(long i=1; i once = new HashSet<>(); Set mult = new HashSet<>(); String[] as = A.split(" "); for (String s: as) { if (once.contains(s)) { once.remove(s); mult.add(s); } else if (!mult.contains(s)) { once.add(s); } } String[] bs = B.split(" "); Set resCand = new HashSet<>(); Set resMult = new HashSet<>(); for (String s: bs) { if (!once.contains(s) && !mult.contains(s)) { if (resCand.contains(s)) { resCand.remove(s); resMult.add(s); } else if (!resMult.contains(s)) { resCand.add(s); } } else if (once.contains(s)) { once.remove(s); mult.add(s); } } String[] res = new String[resCand.size() + once.size()]; int i = 0; for (String c: resCand) { res[i++] = c; } for (String c: once) { res[i++] = c; } return res; } /** * https://leetcode.com/problems/uncommon-words-from-two-sentences/solution/ */ public String[] uncommonFromSentences2(String A, String B) { Map count = new HashMap(); for (String word: A.split(" ")) count.put(word, count.getOrDefault(word, 0) + 1); for (String word: B.split(" ")) count.put(word, count.getOrDefault(word, 0) + 1); List ans = new LinkedList(); for (String word: count.keySet()) if (count.get(word) == 1) ans.add(word); return ans.toArray(new String[ans.size()]); } } ================================================ FILE: src/UndirectedGraphNode.java ================================================ /** * Definition for undirected graph. */ public class UndirectedGraphNode { int label; List neighbors; UndirectedGraphNode(int x) { label = x; neighbors = new ArrayList(); } }; ================================================ FILE: src/UniqueBinarySearchTrees96.java ================================================ /** * Given n, how many structurally unique BST's (binary search trees) that store values 1...n? * * For example, * Given n = 3, there are a total of 5 unique BST's. * * 1 3 3 2 1 * \ / / / \ \ * 3 2 1 1 3 2 * / / \ \ * 2 1 2 3 * */ public class UniqueBinarySearchTrees96 { public int numTrees(int n) { int[][] dp = new int[n][n]; for (int s=0; s j) return 1; if (dp[i][j] != 0) return dp[i][j]; int u = 0; for (int r=i; r<=j; r++) { int left = helper(i, r-1, dp); int right = helper(r+1, j, dp); u += left * right; } dp[i][j] = u; return u; } public int numTrees2(int n) { int[] dp = new int[n]; return helper2(n-1, dp); } private int helper2(int i, int[] dp) { if (i <= 0) return 1; if (dp[i] != 0) return dp[i]; int u = 0; for (int j=0; j<=i; j++) { int left = helper2(j-1, dp); int right = helper2(i-j-1, dp); u += left * right; } dp[i] = u; return u; } /** * https://discuss.leetcode.com/topic/37310/fantastic-clean-java-dp-solution-with-detail-explaination */ public int numTrees3(int n) { int [] dp = new int[n+1]; dp[0]= 1; dp[1] = 1; for(int level = 2; level <=n; level++) for(int root = 1; root<=level; root++) dp[level] += dp[level-root]*dp[root-1]; return dp[n]; } } ================================================ FILE: src/UniqueBinarySearchTreesII95.java ================================================ /** * Given an integer n, generate all structurally unique BST's (binary search * trees) that store values 1...n. * * For example, * Given n = 3, your program should return all 5 unique BST's shown below. * * 1 3 3 2 1 * \ / / / \ \ * 3 2 1 1 3 2 * / / \ \ * 2 1 2 3 * */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class UniqueBinarySearchTreesII95 { public List generateTrees(int n) { return generateTrees(n, 1, n); } public List generateTrees(int n, int l, int r) { List res = new ArrayList<>(); if (l > r) return res; for (int i=l; i<=r; i++) { List lefts = generateTrees(n, l, i-1); if (lefts.isEmpty()) lefts.add(null); List rights = generateTrees(n, i+1, r); if (rights.isEmpty()) rights.add(null); for (TreeNode ll: lefts) { for (TreeNode rr: rights) { TreeNode t = new TreeNode(i); t.left = ll; t.right = rr; res.add(t); } } } return res; } // DP public List generateTrees2(int n) { return generateTrees(n, 1, n, new List[n][n]); } public List generateTrees(int n, int l, int r, List[][] dp) { List res = new ArrayList<>(); if (l > r) return res; if (dp[l-1][r-1] != null) return dp[l-1][r-1]; for (int i=l; i<=r; i++) { List lefts = generateTrees(n, l, i-1, dp); if (lefts.isEmpty()) lefts.add(null); List rights = generateTrees(n, i+1, r, dp); if (rights.isEmpty()) rights.add(null); for (TreeNode ll: lefts) { for (TreeNode rr: rights) { TreeNode t = new TreeNode(i); t.left = ll; t.right = rr; res.add(t); } } } dp[l-1][r-1] = res; return res; } public List generateTrees3(int n) { if (n == 0) return new ArrayList(); List[][] dp = new List[n][n]; List lefts; List rights; for (int len=1; len<=n; len++) { for (int start=1; start<=n+1-len; start++) { int end = start + len - 1; List list = new ArrayList<>(); for (int k=start; k<=end; k++) { if (start > k-1) { lefts = new ArrayList(); lefts.add(null); } else { lefts = dp[start-1][k-2]; } if (k+1 > end) { rights = new ArrayList(); rights.add(null); } else { rights = dp[k][end-1]; } for (TreeNode left: lefts) { for (TreeNode right: rights) { TreeNode curr = new TreeNode(k); curr.left = left; curr.right = right; list.add(curr); } } } dp[start-1][end-1] = list; } } return dp[0][n-1]; } public List generateTrees4(int n) { if (n == 0) return new ArrayList(); List[][] dp = new List[n][n]; for (int i=0; i l = new ArrayList<>(); l.add(new TreeNode(i+1)); dp[i][i] = l; } for (int len=1; len l = new ArrayList<>(); for (int j=i; j<=i+len; j++) { add(dp, i, j, i+len, l); } dp[i][i+len] = l; } } return dp[0][n-1]; } private void add(List[][] dp, int i, int j, int k, List l) { List lefts = get(dp, i, j-1); List rights = get(dp, j+1, k); for (TreeNode lf: lefts) { for (TreeNode rt: rights) { TreeNode n = new TreeNode(j+1); n.left = lf; n.right = rt; l.add(n); } } } private List get(List[][] dp, int i, int j) { if (i > j) { List l = new ArrayList<>(); l.add(null); return l; } return dp[i][j]; } } ================================================ FILE: src/UniqueMorseCodeWords804.java ================================================ /** * International Morse Code defines a standard encoding where each letter is * mapped to a series of dots and dashes, as follows: "a" maps to ".-", "b" * maps to "-...", "c" maps to "-.-.", and so on. * * For convenience, the full table for the 26 letters of the English alphabet * is given below: * [".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..", * "--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-", * "-.--","--.."] * * Now, given a list of words, each word can be written as a concatenation of * the Morse code of each letter. For example, "cab" can be written as * "-.-.-....-", (which is the concatenation "-.-." + "-..." + ".-"). We'll * call such a concatenation, the transformation of a word. * * Return the number of different transformations among all words we have. * * Example: * Input: words = ["gin", "zen", "gig", "msg"] * Output: 2 * Explanation: * The transformation of each word is: * "gin" -> "--...-." * "zen" -> "--...-." * "gig" -> "--...--." * "msg" -> "--...--." * * There are 2 different transformations, "--...-." and "--...--.". * * Note: * The length of words will be at most 100. * Each words[i] will have length in range [1, 12]. * words[i] will only consist of lowercase letters. */ public class UniqueMorseCodeWords804 { private String[] MOSRE_TABLE = new String[]{".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."}; public int uniqueMorseRepresentations(String[] words) { Set set = new HashSet<>(); for (String word: words) { set.add(getMorseCode(word)); } return set.size(); } private String getMorseCode(String word) { StringBuilder sb = new StringBuilder(); for (char ch: word.toCharArray()) { sb.append(MOSRE_TABLE[ch-'a']); } return sb.toString(); } } ================================================ FILE: src/UniquePaths62.java ================================================ /** * A robot is located at the top-left corner of a m x n grid (marked 'Start' * in the diagram below). * * The robot can only move either down or right at any point in time. The robot * is trying to reach the bottom-right corner of the grid (marked 'Finish' in * the diagram below). * * How many possible unique paths are there? * * https://leetcode.com/static/images/problemset/robot_maze.png * * Above is a 3 x 7 grid. How many possible unique paths are there? * * Note: m and n will be at most 100. * */ public class UniquePaths62 { public int uniquePaths(int m, int n) { if (m == 1 || n == 1) return 1; int s = Math.min(m, n); int l = Math.max(m, n); int[][] dp = new int[s][l]; return uniquePaths(m, n, dp); } private int uniquePaths(int m, int n, int[][] dp) { if (m == 1 || n == 1) return 1; int s = Math.min(m, n); int l = Math.max(m, n); if (dp[s-1][l-1] != 0) return dp[s-1][l-1]; int a = uniquePaths(s-1, l, dp); int b = uniquePaths(s, l-1, dp); dp[s-1][l-1] = a + b; return a + b; } public int uniquePaths2(int m, int n) { int[] row = new int[n]; Arrays.fill(row,1); for ( int i = 1; i < m; i++){ for ( int j = 1; j < n; j++){ row[j]+=row[j-1]; } } return row[n-1]; } /** * https://discuss.leetcode.com/topic/31724/java-solution-0ms-4lines */ public int uniquePaths3(int m, int n) { long result = 1; for(int i=0;i. Below are some examples of word * abbreviations: * * a) it --> it (no abbreviation) * * 1 * ↓ * b) d|o|g --> d1g * * 1 1 1 * 1---5----0----5--8 * ↓ ↓ ↓ ↓ ↓ * c) i|nternationalizatio|n --> i18n * * 1 * 1---5----0 * ↓ ↓ ↓ * d) l|ocalizatio|n --> l10n * Assume you have a dictionary and given a word, find whether its abbreviation * is unique in the dictionary. A word's abbreviation is unique if no other * word from the dictionary has the same abbreviation. * * Example: * Given dictionary = [ "deer", "door", "cake", "card" ] * isUnique("dear") -> false * isUnique("cart") -> true * isUnique("cane") -> false * isUnique("make") -> true */ public class UniqueWordAbbreviation288 { class ValidWordAbbr { Map> map = new HashMap<>(); public ValidWordAbbr(String[] dictionary) { for (String word: dictionary) { String encoded = encode(word); if (!map.containsKey(encoded)) { map.put(encoded, new HashSet<>()); } map.get(encoded).add(word); } } public boolean isUnique(String word) { String encoded = encode(word); return !map.containsKey(encoded) || (map.get(encoded).size() == 1 && map.get(encoded).contains(word)); } private String encode(String word) { if (word.length() <= 2) return word; return word.charAt(0) + Integer.toString(word.length()-2) + word.charAt(word.length()-1); } } /** * https://leetcode.com/problems/unique-word-abbreviation/solution/ */ public class ValidWordAbbr2 { private final Map abbrDict = new HashMap<>(); private final Set dict; public ValidWordAbbr2(String[] dictionary) { dict = new HashSet<>(Arrays.asList(dictionary)); for (String s : dict) { String abbr = toAbbr(s); abbrDict.put(abbr, !abbrDict.containsKey(abbr)); } } public boolean isUnique(String word) { String abbr = toAbbr(word); Boolean hasAbbr = abbrDict.get(abbr); return hasAbbr == null || (hasAbbr && dict.contains(word)); } private String toAbbr(String s) { int n = s.length(); if (n <= 2) { return s; } return s.charAt(0) + Integer.toString(n - 2) + s.charAt(n - 1); } } /** * Your ValidWordAbbr object will be instantiated and called as such: * ValidWordAbbr obj = new ValidWordAbbr(dictionary); * boolean param_1 = obj.isUnique(word); */ } ================================================ FILE: src/ValidAnagram242.java ================================================ /** * Given two strings s and t, write a function to determine if t is an * anagram of s. * * For example, * s = "anagram", t = "nagaram", return true. * s = "rat", t = "car", return false. * * Note: * You may assume the string contains only lowercase alphabets. * * Follow up: * What if the inputs contain unicode characters? How would you adapt your * solution to such case? */ public class ValidAnagram242 { public boolean isAnagram(String s, String t) { int[] cs = new int[26]; for (int i=0; i true * " 0.1 " => true * "abc" => false * "1 a" => false * "2e10" => true * * Note: It is intended for the problem statement to be ambiguous. You should * gather all requirements up front before implementing one. */ public class ValidNumber65 { public boolean isNumber(String s) { try { Double.valueOf(s); } catch (Exception e1) { return false; } char last = s.charAt(s.length()-1); if(last == 'D' || last == 'd' || last == 'f' || last == 'F') return false; return true; } } ================================================ FILE: src/ValidPalindrome125.java ================================================ /** * Given a string, determine if it is a palindrome, considering only alphanumeric * characters and ignoring cases. * * For example, * "A man, a plan, a canal: Panama" is a palindrome. * "race a car" is not a palindrome. * * Note: * Have you consider that the string might be empty? This is a good question to * ask during an interview. * * For the purpose of this problem, we define empty string as valid palindrome. * */ public class ValidPalindrome125 { public boolean isPalindrome(String s) { int l = 0; int r = s.length()-1; s = s.toLowerCase(); while (l < r) { while (!isLowerAlphanumeric(s.charAt(l)) && l < r) { l++; } while (!isLowerAlphanumeric(s.charAt(r)) && l < r) { r--; } if (s.charAt(l) != s.charAt(r)) return false; l++; r--; } return true; } private boolean isLowerAlphanumeric(char c) { return (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'); } public boolean isPalindrome2(String s) { int l = 0; int r = s.length()-1; // s = s.toLowerCase(); while (l < r) { while (!isAlphanumeric(s.charAt(l)) && l < r) { l++; } while (!isAlphanumeric(s.charAt(r)) && l < r) { r--; } if (Character.toLowerCase(s.charAt(l)) != Character.toLowerCase(s.charAt(r))) return false; l++; r--; } return true; } private boolean isAlphanumeric(char c) { return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'); } } ================================================ FILE: src/ValidPalindromeII680.java ================================================ /** * Given a non-empty string s, you may delete at most one character. * Judge whether you can make it a palindrome. * * Example 1: * Input: "aba" * Output: True * * Example 2: * Input: "abca" * Output: True * * Explanation: You could delete the character 'c'. * Note: * The string will only contain lowercase characters a-z. * The maximum length of the string is 50000. * */ public class ValidPalindromeII680 { public boolean validPalindrome(String s) { return validPalindrome(s, 0, s.length()-1, false); } private boolean validPalindrome(String s, int l, int r, boolean flag) { while (l < r) { if (s.charAt(l) == s.charAt(r)) { l++; r--; continue; } if (flag) return false; if (l == r) return true; return validPalindrome(s, l+1, r, true) || validPalindrome(s, l, r-1, true); } return true; } // // stackoverflow // private boolean validPalindrome(String s, int l, int r, boolean flag) { // if (l >= r) return true; // if (s.charAt(l) == s.charAt(r)) { // return validPalindrome(s, l+1, r-1, flag); // } else if (!flag) { // return validPalindrome(s, l+1, r, true) || validPalindrome(s, l, r-1, true); // } else { // return false; // } // } } ================================================ FILE: src/ValidParentheses20.java ================================================ /** * Given a string containing just the characters '(', ')', '{', '}', '[' and ']', * determine if the input string is valid. * * The brackets must close in the correct order, "()" and "()[]{}" are all * valid but "(]" and "([)]" are not. */ import java.util.Map; import java.util.HashMap; import java.util.Stack; public class ValidParentheses20 { public boolean isValid(String s) { char[] chars = s.toCharArray(); Stack st = new Stack(); for (char c: chars) { if (isBackP(c)) { if (st.empty()) { return false; } else { char top = (char) st.pop(); if (c != top) { return false; } } } else { st.push(pair(c)); } } return st.empty(); } private boolean isBackP(char c) { return c == '}' || c == ']' || c == ')'; } private char pair(char c) { if (c == '{') { return '}'; } else if (c == '[') { return ']'; } else { return ')'; } } /** * https://discuss.leetcode.com/topic/27572/short-java-solution */ public boolean isValid2(String s) { Stack stack = new Stack(); for (char c : s.toCharArray()) { if (c == '(') stack.push(')'); else if (c == '{') stack.push('}'); else if (c == '[') stack.push(']'); else if (stack.isEmpty() || stack.pop() != c) return false; } return stack.isEmpty(); } public boolean isValid3(String s) { if (s == null || s.length()%2 == 1) return false; if (s.length() == 0) return true; Stack st = new Stack<>(); for (char c : s.toCharArray()) { if (c == '(' || c == '[' || c == '{') { st.push(c); continue; } if (st.isEmpty()) return false; switch (c) { case ')': if (st.peek() == '(') { st.pop(); break; } else { return false; } case ']': if (st.peek() == '[') { st.pop(); break; } else { return false; } case '}': if (st.peek() == '{') { st.pop(); break; } else { return false; } default: return false; } } return st.isEmpty(); } public static void main(String[] args) { ValidParentheses20 vp = new ValidParentheses20(); System.out.println(vp.isValid("[")); System.out.println(vp.isValid("]")); System.out.println(vp.isValid("[]")); } } ================================================ FILE: src/ValidParenthesisString678.java ================================================ /** * Given a string containing only three types of characters: '(', ')' and '*', * write a function to check whether this string is valid. We define the * validity of a string by these rules: * * Any left parenthesis '(' must have a corresponding right parenthesis ')'. * Any right parenthesis ')' must have a corresponding left parenthesis '('. * Left parenthesis '(' must go before the corresponding right parenthesis ')'. * '*' could be treated as a single right parenthesis ')' or a single left parenthesis '(' or an empty string. * An empty string is also valid. * * Example 1: * Input: "()" * Output: True * * Example 2: * Input: "(*)" * Output: True * * Example 3: * Input: "(*))" * Output: True * * Note: * The string size will be in the range [1, 100]. */ public class ValidParenthesisString678 { public boolean checkValidString(String s) { return checkValidString(s.toCharArray(), 0, new int[]{0}); } public boolean checkValidString(char[] chars, int i, int[] count) { if (i == chars.length) return count[0] == 0; char c = chars[i]; if (c == '(') { count[0]++; return checkValidString(chars, i + 1, count); } else if (c == ')') { if (count[0] == 0) return false; count[0]--; return checkValidString(chars, i + 1, count); } else { int pre = count[0]; if (checkValidString(chars, i + 1, count)) return true; count[0] = pre + 1; if (checkValidString(chars, i + 1, count)) return true; count[0] = pre; if (count[0] == 0) return false; count[0]--; return checkValidString(chars, i + 1, count); } } /** * https://leetcode.com/problems/valid-parenthesis-string/solution/ */ public boolean checkValidString2(String s) { int n = s.length(); if (n == 0) return true; boolean[][] dp = new boolean[n][n]; for (int i = 0; i < n; i++) { if (s.charAt(i) == '*') dp[i][i] = true; if (i < n-1 && (s.charAt(i) == '(' || s.charAt(i) == '*') && (s.charAt(i+1) == ')' || s.charAt(i+1) == '*')) { dp[i][i+1] = true; } } for (int size = 2; size < n; size++) { for (int i = 0; i + size < n; i++) { if (s.charAt(i) == '*' && dp[i+1][i+size] == true) { dp[i][i+size] = true; } else if (s.charAt(i) == '(' || s.charAt(i) == '*') { for (int k = i+1; k <= i+size; k++) { if ((s.charAt(k) == ')' || s.charAt(k) == '*') && (k == i+1 || dp[i+1][k-1]) && (k == i+size || dp[k+1][i+size])) { dp[i][i+size] = true; } } } } } return dp[0][n-1]; } /** * https://leetcode.com/problems/valid-parenthesis-string/solution/ */ public boolean checkValidString3(String s) { int lo = 0, hi = 0; for (char c: s.toCharArray()) { lo += c == '(' ? 1 : -1; hi += c != ')' ? 1 : -1; if (hi < 0) break; lo = Math.max(lo, 0); } return lo == 0; } } ================================================ FILE: src/ValidSudoku36.java ================================================ /** * Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules. * http://sudoku.com.au/TheRules.aspx * * The Sudoku board could be partially filled, where empty cells are filled * with the character '.'. * * http://upload.wikimedia.org/wikipedia/commons/thumb/f/ff/Sudoku-by-L2G-20050714.svg/250px-Sudoku-by-L2G-20050714.svg.png * * A partially filled sudoku which is valid. * * Note: * A valid Sudoku board (partially filled) is not necessarily solvable. Only * the filled cells need to be validated. * */ public class ValidSudoku36 { public boolean isValidSudoku(char[][] board) { boolean[][] rows = new boolean[9][9]; boolean[][] cols = new boolean[9][9]; boolean[][] cubs = new boolean[9][9]; for (int i=0; i<9; i++) { for (int j=0; j<9; j++) { if (board[i][j] == '.') continue; int n = board[i][j] - '1'; if (rows[i][n] || cols[j][n] || cubs[cubeId(i,j)][n]) return false; rows[i][n] = true; cols[j][n] = true; cubs[cubeId(i,j)][n] = true; } } return true; } private int cubeId(int i, int j) { return (i/3)*3 + (j/3); } /** * https://leetcode.com/problems/valid-sudoku/discuss/15472/Short+Simple-Java-using-Strings */ public boolean isValidSudoku2(char[][] board) { Set seen = new HashSet(); for (int i=0; i<9; ++i) { for (int j=0; j<9; ++j) { if (board[i][j] != '.') { String b = "(" + board[i][j] + ")"; if (!seen.add(b + i) || !seen.add(j + b) || !seen.add(i/3 + b + j/3)) return false; } } } return true; } /** * https://leetcode.com/problems/valid-sudoku/discuss/15560/Yet-another-java-2ms-solution */ public boolean isValidSudoku3s(char[][] board) { int [] vset = new int [9]; int [] hset = new int [9]; int [] bckt = new int [9]; int idx = 0; for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (board[i][j] != '.') { idx = 1 << (board[i][j] - '0') ; if ((hset[i] & idx) > 0 || (vset[j] & idx) > 0 || (bckt[(i / 3) * 3 + j / 3] & idx) > 0) return false; hset[i] |= idx; vset[j] |= idx; bckt[(i / 3) * 3 + j / 3] |= idx; } } } return true; } } ================================================ FILE: src/ValidTriangleNumber611.java ================================================ /** * Given an array consists of non-negative integers, your task is to count the * number of triplets chosen from the array that can make triangles if we take * them as side lengths of a triangle. * * Example 1: * Input: [2,2,3,4] * Output: 3 * Explanation: * Valid combinations are: * 2,3,4 (using the first 2) * 2,3,4 (using the second 2) * 2,2,3 * * Note: * The length of the given array won't exceed 1000. * The integers in the given array are in the range of [0, 1000]. */ public class ValidTriangleNumber611 { public int triangleNumber(int[] nums) { if (nums == null || nums.length < 3) return 0; Arrays.sort(nums); int res = 0; for (int i=0; i longestSide) longestSide = b; if (c > longestSide) longestSide = c; return longestSide < (a + b + c - longestSide); } public int triangleNumber2(int[] nums) { if (nums == null || nums.length < 3) return 0; Arrays.sort(nums); int[] sum = new int[1001]; for(int n: nums) sum[n]++; for(int i=1; i<1001; i++) sum[i] += sum[i-1]; int res = 0; for (int i=0; i nums[k]) k++; count += k - j - 1; } } return count; } /** * https://leetcode.com/problems/valid-triangle-number/discuss/104174/Java-O(n2)-Time-O(1)-Space */ public static int triangleNumber4(int[] A) { Arrays.sort(A); int count = 0, n = A.length; for (int i=n-1;i>=2;i--) { int l = 0, r = i-1; while (l < r) { if (A[l] + A[r] > A[i]) { count += r-l; r--; } else l++; } } return count; } } ================================================ FILE: src/ValidWordAbbreviation408.java ================================================ /** * Given a non-empty string s and an abbreviation abbr, return whether the * string matches with the given abbreviation. * * A string such as "word" contains only the following valid abbreviations: * * ["word", "1ord", "w1rd", "wo1d", "wor1", "2rd", "w2d", "wo2", "1o1d", * "1or1", "w1r1", "1o2", "2r1", "3d", "w3", "4"] * * Notice that only the above abbreviations are valid abbreviations of the * string "word". Any other string is not a valid abbreviation of "word". * * Note: * Assume s contains only lowercase letters and abbr contains only lowercase * letters and digits. * * Example 1: * Given s = "internationalization", abbr = "i12iz4n": * Return true. * * Example 2: * Given s = "apple", abbr = "a2e": * Return false. */ public class ValidWordAbbreviation408 { public boolean validWordAbbreviation(String word, String abbr) { if (abbr.length() == 0) return word.length() == 0; char[] wordChars = word.toCharArray(); char[] abbrChars = abbr.toCharArray(); int wLen = word.length(); int aLen = abbr.length(); int i = 0; int j = 0; while (i < wLen && j < aLen) { if (isDigit(abbrChars[j])) { if (abbrChars[j] == '0') return false; int preJ = j; while (j < aLen && isDigit(abbrChars[j])) { j++; } int num = Integer.valueOf(abbr.substring(preJ, j)); i += num; if (i > wLen) return false; } else { if (wordChars[i] != abbrChars[j]) return false; i++; j++; } } return i == wLen && j == aLen; } private boolean isDigit(char ch) { return ch >= '0' && ch <= '9'; } } ================================================ FILE: src/ValidateBinarySearchTree98.java ================================================ /** * Given a binary tree, determine if it is a valid binary search tree (BST). * * Assume a BST is defined as follows: * * The left subtree of a node contains only nodes with keys less than the node's key. * The right subtree of a node contains only nodes with keys greater than the node's key. * Both the left and right subtrees must also be binary search trees. * * Example 1: * 2 * / \ * 1 3 * Binary tree [2,1,3], return true. * * Example 2: * 1 * / \ * 2 3 * Binary tree [1,2,3], return false. */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class ValidateBinarySearchTree98 { public boolean isValidBST(TreeNode root) { return helper(root, Long.MIN_VALUE, Long.MAX_VALUE); } private boolean helper(TreeNode root, long min, long max) { if (root == null) return true; if (root.val <= min || root.val >= max) return false; return helper(root.left, min, root.val) && helper(root.right, root.val, max); } public boolean isValidBST2(TreeNode root) { if (root == null) return true; return isValidBST(root, new int[]{0, 0}); } private boolean isValidBST(TreeNode root, int[] bounds) { bounds[0] = root.val; bounds[1] = root.val; if (root.left == null && root.right == null) { return true; } if (root.left != null) { int[] leftBounds = new int[]{0, 0}; boolean left = isValidBST(root.left, leftBounds); if (!left || leftBounds[1] >= root.val) return false; bounds[0] = leftBounds[0]; } if (root.right != null) { int[] rightBounds = new int[]{0, 0}; boolean right = isValidBST(root.right, rightBounds); if (!right || rightBounds[0] <= root.val) return false; bounds[1] = rightBounds[1]; } return true; } /** * https://discuss.leetcode.com/topic/46016/learn-one-iterative-inorder-traversal-apply-it-to-multiple-tree-questions-java-solution */ public boolean isValidBST3(TreeNode root) { if (root == null) return true; Stack stack = new Stack<>(); TreeNode pre = null; while (root != null || !stack.isEmpty()) { while (root != null) { stack.push(root); root = root.left; } root = stack.pop(); if(pre != null && root.val <= pre.val) return false; pre = root; root = root.right; } return true; } } ================================================ FILE: src/ValidateStackSequences946.java ================================================ /** * Given two sequences pushed and popped with distinct values, return true if and * only if this could have been the result of a sequence of push and pop operations on an initially empty stack. * * Example 1: * Input: pushed = [1,2,3,4,5], popped = [4,5,3,2,1] * Output: true * Explanation: We might do the following sequence: * push(1), push(2), push(3), push(4), pop() -> 4, * push(5), pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1 * * Example 2: * Input: pushed = [1,2,3,4,5], popped = [4,3,5,1,2] * Output: false * Explanation: 1 cannot be popped before 2. * * Note: * 0 <= pushed.length == popped.length <= 1000 * 0 <= pushed[i], popped[i] < 1000 * pushed is a permutation of popped. * pushed and popped have distinct values. */ public class ValidateStackSequences946 { public boolean validateStackSequences(int[] pushed, int[] popped) { int i = 0; int j = 0; int len = pushed.length; Stack st = new Stack<>(); while (i < len && j < len) { while (!st.isEmpty() && j < len && popped[j] == st.peek()) { j++; st.pop(); } if (j >= len) break; while (i < len && pushed[i] != popped[j]) { st.push(pushed[i]); i++; } if (i < len && pushed[i] == popped[j]) { st.push(pushed[i]); i++; } } while (!st.isEmpty() && j < len && popped[j] == st.peek()) { j++; st.pop(); } return i == len && j == len && st.isEmpty(); } } ================================================ FILE: src/VerifyPreorderSequenceInBinarySearchTree255.java ================================================ /** * Given an array of numbers, verify whether it is the correct preorder * traversal sequence of a binary search tree. * * You may assume each number in the sequence is unique. * * Consider the following binary search tree: * * 5 * / \ * 2 6 * / \ * 1 3 * * Example 1: * Input: [5,2,6,1,3] * Output: false * * Example 2: * Input: [5,2,1,3,6] * Output: true * * Follow up: * Could you do it using only constant space complexity? */ public class VerifyPreorderSequenceInBinarySearchTree255 { public boolean verifyPreorder(int[] preorder) { if (preorder == null || preorder.length <= 1) return true; Stack stack = new Stack<>(); int lower = Integer.MIN_VALUE; for (int n: preorder) { if (n < lower) return false; while (!stack.isEmpty() && stack.peek() < n) { int top = stack.pop(); if (top > lower) lower = top; } stack.push(n); } return true; } public boolean verifyPreorder2(int[] preorder) { if (preorder == null || preorder.length <= 1) return true; return helper(preorder, 0, preorder.length-1, Integer.MIN_VALUE); } private boolean helper(int[] preorder, int i, int j, int lower) { if (i > j) return true; if (i == j) return preorder[i] > lower; int root = preorder[i]; if (root < lower) return false; int mid = i + 1; while (mid <= j && preorder[mid] < root) { mid++; } return helper(preorder, i+1, mid-1, lower) && helper(preorder, mid, j, root); } public boolean verifyPreorder3(int[] preorder) { if (preorder == null || preorder.length <= 1) return true; int i = -1; int lower = Integer.MIN_VALUE; for (int n: preorder) { if (n < lower) return false; while (i != -1 && preorder[i] < n) { int top = preorder[i--]; if (top > lower) lower = top; } preorder[++i] = n; } return true; } } ================================================ FILE: src/WallsAndGates286.java ================================================ /** * You are given a m x n 2D grid initialized with these three possible values. * * -1 - A wall or an obstacle. * 0 - A gate. * INF - Infinity means an empty room. We use the value 231 - 1 = 2147483647 to * represent INF as you may assume that the distance to a gate is less * than 2147483647. * * Fill each empty room with the distance to its nearest gate. If it is * impossible to reach a gate, it should be filled with INF. * * Example: * * Given the 2D grid: * * INF -1 0 INF * INF INF INF -1 * INF -1 INF -1 * 0 -1 INF INF * * After running your function, the 2D grid should be: * * 3 -1 0 1 * 2 2 1 -1 * 1 -1 2 -1 * 0 -1 3 4 * */ public class WallsAndGates286 { private int[][] directions = new int[][]{{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; public void wallsAndGates(int[][] rooms) { if (rooms == null || rooms.length == 0 || rooms[0].length == 0) return; int n = rooms.length; int m = rooms[0].length; for (int i=0; i= rooms.length || j < 0 || j >= rooms[0].length) return; if (rooms[i][j] == -1 || rooms[i][j] == 0) return; // can be optimized: early stop // rooms[i][j] = Math.min(rooms[i][j], distance); if (rooms[i][j] > distance) { rooms[i][j] = distance; } else if (rooms[i][j] <= distance) { return; } for (int[] dir: directions) { dfs(rooms, distance + 1, i + dir[0], j + dir[1]); } } /** * leetcode solution */ public void wallsAndGates2(int[][] rooms) { if(rooms.length == 0 || rooms[0].length == 0) return; for(int i = 0; i < rooms.length; i++) { for(int j = 0; j < rooms[0].length; j++) { if(rooms[i][j] == 0) { dfs2(rooms, i, j, 0); } } } } private void dfs2(int[][] rooms, int i, int j, int dis) { if(i < 0 || i >= rooms.length || j < 0 || j >= rooms[0].length || dis > rooms[i][j] || rooms[i][j] == -1) return; rooms[i][j] = dis; dfs2(rooms, i + 1, j, dis+1); dfs2(rooms, i - 1, j, dis+1); dfs2(rooms, i, j - 1, dis+1); dfs2(rooms, i, j + 1, dis+1); } /** * https://leetcode.com/problems/walls-and-gates/solution/ */ private static final int EMPTY = Integer.MAX_VALUE; private static final int GATE = 0; private static final List DIRECTIONS = Arrays.asList( new int[] { 1, 0}, new int[] {-1, 0}, new int[] { 0, 1}, new int[] { 0, -1} ); public void wallsAndGates4(int[][] rooms) { int m = rooms.length; if (m == 0) return; int n = rooms[0].length; Queue q = new LinkedList<>(); for (int row = 0; row < m; row++) { for (int col = 0; col < n; col++) { if (rooms[row][col] == GATE) { q.add(new int[] { row, col }); } } } while (!q.isEmpty()) { int[] point = q.poll(); int row = point[0]; int col = point[1]; for (int[] direction : DIRECTIONS) { int r = row + direction[0]; int c = col + direction[1]; if (r < 0 || c < 0 || r >= m || c >= n || rooms[r][c] != EMPTY) { continue; } rooms[r][c] = rooms[row][col] + 1; q.add(new int[] { r, c }); } } } } ================================================ FILE: src/WaterAndJugProblem365.java ================================================ /** * You are given two jugs with capacities x and y litres. There is an infinite amount of water supply available. * You need to determine whether it is possible to measure exactly z litres using these two jugs. * * If z liters of water is measurable, you must have z liters of water contained within one or both buckets by the end. * * Operations allowed: * * Fill any of the jugs completely with water. * Empty any of the jugs. * Pour water from one jug into another till the other jug is completely full or the first jug itself is empty. * * Example 1: (From the famous "Die Hard" example) * Input: x = 3, y = 5, z = 4 * Output: True * * Example 2: * Input: x = 2, y = 6, z = 5 * Output: False */ import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; public class WaterAndJugProblem365 { public boolean canMeasureWater(int x, int y, int z) { if (x < 0 || y < 0 || z < 0) { return false; } if (x == z || y == z || z == 0 || ((x + y) == z)) { return true; } if (x == y) { return false; } return canGetZ(Math.min(x, y), Math.max(x, y), z); } private boolean canGetZ(int x, int y, int z) { Integer a = x; Integer b = 0; do { Integer tempB = a + b; if (tempB == z) { return true; } if (b == y) { b = 0; continue; } if (a == 0) { a = x; continue; } if (tempB > y) { a = tempB - y; b = y; } else { a = 0; b = tempB; } } while (!(a == x && b == 0)); return false; } /** ------------------------------------------------------------------- * Top Solution: * https://discuss.leetcode.com/topic/49238/math-solution-java-solution * https://en.wikipedia.org/wiki/B%C3%A9zout%27s_identity * -------------------------------------------------------------------- */ public boolean canMeasureWaterMath(int x, int y, int z) { //limit brought by the statement that water is finallly in one or both buckets if(x + y < z) return false; //case x or y is zero if( x == z || y == z || x + y == z ) return true; //get GCD, then we can use the property of Bézout's identity return z%GCD(x, y) == 0; } public int GCD(int a, int b){ while(b != 0 ){ int temp = b; b = a%b; a = temp; } return a; } public static void main(String[] args) { WaterAndJugProblem365 wjp = new WaterAndJugProblem365(); System.out.println(wjp.canMeasureWaterMath(3, 5, 4)); System.out.println(wjp.canMeasureWaterMath(4, 6, 8)); System.out.println(wjp.canMeasureWaterMath(1, 2, 3)); System.out.println(wjp.canMeasureWaterMath(2, 6, 5)); } } ================================================ FILE: src/WiggleSort280.java ================================================ /** * Given an unsorted array nums, reorder it in-place such that * nums[0] <= nums[1] >= nums[2] <= nums[3].... * * Example: * * Input: nums = [3,5,2,1,6,4] * Output: One possible answer is [3,5,1,6,2,4] */ public class WiggleSort280 { public void wiggleSort(int[] nums) { if (nums == null || nums.length <= 1) return; int len = nums.length; int i = 0; while (i < len - 1) { if ((i % 2 == 0 && nums[i] > nums[i+1]) || (i % 2 == 1 && nums[i] < nums[i+1])) swap(nums, i, i+1); i++; } } public void wiggleSort2(int[] nums) { if (nums == null || nums.length <= 1) return; Arrays.sort(nums); int len = nums.length; int mid = len / 2; if (mid % 2 == 1) mid++; int left = 1; int right = mid; while (right < len) { swap(nums, left, right); left += 2; right += 2; } } private void swap(int[] nums, int i, int j) { int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; } } ================================================ FILE: src/WiggleSortII324.java ================================================ /** * Given an unsorted array nums, reorder it such that nums[0] < nums[1] > nums[2] < nums[3].... * * Example: * (1) Given nums = [1, 5, 1, 1, 6, 4], one possible answer is [1, 4, 1, 5, 1, 6]. * (2) Given nums = [1, 3, 2, 2, 3, 1], one possible answer is [2, 3, 1, 3, 1, 2]. * * Note: * You may assume all input has valid answer. * * Follow Up: * Can you do it in O(n) time and/or in-place with O(1) extra space? */ public class WiggleSortII324 { /** * https://www.hrwhisper.me/leetcode-wiggle-sort-ii/ */ public void wiggleSort(int[] nums) { Arrays.sort(nums); int[] temp = new int[nums.length]; int s = (nums.length + 1) >> 1, t = nums.length; for (int i = 0; i < nums.length; i++) { temp[i] = (i & 1) == 0 ? nums[--s] : nums[--t] ; } for (int i = 0; i < nums.length; i++) nums[i] = temp[i]; } /** * https://www.hrwhisper.me/leetcode-wiggle-sort-ii/ */ public void wiggleSort2(int[] nums) { int medium = findMedium(nums, 0, nums.length - 1, (nums.length + 1) >> 1); int s = 0, t = nums.length - 1 , mid_index = (nums.length + 1) >> 1; int[] temp = new int[nums.length]; for (int i = 0; i < nums.length; i++) { if (nums[i] < medium) temp[s++] = nums[i]; else if (nums[i] > medium) temp[t--] = nums[i]; } while (s < mid_index) temp[s++] = medium; while (t >= mid_index) temp[t--] = medium; t = nums.length; for (int i = 0; i < nums.length; i++) nums[i] = (i & 1) == 0 ? temp[--s] : temp[--t]; } private int findMedium(int[] nums, int L, int R, int k) { if (L >= R) return nums[R]; int i = partition(nums, L, R); int cnt = i - L + 1; if (cnt == k) return nums[i]; return cnt > k ? findMedium(nums, L, i - 1, k) : findMedium(nums, i + 1, R, k - cnt); } private int partition(int[] nums, int L, int R) { int val = nums[L]; int i = L, j = R + 1; while (true) { while (++i < R && nums[i] < val) ; while (--j > L && nums[j] > val) ; if (i >= j) break; swap(nums, i, j); } swap(nums, L, j); return j; } private void swap(int[] nums, int i, int j) { int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; } } ================================================ FILE: src/WiggleSubsequence376.java ================================================ /** * A sequence of numbers is called a wiggle sequence if the differences between * successive numbers strictly alternate between positive and negative. The * first difference (if one exists) may be either positive or negative. A * sequence with fewer than two elements is trivially a wiggle sequence. * * For example, [1,7,4,9,2,5] is a wiggle sequence because the differences * (6,-3,5,-7,3) are alternately positive and negative. In contrast, * [1,4,7,2,5] and [1,7,4,5,5] are not wiggle sequences, the first because its * first two differences are positive and the second because its last * difference is zero. * * Given a sequence of integers, return the length of the longest subsequence * that is a wiggle sequence. A subsequence is obtained by deleting some number * of elements (eventually, also zero) from the original sequence, leaving the * remaining elements in their original order. * * Examples: * Input: [1,7,4,9,2,5] * Output: 6 * The entire sequence is a wiggle sequence. * * Input: [1,17,5,10,13,15,10,5,16,8] * Output: 7 * There are several subsequences that achieve this length. * One is [1,17,10,13,10,16,8]. * * Input: [1,2,3,4,5,6,7,8,9] * Output: 2 * * Follow up: * Can you do it in O(n) time? */ public class WiggleSubsequence376 { public int wiggleMaxLength(int[] nums) { if (nums == null || nums.length == 0) return 0; int N = nums.length; int[] up = new int[N]; int[] down = new int[N]; up[0] = 1; down[0] = 1; for (int i=1; i nums[j]) { up[i] = Math.max(up[i], down[j] + 1); } else if (nums[i] < nums[j]) { down[i] = Math.max(down[i], up[j] + 1); } } } return Math.max(up[N-1], down[N-1]); } public int wiggleMaxLength2(int[] nums) { if (nums == null || nums.length == 0) return 0; int N = nums.length; int[] up = new int[N]; int[] down = new int[N]; for (int i=1; i nums[j]) { up[i] = Math.max(up[i], down[j] + 1); } else if (nums[i] < nums[j]) { down[i] = Math.max(down[i], up[j] + 1); } } } return Math.max(up[N-1], down[N-1]) + 1; } public int wiggleMaxLength3(int[] nums) { if (nums == null || nums.length == 0) return 0; int N = nums.length; int[] up = new int[N]; int[] down = new int[N]; up[0] = 1; down[0] = 1; for (int i=1; i nums[i-1]) { up[i] = down[i-1] + 1; down[i] = down[i-1]; } else { up[i] = up[i-1]; down[i] = up[i-1] + 1; } } return Math.max(up[N-1], down[N-1]); } public int wiggleMaxLength4(int[] nums) { if (nums == null || nums.length == 0) return 0; int N = nums.length; int up = 1; int down = 1; for (int i=1; i nums[i-1]) { up = down + 1; } else if (nums[i] < nums[i-1]){ down = up + 1; } } return Math.max(up, down); } /** * https://leetcode.com/problems/wiggle-subsequence/solution/ */ public int wiggleMaxLength5(int[] nums) { if (nums.length < 2) return nums.length; int prevdiff = nums[1] - nums[0]; int count = prevdiff != 0 ? 2 : 1; for (int i = 2; i < nums.length; i++) { int diff = nums[i] - nums[i - 1]; if ((diff > 0 && prevdiff <= 0) || (diff < 0 && prevdiff >= 0)) { count++; prevdiff = diff; } } return count; } } ================================================ FILE: src/WildcardMatching44.java ================================================ /** * Implement wildcard pattern matching with support for '?' and '*'. * * '?' Matches any single character. * '*' Matches any sequence of characters (including the empty sequence). * * The matching should cover the entire input string (not partial). * * The function prototype should be: * bool isMatch(const char *s, const char *p) * * Some examples: * isMatch("aa","a") → false * isMatch("aa","aa") → true * isMatch("aaa","aa") → false * isMatch("aa", "*") → true * isMatch("aa", "a*") → true * isMatch("ab", "?*") → true * isMatch("aab", "c*a*b") → false * */ public class WildcardMatching44 { // time limit exceeded public boolean isMatch(String s, String p) { if (s == null || p == null) return false; return isMatch(s, 0, p, 0); } private boolean isMatch(String s, int i, String p, int j) { if (i >= s.length()) return restAreStars(p, j); if (j >= p.length()) return false; switch (p.charAt(j)) { case '?': return isMatch(s, i+1, p, j+1); case '*': while (j+1 < p.length() && p.charAt(j+1) == '*') j++; return isMatch(s, i, p, j+1) || isMatch(s, i+1, p, j+1) || isMatch(s, i+1, p, j); default: return s.charAt(i) == p.charAt(j) && isMatch(s, i+1, p, j+1); } } private boolean restAreStars(String p, int j) { while (j < p.length()) { if (p.charAt(j) != '*') return false; j++; } return true; } // DP, 2D space public boolean isMatch2(String s, String p) { if (s == null || p == null) return false; boolean[][] dp = new boolean[p.length()+1][s.length()+1]; dp[0][0] = true; for (int j=1; j<=s.length(); j++) dp[0][j] = false; for (int i=1; i<=p.length(); i++) dp[i][0] = p.charAt(i-1) == '*' ? dp[i-1][0] : false; for (int i=1; i<=p.length(); i++) { char c = p.charAt(i-1); for (int j=1; j<=s.length(); j++) { switch (c) { case '?': dp[i][j] = dp[i-1][j-1]; break; case '*': dp[i][j] = dp[i-1][j] || dp[i-1][j-1] || dp[i][j-1]; break; default: dp[i][j] = c == s.charAt(j-1) && dp[i-1][j-1]; } } } return dp[p.length()][s.length()]; } // DP, 1D space public boolean isMatch3(String s, String p) { if (s == null || p == null) return false; boolean[] dp = new boolean[s.length()+1]; dp[0] = true; for (int j=1; j<=s.length(); j++) dp[j] = false; for (int i=1; i<=p.length(); i++) { boolean old = dp[0]; boolean pre = dp[0]; dp[0] = p.charAt(i-1) == '*' ? dp[0] : false; char c = p.charAt(i-1); for (int j=1; j<=s.length(); j++) { old = dp[j]; switch (c) { case '?': dp[j] = pre; break; case '*': dp[j] = old || pre || dp[j-1]; break; default: dp[j] = c == s.charAt(j-1) && pre; } pre = old; } } return dp[s.length()]; } /** * https://leetcode.com/problems/wildcard-matching/discuss/17810/Linear-runtime-and-constant-space-solution */ boolean isMatch4(String str, String pattern) { int s = 0, p = 0, match = 0, starIdx = -1; while (s < str.length()){ // advancing both pointers if (p < pattern.length() && (pattern.charAt(p) == '?' || str.charAt(s) == pattern.charAt(p))){ s++; p++; } // * found, only advancing pattern pointer else if (p < pattern.length() && pattern.charAt(p) == '*'){ starIdx = p; match = s; p++; } // last pattern pointer was *, advancing string pointer else if (starIdx != -1){ p = starIdx + 1; match++; s = match; } //current pattern pointer is not star, last patter pointer was not * //characters do not match else return false; } //check for remaining characters in pattern while (p < pattern.length() && pattern.charAt(p) == '*') p++; return p == pattern.length(); } public boolean isMatch5(String s, String p) { if (p.length() == 0) return s.length() == 0; Map memo = new HashMap<>(); return isMatch(s.toCharArray(), 0, p.toCharArray(), 0, memo); } public boolean isMatch(char[] s, int i, char[] p, int j, Map memo) { int idx = i * p.length + j; if (memo.containsKey(idx)) return memo.get(idx); if (j == p.length) return i == s.length; boolean res = false; char pChar = p[j]; if (i == s.length) { res = pChar == '*' && isMatch(s, i, p, j+1, memo); } else { char sChar = s[i]; if (pChar == '?') { res = isMatch(s, i+1, p, j+1, memo); } else if (pChar == '*') { res = isMatch(s, i+1, p, j+1, memo) || isMatch(s, i, p, j+1, memo) || isMatch(s, i+1, p, j, memo); } else { res = pChar == sChar && isMatch(s, i+1, p, j+1, memo); } } memo.put(idx, res); return res; } } ================================================ FILE: src/WordAbbreviation527.java ================================================ /** * Given an array of n distinct non-empty strings, you need to generate minimal * possible abbreviations for every word following rules below. * * Begin with the first character and then the number of characters abbreviated, * which followed by the last character. * * If there are any conflict, that is more than one words share the same * abbreviation, a longer prefix is used instead of only the first character * until making the map from word to abbreviation become unique. In other * words, a final abbreviation cannot map to more than one original words. * If the abbreviation doesn't make the word shorter, then keep it as original. * * Example: * Input: ["like", "god", "internal", "me", "internet", "interval", "intension", "face", "intrusion"] * Output: ["l2e","god","internal","me","i6t","interval","inte4n","f2e","intr4n"] * * Note: * Both n and the length of each word will not exceed 400. * The length of each word is greater than 1. * The words consist of lowercase English letters only. * The return answers should be in the same order as the original array. */ public class WordAbbreviation527 { public List wordsAbbreviation(List dict) { int N = dict.size(); Abbr[] abbrs = new Abbr[N]; for (int i=0; i duplicates = new HashSet<>(); for (int j=i+1; j res = new ArrayList<>(); for (Abbr abbr: abbrs) { res.add(abbr.abbr); } return res; } private String encode(String word, int offset) { if (offset + 2 >= word.length()) return word; String encoded = word.substring(0, offset+1) + Integer.toString(word.length()-offset-2) + word.charAt(word.length()-1); return encoded.length() >= word.length() ? word : encoded; } class Abbr { String word; String abbr; int offset; Abbr(String word, String abbr, int offset) { this.word = word; this.abbr = abbr; this.offset = offset; } } /** * https://leetcode.com/problems/word-abbreviation/solution/s */ public List wordsAbbreviation2(List words) { Map> groups = new HashMap(); String[] ans = new String[words.size()]; int index = 0; for (String word: words) { String ab = abbrev(word, 0); if (!groups.containsKey(ab)) groups.put(ab, new ArrayList()); groups.get(ab).add(new IndexedWord(word, index)); index++; } for (List group: groups.values()) { Collections.sort(group, (a, b) -> a.word.compareTo(b.word)); int[] lcp = new int[group.size()]; for (int i = 1; i < group.size(); ++i) { int p = longestCommonPrefix(group.get(i-1).word, group.get(i).word); lcp[i] = p; lcp[i-1] = Math.max(lcp[i-1], p); } for (int i = 0; i < group.size(); ++i) ans[group.get(i).index] = abbrev(group.get(i).word, lcp[i]); } return Arrays.asList(ans); } public String abbrev(String word, int i) { int N = word.length(); if (N - i <= 3) return word; return word.substring(0, i+1) + (N - i - 2) + word.charAt(N-1); } public int longestCommonPrefix(String word1, String word2) { int i = 0; while (i < word1.length() && i < word2.length() && word1.charAt(i) == word2.charAt(i)) i++; return i; } class IndexedWord { String word; int index; IndexedWord(String w, int i) { word = w; index = i; } } /** * https://leetcode.com/problems/word-abbreviation/solution/s */ public List wordsAbbreviation3(List words) { Map> groups = new HashMap(); String[] ans = new String[words.size()]; int index = 0; for (String word: words) { String ab = abbrev(word, 0); if (!groups.containsKey(ab)) groups.put(ab, new ArrayList()); groups.get(ab).add(new IndexedWord(word, index)); index++; } for (List group: groups.values()) { TrieNode trie = new TrieNode(); for (IndexedWord iw: group) { TrieNode cur = trie; for (char letter: iw.word.substring(1).toCharArray()) { if (cur.children[letter - 'a'] == null) cur.children[letter - 'a'] = new TrieNode(); cur.count++; cur = cur.children[letter - 'a']; } } for (IndexedWord iw: group) { TrieNode cur = trie; int i = 1; for (char letter: iw.word.substring(1).toCharArray()) { if (cur.count == 1) break; cur = cur.children[letter - 'a']; i++; } ans[iw.index] = abbrev(iw.word, i-1); } } return Arrays.asList(ans); } class TrieNode { TrieNode[] children; int count; TrieNode() { children = new TrieNode[26]; count = 0; } } } ================================================ FILE: src/WordBreak139.java ================================================ /** * Given a non-empty string s and a dictionary wordDict containing a list of * non-empty words, determine if s can be segmented into a space-separated * sequence of one or more dictionary words. You may assume the dictionary * does not contain duplicate words. * * For example, given * s = "leetcode", * dict = ["leet", "code"]. * * Return true because "leetcode" can be segmented as "leet code". * * UPDATE (2017/1/4): * The wordDict parameter had been changed to a list of strings (instead of a * set of strings). Please reload the code definition to get the latest changes. */ public class WordBreak139 { public boolean wordBreak(String s, List wordDict) { int L = s.length(); if (L == 0) return true; boolean[] dp = new boolean[L+1]; dp[0] = true; int k = 0; for (int i=0; i<=L; i++) { for (int j=0; j<=i; j++) { if (dp[j] && wordDict.contains(s.substring(j, i))) { dp[i] = true; } } } return dp[L]; } public boolean wordBreak2(String s, List wordDict) { boolean[] dp = new boolean[s.length()+1]; dp[0] = true; for (int j=1; j<=s.length(); j++) { for (String word: wordDict) { if (j >= word.length() && s.startsWith(word, j - word.length()) && dp[j - word.length()]) dp[j] = true; } } return dp[s.length()]; } } ================================================ FILE: src/WordBreakII140.java ================================================ /** * Given a non-empty string s and a dictionary wordDict containing a list of * non-empty words, add spaces in s to construct a sentence where each word is * a valid dictionary word. Return all such possible sentences. * * Note: * The same word in the dictionary may be reused multiple times in the segmentation. * You may assume the dictionary does not contain duplicate words. * * Example 1: * Input: * s = "catsanddog" * wordDict = ["cat", "cats", "and", "sand", "dog"] * Output: * [ * "cats and dog", * "cat sand dog" * ] * * Example 2: * Input: * s = "pineapplepenapple" * wordDict = ["apple", "pen", "applepen", "pine", "pineapple"] * Output: * [ * "pine apple pen apple", * "pineapple pen apple", * "pine applepen apple" * ] * Explanation: Note that you are allowed to reuse a dictionary word. * * Example 3: * Input: * s = "catsandog" * wordDict = ["cats", "dog", "sand", "and", "cat"] * Output: * [] */ public class WordBreakII140 { // Memory Limit Exceeded // public List wordBreak(String s, List wordDict) { // int N = s.length(); // LinkedList[] dp = new LinkedList[N+1]; // for (int i=0; i<=N; i++) dp[i] = new LinkedList<>(); // Set wordSet = new HashSet<>(wordDict); // dp[0].add(""); // for (int i=1; i<=N; i++) { // for (int j=0; j 0 && wordSet.contains(w)) { // for (String p: dp[j]) { // dp[i].add(p.length() == 0 ? w : (p + " " + w)); // } // } // } // } // return dp[N]; // } // DP public List wordBreak(String s, List wordDict) { Set wordSet = new HashSet<>(wordDict); if (!wordIsBreakable(s, wordSet)) return new ArrayList<>(); return wordBreak(s, wordSet); } public List wordBreak(String s, Set wordDict) { LinkedList[] dp = new LinkedList[s.length() + 1]; LinkedList initial = new LinkedList<>(); initial.add(""); dp[0] = initial; for (int i = 1; i <= s.length(); i++) { LinkedList list = new LinkedList<>(); for (int j = 0; j < i; j++) { if (dp[j].size() > 0 && wordDict.contains(s.substring(j, i))) { for (String l : dp[j]) { list.add(l + (l.equals("") ? "" : " ") + s.substring(j, i)); } } } dp[i] = list; } return dp[s.length()]; } public boolean wordIsBreakable(String s, Set wordDictSet) { boolean[] dp = new boolean[s.length() + 1]; dp[0] = true; for (int i = 1; i <= s.length(); i++) { for (int j = 0; j < i; j++) { if (dp[j] && wordDictSet.contains(s.substring(j, i))) { dp[i] = true; break; } } } return dp[s.length()]; } // Backtracing public List wordBreak2(String s, List wordDict) { if (!wordIsBreakable(s, new HashSet<>(wordDict))) return new ArrayList<>(); int N = s.length(); Set[] dp = new Set[N]; for (int i=0; i(); for (int i=0; i res = new ArrayList<>(); helper(N, dp, res, new StringBuilder(), 0); return res; } private void helper(int N, Set[] dp, List res, StringBuilder sb, int i) { if (i == N) { res.add(sb.substring(0, sb.length()-1).toString()); return; } for (String w: dp[i]) { sb.append(w).append(" "); helper(N, dp, res, sb, i+w.length()); sb.delete(sb.length()-w.length()-1, sb.length()); } } /** * https://leetcode.com/problems/word-break-ii/discuss/44167/My-concise-JAVA-solution-based-on-memorized-DFS */ public List wordBreak3(String s, Set wordDict) { return DFS(s, wordDict, new HashMap>()); } // DFS function returns an array including all substrings derived from s. List DFS(String s, Set wordDict, HashMap>map) { if (map.containsKey(s)) return map.get(s); LinkedListres = new LinkedList(); if (s.length() == 0) { res.add(""); return res; } for (String word : wordDict) { if (s.startsWith(word)) { Listsublist = DFS(s.substring(word.length()), wordDict, map); for (String sub : sublist) res.add(word + (sub.isEmpty() ? "" : " ") + sub); } } map.put(s, res); return res; } } ================================================ FILE: src/WordDictionary.java ================================================ /** * Design a data structure that supports the following two operations: * * void addWord(word) * bool search(word) * search(word) can search a literal word or a regular expression string * containing only letters a-z or .. A . means it can represent any one letter. * * For example: * * addWord("bad") * addWord("dad") * addWord("mad") * search("pad") -> false * search("bad") -> true * search(".ad") -> true * search("b..") -> true * Note: * You may assume that all words are consist of lowercase letters a-z. * */ public class WordDictionary { Trie t = new Trie(); /** Initialize your data structure here. */ public WordDictionary() { } /** Adds a word into the data structure. */ public void addWord(String word) { add(t, word.toCharArray(), 0); } private static void add(Trie tr, char[] chars, int i) { while (i < chars.length) tr = tr.add(chars[i++]); tr.isWord = true; } // private static void add(Trie tr, char[] chars, int i) { // if (i >= chars.length) { // tr.isWord = true; // return; // } // add(tr.add(chars[i]), chars, i+1); // } /** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */ public boolean search(String word) { return search(t, word.toCharArray(), 0); } private static boolean search(Trie tr, char[] chars, int i) { while (i < chars.length) { char c = chars[i]; if (c == '.') { for (char nc: tr.map.keySet()) { if (tr.has(nc) && search(tr.get(nc), chars, i+1)) { return true; } } return false; } else { if (!tr.has(c)) return false; tr = tr.get(c); i++; } } return tr.isWord; } // private static boolean search(Trie tr, char[] chars, int i) { // if (i >= chars.length) return tr.isWord; // char c = chars[i]; // if (c == '.') { // for (char nc: tr.map.keySet()) { // if (tr.has(nc) && search(tr.get(nc), chars, i+1)) { // return true; // } // } // return false; // } else { // return tr.has(c) && search(tr.get(c), chars, i+1); // } // } } class Trie { // also Trie[] map = new Trie[26]; Map map = new HashMap<>(); boolean isWord = false; public Trie() { } public Trie get(char c) { return this.map.get(c); } public Trie add(char c) { return this.map.computeIfAbsent(c, cc -> new Trie()); } public boolean has(char c) { return c == '.' || this.map.containsKey(c); } } /** * Your WordDictionary object will be instantiated and called as such: * WordDictionary obj = new WordDictionary(); * obj.addWord(word); * boolean param_2 = obj.search(word); */ ================================================ FILE: src/WordLadder127.java ================================================ /** * Given two words (beginWord and endWord), and a dictionary's word list, find * the length of shortest transformation sequence from beginWord to endWord, * such that: * * Only one letter can be changed at a time. * Each transformed word must exist in the word list. Note that beginWord is not a transformed word. * For example, * * Given: * beginWord = "hit" * endWord = "cog" * wordList = ["hot","dot","dog","lot","log","cog"] * * As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog", * return its length 5. * Note: * Return 0 if there is no such transformation sequence. * All words have the same length. * All words contain only lowercase alphabetic characters. * You may assume no duplicates in the word list. * You may assume beginWord and endWord are non-empty and are not the same. * */ import java.util.Arrays; import java.util.List; import java.util.ArrayList; import java.util.LinkedList; import java.util.Queue; import java.util.Set; import java.util.HashSet; public class WordLadder127 { // DFS too slow // BFS public int ladderLength(String start, String end, List dictL) { Set dict = new HashSet<>(dictL); if (!dict.contains(end)) { return 0; } Queue queue = new LinkedList(); queue.add(start); // Mark visited word Set visited = new HashSet(); visited.add(start); int level = 1; while (!queue.isEmpty()) { int size = queue.size(); for (int q=0; q dictL) { Set dict = new HashSet<>(dictL); if (!dict.contains(end)) { return 0; } Queue queue = new LinkedList(); queue.add(start); queue.add(null); // Mark visited word Set visited = new HashSet(); visited.add(start); int level = 1; while (!queue.isEmpty()) { String str = queue.poll(); if (str != null) { // Modify str's each character (so word distance is 1) for (int i = 0; i < str.length(); i++) { char[] chars = str.toCharArray(); for (char c = 'a'; c <= 'z'; c++) { chars[i] = c; String word = new String(chars); // Found the end word if (word.equals(end)) return level + 1; // Put it to the queue if (dict.contains(word) && !visited.contains(word)) { queue.add(word); visited.add(word); } } } } else { level++; if (!queue.isEmpty()) { queue.add(null); } } } return 0; } /** * Two-end BFS in Java 31ms. * https://discuss.leetcode.com/topic/29303/two-end-bfs-in-java-31ms */ public int ladderLength3(String beginWord, String endWord, List wordL) { Set wordList = new HashSet<>(wordL); if (!wordList.contains(endWord)) { return 0; } Set beginSet = new HashSet(), endSet = new HashSet(); int len = 1; int strLen = beginWord.length(); HashSet visited = new HashSet(); beginSet.add(beginWord); endSet.add(endWord); while (!beginSet.isEmpty() && !endSet.isEmpty()) { if (beginSet.size() > endSet.size()) { Set set = beginSet; beginSet = endSet; endSet = set; } Set temp = new HashSet(); for (String word : beginSet) { char[] chs = word.toCharArray(); for (int i = 0; i < chs.length; i++) { for (char c = 'a'; c <= 'z'; c++) { char old = chs[i]; chs[i] = c; String target = String.valueOf(chs); if (endSet.contains(target)) { return len + 1; } if (!visited.contains(target) && wordList.contains(target)) { temp.add(target); visited.add(target); } chs[i] = old; } } } beginSet = temp; len++; } return 0; } /** * https://discuss.leetcode.com/topic/20965/java-solution-using-dijkstra-s-algorithm-with-explanation */ public int ladderLength4(String beginWord, String endWord, List dictL) { Set wordDict = new HashSet<>(dictL); if (!wordDict.contains(endWord)) { return 0; } Set reached = new HashSet(); reached.add(beginWord); int distance = 1; while (!reached.contains(endWord)) { Set toAdd = new HashSet(); for (String each : reached) { for (int i = 0; i < each.length(); i++) { char[] chars = each.toCharArray(); for (char ch = 'a'; ch <= 'z'; ch++) { chars[i] = ch; String word = new String(chars); if (wordDict.contains(word)) { toAdd.add(word); wordDict.remove(word); } } } } distance++; if (toAdd.size() == 0) return 0; reached = toAdd; } return distance; } public static void main(String[] args) { WordLadder127 wl = new WordLadder127(); System.out.println("--------"); System.out.println(wl.ladderLength2("hit", "cog", Arrays.asList(new String[]{"hot", "dot", "dog","lot","log","cog"}))); System.out.println("--------"); System.out.println(wl.ladderLength2("hot", "dog", Arrays.asList(new String[]{"hot","cog","dog","tot","hog","hop","pot","dot"}))); System.out.println("--------"); System.out.println(wl.ladderLength2("hit", "cog", Arrays.asList(new String[]{"hot","dot","dog","lot","log"}))); } } ================================================ FILE: src/WordLadderII126.java ================================================ /** * Given two words (beginWord and endWord), and a dictionary's word list, find * all shortest transformation sequence(s) from beginWord to endWord, such that: * * Only one letter can be changed at a time * Each transformed word must exist in the word list. Note that beginWord is * not a transformed word. * * Note: * Return an empty list if there is no such transformation sequence. * All words have the same length. * All words contain only lowercase alphabetic characters. * You may assume no duplicates in the word list. * You may assume beginWord and endWord are non-empty and are not the same. * * Example 1: * Input: * beginWord = "hit", * endWord = "cog", * wordList = ["hot","dot","dog","lot","log","cog"] * Output: * [ * ["hit","hot","dot","dog","cog"], * ["hit","hot","lot","log","cog"] * ] * * Example 2: * Input: * beginWord = "hit" * endWord = "cog" * wordList = ["hot","dot","dog","lot","log"] * Output: [] * * Explanation: The endWord "cog" is not in wordList, therefore no possible * transformation. */ public class WordLadderII126 { public List> findLadders(String beginWord, String endWord, List wordList) { Set wordDict = new HashSet<>(wordList); if (!wordDict.contains(endWord)) return new ArrayList<>(); wordDict.remove(beginWord); Set visited = new HashSet<>(); List first = new ArrayList<>(); first.add(beginWord); List> res = new ArrayList<>(); res.add(first); while (true) { List> newRes = new ArrayList<>(); Set localVisited = new HashSet<>(); boolean found = false; for (int i=0; i path = res.get(i); String word = path.get(path.size()-1); for (int j=0; j newPath = new ArrayList<>(path); newPath.add(newWord); newRes.add(newPath); if (!newWord.equals(endWord)) localVisited.add(newWord); // wordDict.remove(newWord); } } } } if (newRes.size() == 0) return newRes; if (found) { List> returned = new ArrayList<>(); for (List p: newRes) { if (p.get(p.size()-1).equals(endWord)) { returned.add(p); } } return returned; } res = newRes; visited.addAll(localVisited); } } /** * https://leetcode.com/problems/word-ladder-ii/discuss/40477/Super-fast-Java-solution-(two-end-BFS) */ public List> findLadders2(String start, String end, List wordList) { Set dict = new HashSet(wordList); if (!dict.contains(end)) return new ArrayList<>(); // hash set for both ends Set set1 = new HashSet(); Set set2 = new HashSet(); // initial words in both ends set1.add(start); set2.add(end); // we use a map to help construct the final result Map> map = new HashMap>(); // build the map helper(dict, set1, set2, map, false); List> res = new ArrayList>(); List sol = new ArrayList(Arrays.asList(start)); // recursively build the final result generateList(start, end, map, sol, res); return res; } private boolean helper(Set dict, Set set1, Set set2, Map> map, boolean flip) { if (set1.isEmpty()) { return false; } if (set1.size() > set2.size()) { return helper(dict, set2, set1, map, !flip); } // remove words on current both ends from the dict dict.removeAll(set1); dict.removeAll(set2); // as we only need the shortest paths // we use a boolean value help early termination boolean done = false; // set for the next level Set set = new HashSet(); // for each string in end 1 for (String str : set1) { for (int i = 0; i < str.length(); i++) { char[] chars = str.toCharArray(); // change one character for every position for (char ch = 'a'; ch <= 'z'; ch++) { chars[i] = ch; String word = new String(chars); // make sure we construct the tree in the correct direction String key = flip ? word : str; String val = flip ? str : word; List list = map.containsKey(key) ? map.get(key) : new ArrayList(); if (set2.contains(word)) { done = true; list.add(val); map.put(key, list); } if (!done && dict.contains(word)) { set.add(word); list.add(val); map.put(key, list); } } } } // early terminate if done is true return done || helper(dict, set2, set, map, !flip); } private void generateList(String start, String end, Map> map, List sol, List> res) { if (start.equals(end)) { res.add(new ArrayList(sol)); return; } // need this check in case the diff between start and end happens to be one // e.g "a", "c", {"a", "b", "c"} if (!map.containsKey(start)) { return; } for (String word : map.get(start)) { sol.add(word); generateList(word, end, map, sol, res); sol.remove(sol.size() - 1); } } List> ans = new ArrayList<>(); public List> findLadders3(String beginWord, String endWord, List wordList) { // for each level, // should NOT use the words in upper level // should NOT add same words into queue // however, should use the same word in current level Map> map = new HashMap<>(); Set unvisited = new HashSet<>(wordList); Set visited = new HashSet<>(); Deque queue = new LinkedList<>(); queue.offer(beginWord); visited.add(beginWord); unvisited.remove(beginWord); boolean found = false; while(!found && !queue.isEmpty()){ // begin each level int size = queue.size(); visited.clear(); for(int k = 0; k < size; k++){ String word = queue.poll(); for(int i = 0; i < word.length(); i++){ StringBuilder sb = new StringBuilder(word); for(char c = 'a'; c < 'z'; c++){ sb.setCharAt(i, c); String newWord = sb.toString(); if(unvisited.contains(newWord)){ if(visited.add(newWord)){ queue.offer(newWord); } if(map.containsKey(newWord)){ map.get(newWord).add(word); }else{ List adj = new ArrayList<>(); adj.add(word); map.put(newWord, adj); } if(newWord.equals(endWord)){ found = true; } } } } } // end of each level unvisited.removeAll(visited); } List path = new ArrayList<>(); path.add(endWord); dfs(beginWord, path, map); return ans; } private void dfs(String beginWord, List path, Map> map){ String word = path.get(0); if(word.equals(beginWord)){ ans.add(new ArrayList<>(path)); return; } if(map.containsKey(word)){ for(String prevWord : map.get(word)){ path.add(0, prevWord); dfs(beginWord, path, map); path.remove(0); } } } } ================================================ FILE: src/WordPattern290.java ================================================ /** * Given a pattern and a string str, find if str follows the same pattern. * * Here follow means a full match, such that there is a bijection between a * letter in pattern and a non-empty word in str. * * Example 1: * Input: pattern = "abba", str = "dog cat cat dog" * Output: true * * Example 2: * Input:pattern = "abba", str = "dog cat cat fish" * Output: false * * Example 3: * Input: pattern = "aaaa", str = "dog cat cat dog" * Output: false * * Example 4: * Input: pattern = "abba", str = "dog dog dog dog" * Output: false * * Notes: * You may assume pattern contains only lowercase letters, and str contains * lowercase letters separated by a single space. */ public class WordPattern290 { public boolean wordPattern(String pattern, String str) { String[] words = str.trim().split("\\s+"); if (pattern.length() != words.length) return false; Map map = new HashMap<>(); int N = pattern.length(); for (int i=0; i set = new HashSet<>(); int N = pattern.length(); for (int i=0; i()); } private boolean match(String pattern, int i, String str, int j, String[] p2s, Map s2p) { if (i == pattern.length()) return j == str.length(); if (j == str.length()) return false; char p = pattern.charAt(i); if (p2s[p-'a'] != null) { String sub = p2s[p-'a']; if (!str.startsWith(sub, j)) return false; if (match(pattern, i+1, str, j+sub.length(), p2s, s2p)) return true; } else { for (int k=j+1; k<=str.length(); k++) { String sub = str.substring(j, k); if (s2p.containsKey(sub)) { char p0 = s2p.get(sub); if (p0 != p) continue; if (match(pattern, i+1, str, j+sub.length(), p2s, s2p)) return true; } else { p2s[p-'a'] = sub; s2p.put(sub, p); if (match(pattern, i+1, str, j+sub.length(), p2s, s2p)) return true; p2s[p-'a'] = null; s2p.remove(sub); } } } return false; } } ================================================ FILE: src/WordSearch79.java ================================================ /** * Given a 2D board and a word, find if the word exists in the grid. * * The word can be constructed from letters of sequentially adjacent cell, * where "adjacent" cells are those horizontally or vertically neighboring. * The same letter cell may not be used more than once. * * For example, * Given board = * * [ * ['A','B','C','E'], * ['S','F','C','S'], * ['A','D','E','E'] * ] * word = "ABCCED", -> returns true, * word = "SEE", -> returns true, * word = "ABCB", -> returns false. * */ public class WordSearch79 { public boolean exist(char[][] board, String word) { if (word.length() == 0) { return true; } if (board.length == 0) { return false; } int m = board.length; int n = board[0].length; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { boolean[][] visited = new boolean[m][n]; if (helper(i, j, 0, board, word, visited)) { return true; } } } return false; } private boolean helper(int i, int j, int index, char[][] board, String word, boolean[][] visited) { if (index >= word.length()) { return true; } if (i < 0 || i >= board.length || j < 0 || j >= board[0].length) { return false; } if (visited[i][j] || board[i][j] != word.charAt(index)) { return false; } visited[i][j] = true; if (helper(i, j+1, index + 1, board, word, visited) || helper(i+1, j, index + 1, board, word, visited) || helper(i, j-1, index + 1, board, word, visited) || helper(i-1, j, index + 1, board, word, visited)) { return true; } visited[i][j] = false; return false; } /** * https://discuss.leetcode.com/topic/7907/accepted-very-short-java-solution-no-additional-space */ public boolean exist2(char[][] board, String word) { if (word.length() == 0) { return true; } if (board.length == 0) { return false; } int m = board.length; int n = board[0].length; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (helper(i, j, 0, board, word)) { return true; } } } return false; } private boolean helper(int i, int j, int index, char[][] board, String word) { if (index >= word.length()) { return true; } if (i < 0 || i >= board.length || j < 0 || j >= board[0].length) { return false; } if (board[i][j] != word.charAt(index)) { return false; } board[i][j] ^= 256; if (helper(i, j+1, index + 1, board, word) || helper(i+1, j, index + 1, board, word) || helper(i, j-1, index + 1, board, word) || helper(i-1, j, index + 1, board, word)) { return true; } board[i][j] ^= 256; return false; } } ================================================ FILE: src/WordSearchII212.java ================================================ /** * Given a 2D board and a list of words from the dictionary, find all words in * the board. * * Each word must be constructed from letters of sequentially adjacent cell, * where "adjacent" cells are those horizontally or vertically neighboring. * The same letter cell may not be used more than once in a word. * * For example, * Given words = ["oath","pea","eat","rain"] and board = * * [ * ['o','a','a','n'], * ['e','t','a','e'], * ['i','h','k','r'], * ['i','f','l','v'] * ] * Return ["eat","oath"]. * Note: * You may assume that all inputs are consist of lowercase letters a-z. * * Hint: * You would need to optimize your backtracking to pass the larger test. Could * you stop backtracking earlier? * * If the current candidate does not exist in all words' prefix, you could stop * backtracking immediately. What kind of data structure could answer such query * efficiently? Does a hash table work? Why or why not? How about a Trie? If * you would like to learn how to implement a basic trie, please work on this * problem: Implement Trie (Prefix Tree) first. * */ public class WordSearchII212 { public List findWords(char[][] board, String[] words) { List res = new ArrayList<>(); TrieNode root = buildTrie(words); for (int i = 0; i < board.length; i++) { for (int j = 0; j < board[0].length; j++) { helper(board, i, j, root, res); } } return res; } private void helper(char[][] board, int i, int j, TrieNode node, List res) { if (i < 0 || i >= board.length || j < 0 || j >= board[0].length || board[i][j] == '#' || !node.containsKey(board[i][j])) { return; } char curr = board[i][j]; node = node.get(curr); if (node.containsWord()) { res.add(node.getWord()); node.setWord(null); } board[i][j] = '#'; helper(board, i, j+1, node, res); helper(board, i+1, j, node, res); helper(board, i, j-1, node, res); helper(board, i-1, j, node, res); board[i][j] = curr; } public TrieNode buildTrie(String[] words) { TrieNode root = new TrieNode(); for (String w : words) { TrieNode node = root; for (int i = 0; i < w.length(); i++) { char c = w.charAt(i); if (!node.containsKey(c)) { node.put(c, new TrieNode()); } node = node.get(c); } node.setWord(w); } return root; } class TrieNode { // R links to node children private TrieNode[] links; private final int R = 26; private String word; public TrieNode() { links = new TrieNode[R]; } public boolean containsKey(char c) { return links[c -'a'] != null; } public TrieNode get(char c) { return links[c -'a']; } public void put(char c, TrieNode node) { links[c -'a'] = node; } public void setWord(String w) { word = w; } public String getWord() { return word; } public boolean containsWord() { return word != null; } } private int[][] dirs = new int[][]{{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; public List findWords2(char[][] board, String[] words) { if (board == null || board.length == 0 || board[0].length == 0 || words.length == 0) return new ArrayList<>(); int M = board.length; int N = board[0].length; Trie trie = constructTrie(words); Set set = new HashSet<>(); boolean[][] visited = new boolean[M][N]; for (int i=0; i(set); } private void dfs(char[][] board, boolean[][] visited, Trie trie, int i, int j, int M, int N, Set set) { if (trie == null) return; if (trie.word != null) set.add(trie.word); if (i < 0 || j < 0 || i >= M || j >= N || visited[i][j]) return; visited[i][j] = true; char c = board[i][j]; Trie next = trie.get(c); // if (next == null) return; for (int[] d: dirs) { dfs(board, visited, next, i+d[0], j+d[1], M, N, set); } visited[i][j] = false; } private Trie constructTrie(String[] words) { Trie t = new Trie(); for (String word: words) t.addWord(word); return t; } class Trie { Trie[] children = new Trie[26]; String word = null; public void addWord(String word) { addWord(word.toCharArray(), 0); } public void addWord(char[] chars, int i) { if (i == chars.length) { word = new String(chars); return; } if (children[chars[i]-'a'] == null) { children[chars[i]-'a'] = new Trie(); } children[chars[i]-'a'].addWord(chars, i+1); } public Trie get(char c) { return children[c-'a']; } } /** * https://leetcode.com/problems/word-search-ii/discuss/59780/Java-15ms-Easiest-Solution-(100.00) * * 59ms: Use search and startsWith in Trie class like this popular solution. * 33ms: Remove Trie class which unnecessarily starts from root in every dfs call. * 30ms: Use w.toCharArray() instead of w.charAt(i). * 22ms: Use StringBuilder instead of c1 + c2 + c3. * 20ms: Remove StringBuilder completely by storing word instead of boolean in TrieNode. * 20ms: Remove visited[m][n] completely by modifying board[i][j] = '#' directly. * 18ms: check validity, e.g., if(i > 0) dfs(...), before going to the next dfs. * 17ms: De-duplicate c - a with one variable i. * 15ms: Remove HashSet completely. dietpepsi's idea is awesome. */ public List findWords3(char[][] board, String[] words) { List res = new ArrayList<>(); TrieNode root = buildTrie2(words); for (int i = 0; i < board.length; i++) { for (int j = 0; j < board[0].length; j++) { dfs (board, i, j, root, res); } } return res; } public void dfs(char[][] board, int i, int j, TrieNode p, List res) { char c = board[i][j]; if (c == '#' || p.next[c - 'a'] == null) return; p = p.next[c - 'a']; if (p.word != null) { // found one res.add(p.word); p.word = null; // de-duplicate } board[i][j] = '#'; if (i > 0) dfs(board, i - 1, j ,p, res); if (j > 0) dfs(board, i, j - 1, p, res); if (i < board.length - 1) dfs(board, i + 1, j, p, res); if (j < board[0].length - 1) dfs(board, i, j + 1, p, res); board[i][j] = c; } public TrieNode buildTrie2(String[] words) { TrieNode root = new TrieNode(); for (String w : words) { TrieNode p = root; for (char c : w.toCharArray()) { int i = c - 'a'; if (p.next[i] == null) p.next[i] = new TrieNode(); p = p.next[i]; } p.word = w; } return root; } class TrieNode { TrieNode[] next = new TrieNode[26]; String word; } } ================================================ FILE: src/WordSquares425.java ================================================ /** * Given a set of words (without duplicates), find all word squares you can * build from them. * * A sequence of words forms a valid word square if the kth row and column read * the exact same string, where 0 ≤ k < max(numRows, numColumns). * * For example, the word sequence ["ball","area","lead","lady"] forms a word * square because each word reads the same both horizontally and vertically. * * b a l l * a r e a * l e a d * l a d y * * Note: * - There are at least 1 and at most 1000 words. * - All words will have the exact same length. * - Word length is at least 1 and at most 5. * - Each word contains only lowercase English alphabet a-z. * * Example 1: * * Input: * ["area","lead","wall","lady","ball"] * * Output: * [ * [ "wall", * "area", * "lead", * "lady" * ], * [ "ball", * "area", * "lead", * "lady" * ] * ] * * Explanation: * The output consists of two word squares. The order of output does not matter * (just the order of words in each word square matters). * * Example 2: * * Input: * ["abat","baba","atan","atal"] * * Output: * [ * [ "baba", * "abat", * "baba", * "atan" * ], * [ "baba", * "abat", * "baba", * "atal" * ] * ] * * Explanation: * The output consists of two word squares. The order of output does not matter * (just the order of words in each word square matters). */ import java.util.List; import java.util.ArrayList; import java.util.Arrays; public class WordSquares425 { public List> wordSquares(String[] words) { List> res = new ArrayList<>(); if (words == null || words.length == 0 || words[0].length() == 0) return res; int len = words[0].length(); TrieNode root = new TrieNode(); for (String word: words) root.addWord(word); helper(new char[len][len], root, 0, len, new ArrayList(), res); return res; } private void helper(char[][] square, TrieNode root, int pos, int len, List sqr, List> res) { if (pos == len) { if (sqr.size() == len) { List newSqr = new ArrayList(); for (String s: sqr) { newSqr.add(s); } res.add(newSqr); } return; } List finds = root.search(Arrays.copyOfRange(square[pos], 0, pos), len); if (finds.size() == 0) return; for (String w: finds) { sqr.add(w); for (int j=pos; j search(char[] prefix, int length) { List res = new ArrayList(); search(prefix, length, 0, res); return res; } public void search(char[] prefix, int length, int i, List res) { if (i == length) { if (word != null) res.add(word); return; } if (i < prefix.length) { if (children[prefix[i] - 'a'] == null) return; children[prefix[i] - 'a'].search(prefix, length, i+1, res); } else { for (TrieNode child: children) { if (child != null) child.search(prefix, length, i+1, res); } } } } public List> wordSquares2(String[] words) { Arrays.sort(words); List> res = new ArrayList<>(); int W = words[0].length(); char[][] board = new char[W][W]; helper(board, 0, words, res, W); return res; } private void helper(char[][] board, int i, String[] words, List> res, int W) { if (i >= W) { List r = new ArrayList<>(); for (int j=0; j q = new LinkedList<>(); for (int i=0; i= M || y >= N || matrix[x][y] <= matrix[i][j] || matrix[x][y] == 0) continue; q.add(new int[]{x, y}); matrix[x][y] = matrix[i][j] + 1; } } return matrix; } /** * https://leetcode.com/problems/01-matrix/discuss/101051/Simple-Java-solution-beat-99-(use-DP) */ public int[][] updateMatrix2(int[][] matrix) { if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { return matrix; } int[][] dis = new int[matrix.length][matrix[0].length]; int range = matrix.length * matrix[0].length; for (int i = 0; i < matrix.length; i++) { for (int j = 0; j < matrix[0].length; j++) { if (matrix[i][j] == 0) { dis[i][j] = 0; } else { int upCell = (i > 0) ? dis[i - 1][j] : range; int leftCell = (j > 0) ? dis[i][j - 1] : range; dis[i][j] = Math.min(upCell, leftCell) + 1; } } } for (int i = matrix.length - 1; i >= 0; i--) { for (int j = matrix[0].length - 1; j >= 0; j--) { if (matrix[i][j] == 0) { dis[i][j] = 0; } else { int downCell = (i < matrix.length - 1) ? dis[i + 1][j] : range; int rightCell = (j < matrix[0].length - 1) ? dis[i][j + 1] : range; dis[i][j] = Math.min(Math.min(downCell, rightCell) + 1, dis[i][j]); } } } return dis; } } ================================================ FILE: src/ZigzagIterator281.java ================================================ /** * Given two 1d vectors, implement an iterator to return their elements alternately. * * Example: * Input: * v1 = [1,2] * v2 = [3,4,5,6] * Output: [1,3,2,4,5,6] * Explanation: By calling next repeatedly until hasNext returns false, * the order of elements returned by next should be: [1,3,2,4,5,6]. * * Follow up: What if you are given k 1d vectors? How well can your code be * extended to such cases? * * Clarification for the follow up question: * The "Zigzag" order is not clearly defined and is ambiguous for k > 2 cases. * If "Zigzag" does not look right to you, replace "Zigzag" with "Cyclic". * * For example: * Input: * [1,2,3] * [4,5,6,7] * [8,9] * Output: [1,4,8,2,5,9,3,6,7]. */ public class ZigzagIterator281 { class ZigzagIterator { private int total; private int k; private int pos = 0; private int index = 0; private List[] cache; public ZigzagIterator(List v1, List v2) { this.cache = new List[2]; this.cache[0] = v1; this.cache[1] = v2; this.total = v1.size() + v2.size(); this.k = 2; } public int next() { int x = this.index % k; int y = this.index / k; while (y >= this.cache[x].size()) { this.index++; x = this.index % k; y = this.index / k; } int res = this.cache[x].get(y); this.index++; this.pos++; return res; } public boolean hasNext() { return this.pos < this.total; } } /** * https://leetcode.com/problems/zigzag-iterator/discuss/71779/Simple-Java-solution-for-K-vector */ class ZigzagIterator2 { LinkedList list; public ZigzagIterator(List v1, List v2) { list = new LinkedList(); if(!v1.isEmpty()) list.add(v1.iterator()); if(!v2.isEmpty()) list.add(v2.iterator()); } public int next() { Iterator poll = list.remove(); int result = (Integer)poll.next(); if(poll.hasNext()) list.add(poll); return result; } public boolean hasNext() { return !list.isEmpty(); } } /** * https://leetcode.com/problems/zigzag-iterator/discuss/71781/Short-Java-O(1)-space */ class ZigzagIterator3 { private Iterator i, j, tmp; public ZigzagIterator(List v1, List v2) { i = v2.iterator(); j = v1.iterator(); } public int next() { if (j.hasNext()) { tmp = j; j = i; i = tmp; } return i.next(); } public boolean hasNext() { return i.hasNext() || j.hasNext(); } } /** * Your ZigzagIterator object will be instantiated and called as such: * ZigzagIterator i = new ZigzagIterator(v1, v2); * while (i.hasNext()) v[f()] = i.next(); */ } ================================================ FILE: src/data-structures/BinaryIndexedTree.java ================================================ /** * https://www.topcoder.com/community/competitive-programming/tutorials/binary-indexed-trees/ * https://www.geeksforgeeks.org/binary-indexed-tree-or-fenwick-tree-2/ */ public class BinaryIndexedTree { private int[] tree; private int N; public BinaryIndexedTree(int[] nums) { if (nums == null) return; this.N = nums.length; this.tree = new int[N+1]; constructBIT(nums); } public BinaryIndexedTree(int N) { this.N = N; this.tree = new int[N+1]; } private void constructBIT(int[] nums) { int N = nums.length; for (int i=0; i 0) { res += this.tree[k]; k -= lowBit(k); } return res; } private int lowBit(int x) { return x & (-x); } } ================================================ FILE: src/data-structures/BinarySearchTree.java ================================================ public class BinarySearchTree { private Node root; BinarySearchTree() { } public Node search(int x) { return search(this.root, x); // return searchIteratively(this.root, x); } private Node search(Node node, int x) { if (node == null || node.val == x) return node; if (node.val > x) { return search(node.left, x); } else { return search(node.right, x); } } private Node searchIteratively(Node node, int x) { Node res = node; while (res != null && res.val != x) { if (res.val > x) { res = res.left; } else { res = res.right; } } return res; } public void insert(int x) { this.root = insert(this.root, x); // this.root = insertIteratively(this.root, x); } public Node insert(Node node, int x) { if (node == null) return new Node(x); if (node.val > x) { node.left = insert(node.left, x); } else if (node.val < x) { node.right = insert(node.right, x); } return node; } public Node insertIteratively(Node node, int x) { Node newNode = new Node(x); if (node == null) return newNode; Node res = node; while (res != null && res.val != x) { if (res.val > x) { if (res.left == null) { res.left = newNode; } else { res = res.left; } } else { if (res.right == null) { res.right = newNode; } else { res = res.right; } } } return node; } /** * 1) Node to be deleted is leaf: Simply remove from the tree. * * 2) Node to be deleted has only one child: Copy the child to the node and * delete the child * * 3) Node to be deleted has two children: Find inorder successor of the node. * Copy contents of the inorder successor to the node and delete the inorder * successor. Note that inorder predecessor can also be used. * * The important thing to note is, inorder successor is needed only when right * child is not empty. In this particular case, inorder successor can be * obtained by finding the minimum value in right child of the node. */ public void delete(int x) { this.root = delete(this.root, x); } public Node delete(Node node, int x) { if (node == null) return null; if (node.val == x) { if (node.left == null) { return node.right; } else if (node.right == null) { return node.left; } else { Node succ = node.right; while (succ.left != null) { succ = succ.left; } node.val = succ.val; node.right = delete(node.right, node.val); } } else if (node.val > x) { node.left = delete(node.left, x); } else { node.right = delete(node.right, x); } return node; } public Node getRoot() { return this.root; } class Node { int val; Node left; Node right; Node(int x) { this.val = x; } } } ================================================ FILE: src/data-structures/BinarySearchTreeWithParent.java ================================================ /** * This class is having two more methods that BinarySearchTree: inorderSuccessor and inorderPredecessor */ public class BinarySearchTreeWithParent { private Node root; BinarySearchTree() { } public Node search(int x) { return search(this.root, x); // return searchIteratively(this.root, x); } private Node search(Node node, int x) { if (node == null || node.val == x) return node; if (node.val > x) { return search(node.left, x); } else { return search(node.right, x); } } private Node searchIteratively(Node node, int x) { Node res = node; while (res != null && res.val != x) { if (res.val > x) { res = res.left; } else { res = res.right; } } return res; } public void insert(int x) { this.root = insert(this.root, x); // this.root = insertIteratively(this.root, x); } public Node insert(Node node, int x) { if (node == null) return new Node(x); if (node.val > x) { node.left = insert(node.left, x); } else if (node.val < x) { node.right = insert(node.right, x); } return node; } public Node insertIteratively(Node node, int x) { Node newNode = new Node(x); if (node == null) return newNode; Node res = node; while (res != null && res.val != x) { if (res.val > x) { if (res.left == null) { res.left = newNode; } else { res = res.left; } } else { if (res.right == null) { res.right = newNode; } else { res = res.right; } } } return node; } /** * 1) Node to be deleted is leaf: Simply remove from the tree. * * 2) Node to be deleted has only one child: Copy the child to the node and * delete the child * * 3) Node to be deleted has two children: Find inorder successor of the node. * Copy contents of the inorder successor to the node and delete the inorder * successor. Note that inorder predecessor can also be used. * * The important thing to note is, inorder successor is needed only when right * child is not empty. In this particular case, inorder successor can be * obtained by finding the minimum value in right child of the node. */ public void delete(int x) { this.root = delete(this.root, x); } public Node delete(Node node, int x) { if (node == null) return null; if (node.val == x) { if (node.left == null) { return node.right; } else if (node.right == null) { return node.left; } else { Node succ = node.right; while (succ.left != null) { succ = succ.left; } node.val = succ.val; node.right = delete(node.right, node.val); } } else if (node.val > x) { node.left = delete(node.left, x); } else { node.right = delete(node.right, x); } return node; } public Node getRoot() { return this.root; } class Node { int val; Node left; Node right; Node parent; Node(int x) { this.val = x; } Node(int x, Node p) { this.val = x; this.parent = p; } public Node inorderSuccessor() { if (this.right == null) { Node res = this; while (res.parent != null && res.parent.right == res) { res = res.parent; } return res.parent; } else { Node res = this.right; while (res.left != null) { res = res.left; } return res; } } public Node inorderPredecessor() { if (this.left == null) { Node res = this; while (res.parent != null && res.parent.left == res) { res = res.parent; } return res.parent; } else { Node res = this.left; while (res.right != null) { res = res.right; } return res; } } } } ================================================ FILE: src/data-structures/DisjointSet.java ================================================ /** * A.K.A.: Union-Find with Path Compression and Union by Rank */ public class DisjointSet { private int[] parent; private int[] rank; public DisjointSet(int v) { this.parent = new int[v]; for (int i=0; i this.rank[yy]) { this.parent[yy] = xx; } else { this.parent[xx] = yy; this.parent[yy]++; } } } ================================================ FILE: src/data-structures/LFUCache.java ================================================ /** * */ public class LFUCache { private FreqNode head; private Map freqMap = new HashMap<>(); private Map itemMap = new HashMap<>(); private int capacity; public LFUCache(int capacity) { this.capacity = capacity; this.head = new FreqNode(); this.head.next = this.head; this.head.prev = this.head; } public int get(int key) { if (!this.itemMap.containsKey(key)) return -1; ItemNode item = this.itemMap.get(key); updateNodeFreq(item); return item.val; } private void updateNodeFreq(ItemNode item) { dislinkNode(item); Integer freq = item.freq; item.freq++; FreqNode currFreqNode = freqMap.get(freq); FreqNode newFreqNode = freqMap.get(freq+1); if (newFreqNode == null) { newFreqNode = new FreqNode(freq+1); freqMap.put(freq+1, newFreqNode); addAfter(currFreqNode, newFreqNode); } addBefore(newFreqNode.itemHead, item); if (itemNodeIsEmpty(currFreqNode.itemHead)) { removeNode(currFreqNode); } } private boolean itemNodeIsEmpty(ItemNode node) { return node.next == node; } private void removeNode(FreqNode node) { dislinkNode(node); this.freqMap.remove(node.freq); } private void removeNode(ItemNode node) { dislinkNode(node); this.itemMap.remove(node.key); } private void dislinkNode(FreqNode node) { node.prev.next = node.next; node.next.prev = node.prev; } private void dislinkNode(ItemNode node) { node.prev.next = node.next; node.next.prev = node.prev; } private void addAfter(FreqNode currNode, FreqNode newNode) { newNode.next = currNode.next; newNode.prev = currNode; currNode.next.prev = newNode; currNode.next = newNode; } private void addAfter(ItemNode currNode, ItemNode newNode) { newNode.next = currNode.next; newNode.prev = currNode; currNode.next.prev = newNode; currNode.next = newNode; } private void addBefore(ItemNode currNode, ItemNode newNode) { newNode.next = currNode; newNode.prev = currNode.prev; currNode.prev.next = newNode; currNode.prev = newNode; } public void put(int key, int value) { if (this.capacity == 0) return; if (this.itemMap.containsKey(key)) { ItemNode item = this.itemMap.get(key); item.val = value; updateNodeFreq(item); return; } if (this.itemMap.size() == this.capacity) { FreqNode first = this.head.next; ItemNode toBeRemoved = first.itemHead.next; removeNode(toBeRemoved); if (itemNodeIsEmpty(first.itemHead)) { removeNode(first); } } FreqNode newFreqNode = freqMap.get(1); if (newFreqNode == null) { newFreqNode = new FreqNode(1); freqMap.put(1, newFreqNode); addAfter(this.head, newFreqNode); } ItemNode newItem = new ItemNode(key, value, 1); addBefore(newFreqNode.itemHead, newItem); this.itemMap.put(key, newItem); } private ItemNode newItemHead() { ItemNode head = new ItemNode(); head.prev = head; head.next = head; return head; } class ItemNode extends Node { ItemNode next; ItemNode prev; int key; int val; int freq; ItemNode(int key, int val, int freq) { this.key = key; this.val = val; this.freq = freq; } ItemNode() { this.key = -1; this.val = -1; this.freq = -1; } } class FreqNode extends Node { FreqNode next; FreqNode prev; int freq; ItemNode itemHead; FreqNode(int freq) { this.freq = freq; this.itemHead = newItemHead(); } FreqNode() { this.freq = -1; } } abstract class Node { Node next; Node prev; } } ================================================ FILE: src/data-structures/LRUCache.java ================================================ /** * 146. LRU Cache * * Design and implement a data structure for Least Recently Used (LRU) cache. * https://en.wikipedia.org/wiki/Cache_replacement_policies#LRU * * It should support the following operations: get and put. * * get(key) - Get the value (will always be positive) of the key if the key * exists in the cache, otherwise return -1. * put(key, value) - Set or insert the value if the key is not already present. * When the cache reached its capacity, it should invalidate * the least recently used item before inserting a new item. * * Follow up: * Could you do both operations in O(1) time complexity? * * Example: * * LRUCache cache = new LRUCache( 2 ); // capacity * * cache.put(1, 1); * cache.put(2, 2); * cache.get(1); // returns 1 * cache.put(3, 3); // evicts key 2 * cache.get(2); // returns -1 (not found) * cache.put(4, 4); // evicts key 1 * cache.get(1); // returns -1 (not found) * cache.get(3); // returns 3 * cache.get(4); // returns 4 */ /** * Your LRUCache object will be instantiated and called as such: * LRUCache obj = new LRUCache(capacity); * int param_1 = obj.get(key); * obj.put(key,value); */ import java.util.LinkedHashMap; import java.util.Map; public class LRUCache { private Map map = new HashMap<>(); private Node head = new Node(0, 0); private int capacity; public LRUCache(int capacity) { head.next = head; head.prev = head; this.capacity = capacity; } public int get(int key) { Node curr = map.get(key); if (curr == null) { return -1; } delete(curr); moveToEnd(curr); return curr.value; } private void delete(Node node) { node.prev.next = node.next; node.next.prev = node.prev; } private void moveToEnd(Node node) { head.prev.next = node; node.next = head; node.prev = head.prev; head.prev = node; } public void put(int key, int value) { Node curr = map.get(key); if (curr == null) { Node newNode = new Node(key, value); moveToEnd(newNode); map.put(key, newNode); if (map.size() > capacity) { Node toRemove = head.next; delete(toRemove); map.remove(toRemove.key); } return; } curr.value = value; delete(curr); moveToEnd(curr); } class Node { int key; int value; Node next; Node prev; Node (int k, int v) { this.key = k; this.value = v; } } } ================================================ FILE: src/data-structures/MinHeap.java ================================================ import java.util.NoSuchElementException; public class MinHeap { private int size; private int capacity; private int[] arr; public MinHeap(int capacity) { this.size = 0; this.capacity = capacity; this.arr = new int[capacity]; } public int getMin() { if (this.size == 0) throw new NoSuchElementException(); return this.arr[0]; } public int extractMin() { if (this.size == 0) throw new NoSuchElementException(); if (this.size == 1) { this.size--; return this.arr[0]; } int minVal = this.arr[0]; this.arr[0] = this.arr[this.size - 1]; this.size--; heapify(0); return minVal; } private void heapify(int idx) { heapify(this.arr, this.size, idx); } private void heapify(int[] A, int size, int idx) { int l = left(idx); int r = right(idx); int minIdx = idx; if (l < size && A[l] < A[minIdx]) minIdx = l; if (r < size && A[r] < A[minIdx]) minIdx = r; if (minIdx != idx) { swap(A, minIdx, idx); heapify(minIdx); } } private void swap(int[] A, int i, int j) { int temp = A[i]; A[i] = A[j]; A[j] = temp; } public void decreaseKey(int idx, int x) { if (this.size <= idx) throw new NoSuchElementException(); this.arr[idx] = x; popUp(idx); } public void insert(int x) { if (this.size >= this.capacity) throw new StackOverflowError(); this.arr[this.size++] = x; popUp(this.size - 1); } private void popUp(int idx) { int i = idx; while (i > 0 && this.arr[i] < this.arr[parent(i)]) { swap(this.arr, i, parent(i)); i = parent(i); } } public int delete(int idx) { decreaseKey(idx, Integer.MIN_VALUE); return extractMin(); } public void buildHeap(int[] A) { for (int i = parent(A.length-1); i >= 0; i--) { heapify(A, A.length, i); } } // Heap Sort in Descending Order public void sort(int[] A) { buildHeap(A); for (int i = 0; i < A.length; i++) { swap(A, i, A.length - 1); heapify(A, A.length - i - 1, 0); } } private int parent(int i) { return (i - 1) / 2; } private int left(int i) { return i * 2 + 1; } private int right(int i) { return i * 2 + 2; } } ================================================ FILE: src/data-structures/Trie.java ================================================ /** * 208. Implement Trie (Prefix Tree) * * Implement a trie with insert, search, and startsWith methods. * * Note: * You may assume that all inputs are consist of lowercase letters a-z. */ /** * For Recursive version of the Trie implementation, see * https://github.com/fluency03/leetcode-java/blob/master/src/ImplementTriePrefixTree208.java */ public class Trie { private TrieNode root; /** Initialize your data structure here. */ public Trie() { root = new TrieNode(); } /** Inserts a word into the trie. */ public void insert(String word) { TrieNode node = root; for (int i = 0; i < word.length(); i++) { char c = word.charAt(i); if (!node.containsKey(c)) { node.put(c, new TrieNode()); } node = node.get(c); } node.setLeaf(); } /** Returns if the word is in the trie. */ public boolean search(String word) { TrieNode node = root; for (int i = 0; i < word.length(); i++) { char c = word.charAt(i); if (!node.containsKey(c)) { return false; } node = node.get(c); } return node.isLeaf(); } /** Returns if there is any word in the trie that starts with the given prefix. */ public boolean startsWith(String prefix) { TrieNode node = root; for (int i = 0; i < prefix.length(); i++) { char c = prefix.charAt(i); if (!node.containsKey(c)) { return false; } node = node.get(c); } return true; } } /** * Your Trie object will be instantiated and called as such: * Trie obj = new Trie(); * obj.insert(word); * boolean param_2 = obj.search(word); * boolean param_3 = obj.startsWith(prefix); */ ================================================ FILE: src/data-structures/TrieNode.java ================================================ /** * Definition for a trie (prefix tree) node. * * https://leetcode.com/articles/implement-trie-prefix-tree/ */ public class TrieNode { // R links to node children private TrieNode[] links; private final int R = 26; private boolean isLeaf; public TrieNode() { links = new TrieNode[R]; } public boolean containsKey(char c) { return links[c -'a'] != null; } public TrieNode get(char c) { return links[c -'a']; } public void put(char c, TrieNode node) { links[c -'a'] = node; } public void setLeaf() { isLeaf = true; } public boolean isLeaf() { return isLeaf; } } ================================================ FILE: src/graph/Dijkstra.java ================================================ /** * References: * https://www.geeksforgeeks.org/greedy-algorithms-set-6-dijkstras-shortest-path-algorithm/ * https://www.geeksforgeeks.org/greedy-algorithms-set-7-dijkstras-algorithm-for-adjacency-list-representation/ * https://www.geeksforgeeks.org/printing-paths-dijkstras-shortest-path-algorithm/ * https://www.geeksforgeeks.org/dijkstras-shortest-path-algorithm-using-set-in-stl/ */ /** * All edge weights are non-negative. */ public class Dijkstra { // Adjacency Matrix Representation /** * Output shortest paths distance from the source to all the vertices. */ public int[] shortestDistancesFrom(int[][] graph, int src) { if (graph == null || graph.length == 0 || graph[0].length == 0) return new int[0]; int len = graph.length; int[] dist = new int[len]; Set sptSet = new HashSet[len]; // initialization for (int i = 0; i < len; i++) { dist[i] = Integer.MAX_VALUE; } dist[src] = 0; while (sptSet.size() < len) { int u = extractMin(dist, sptSet); sptSet.add(u); for (int v=0; v 0 && dist[u] != Integer.MAX_VALUE && dist[u] + graph[u][v] < dist[v]) { dist[v] = dist[u] + graph[u][v]; } } } return dist; } // This can be optimized by MinHeap private int extractMin(int[] dist, Set sptSet) { int minIdx = -1; int minVal = Integer.MAX_VALUE; for (int i=0; i sptSet = new HashSet[len]; // initialization for (int i = 0; i < len; i++) { dist[i] = Integer.MAX_VALUE; } dist[src] = 0; while (sptSet.size() < len) { int u = minDistance(dist, sptSet); // early return when you fidn the target if (u = target) return dist[u]; sptSet.add(u); for (int v=0; v 0 && dist[u] != Integer.MAX_VALUE && dist[u] + graph[u][v] < dist[v]) { dist[v] = dist[u] + graph[u][v]; } } } return -1; } /** * Output shortest path from the source to the destination. */ public List shortestPath(int[][] graph, int src, int dest) { if (graph == null || graph.length == 0 || graph[0].length == 0) return new int[0]; int len = graph.length; int[] dist = new int[len]; int[] parent = new int[len]; Set sptSet = new HashSet[len]; // initialization for (int i = 0; i < len; i++) { dist[i] = Integer.MAX_VALUE; parent[i] = i; } dist[src] = 0; while (sptSet.size() < len) { int u = extractMin(dist, sptSet); if (u = target) return constructShortestPath(parent, src, dest); sptSet.add(u); for (int v=0; v 0 && dist[u] != Integer.MAX_VALUE && dist[u] + graph[u][v] < dist[v]) { dist[v] = dist[u] + graph[u][v]; parent[v] = u; } } } return dist; } private List constructShortestPath(int[] parent, int src, int dest) { LinkedList path = new LinkedList<>(); path.add(dest); while (path.getFirst() != src) { int head = path.getFirst(); if (parent[head] == head) return new LinkedList<>(); path.addFirst(parent[head]); } return path; } } ================================================ FILE: src/graph/README.md ================================================ # Graph Reference: https://www.geeksforgeeks.org/graph-data-structure-and-algorithms/ ## Representations Assume the labels are integers from 0 to n. ### Adjacency Matrix ```java public class GraphInAdjacencyMatrix { int V; int[][] graph; GraphInAdjacencyMatrix(int v) { this.V = v; this.graph = new int[v][v]; } } ``` ### Adjacency List ```java public class GraphInAdjacencyList { int V; List[] graph; GraphInAdjacencyList(int v) { this.V = v; this.graph = new LinkedList[v]; for (int i=0; i()); } } } ``` ### Adjacency Set ```java public class GraphInAdjacencySet { int V; Set[] graph; GraphInAdjacencySet(int v) { this.V = v; this.graph = new HashSet[v]; for (int i=0; i()); } } } ``` ================================================ FILE: src/graph/StrongConnectivity.java ================================================ /** * For Directed Graph. (It is easy for Undirected graph, we can just do a BFS * and DFS starting from any vertex. If BFS or DFS visits all vertices, then * the given undirected graph is connected.) * * References: * https://www.geeksforgeeks.org/strongly-connected-components/ * https://www.geeksforgeeks.org/connectivity-in-a-directed-graph/ * https://www.geeksforgeeks.org/tarjan-algorithm-find-strongly-connected-components/ */ public class StrongConnectivity { // Kosaraju's algorithm public boolean isStronglyConnected(Set[] graph) { if (graph == null) return false; if (graph.length == 0) return true; int len = graph.length; boolean[] visited = new boolean[len]; dfs(graph, 0, visited); for (boolean vz: visited) { if (!vz) return false; } Set[] graphT = transpose(graph); for (int i=0; i[] graph, int i, boolean[] visited) { if (visited[i]) return; visited[i] = true; for (int next: graph[i]) { if (!visited[next]) { dfs(graph, next, visited); } } } private Set[] transpose(Set[] graph) { if (graph == null) return null; if (graph.length == 0) return new Set[0]; int len = graph.length; Set[] newGraph = new Set[len]; for (int i=0; i(); for (int i=0; i> stronglyConnectedComponents(Set[] graph) { if (graph == null) return null; List> res = new ArrayList<>(); if (graph.length == 0) return res; int len = graph.length; boolean[] visited = new boolean[len]; Stack stack = new Stack<>(); for (int i=0; i[] graphT = transpose(graph); for (int i=0; i newC = new HashSet<>(); getComponent(graphT, i, visited, newC); res.add(newC); } } return res; } private void traverseComponent(Set[] graph, int i, boolean[] visited, Stack stack) { if (visited[i]) return; visited[i] = true; for (int next: graph[i]) { if (!visited[next]) { traverseComponent(graph, next, visited, stack); } } stack.add(i); } private void getComponent(Set[] graph, int i, boolean[] visited, Set res) { if (visited[i]) return; visited[i] = true; res.add(i); for (int next: graph[i]) { if (!visited[next]) { getComponent(graph, next, visited, res); } } } } ================================================ FILE: src/graph/TopologicalSort.java ================================================ /** * For Directed Acyclic Graph (DAG) * * References: * https://www.geeksforgeeks.org/topological-sorting/ * https://www.geeksforgeeks.org/topological-sorting-indegree-based-solution/ */ public class TopologicalSort { public List sortByStack(Set[] graph) { if (graph == null || graph.length == 0) return new ArrayList<>(); int len = graph.length; boolean[] visited = new boolean[len]; LinkedList ll = new LinkedList<>(); for (int i=0; i[] graph, int i, int[] visited, LinkedList ll) { if (visited[i]) return; visited[i] = true; for (int j: graph[i]) { if (!visited[j]) { sortByStack(graph, j, visited, stack); } } ll.addFirst(i); } public List sortByIndegree(Set[] graph) { if (graph == null || graph.length == 0) return new ArrayList<>(); int len = graph.length; int[] indegree = new int[len]; for (int i=0; i q = new LinkedList<>(); for (int i=0; i sorted = new ArrayList<>(); int count = 0; while (!q.isEmpty()) { int curr = q.poll(); for (int d: graph[curr]) { indegree[d]--; if (indegree[d] == 0) { q.add(d); } } count++; sorted.add(curr); } if (count != len) return new ArrayList<>(); return sorted; } } ================================================ FILE: src/knapsack/CompleteKnapsack.java ================================================ /** * There are N objects and a bag with capacity of V. Evey type of object can be * used with unlimited number of times. * The ith object is having costs[i] and weights[i]. * Find out which objects can be put into the bag in order to have maximum value. */ public class CompleteKnapsack { /** * dp[i][v] = max{dp[i-1][v], dp[i][v-c[i]] + w[i]} */ public int maxValue(int[] costs, int[] weights, int V) { if (costs == null || weights == null) return 0; int N = costs.length; int[][] dp = new int[N + 1][V + 1]; for (int i=1; i<=N; i++) { for (int v=1; v<=V; v++) { if (v < costs[i-1]) { dp[i][v] = dp[i-1][v]; } else { dp[i][v] = Math.max(dp[i-1][v], dp[i][v - costs[i-1]] + weights[i-1]); } } } return dp[N][V]; } /** * dp[v] = max{dp[v], dp[v-c[i]] + w[i]} */ public int maxValue2(int[] costs, int[] weights, int V) { if (costs == null || weights == null) return 0; int N = costs.length; int[] dp = new int[V + 1]; for (int i=0; i=V // CompletePack(cost,weight) // return // integer k=1 // while k=costs[i]; v--) { dp[v] = Math.max(dp[v], dp[v - costs[i]] + weights[i]); } } return dp[V]; } public static void main(String[] args) { ZeroOneKnapsack slt = new ZeroOneKnapsack(); int[] costs = new int[]{10, 20, 30}; int[] weights = new int[]{60, 100, 120}; System.out.println(slt.maxValue(costs, weights, 50)); System.out.println(slt.maxValue2(costs, weights, 50)); costs = new int[]{10, 20, 30}; weights = new int[]{60, 100, 10}; System.out.println(slt.maxValue(costs, weights, 50)); System.out.println(slt.maxValue2(costs, weights, 50)); costs = new int[]{2, 2, 6, 5, 4}; weights = new int[]{6, 3, 5, 4, 6}; System.out.println(slt.maxValue(costs, weights, 10)); System.out.println(slt.maxValue2(costs, weights, 10)); costs = new int[]{2, 2, 6, 5, 4}; weights = new int[]{6, 3, 10, 4, 6}; System.out.println(slt.maxValue(costs, weights, 10)); System.out.println(slt.maxValue2(costs, weights, 10)); costs = new int[]{5, 5, 5, 5, 4}; weights = new int[]{6, 3, 5, 4, 6}; System.out.println(slt.maxValue(costs, weights, 10)); System.out.println(slt.maxValue2(costs, weights, 10)); costs = new int[]{2, 2, 6, 5, 4}; weights = new int[]{6, 3, 5, 4, 6}; System.out.println(slt.maxValue(costs, weights, 10)); System.out.println(slt.maxValue2(costs, weights, 10)); costs = new int[]{}; weights = new int[]{}; System.out.println(slt.maxValue(costs, weights, 10)); System.out.println(slt.maxValue2(costs, weights, 10)); costs = new int[]{2}; weights = new int[]{2}; System.out.println(slt.maxValue(costs, weights, 2)); System.out.println(slt.maxValue2(costs, weights, 2)); costs = new int[]{2}; weights = new int[]{2}; System.out.println(slt.maxValue(costs, weights, 3)); System.out.println(slt.maxValue2(costs, weights, 3)); costs = new int[]{2}; weights = new int[]{2}; System.out.println(slt.maxValue(costs, weights, 1)); System.out.println(slt.maxValue2(costs, weights, 1)); } // for i=1..N // ZeroOnePack(c[i],w[i]); // procedure ZeroOnePack(cost,weight) // for v=V..cost // f[v]=max{f[v],f[v-cost]+weight} } ================================================ FILE: src/search/BinarySearch.java ================================================ /** * LinearSearch: search a sorted array by resursively dividing the array into half. * * Time complexity: O(Logn). * Space complexity: * - Recursively: O(Logn). * - Iteratively: O(1). * * Every time, compare x with the middle element of the array. * - If x matches with the middle element, return the mid index; * - Else if x is greater than the mid element, go to right half of the array; * - Otherwise, go to the left half. * */ public class BinarySearch { public static int searchRecursively(int arr[], int x) { return binarySearch(arr, 0, arr.length - 1, x); } public static int searchIteratively(int arr[], int x) { return binarySearch(arr, x); } // Recursively public static int binarySearch(int arr[], int l, int r, int x) { if (r >= l) { int mid = l + (r - l)/2; if (arr[mid] == x) return mid; if (arr[mid] > x) return binarySearch(arr, l, mid-1, x); return binarySearch(arr, mid+1, r, x); } return -1; } // Iteratively public static int binarySearch(int arr[], int x) { int l = 0; int r = arr.length - 1; while (l <= r) { int m = l + (r-l)/2; if (arr[m] == x) return m; if (arr[m] > x) { r = m - 1; } else { l = m + 1; } } return -1; } public static void main(String[] args) { int[] arr = {3, 5, 7, 10, 15, 20}; System.out.println(BinarySearch.search(arr, 10)); System.out.println(BinarySearch.search(arr, 1)); } } ================================================ FILE: src/search/ExponentialSearch.java ================================================ /** * ExponentialSearch: 1. Find range where element is present; * 2. Do Binary Search in above found range. * * Time complexity: O(Logn). * Space complexity: * - Recursively: O(Logn). * - Iteratively: O(1). * * * Different from JumpSearch, where every jump is having fixed number of steps, * ExponentialSearch is having jumps with exponentially increasing number of steps. * * The target x will be within the range (i/2, i), where arr[i/2] < x < arr[i]. * */ import java.util.Arrays; public class ExponentialSearch { public static int search(int arr[], int x) { int n = arr.length; if (arr[0] == x) return 0; int i = 1; while (i < n && arr[i] <= x) i *= 2; return Arrays.binarySearch(arr, i/2, Math.min(i, n), x); } public static void main(String[] args) { int[] arr = {3, 5, 7, 10, 15, 20}; System.out.println(ExponentialSearch.search(arr, 10)); System.out.println(ExponentialSearch.search(arr, 1)); } } ================================================ FILE: src/search/InterpolationSearch.java ================================================ /** * InterpolationSearch: search x from a sorted array of n uniformly distributed values. * * Time complexity: * - If elements are uniformly distributed, O(log(logn)); * - Worst case: O(n). * Space complexity: O(1). * * The Interpolation Search is an improvement over Binary Search, where the * values in a sorted array are uniformly distributed. Instead of always going * to the middle element, interpolation search may go to a different location * based on the value of value being searched. For example, if the value is * closer to the last element, interpolation search is likely to start search * toward the end side. * * To find the position to be searched, instead of * mid = l + (r-l)/2 * it uses following formula: * pos = lo + [ (hi-lo) / (arr[hi]-arr[Lo]) * (x-arr[lo])] * */ public class InterpolationSearch { public static int search(int[] arr, int x) { int lo = 0; int hi = arr.length - 1; while (lo <= hi && x >= arr[lo] && x <= arr[hi]) { int pos = lo + (((hi-lo)/(arr[hi]-arr[lo]))*(x-arr[lo])); if (arr[pos] == x) return pos; if (arr[pos] > x) { hi = pos - 1; } else { lo = pos + 1; } } return -1; } public static void main(String[] args) { int[] arr = {3, 5, 7, 10, 15, 20}; System.out.println(InterpolationSearch.search(arr, 10)); System.out.println(InterpolationSearch.search(arr, 1)); } } ================================================ FILE: src/search/JumpSearch.java ================================================ /** * JumpSearch: search from an sorted array by jumping ahead fixed number of steps every time. * * Time complexity: * - O(√n). Between Linear Search O(n) and Binary Search O(Logn). * - Wosrt case: (n/m) + m-1, where n is number of elements, m is number of steps every time. * Space complexity: O(1). * * Start from the leftmost element of the array, and jump m number of elements * every time then compare x with current element. * - If found, return the index; * - Else if current is less than x, keep jumping; * - Else if current is larger than x, do linear search between last element and current one; * - Otherwise, not found, return -1. * */ public class JumpSearch { public static int search(int[] arr, int x) { int n = arr.length; int step = (int)Math.floor(Math.sqrt(n)); int last = 0; int now = step; while (arr[Math.min(now, n)-1] < x) { last = now; now += step; if (last >= n) return -1; } while (arr[last] < x) { last++; if (last == Math.min(now, n)) return -1; } if (arr[last] == x) return last; return -1; } public static void main(String[] args) { int[] arr = {3, 5, 7, 10, 15, 20}; System.out.println(JumpSearch.search(arr, 10)); System.out.println(JumpSearch.search(arr, 1)); } } ================================================ FILE: src/search/LinearSearch.java ================================================ /** * LinearSearch: search an array of int linearly. * * Time complexity: O(n). * Space complexity: O(1). * * Start from the leftmost element of the array and one by one compare x with * each element. * - If found, return the index; * - Otherwise, not found, return -1. * */ public class LinearSearch { public static int search(int arr[], int x) { for (int i = 0; i < arr.length; i++) { if (arr[i] == x) return i; } return -1; } public static void main(String[] args) { int[] arr = {3, 5, 7, 10, 15, 20}; System.out.println(LinearSearch.search(arr, 10)); System.out.println(LinearSearch.search(arr, 1)); } } ================================================ FILE: src/search/README.md ================================================ # search Reference: http://www.geeksforgeeks.org/fundamentals-of-algorithms/#SearchingandSorting ================================================ FILE: src/search/TernarySearch.java ================================================ /** * LinearSearch: search a sorted array by resursively dividing the array into half. * * Time complexity: O(Logn). * Space complexity: * - Recursively: O(Logn). * - Iteratively: O(1). * * Every time, compare x with the middle element of the array. * - If x matches with the middle element, return the mid index; * - Else if x is greater than the mid element, go to right half of the array; * - Otherwise, go to the left half. * */ public class TernarySearch { public static int searchRecursively(int arr[], int x) { return ternarySearch(arr, 0, arr.length - 1, x); } public static int searchIteratively(int arr[], int x) { return ternarySearch(arr, x); } // Recursively public static int ternarySearch(int arr[], int l, int r, int x) { if (r >= l) { int mid1 = l + (r - l)/3; int mid2 = mid1 + (r - l)/3; if (arr[mid1] == x) return mid1; if (arr[mid2] == x) return mid2; if (arr[mid1] > x) return ternarySearch(arr, l, mid1-1, x); if (arr[mid2] < x) return ternarySearch(arr, mid2+1, r, x); return ternarySearch(arr, mid1+1, mid2-1, x); } return -1; } // Iteratively public static int ternarySearch(int arr[], int x) { int l = 0; int r = arr.length - 1; while (l <= r) { int mid1 = l + (r - l)/3; int mid2 = mid1 + (r - l)/3; if (arr[mid1] == x) return mid1; if (arr[mid2] == x) return mid2; if (arr[mid1] > x) { r = mid1 - 1; continue; } if (arr[mid2] < x) { l = mid2 + 1; continue; } } return -1; } public static void main(String[] args) { int[] arr = {3, 5, 7, 10, 15, 20}; System.out.println(TernarySearch.searchIteratively(arr, 10)); System.out.println(TernarySearch.searchIteratively(arr, 1)); } } ================================================ FILE: src/sort/BubbleSort.java ================================================ /** * BubbleSort: sort an array by repeatedly swapping the adjacent elements if * they are in wrong order. * * Worst and Average Case Time Complexity: O(n^2). * Best Case Time Complexity: O(n). * Space Complexity: O(1) * */ import java.util.Arrays; public class BubbleSort { public static void sort(int[] arr) { for (int i = 0; i < arr.length-1; i++) { for (int j = 0; j < arr.length-i-1; j++) if (arr[j] > arr[j+1]) swap(arr, j, j+1); } } public static void sortEarlyStop(int[] arr) { boolean swapped = false; for (int i = 0; i < arr.length-1; i++) { for (int j = 0; j < arr.length-i-1; j++) { if (arr[j] > arr[j+1]) { swap(arr, j, j+1); swapped = true; } } if (swapped == false) break; } } private static void swap(int[] arr, int i, int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } public static void main(String[] args) { int[] arr1 = {10, 3, 7, 5, 1, 15, 20}; BubbleSort.sortEarlyStop(arr1); System.out.println(Arrays.toString(arr1)); int[] arr2 = {}; BubbleSort.sortEarlyStop(arr2); System.out.println(Arrays.toString(arr2)); int[] arr3 = {10}; BubbleSort.sortEarlyStop(arr3); System.out.println(Arrays.toString(arr3)); } } ================================================ FILE: src/sort/BucketSort.java ================================================ /** * BucketSort: mainly sort an array with elements uniformly distributed over a range. * * Worst Case Time Complexity: O(n^2). * Best and Average Case Time Complexity: O(n + k). * Space Complexity: O(n * k). * */ import java.util.Arrays; import java.util.List; import java.util.ArrayList; /** * http://www.growingwiththeweb.com/2015/06/bucket-sort.html */ public class BucketSort { private static final int DEFAULT_BUCKET_SIZE = 5; public static void sort(int[] arr) { bucketSort(arr, DEFAULT_BUCKET_SIZE); } public static void bucketSort(int arr[], int size) { if (arr.length == 0) return; Integer minValue = arr[0]; Integer maxValue = arr[0]; for (int i = 1; i < arr.length; i++) { if (arr[i] < minValue) { minValue = arr[i]; } else if (arr[i] > maxValue) { maxValue = arr[i]; } } int bucketCount = (maxValue - minValue) / size + 1; List> buckets = new ArrayList>(bucketCount); for (int i = 0; i < bucketCount; i++) { buckets.add(new ArrayList()); } for (int i = 0; i < arr.length; i++) { buckets.get((arr[i] - minValue) / size).add(arr[i]); } int currentIndex = 0; for (int i = 0; i < buckets.size(); i++) { Integer[] bucketArray = new Integer[buckets.get(i).size()]; bucketArray = buckets.get(i).toArray(bucketArray); InsertionSort.sort(bucketArray); for (int j = 0; j < bucketArray.length; j++) { arr[currentIndex++] = bucketArray[j]; } } } public static void main(String[] args) { int[] arr1 = {10, 3, 7, 5, 1, 15, 20}; BucketSort.sort(arr1); System.out.println(Arrays.toString(arr1)); int[] arr2 = {}; BucketSort.sort(arr2); System.out.println(Arrays.toString(arr2)); int[] arr3 = {10}; BucketSort.sort(arr3); System.out.println(Arrays.toString(arr3)); } } ================================================ FILE: src/sort/CountingSort.java ================================================ /** * CountingSort: sort an array based on keys between a specific range. It works * by counting the number of objects having distinct key values, and based on * the counts, calculate the position of each element in the output array. * * It only works if you already know the range (of the distinct elements) of * your input array. * * Time Complexity: O(n+k). * Space Complexity: O(n+k). * * n is the number of elements in input array and k is the range of input. * * The following implementation is only working on non-negative keys. * */ import java.util.Arrays; public class CountingSort { public static void sort(int arr[], int range) { int n = arr.length; int output[] = new int[n]; final int R = range; int count[] = new int[R]; for (int i=0; i=0; i--) { output[count[arr[i]]-1] = arr[i]; --count[arr[i]]; } for (int i = 0; i= 0; i--) heapify(arr, n, i); for (int i=n-1; i>=0; i--) { swap(arr, 0, i); heapify(arr, i, 0); } } private static void heapify(int arr[], int n, int i) { int largest = i; int l = 2*i + 1; int r = 2*i + 2; if (l < n && arr[l] > arr[largest]) largest = l; if (r < n && arr[r] > arr[largest]) largest = r; if (largest != i) { swap(arr, i, largest); heapify(arr, n, largest); } } private static void swap(int[] nums, int i, int j) { int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; } public static void main(String[] args) { int[] arr1 = {10, 3, 7, 5, 20, 15, 1}; HeapSort.sort(arr1); System.out.println(Arrays.toString(arr1)); int[] arr2 = {}; HeapSort.sort(arr2); System.out.println(Arrays.toString(arr2)); int[] arr3 = {10}; HeapSort.sort(arr3); System.out.println(Arrays.toString(arr3)); } } ================================================ FILE: src/sort/InsertionSort.java ================================================ /** * InsertionSort: for every element in the array, insert it into sorted sequence iteratively. * * Time Complexity: O(n^2). * Space Complexity: O(1). * */ import java.util.Arrays; public class InsertionSort { public static void sort(int[] arr) { for (int i=1; i < arr.length; i++) { int curr = arr[i]; int j = i-1; while (j >= 0 && arr[j] > curr) { arr[j+1] = arr[j]; j--; } arr[j+1] = curr; } } public static void sort(Integer[] arr) { for (int i=1; i < arr.length; i++) { int curr = arr[i]; int j = i-1; while (j >= 0 && arr[j] > curr) { arr[j+1] = arr[j]; j--; } arr[j+1] = curr; } } public static void main(String[] args) { int[] arr1 = {10, 3, 7, 5, 1, 15, 20}; InsertionSort.sort(arr1); System.out.println(Arrays.toString(arr1)); int[] arr2 = {}; InsertionSort.sort(arr2); System.out.println(Arrays.toString(arr2)); int[] arr3 = {10}; InsertionSort.sort(arr3); System.out.println(Arrays.toString(arr3)); } } ================================================ FILE: src/sort/MergeSort.java ================================================ /** * MergeSort: It divides input array in two halves, calls itself for the two * halves and then merges the two sorted halves. * * Time Complexity: O(nLogn) in all 3 cases (worst, average and best). * Space Complexity: O(n). * */ import java.util.Arrays; public class MergeSort { public static void sort(int[] arr) { mergeSort(arr, 0, arr.length-1); // int[] helper = new int[arr.length]; // mergeSort(arr, helper, 0, arr.length-1); } private static void mergeSort(int[] arr, int l, int r) { if (l >= r) return; int m = (l+r)/2; mergeSort(arr, l, m); mergeSort(arr, m+1, r); merge(arr, l, m, r); } private static void merge(int[] arr, int l, int m, int r) { int len1 = m - l + 1; int len2 = r - m; int L[] = new int [len1]; int R[] = new int [len2]; for (int i=0; i < len1; i++) L[i] = arr[l + i]; for (int j=0; j < len2; j++) R[j] = arr[m + 1 + j]; int i = 0; int j = 0; int k = l; while (i < len1 && j < len2) { if (L[i] <= R[j]) { arr[k] = L[i]; i++; } else { arr[k] = R[j]; j++; } k++; } while (i < len1) { arr[k] = L[i]; i++; k++; } while (j < len2) { arr[k] = R[j]; j++; k++; } } // private static void mergeSort(int[] arr, int[] helper, int l, int r) { if (l >= r) return; int m = (l+r)/2; mergeSort(arr, helper, l, m); mergeSort(arr, helper, m+1, r); merge(arr, helper, l, m, r); } private static void merge(int[] arr, int[] helper, int l, int m, int r) { for (int i = l; i <= r; i++) { helper[i] = arr[i]; } int i = l; int j = m + 1; int k = l; while (i <= m && j <= r) { if (helper[i] <= helper[j]) { arr[k] = helper[i]; i++; } else { arr[k] = helper[j]; j++; } k++; } while (i <= m) { arr[k] = helper[i]; k++; i++; } } public static void main(String[] args) { int[] arr1 = {10, 3, 7, 5, 20, 15, 1}; MergeSort.sort(arr1); System.out.println(Arrays.toString(arr1)); int[] arr2 = {}; MergeSort.sort(arr2); System.out.println(Arrays.toString(arr2)); int[] arr3 = {10}; MergeSort.sort(arr3); System.out.println(Arrays.toString(arr3)); } } ================================================ FILE: src/sort/QuickSort.java ================================================ /** * QuickSort: every time, it picks one element as a pivot and partitions the * array to two parts, where the elements of the first part before pivot are * always less or equal to the pivot, and the elements of the second part after. * * Worst Case Time Complexity: O(n^2). * Best and Average Case Time Complexity: O(nlogn). * Space Complexity: O(n). * * Different ways of picking the pivot: * * - Always pick first element as pivot. * - Always pick last element as pivot (implemented below) * - Pick a random element as pivot. * - Pick median as pivot. * */ import java.util.Arrays; public class QuickSort { public static void sortRecursively(int[] nums) { quickSortRecursively(nums, 0, nums.length - 1); } public static void sortIteratively(int[] nums) { if (nums.length == 0 || nums.length == 1) return; quickSortIteratively(nums, 0, nums.length - 1); } private static void quickSortRecursively(int[] nums, int left, int right) { if (left >= right) return; int p = partition(nums, left, right); quickSortRecursively(nums, left, p - 1); quickSortRecursively(nums, p + 1, right); } private static void quickSortIteratively(int arr[], int l, int h) { int stack[] = new int[h-l+1]; int top = -1; stack[++top] = l; stack[++top] = h; while (top >= 0) { h = stack[top--]; l = stack[top--]; int p = partition(arr, l, h); if (p-1 > l) { stack[++top] = l; stack[++top] = p - 1; } if (p+1 < h) { stack[++top] = p + 1; stack[++top] = h; } } } private static int partition(int[] nums, int left, int right) { int pivot = nums[right]; int i = (left - 1); for (int j = left; j < right; j++) { if (nums[j] <= pivot) { i++; swap(nums, i, j); } } swap(nums, i+1, right); return (i + 1); } private static int partition2(int[] nums, int left, int right) { int pivot = nums[right]; int i = left; for (int j=left; j pivot) j--; if (i >= j) break; swap(nums, i, j); } swap(nums, left, j); return j; } private static void swap(int[] nums, int i, int j) { int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; } public static void main(String[] args) { int[] arr1 = {10, 3, 7, 5, 20, 15, 1}; QuickSort.sortIteratively(arr1); System.out.println(Arrays.toString(arr1)); int[] arr2 = {}; QuickSort.sortIteratively(arr2); System.out.println(Arrays.toString(arr2)); int[] arr3 = {10}; QuickSort.sortIteratively(arr3); System.out.println(Arrays.toString(arr3)); } } ================================================ FILE: src/sort/README.md ================================================ # sort Reference: http://www.geeksforgeeks.org/fundamentals-of-algorithms/#SearchingandSorting ================================================ FILE: src/sort/RadixSort.java ================================================ /** * RadixSort: sort an array of integers digit by digit sort starting from least * significant digit to most significant digit. For every single digit, counting * sort is considered. * * Time Complexity: O(wn) for n keys which are integers of word size w. * Space Complexity: O(w + N). * */ import java.util.Arrays; public class RadixSort { public static void sort(int[] arr) { radixSort(arr, arr.length); } private static void radixSort(int arr[], int n) { int m = getMax(arr, n); for (int exp = 1; m/exp > 0; exp *= 10) countSort(arr, n, exp); } private static int getMax(int arr[], int n) { int mx = arr[0]; for (int i = 1; i < n; i++) { if (arr[i] > mx) mx = arr[i]; } return mx; } private static void countSort(int arr[], int n, int exp) { int output[] = new int[n]; int i; int count[] = new int[10]; for (i = 0; i < n; i++) count[ (arr[i]/exp)%10 ]++; for (i = 1; i < 10; i++) count[i] += count[i-1]; for (i = n - 1; i >= 0; i--) { output[count[ (arr[i]/exp)%10 ] - 1] = arr[i]; count[ (arr[i]/exp)%10 ]--; } for (i = 0; i < n; i++) arr[i] = output[i]; } public static void main(String[] args) { int[] arr1 = {10, 3, 7, 5, 20, 15, 1}; MergeSort.sort(arr1); System.out.println(Arrays.toString(arr1)); int[] arr2 = {}; MergeSort.sort(arr2); System.out.println(Arrays.toString(arr2)); int[] arr3 = {10}; MergeSort.sort(arr3); System.out.println(Arrays.toString(arr3)); } } ================================================ FILE: src/sort/SelectionSort.java ================================================ /** * SelectionSort: sorts an array by repeatedly finding the minimum element from * unsorted part and putting it at the beginning. * * Time Complexity: O(n^2). * Space Complexity: O(1). * */ import java.util.Arrays; public class SelectionSort { public static void sort(int[] arr) { for (int i=0; i < arr.length-1; i++) { int minIndex = i; for (int j = i+1; j < arr.length-1; j++) { if (arr[j] < arr[minIndex]) minIndex = j; } swap(arr, i, minIndex); } } private static void swap(int[] arr, int i, int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } public static void main(String[] args) { int[] arr1 = {10, 3, 7, 5, 1, 15, 20}; SelectionSort.sort(arr1); System.out.println(Arrays.toString(arr1)); int[] arr2 = {}; SelectionSort.sort(arr2); System.out.println(Arrays.toString(arr2)); int[] arr3 = {10}; SelectionSort.sort(arr3); System.out.println(Arrays.toString(arr3)); } }