├── Array ├── AsteroidCollision.swift ├── CanPlaceFlowers.swift ├── CheckArrayFormationThroughConcatenation.swift ├── ContainsDuplicate.swift ├── ContainsDuplicateII.swift ├── CreateMaximumNumber.swift ├── DiagonalTraverse.swift ├── ExamRoom.swift ├── FindDisappearedNumbers.swift ├── FirstMissingPositive.swift ├── FourSum.swift ├── GameLife.swift ├── GasStation.swift ├── Heaters.swift ├── IncreasingTripletSubsequence.swift ├── IntersectionTwoArrays.swift ├── IntersectionTwoArraysII.swift ├── IslandPerimeter.swift ├── LongestConsecutiveSequence.swift ├── MajorityElement.swift ├── MajorityElementII.swift ├── MaxConsecutiveOnes.swift ├── MaxNumberOfK-SumPairs.swift ├── MaximizeDistanceToClosestPerson.swift ├── MaximumSizeSubarraySumEqualsK.swift ├── MinimumSizeSubarraySum.swift ├── MissingRanges.swift ├── MoveZeroes.swift ├── NextPermutation.swift ├── NumMatrix.swift ├── NumberBoomerangs.swift ├── ProductExceptSelf.swift ├── RemoveDuplicatesFromSortedArray.swift ├── RemoveDuplicatesFromSortedArrayII.swift ├── RemoveElement.swift ├── RotateArray.swift ├── RotateImage.swift ├── SetMatrixZeroes.swift ├── ShortestWordDistance.swift ├── ShortestWordDistanceII.swift ├── ShortestWordDistanceIII.swift ├── SlidingWindowMaximum.swift ├── SmallestRange.swift ├── SortArrayByParity.swift ├── SpiralMatrix.swift ├── SpiralMatrixII.swift ├── StrobogrammaticNumber.swift ├── SummaryRanges.swift ├── TaskScheduler.swift ├── ThreeSum.swift ├── ThreeSumClosest.swift ├── TwoSum.swift ├── TwoSumII.swift ├── TwoSumIII.swift ├── TwoSumLessThanK.swift ├── ValidSudoku.swift ├── ValidateIPAddress.swift └── VerifyingAlienDictionary.swift ├── BFS ├── EvaluateDivision.swift ├── JumpGameIV.swift ├── ShortestDistanceAllBuildings.swift └── WordLadder.swift ├── DFS ├── BeautifulArrangement.swift ├── CombinationSum.swift ├── CombinationSumII.swift ├── CombinationSumIII.swift ├── Combinations.swift ├── CourseSchedule.swift ├── CourseScheduleII.swift ├── ExpressionAddOperators.swift ├── FactorCombinations.swift ├── GeneralizedAbbreviation.swift ├── IsGraphBipartite.swift ├── LetterCombinationsPhoneNumber.swift ├── NQueens.swift ├── NQueensII.swift ├── NumberofIslands.swift ├── PalindromePartitioning.swift ├── PartitionKEqualSumSubsets.swift ├── Permutations.swift ├── PermutationsII.swift ├── RemoveInvalidParentheses.swift ├── StrobogrammaticNumberII.swift ├── Subsets.swift ├── SubsetsII.swift ├── SudokuSolver.swift ├── WallsGates.swift ├── WordDictionary.swift ├── WordPatternII.swift ├── WordSearch.swift ├── WordSearchII.swift └── WordSquares.swift ├── DP ├── BestTimeBuySellStock.swift ├── BestTimeBuySellStockCooldown.swift ├── BestTimeBuySellStockII.swift ├── BestTimeBuySellStockIII.swift ├── BestTimeBuySellStockIV.swift ├── BoatsToSavePeople.swift ├── BurstBalloons.swift ├── CanIWin.swift ├── ClimbingStairs.swift ├── CoinChange.swift ├── CoinChangeII.swift ├── CombinationSumIV.swift ├── CountSortedVowelStrings.swift ├── DecodeWays.swift ├── DifferentWaysAddParentheses.swift ├── DungeonGame.swift ├── EditDistance.swift ├── FlipGameII.swift ├── FrogJump.swift ├── GenerateParentheses.swift ├── GuessNumberHigherOrLowerII.swift ├── HouseRobber.swift ├── HouseRobberII.swift ├── JumpGame.swift ├── LongestIncreasingSubsequence.swift ├── LongestPalindromicSubstring.swift ├── MaximalSquare.swift ├── MaximumProductSubarray.swift ├── MaximumSubarray.swift ├── MaximumSumThreeNonOverlappingSubarrays.swift ├── MinCostClimbingStairs.swift ├── MinimumOperationsToReduceXToZero.swift ├── MinimumPathSum.swift ├── MinimumWindowSubsequence.swift ├── NestedListWeightSum.swift ├── NestedListWeightSumII.swift ├── PaintFence.swift ├── PaintHouse.swift ├── PaintHouseII.swift ├── PalindromicSubstrings.swift ├── PerfectSquares.swift ├── RegularExpressionMatching.swift ├── Triangle.swift ├── UniquePaths.swift ├── UniquePathsII.swift ├── WiggleSubsequence.swift └── WildcardMatching.swift ├── Design ├── AddSearchWord.swift ├── AllOne.swift ├── DesignHashMap.swift ├── DesignTicTacToe.swift ├── FlattenNestedListIterator.swift ├── ImplementTrie.swift ├── InsertDeleteGetRandom.swift ├── LRUCache.swift ├── ShuffleAnArray.swift └── Vector2D.swift ├── Graph ├── AlienDictionary.swift ├── CourseSchedule.swift ├── CourseScheduleII.swift ├── GraphValidTree.swift ├── NumberConnectedComponentsUndirectedGraph.swift └── NumberIslandsII.swift ├── Leetcode_Contributors.png ├── License.md ├── LinkedList ├── LFUCache.swift ├── LRUCache.swift ├── MergeKSortedLists.swift ├── MergeTwoSortedLists.swift ├── OddEvenLinkedList.swift ├── PalindromeLinkedList.swift ├── PartitionList.swift ├── PseudoPalindromicPathsInABinaryTree.swift ├── RemoveDuplicatesFromSortedList.swift ├── RemoveDuplicatesFromSortedListII.swift ├── RemoveLinkedListElements.swift ├── RemoveNthFromEnd.swift ├── ReorderList.swift ├── ReverseLinkedList.swift ├── ReverseNodesInKGroup.swift ├── RotateList.swift └── SwapNodesInPairs.swift ├── Math ├── AddBinary.swift ├── AddDigits.swift ├── AddTwoNumbers.swift ├── Atoi.swift ├── ContainerMostWater.swift ├── CountPrimes.swift ├── CountingBits.swift ├── DivideTwoIntegers.swift ├── ExcelSheetColumnNumber.swift ├── FactorialTrailingZeroes.swift ├── FractionToRecurringDecimal.swift ├── GaryCode.swift ├── HammingDistance.swift ├── HappyNumber.swift ├── IntegerBreak.swift ├── IntegerEnglishWords.swift ├── IntegerToRoman.swift ├── KthSmallestLexicographicalOrder.swift ├── LineReflection.swift ├── MinimumMovesEqualArrayElements.swift ├── MissingNumber.swift ├── NumberComplement.swift ├── PalindromeNumber.swift ├── PermutationSequence.swift ├── PlusOne.swift ├── Pow.swift ├── PowerThree.swift ├── PowerTwo.swift ├── ReachANumber.swift ├── RectangleArea.swift ├── ReverseInteger.swift ├── RomanToInteger.swift ├── SingleNumber.swift ├── SingleNumberII.swift ├── SparseMatrixMultiplication.swift ├── SudokuSolver.swift ├── SumTwoIntegers.swift ├── SuperPow.swift ├── SuperUglyNumber.swift ├── TrappingRainWater.swift ├── UglyNumber.swift ├── UglyNumberII.swift └── ValidNumber.swift ├── Queue └── ImplementQueueUsingStacks.swift ├── README.md ├── Search ├── ClosestBinarySearchTreeValue.swift ├── ClosestBinarySearchTreeValueII.swift ├── FindMinimumRotatedSortedArray.swift ├── FindMinimumRotatedSortedArrayII.swift ├── FindPeakElement.swift ├── MedianOfTwoSortedArrays.swift ├── MedianTwoSortedArrays.swift ├── MinimizeMaxDistanceGasStation.swift ├── PeakIndexMountainArray.swift ├── RandomPickWeight.swift ├── Search2DMatrix.swift ├── Search2DMatrixII.swift ├── SearchForARange.swift ├── SearchInRotatedSortedArray.swift ├── SearchInRotatedSortedArrayII.swift ├── SearchInsertPosition.swift └── Sqrtx.swift ├── Sort ├── ArrayPartitionI.swift ├── InsertInterval.swift ├── KthLargestElementInArray.swift ├── LargestNumber.swift ├── MeetingRooms.swift ├── MeetingRoomsII.swift ├── MergeIntervals.swift ├── MergeSortedArray.swift ├── SortColors.swift ├── SortTransformedArray.swift ├── TopKFrequentElements.swift ├── WiggleSort.swift └── WiggleSortII.swift ├── Stack ├── BasicCalculator.swift ├── BinarySearchTreeIterator.swift ├── DecodeString.swift ├── EvaluateReversePolishNotation.swift ├── ExclusiveTimeFunctions.swift ├── InorderTraversal.swift ├── LargestRectangleInHistogram.swift ├── LongestValidParentheses.swift ├── MaxStack.swift ├── MinStack.swift ├── PostorderTraversal.swift ├── PreorderTraversal.swift ├── RemoveKDigits.swift ├── SimplifyPath.swift ├── TernaryExpressionParser.swift └── ValidParentheses.swift ├── String ├── AddStrings.swift ├── CountAndSay.swift ├── DetectCapital.swift ├── DetermineIfTwoStringsAreClose.swift ├── FindAllAnagramsInAString.swift ├── FindClosestPalindrome.swift ├── FindDuplicateFileInSystem.swift ├── FirstUniqueCharacterInString.swift ├── FizzBuzz.swift ├── FlipGame.swift ├── GroupAnagrams.swift ├── IsomorphicStrings.swift ├── KeyboardRow.swift ├── LengthLastWord.swift ├── LongestCommonPrefix.swift ├── LongestSubstringMostKDistinctCharacters.swift ├── LongestSubstringMostTwoDistinctCharacters.swift ├── LongestSubstringWithoutRepeatingCharacters.swift ├── MinimumWindowSubstring.swift ├── MultiplyStrings.swift ├── OneEditDistance.swift ├── PalindromePermutation.swift ├── PermutationInString.swift ├── RansomNote.swift ├── RegularExpressionMatching.swift ├── ReverseString.swift ├── ReverseStringII.swift ├── ReverseVowelsOfAString.swift ├── ReverseWordsString.swift ├── ReverseWordsStringII.swift ├── ReverseWordsStringIII.swift ├── ShortestDistanceToACharacter.swift ├── StrStr.swift ├── StringCompression.swift ├── TextJustification.swift ├── ValidAnagram.swift ├── ValidPalindrome.swift ├── ValidPalindromeII.swift ├── ValidWordAbbreviation.swift ├── WordPattern.swift └── ZigZagConverstion.swift ├── Tree ├── BalancedBinaryTree.swift ├── BinaryTreeLevelOrderTraversal.swift ├── BinaryTreeLevelOrderTraversalII.swift ├── BinaryTreeMaximumPathSum.swift ├── BinaryTreePaths.swift ├── BinaryTreeRightSideView.swift ├── BinaryTreeUpsideDown.swift ├── BinaryTreeVerticalOrderTraversal.swift ├── BinaryTreeZigzagLevelOrderTraversal.swift ├── ConstructBinaryTreeInorderPostorder.swift ├── ConstructBinaryTreePreorderInorder.swift ├── ConvertSortedArrayBinarySearchTree.swift ├── DiameterBinaryTree.swift ├── FlattenBinaryTreeLinkedList.swift ├── HouseRobberIII.swift ├── InvertBinaryTree.swift ├── KthSmallestElementBST.swift ├── MaximumDepthOfBinaryTree.swift ├── MergeTwoBinaryTrees.swift ├── MinimumDepthOfBinaryTree.swift ├── PathSum.swift ├── PathSumII.swift ├── PathSumIII.swift ├── RecoverBinarySearchTree.swift ├── SameTree.swift ├── SerializeDeserializeBinaryTree.swift ├── SerializeDeserializeNAryTree.swift ├── SumLeftLeaves.swift ├── SymmetricTree.swift ├── UniqueBinarySearchTrees.swift └── ValidateBinarySearchTree.swift └── logo.png /Array/CheckArrayFormationThroughConcatenation.swift: -------------------------------------------------------------------------------- 1 | class Solution { 2 | func canFormArray(_ arr: [Int], _ pieces: [[Int]]) -> Bool { 3 | var map = pieces.reduce(into: [Int:[Int]]()) { $0[arr.firstIndex(of: $1[0]) ?? 0] = $1 } 4 | var smap = Array(map.sorted { $0.0 < $1.0 }.flatMap{ $0.1 }) 5 | 6 | return arr.hashValue == smap.hashValue 7 | } 8 | } -------------------------------------------------------------------------------- /Array/ContainsDuplicate.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/contains-duplicate/ 3 | * Primary idea: traverse the array and use a set to check duplicates 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class ContainsDuplicate { 10 | func containsDuplicate(nums: [Int]) -> Bool { 11 | return nums.count > Set(nums).count 12 | } 13 | } -------------------------------------------------------------------------------- /Array/ContainsDuplicateII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/contains-duplicate-ii/ 3 | * Primary idea: use a dictionary to check duplicates, then judge if their distance is less than k 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class ContainsDuplicateII { 10 | func containsNearbyDuplicate(_ nums: [Int], _ k: Int) -> Bool { 11 | guard nums.count > 1 else { 12 | return false 13 | } 14 | 15 | var numToLastIndex = [Int: Int]() 16 | 17 | for (i, num) in nums.enumerated() { 18 | if let lastIndex = numToLastIndex[num], i - lastIndex <= k { 19 | return true 20 | } else { 21 | numToLastIndex[num] = i 22 | } 23 | } 24 | 25 | return false 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Array/DiagonalTraverse.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/diagonal-traverse/ 3 | * Primary idea: use sum to track matrix index, note to set lower and upper bound to avoid duplicates 4 | * 5 | * Time Complexity: O(mn), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class DiagonalTraverse { 10 | func findDiagonalOrder(_ matrix: [[Int]]) -> [Int] { 11 | var res = [Int]() 12 | 13 | guard matrix.count > 0 && matrix[0].count > 0 else { 14 | return res 15 | } 16 | 17 | let m = matrix.count, n = matrix[0].count 18 | var fromTop = false 19 | 20 | for sum in 0...m + n - 2 { 21 | if fromTop { 22 | for i in max(sum - n + 1, 0)...min(m - 1, sum) { 23 | res.append(matrix[i][sum - i]) 24 | } 25 | } else { 26 | for i in (max(sum - n + 1, 0)...min(m - 1, sum)).reversed() { 27 | res.append(matrix[i][sum - i]) 28 | } 29 | } 30 | 31 | fromTop = !fromTop 32 | } 33 | 34 | return res 35 | } 36 | } -------------------------------------------------------------------------------- /Array/FindDisappearedNumbers.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/find-all-numbers-disappeared-in-an-array/ 3 | * primary idea: Traverse the array and get num really position in array, then set negative. 4 | * In the final, filter greater than 0 num. 5 | * 6 | * Time Complexity: O(n), Space Complexity: O(1) 7 | * 8 | */ 9 | 10 | class FindDisappearedNumbers { 11 | func findDisappearedNumbers(_ nums: [Int]) -> [Int] { 12 | var nums = nums 13 | var result = [Int]() 14 | 15 | for i in 0.. 0 { 18 | nums[index] = -nums[index] 19 | } 20 | } 21 | 22 | for i in 0.. 0 { 24 | result.append(i+1) 25 | } 26 | } 27 | 28 | return result 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Array/FirstMissingPositive.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/first-missing-positive/ 3 | * Primary idea: Use a set to hold number in the array and iterate through 1...nums.count to find the missing one 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | * 6 | */ 7 | 8 | class FirstMissingPositive { 9 | func firstMissingPositive(_ nums: [Int]) -> Int { 10 | let set = Set(nums) 11 | 12 | for i in 0.. Int { 12 | let totalGas = gas.reduce(0) { $0 + $1 }, totalCost = cost.reduce(0) { $0 + $1 } 13 | guard totalGas >= totalCost else { 14 | return -1 15 | } 16 | 17 | var start = 0, gasSum = 0, costSum = 0 18 | 19 | for (i, currentGas) in gas.enumerated() { 20 | let currentCost = cost[i] 21 | 22 | gasSum += currentGas 23 | costSum += currentCost 24 | 25 | if gasSum < costSum { 26 | start = i + 1 27 | gasSum = 0 28 | costSum = 0 29 | } 30 | } 31 | 32 | return start 33 | } 34 | } -------------------------------------------------------------------------------- /Array/Heaters.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/heaters/ 3 | * Primary idea: Two pointers, get the closest heater for the house, and update radius 4 | * Time Complexity: O(nlogn), Space Complexity: O(1) 5 | * 6 | */ 7 | 8 | class Heaters { 9 | func findRadius(_ houses: [Int], _ heaters: [Int]) -> Int { 10 | var i = 0, radius = 0 11 | let houses = houses.sorted(), heaters = heaters.sorted() 12 | 13 | for house in houses { 14 | while i < heaters.count - 1 && 2 * house >= heaters[i] + heaters[i + 1] { 15 | i += 1 16 | } 17 | 18 | radius = max(radius, abs(house - heaters[i])) 19 | } 20 | 21 | return radius 22 | } 23 | } -------------------------------------------------------------------------------- /Array/IncreasingTripletSubsequence.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/increasing-triplet-subsequence/ 3 | * Primary idea: Two pointers. One is to store the smallest value, 4 | * the other is to store the second smallest value. 5 | * Return true once find a value greater than both. 6 | * Time Complexity: O(n), Space Complexity: O(1) 7 | */ 8 | 9 | class IncreasingTripletSubsequence { 10 | func increasingTriplet(_ nums: [Int]) -> Bool { 11 | var smallest = Int.max, smaller = Int.max 12 | 13 | for num in nums { 14 | if smallest >= num { 15 | smallest = num 16 | } else if smaller >= num { 17 | smaller = num 18 | } else { 19 | return true 20 | } 21 | } 22 | 23 | return false 24 | } 25 | } -------------------------------------------------------------------------------- /Array/IntersectionTwoArrays.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/intersection-of-two-arrays/ 3 | * Primary idea: Use set to hold numbers for one array and iterate the other one to output result, 4 | * remove the number from set to avoid duplicates. 5 | * 6 | * Note: Do not use built-in intersection function for Set in Swift, that is not this question is asking for. 7 | * 8 | * Time Complexity: O(n), Space Complexity: O(n) 9 | * 10 | */ 11 | 12 | class IntersectionTwoArrays { 13 | func intersection(_ nums1: [Int], _ nums2: [Int]) -> [Int] { 14 | var set = Set(nums1), res = [Int]() 15 | 16 | for num in nums2 where set.contains(num) { 17 | res.append(num) 18 | set.remove(num) 19 | } 20 | 21 | return res 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Array/IntersectionTwoArraysII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/intersection-of-two-arrays-ii/ 3 | * Primary idea: Use dictionary to get frequencies of elements of one array, and 4 | * compare with another array to filter the intersection 5 | * Note: Set cannot help you to find the number of common elements; thus it is not effective 6 | * 7 | * Time Complexity: O(n), Space Complexity: O(n) 8 | * 9 | */ 10 | 11 | class IntersectionTwoArraysII { 12 | func intersect(_ nums1: [Int], _ nums2: [Int]) -> [Int] { 13 | var numsFreq = Dictionary(nums1.map { ($0, 1) }, uniquingKeysWith: +) 14 | var res = [Int]() 15 | 16 | for num in nums2 { 17 | if let freq = numsFreq[num], freq > 0 { 18 | res.append(num) 19 | numsFreq[num] = freq - 1 20 | } 21 | } 22 | 23 | return res 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Array/IslandPerimeter.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/island-perimeter/ 3 | * Primary idea: Go through the matrix and check right and down neighbors. 4 | * Time Complexity: O(nm), Space Complexity: O(1) 5 | * 6 | */ 7 | 8 | class IslandPerimeter { 9 | func islandPerimeter(_ grid: [[Int]]) -> Int { 10 | var islands = 0, neighbors = 0 11 | 12 | for i in 0 ..< grid.count { 13 | for j in 0 ..< grid[0].count { 14 | if grid[i][j] == 1 { 15 | islands += 1 16 | if i < grid.count - 1 && grid[i + 1][j] == 1 { 17 | neighbors += 1 18 | } 19 | if (j < grid[0].count - 1 && grid[i][j + 1] == 1) { 20 | neighbors += 1 21 | } 22 | } 23 | } 24 | } 25 | 26 | return islands * 4 - neighbors * 2 27 | } 28 | } -------------------------------------------------------------------------------- /Array/LongestConsecutiveSequence.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/longest-consecutive-sequence/ 3 | * Primary idea: Iterate the array and check all neighbor numbers with the help of set 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class LongestConsecutiveSequence { 10 | func longestConsecutive(_ nums: [Int]) -> Int { 11 | var set = Set(nums), longest = 0 12 | 13 | for num in nums { 14 | var currentLength = 1 15 | dfs(num, &set, &longest, ¤tLength) 16 | } 17 | 18 | return longest 19 | } 20 | 21 | private func dfs(_ num: Int, _ set: inout Set, _ longest: inout Int, _ length: inout Int) { 22 | if !set.contains(num) { 23 | return 24 | } 25 | 26 | longest = max(longest, length) 27 | set.remove(num) 28 | length += 1 29 | 30 | dfs(num + 1, &set, &longest, &length) 31 | dfs(num - 1, &set, &longest, &length) 32 | } 33 | } -------------------------------------------------------------------------------- /Array/MajorityElement.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/majority-element/ 3 | * Primary idea: traverse the array and track the majority element accordingly 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class MajorityElement { 10 | func majorityElement(_ nums: [Int]) -> Int { 11 | var count = 0, candidate = 0 12 | 13 | for num in nums { 14 | if count == 0 { 15 | candidate = num 16 | } 17 | 18 | count += (candidate == num) ? 1 : -1 19 | } 20 | 21 | return candidate 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Array/MaxConsecutiveOnes.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/max-consecutive-ones/ 3 | * Primary idea: Iterate the whole array and summarize consective ones locally and update globally encountering 0 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | * 6 | */ 7 | 8 | class MaxConsecutiveOnes { 9 | func findMaxConsecutiveOnes(_ nums: [Int]) -> Int { 10 | var globalMax = 0, localMax = 0 11 | 12 | for num in nums { 13 | if num == 1 { 14 | localMax += 1 15 | globalMax = max(globalMax, localMax) 16 | } else { 17 | localMax = 0 18 | } 19 | } 20 | 21 | return globalMax 22 | } 23 | } -------------------------------------------------------------------------------- /Array/MaxNumberOfK-SumPairs.swift: -------------------------------------------------------------------------------- 1 | class Solution { 2 | func maxOperations(_ nums: [Int], _ k: Int) -> Int { 3 | var rest = [Int: Int]() 4 | var result = 0 5 | for num in nums { 6 | if let count = rest[k-num], count > 0 { 7 | rest[k-num] = count-1 8 | result += 1 9 | } else { 10 | rest[num, default: 0] += 1 11 | } 12 | } 13 | 14 | return result 15 | } 16 | } -------------------------------------------------------------------------------- /Array/MaximizeDistanceToClosestPerson.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/maximize-distance-to-closest-person/ 3 | * Primary idea: Calculate and compare middle point between two taken seats. 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class MaximizeDistanceToClosestPerson { 10 | func maxDistToClosest(_ seats: [Int]) -> Int { 11 | var lastOne = -1, maxDistance = 0 12 | 13 | for (i, seat) in seats.enumerated() { 14 | if seat == 1 { 15 | if lastOne == -1 { 16 | maxDistance = max(maxDistance, i) 17 | } else { 18 | maxDistance = max(maxDistance, (i - lastOne) / 2) 19 | } 20 | 21 | lastOne = i 22 | } 23 | } 24 | 25 | // edge case: only one sitting person 26 | maxDistance = max(maxDistance, seats.count - lastOne - 1) 27 | 28 | return maxDistance 29 | } 30 | } -------------------------------------------------------------------------------- /Array/MaximumSizeSubarraySumEqualsK.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/maximum-size-subarray-sum-equals-k/ 3 | * Primary idea: Use a dictionary to track the sum so far since the first until the current 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | */ 6 | 7 | class MaximumSizeSubarraySumEqualsK { 8 | func maxSubArrayLen(_ nums: [Int], _ k: Int) -> Int { 9 | var longestLen = 0, sum = 0, sumToIdx = [Int: Int]() 10 | sumToIdx[0] = -1 11 | 12 | for (i, num) in nums.enumerated() { 13 | sum += num 14 | 15 | if let idx = sumToIdx[sum - k] { 16 | longestLen = max(longestLen, i - idx) 17 | } 18 | 19 | guard let idx = sumToIdx[sum] else { 20 | sumToIdx[sum] = i 21 | continue 22 | } 23 | } 24 | 25 | return longestLen 26 | } 27 | } -------------------------------------------------------------------------------- /Array/MinimumSizeSubarraySum.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/minimum-size-subarray-sum/ 3 | * Primary idea: Two Pointers, anchor the former and move forward the latter one to ensure the sum of subarray just covers the target 4 | * Note: There could be no valid subarray which sum >= target 5 | * Time Complexity: O(n), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class MinimumSizeSubarraySum { 10 | func minSubArrayLen(_ s: Int, _ nums: [Int]) -> Int { 11 | var miniSize = Int.max, start = 0, currentSum = 0 12 | 13 | for (i, num) in nums.enumerated() { 14 | currentSum += num 15 | 16 | while currentSum >= s, start <= i { 17 | miniSize = min(miniSize, i - start + 1) 18 | 19 | currentSum -= nums[start] 20 | start += 1 21 | } 22 | } 23 | 24 | return miniSize == Int.max ? 0 : miniSize 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Array/MissingRanges.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/missing-ranges/ 3 | * Primary idea: Scan the array and compare each element with previous one and generate corresponding ranges 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class MissingRanges { 10 | func findMissingRanges(_ nums: [Int], _ lower: Int, _ upper: Int) -> [String] { 11 | var res = [String]() 12 | 13 | guard !nums.isEmpty else { 14 | addRange(&res, lower, upper) 15 | return res 16 | } 17 | 18 | addRange(&res, lower, nums[0] - 1) 19 | 20 | for i in 1.. end { 31 | return 32 | } else if start == end { 33 | res.append("\(end)") 34 | } else { 35 | res.append("\(start)->\(end)") 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /Array/MoveZeroes.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/move-zeroes/ 3 | * Primary idea: keep index for element not equal to 0, traverse and set up the index 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class MoveZeroes { 10 | func moveZeroes(_ nums: inout [Int]) { 11 | var nonZeroIdx = 0 12 | 13 | for num in nums where num != 0 { 14 | nums[nonZeroIdx] = num 15 | nonZeroIdx += 1 16 | } 17 | 18 | while nonZeroIdx < nums.count { 19 | nums[nonZeroIdx] = 0 20 | nonZeroIdx += 1 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /Array/NumberBoomerangs.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/number-of-boomerangs/ 3 | * Primary idea: traverse the array and compare distance one by one 4 | * 5 | * Time Complexity: O(n^2), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class NumberBoomerangs { 10 | func numberOfBoomerangs(_ points: [[Int]]) -> Int { 11 | var num = 0 12 | 13 | for (i, point) in points.enumerated() { 14 | var dict = [Int: Int]() 15 | for (j, anotherpoint) in points.enumerated() { 16 | if i == j { 17 | continue 18 | } 19 | 20 | let distance = (anotherpoint[0] - point[0]) * (anotherpoint[0] - point[0]) + (anotherpoint[1] - point[1]) * (anotherpoint[1] - point[1]) 21 | 22 | if let sameDistancePoints = dict[distance] { 23 | dict[distance] = sameDistancePoints + 1 24 | } else { 25 | dict[distance] = 1 26 | } 27 | } 28 | 29 | for key in dict.keys { 30 | num += dict[key]! * (dict[key]! - 1) 31 | } 32 | } 33 | return num 34 | } 35 | } -------------------------------------------------------------------------------- /Array/RemoveDuplicatesFromSortedArray.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/remove-duplicates-from-sorted-array/ 3 | * Primary idea: keep a index, compare the element at that index with the element moving forward 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | * 6 | */ 7 | 8 | class RemoveDuplicatesFromSortedArray { 9 | func removeDuplicates(inout nums: [Int]) -> Int { 10 | guard nums.count > 0 else { 11 | return 0 12 | } 13 | 14 | var index = 0 15 | 16 | for num in nums where num != nums[index] { 17 | index += 1 18 | nums[index] = num 19 | } 20 | 21 | return index + 1 22 | } 23 | } -------------------------------------------------------------------------------- /Array/RemoveDuplicatesFromSortedArrayII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/remove-duplicates-from-sorted-array-ii/ 3 | * Primary idea: keep a index, compare between the element at that index, the element at index - 1, 4 | * and the element moving forward 5 | * Time Complexity: O(n), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class RemoveDuplicatesFromSortedArrayII { 10 | func removeDuplicates(inout nums: [Int]) -> Int { 11 | guard nums.count > 2 else { 12 | return nums.count 13 | } 14 | 15 | var index = 1 16 | 17 | for i in 2.. Int { 10 | nums = nums.filter { (num) in num != val } 11 | return nums.count 12 | } 13 | } -------------------------------------------------------------------------------- /Array/RotateImage.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/rotate-image/ 3 | * Primary idea: Go from clockwise and from outside to inside, use offset for convenience 4 | * 5 | * Time Complexity: O(n^2), Space Complexity: O(1) 6 | */ 7 | 8 | class RotateImage { 9 | func rotate(_ matrix: inout [[Int]]) { 10 | let n = matrix.count 11 | 12 | for layer in 0.. Int { 9 | var minDistance = Int.max, word1Idx = -1, word2Idx = -1 10 | 11 | for (i, word) in words.enumerated() { 12 | if word == word1 { 13 | word1Idx = i 14 | 15 | if word2Idx != -1 { 16 | minDistance = min(i - word2Idx, minDistance) 17 | } 18 | } else if word == word2 { 19 | word2Idx = i 20 | 21 | if word1Idx != -1 { 22 | minDistance = min(i - word1Idx, minDistance) 23 | } 24 | } 25 | } 26 | 27 | return minDistance 28 | } 29 | } -------------------------------------------------------------------------------- /Array/ShortestWordDistanceII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/shortest-word-distance/ 3 | * Primary idea: Save indexes of all words and use two pointers to get the shortest distance. 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | */ 6 | 7 | class WordDistance { 8 | 9 | var wordToIdx: [String: [Int]] 10 | 11 | init(_ words: [String]) { 12 | wordToIdx = [String: [Int]]() 13 | 14 | for (idx, word) in words.enumerated() { 15 | wordToIdx[word, default:[]].append(idx) 16 | } 17 | } 18 | 19 | func shortest(_ word1: String, _ word2: String) -> Int { 20 | guard let idxes1 = wordToIdx[word1], let idxes2 = wordToIdx[word2] else { 21 | fatalError("Invalid Input") 22 | } 23 | 24 | var i = 0, j = 0, minDistance = Int.max 25 | 26 | while i < idxes1.count && j < idxes2.count { 27 | minDistance = min(abs(idxes1[i] - idxes2[j]), minDistance) 28 | 29 | if idxes1[i] < idxes2[j] { 30 | i += 1 31 | } else { 32 | j += 1 33 | } 34 | } 35 | 36 | return minDistance 37 | } 38 | } -------------------------------------------------------------------------------- /Array/ShortestWordDistanceIII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/shortest-word-distance-iii/ 3 | * Primary idea: Iterate and update index and distance when encounter word1 or word2, use 4 | * a temp variable to memorize the previous postion if word1 == word2 5 | * 6 | * Time Complexity: O(n), Space Complexity: O(1) 7 | */ 8 | 9 | class ShortestWordDistanceIII { 10 | func shortestWordDistance(_ words: [String], _ word1: String, _ word2: String) -> Int { 11 | var idx1 = -1, idx2 = -1, res = Int.max 12 | 13 | for (i, word) in words.enumerated() { 14 | var prev = idx1 15 | 16 | if word == word1 { 17 | idx1 = i 18 | } 19 | if word == word2 { 20 | idx2 = i 21 | } 22 | 23 | if idx1 != -1 && idx2 != -1 { 24 | if word1 == word2 && prev != -1 && prev != idx1 { 25 | res = min(res, idx1 - prev) 26 | } else if idx1 != idx2 { 27 | res = min(res, abs(idx1 - idx2)) 28 | } 29 | } 30 | } 31 | 32 | return res 33 | } 34 | } -------------------------------------------------------------------------------- /Array/SlidingWindowMaximum.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/sliding-window-maximum/ 3 | * Primary idea: Use an array to store indices of elements, from larger to smaller, 4 | * adjust it while iterating the array 5 | * 6 | * Time Complexity: O(n), Space Complexity: O(n) 7 | * 8 | */ 9 | 10 | class SlidingWindowMaximum { 11 | func maxSlidingWindow(_ nums: [Int], _ k: Int) -> [Int] { 12 | var maxIdx = [Int]() 13 | var res = [Int]() 14 | 15 | for i in 0.. 0 && nums[maxIdx.last!] < nums[i] { 17 | maxIdx.removeLast() 18 | } 19 | 20 | maxIdx.append(i) 21 | 22 | if i >= k - 1 { 23 | if maxIdx.first! + k == i { 24 | maxIdx.removeFirst() 25 | } 26 | 27 | res.append(nums[maxIdx.first!]) 28 | } 29 | } 30 | 31 | return res 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Array/SortArrayByParity.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/sort-array-by-parity/ 3 | * Primary idea: traverse the array and insert Even into the 0 th index and odd into the last index 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class SortArrayByParity { 10 | func sortArrayByParity(_ A: [Int]) -> [Int] { 11 | return A.enumerated().reduce(into: [Int]()) { (acc, arg) in 12 | let (_, value) = arg 13 | acc.insert(value, at: value.isMultiple(of: 2) ? 0 : acc.count) 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Array/StrobogrammaticNumber.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/strobogrammatic-number/ 3 | * Primary idea: Two pointers, compare two characters until they are all valid 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class StrobogrammaticNumber { 10 | func isStrobogrammatic(_ num: String) -> Bool { 11 | let numChars = Array(num) 12 | var i = 0, j = num.count - 1 13 | 14 | while i <= j { 15 | if isValid(numChars[i], numChars[j]) { 16 | i += 1 17 | j -= 1 18 | } else { 19 | return false 20 | } 21 | } 22 | 23 | return true 24 | } 25 | 26 | fileprivate func isValid(_ charA: Character, _ charB: Character) -> Bool { 27 | guard let digitA = Int(String(charA)), let digitB = Int(String(charB)) else { 28 | fatalError("Invalid input") 29 | } 30 | 31 | if let mirrorA = mirrorDigits[digitA], mirrorA == digitB { 32 | return true 33 | } else { 34 | return false 35 | } 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /Array/SummaryRanges.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/summary-ranges/ 3 | * Primary idea: Traverse the array and build string when num[i] != num[i - 1] + 1, 4 | * note to handle the edge case when it goes to the end of the array 5 | * 6 | * Time Complexity: O(n), Space Complexity: O(n) 7 | */ 8 | 9 | class SummaryRanges { 10 | func summaryRanges(nums: [Int]) -> [String] { 11 | var res = [String]() 12 | var str = "" 13 | var start = 0 14 | 15 | guard nums.count > 0 else { 16 | return res 17 | } 18 | 19 | for i in 0...nums.count { 20 | if i == nums.count || (i > 0 && nums[i] != nums[i - 1] + 1) { 21 | str = "\(nums[start])" 22 | if i - 1 != start { 23 | str += "->\(nums[i - 1])" 24 | } 25 | res.append(str) 26 | start = i 27 | } 28 | } 29 | return res 30 | } 31 | } -------------------------------------------------------------------------------- /Array/TaskScheduler.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/task-scheduler/ 3 | * Primary idea: Most frequent character should be put at head of each cycle and join the chunks with less frequent one. 4 | * 5 | * Time Complexity: O(nlogn), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class TaskScheduler { 10 | func leastInterval(_ tasks: [Character], _ n: Int) -> Int { 11 | guard tasks.count > 0 else { 12 | return 0 13 | } 14 | 15 | let taskFreqs = Dictionary(tasks.map { ($0, 1) }, uniquingKeysWith: +) 16 | let sortedTasks = taskFreqs.keys.sorted { return taskFreqs[$0]! > taskFreqs[$1]! } 17 | var mostFreqCount = 0 18 | 19 | // get interval number for last cycle 20 | for sortedTask in sortedTasks { 21 | if taskFreqs[sortedTask] != taskFreqs[sortedTasks[0]] { 22 | break 23 | } 24 | 25 | mostFreqCount += 1 26 | } 27 | 28 | // when number of different tasks is greater than n + 1, and the most freqent task won't cause idle run, 29 | // then we should return tasks.count 30 | return max(tasks.count, (taskFreqs[sortedTasks[0]]! - 1) * (n + 1) + mostFreqCount) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Array/TwoSum.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/two-sum/ 3 | * Primary idea: Traverse the array and store target - nums[i] in a dict 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(n) 6 | */ 7 | 8 | class TwoSum { 9 | func twoSum(_ nums: [Int], _ target: Int) -> [Int] { 10 | var dict = [Int: Int]() 11 | 12 | for (i, num) in nums.enumerated() { 13 | if let lastIndex = dict[target - num] { 14 | return [lastIndex, i] 15 | } 16 | 17 | dict[num] = i 18 | } 19 | 20 | fatalError("No valid outputs") 21 | } 22 | } -------------------------------------------------------------------------------- /Array/TwoSumII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/ 3 | * Primary idea: Two pointers -- left moves forward and right moves backward to meet the right two sum. 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(n) 6 | */ 7 | 8 | class TwoSumII { 9 | func twoSum(_ numbers: [Int], _ target: Int) -> [Int] { 10 | if numbers.count <= 1 { 11 | return [Int]() 12 | } 13 | 14 | var left = 0, right = numbers.count - 1 15 | 16 | while left < right { 17 | if numbers[left] + numbers[right] < target { 18 | left += 1 19 | } else if numbers[left] + numbers[right] > target { 20 | right -= 1 21 | } else { 22 | return [left + 1, right + 1] 23 | } 24 | } 25 | 26 | return [Int]() 27 | } 28 | } -------------------------------------------------------------------------------- /Array/TwoSumIII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/two-sum-iii-data-structure-design/ 3 | * 4 | * Note: This answer offers a different solution instead of the one requsted by leetcode. 5 | * Assuming the use case is find API is called many more times than add API. 6 | * For the answer accepted by leetcode, you could reference Two Sum and Two Sum II. 7 | * 8 | * Primary idea: Use a set for all two sums value, and array to keep all numbers added. 9 | * Time Complexity: add - O(n), find - O(1), Space Complexity: O(n) 10 | */ 11 | 12 | class TwoSumIII { 13 | 14 | var nums: [Int] 15 | var twoSums: Set() 16 | 17 | /** Initialize your data structure here. */ 18 | init() { 19 | nums = [Int]() 20 | twoSums = Set() 21 | } 22 | 23 | /** Add the number to an internal data structure.. */ 24 | func add(_ number: Int) { 25 | nums.forEach { twoSums.insert($0 + number) } 26 | nums.append(number) 27 | } 28 | 29 | /** Find if there exists any pair of numbers which sum is equal to the value. */ 30 | func find(_ value: Int) -> Bool { 31 | return twoSums.contains(value) 32 | } 33 | } -------------------------------------------------------------------------------- /Array/TwoSumLessThanK.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/two-sum-less-than-k/ 3 | * Primary idea: Sort the arry and use two pointers to get the closest maximum value. 4 | * 5 | * Note: Directly using two points and update values correspondly to try to solve the 6 | * problem with O(n) time complexity does not work -- it has too many edge cases. 7 | * 8 | * Time Complexity: O(n), Space Complexity: O(n) 9 | */ 10 | 11 | class TwoSumLessThanK { 12 | func twoSumLessThanK(_ A: [Int], _ K: Int) -> Int { 13 | let sortedA = A.sorted() 14 | var left = 0, right = sortedA.count - 1 15 | var closest = -1 16 | 17 | while left < right { 18 | if sortedA[left] + sortedA[right] < K { 19 | closest = max(sortedA[left] + sortedA[right], closest) 20 | left += 1 21 | } else { 22 | right -= 1 23 | } 24 | } 25 | 26 | return closest 27 | } 28 | } -------------------------------------------------------------------------------- /DFS/BeautifulArrangement.swift: -------------------------------------------------------------------------------- 1 | class Solution { 2 | func countArrangement(_ n: Int) -> Int { 3 | var arr = Array(repeating: false, count: n) 4 | return countArr(1, &arr) 5 | } 6 | 7 | func countArr(_ c: Int, _ arr: inout [Bool]) -> Int { 8 | if c > arr.count { return 1 } 9 | 10 | var count = 0 11 | for x in 0.. [[Int]] { 11 | var combination = [Int](), combinations = [[Int]]() 12 | 13 | dfs(candidates.sorted(), target, 0, &combinations, &combination) 14 | 15 | return combinations 16 | } 17 | 18 | private func dfs(_ candidates: [Int], _ target: Int, _ index: Int, _ combinations: inout [[Int]], _ combination: inout [Int]) { 19 | if target == 0 { 20 | combinations.append(combination) 21 | return 22 | } 23 | 24 | for i in index.. [[Int]] { 11 | var res = [[Int]](), path = [Int]() 12 | 13 | dfs(&res, &path, target, candidates.sorted(), 0) 14 | 15 | return res 16 | } 17 | 18 | fileprivate func dfs(_ res: inout [[Int]], _ path: inout [Int], _ target: Int, _ candidates: [Int], _ index: Int) { 19 | if target == 0 { 20 | res.append(Array(path)) 21 | return 22 | } 23 | 24 | for i in index.. 0 && candidates[i] == candidates[i - 1] && i != index { 30 | continue 31 | } 32 | 33 | path.append(candidates[i]) 34 | _dfs(&res, &path, target - candidates[i], candidates, i + 1) 35 | path.removeLast() 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /DFS/CombinationSumIII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/combination-sum-iii/ 3 | * Primary idea: Classic Depth-first Search 4 | * 5 | * Time Complexity: O(n^n), Space Complexity: O(nCk) 6 | * 7 | */ 8 | 9 | class CombinationSumIII { 10 | func combinationSum3(k: Int, _ n: Int) -> [[Int]] { 11 | let candidates = [Int](1...9) 12 | var res = [[Int]](), path = [Int]() 13 | 14 | dfs(&res, &path, candidates, n, 0, k) 15 | 16 | return res 17 | } 18 | 19 | fileprivate func dfs(_ res: inout [[Int]], _ path: inout [Int], _ candidates: [Int], _ target: Int, _ index: Int, _ size: Int) { 20 | if target == 0 && path.count == size { 21 | res.append(Array(path)) 22 | return 23 | } 24 | 25 | guard path.count < size else { 26 | return 27 | } 28 | 29 | for i in index.. [[Int]] { 11 | var res = [[Int]]() 12 | var path = [Int]() 13 | let nums = [Int](1...n) 14 | 15 | _dfs(nums, &res, &path, 0, k) 16 | 17 | return res 18 | } 19 | 20 | private func _dfs(nums: [Int], inout _ res: [[Int]], inout _ path: [Int], _ index: Int, _ k: Int) { 21 | if path.count == k { 22 | res.append([Int](path)) 23 | return 24 | } 25 | 26 | for i in index.. [[Int]] { 11 | var paths = [[Int]](), path = [Int]() 12 | 13 | dfs(&paths, path, 2, n) 14 | 15 | return paths 16 | } 17 | 18 | private func dfs(_ paths: inout [[Int]], _ path: [Int], _ start: Int, _ target: Int) { 19 | if target == 1 { 20 | if path.count > 1 { 21 | paths.append(path) 22 | } 23 | return 24 | } 25 | 26 | guard start <= target else { 27 | return 28 | } 29 | 30 | for factor in start...target where target % factor == 0 { 31 | dfs(&paths, path + [factor], factor, target / factor) 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /DFS/GeneralizedAbbreviation.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/generalized-abbreviation/ 3 | * Primary idea: Classic Depth-first Search 4 | * 5 | * Time Complexity: O(n^n), Space Complexity: O(2^n) 6 | * 7 | */ 8 | 9 | class GeneralizedAbbreviation { 10 | func generateAbbreviations(_ word: String) -> [String] { 11 | var res = [String]() 12 | let chars = Array(word.characters) 13 | 14 | dfs(chars, &res, "", 0) 15 | 16 | return res 17 | } 18 | 19 | private func dfs(_ word: [Character], _ res: inout [String], _ subset: String, _ index: Int) { 20 | if word.count == index { 21 | res.append(String(subset)) 22 | return 23 | } 24 | 25 | res.append(subset + String(word.count - index)) 26 | 27 | for i in index.. Bool { 11 | var colors = Array(repeating: -1, count: graph.count) 12 | 13 | for i in 0.. Bool { 23 | if colors[index] != -1 { 24 | return colors[index] == color 25 | } 26 | 27 | colors[index] = color 28 | 29 | for neighbor in graph[index] { 30 | if !validColor(&colors, 1 - color, graph, neighbor) { 31 | return false 32 | } 33 | } 34 | 35 | return true 36 | } 37 | } -------------------------------------------------------------------------------- /DFS/Permutations.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/permutations/ 3 | * Primary idea: Classic Depth-first Search, remember backtracking 4 | * 5 | * Time Complexity: O(n^n), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class Permutations { 10 | func permute(_ nums: [Int]) -> [[Int]] { 11 | var res = [[Int]]() 12 | var path = [Int]() 13 | var isVisited = [Bool](repeating: false, count: nums.count) 14 | 15 | dfs(&res, &path, &isVisited, nums) 16 | 17 | return res 18 | } 19 | 20 | private func dfs(_ res: inout [[Int]], _ path: inout [Int], _ isVisited: inout [Bool], _ nums: [Int]) { 21 | guard path.count != nums.count else { 22 | res.append(path) 23 | return 24 | } 25 | 26 | for (i, num) in nums.enumerated() where !isVisited[i] { 27 | path.append(num) 28 | isVisited[i] = true 29 | dfs(&res, &path, &isVisited, nums) 30 | isVisited[i] = false 31 | path.removeLast() 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /DFS/PermutationsII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/permutations-ii/ 3 | * Primary idea: Classic Depth-first Search, adopt last occurrence to avoid dupliates 4 | * 5 | * Time Complexity: O(n^n), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class PermutationsII { 10 | func permuteUnique(_ nums: [Int]) -> [[Int]] { 11 | var res = [[Int]](), path = [Int](), visited = [Bool](repeating: false, count: nums.count) 12 | 13 | let nums = nums.sorted(by: <) 14 | 15 | _dfs(&res, &path, nums, &visited) 16 | 17 | return res 18 | } 19 | 20 | private func _dfs(inout res: [[Int]], inout _ path: [Int], _ nums: [Int], inout _ visited: [Bool]) { 21 | // termination case 22 | if path.count == nums.count { 23 | res.append(path) 24 | return 25 | } 26 | 27 | for i in 0.. 0 && nums[i] == nums[i - 1] && visited[i - 1]) { 29 | continue 30 | } 31 | 32 | path.append(nums[i]) 33 | visited[i] = true 34 | _dfs(&res, &path, nums, &visited) 35 | visited[i] = false 36 | path.removeLast() 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /DFS/Subsets.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/subsets/ 3 | * Primary idea: Classic Depth-first Search 4 | * 5 | * Time Complexity: O(n^n), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class Subsets { 10 | func subsets(nums: [Int]) -> [[Int]] { 11 | var res = [[Int]]() 12 | var path = [Int]() 13 | 14 | let nums = nums.sorted(by: <) 15 | 16 | _dfs(&res, &path, nums, 0) 17 | 18 | return res 19 | } 20 | 21 | private func _dfs(inout res: [[Int]], inout _ path: [Int], _ nums: [Int], _ index: Int) { 22 | // termination case 23 | 24 | res.append(path) 25 | 26 | for i in index.. [[Int]] { 11 | var res = [[Int]](), path = [Int]() 12 | 13 | let nums = nums.sorted(by: <) 14 | 15 | _dfs(&res, &path, nums, 0) 16 | 17 | return res 18 | } 19 | 20 | private func _dfs(inout res: [[Int]], inout _ path:[Int], _ nums: [Int], _ index: Int) { 21 | res.append(path) 22 | 23 | for i in index.. 0 && nums[i] == nums[i - 1] && i != index { 25 | continue 26 | } 27 | 28 | path.append(nums[i]) 29 | _dfs(&res, &path, nums, i + 1) 30 | path.removeLast() 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /DP/BestTimeBuySellStock.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/best-time-to-buy-and-sell-stock/ 3 | * Primary idea: Dynamic Programming, iterate the array while changing lowest 4 | * when there is smaller value and update the result 5 | * Time Complexity: O(n), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class BestTimeBuySellStock { 10 | func maxProfit(prices: [Int]) -> Int { 11 | guard prices.count > 0 else {return 0} 12 | var maxProfit = 0 13 | var buyDay = 0 14 | 15 | for i in 1 ..< prices.count { 16 | let profit = prices[i] - prices[buyDay] 17 | if profit < 0 { 18 | buyDay = i 19 | } 20 | maxProfit = max(profit, maxProfit) 21 | } 22 | 23 | return maxProfit 24 | } 25 | } -------------------------------------------------------------------------------- /DP/BestTimeBuySellStockCooldown.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/ 3 | * Primary idea: Dynamic programming, dp array means the max value sold at today 4 | * Time Complexity: O(n^2), Space Complexity: O(n) 5 | * 6 | */ 7 | 8 | class BestTimeBuySellStockCooldown { 9 | func maxProfit(_ prices: [Int]) -> Int { 10 | guard prices.count > 1 else { 11 | return 0 12 | } 13 | 14 | var res = 0 15 | var dp = Array(repeating: 0, count: prices.count) 16 | 17 | for i in 1..= 2 { 20 | dp[i] = max(dp[i], prices[i] - prices[j] + dp[j - 2]) 21 | } else { 22 | dp[i] = max(dp[i], prices[i] - prices[j]) 23 | } 24 | } 25 | 26 | dp[i] = max(dp[i], dp[i - 1]) 27 | res = max(res, dp[i]) 28 | } 29 | 30 | return res 31 | } 32 | } -------------------------------------------------------------------------------- /DP/BestTimeBuySellStockII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/ 3 | * Primary idea: Add all substractions if sell stock could earn money 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | * 6 | */ 7 | 8 | class BestTimeBuySellStockII { 9 | func maxProfit(_ prices: [Int]) -> Int { 10 | var max = 0 11 | 12 | guard prices.count > 1 else { 13 | return max 14 | } 15 | 16 | for i in 1.. prices[i - 1] { 17 | max += prices[i] - prices[i - 1] 18 | } 19 | 20 | return max 21 | } 22 | } -------------------------------------------------------------------------------- /DP/BestTimeBuySellStockIII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/ 3 | * Primary idea: Dynamic Programming, find point where sum of [0, i] and [i, count - 1] 4 | * is largest 5 | * Time Complexity: O(n), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class BestTimeBuySellStockIII { 10 | func maxProfit(_ prices: [Int]) -> Int { 11 | guard prices.count > 0 else { 12 | return 0 13 | } 14 | 15 | var maxProfit = 0 16 | var finalMaxProfit = 0 17 | var maxProfitLeft = [Int]() 18 | var low = prices.first! 19 | var high = prices.last! 20 | 21 | for price in prices { 22 | maxProfit = max(price - low, maxProfit) 23 | low = min(price, low) 24 | maxProfitLeft.append(maxProfit) 25 | } 26 | 27 | maxProfit = 0 28 | 29 | for i in (0.. Int { 3 | var people = people.sorted() 4 | var result = people.count 5 | var l = 0, r = result-1 6 | 7 | while l < r { 8 | if people[l] + people[r] <= limit { 9 | l += 1 10 | result -= 1 11 | } 12 | r -= 1 13 | } 14 | 15 | return result 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /DP/ClimbingStairs.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/climbing-stairs/ 3 | * Primary idea: Dynamic Programming, dp[i] = dp[i - 1] + dp[i - 2] 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | * 6 | */ 7 | 8 | class ClimbingStairs { 9 | func climbStairs(_ n: Int) -> Int { 10 | if n < 0 { 11 | return 0 12 | } 13 | if n == 0 || n == 1 { 14 | return 1 15 | } 16 | 17 | var prev = 0, post = 1, total = 0 18 | 19 | for i in 1...n { 20 | total = prev + post 21 | 22 | prev = post 23 | post = total 24 | } 25 | 26 | return total 27 | } 28 | } -------------------------------------------------------------------------------- /DP/CoinChange.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/coin-change/ 3 | * Primary idea: Dynamic Programming, transition function is min[i] = min[i - coin] + 1 4 | * Time Complexity: O(n^2), Space Complexity: O(n) 5 | */ 6 | 7 | class CoinChange { 8 | func coinChange(_ coins: [Int], _ amount: Int) -> Int { 9 | guard amount > 0 else { 10 | return 0 11 | } 12 | 13 | let coins = coins.sorted() 14 | var minAmounts = Array(repeating: -1, count: amount + 1) 15 | minAmounts[0] = 0 16 | 17 | for i in 1...amount { 18 | for coin in coins { 19 | if coin > i { 20 | break 21 | } 22 | 23 | if minAmounts[i - coin] == -1 { 24 | continue 25 | } 26 | 27 | minAmounts[i] = minAmounts[i] == -1 ? minAmounts[i - coin] + 1 : min(minAmounts[i - coin] + 1, minAmounts[i]) 28 | } 29 | } 30 | 31 | return minAmounts[amount] 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /DP/CoinChangeII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/coin-change-ii/ 3 | * Primary idea: Dynamic Programming, dp[i] += dp[i - coin] 4 | * Note: Loopo of coins should be outside to avoid duplicates 5 | * Time Complexity: O(n^2), Space Complexity: O(n) 6 | */ 7 | 8 | class CoinChangeII { 9 | func change(_ amount: Int, _ coins: [Int]) -> Int { 10 | guard amount > 0 else { 11 | return 1 12 | } 13 | 14 | var dp = [Int](repeating: 0, count: amount + 1) 15 | dp[0] = 1 16 | 17 | for coin in coins { 18 | for i in 1...amount { 19 | if i >= coin { 20 | dp[i] += dp[i - coin] 21 | } 22 | } 23 | } 24 | 25 | return dp[amount] 26 | } 27 | } -------------------------------------------------------------------------------- /DP/CombinationSumIV.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/combination-sum-iv/ 3 | * Primary idea: DFS cannot solve without time limited error, so use DP 4 | * 5 | * Note: Integer overflow 6 | * Space Complexity: O(n) 7 | * 8 | */ 9 | 10 | class CombinationSumIV { 11 | func combinationSum4(_ nums: [Int], _ target: Int) -> Int { 12 | var dp = [Int](repeating: 0, count: target + 1) 13 | dp[0] = 1 14 | let nums = nums.sorted() 15 | 16 | for i in 1...target { 17 | for num in nums { 18 | if i < num { 19 | break 20 | } 21 | 22 | if dp[i - num] > Int.max - dp[i] { 23 | continue 24 | } 25 | dp[i] += dp[i - num] 26 | } 27 | } 28 | 29 | return dp.last! 30 | } 31 | } -------------------------------------------------------------------------------- /DP/CountSortedVowelStrings.swift: -------------------------------------------------------------------------------- 1 | class Solution { 2 | func countVowelStrings(_ n: Int) -> Int { 3 | var curr = [0, 0, 0, 0, 1] 4 | 5 | for _ in 1.. Int { 11 | let s = Array(s) 12 | var dp = Array(repeating: 0, count: s.count + 1) 13 | dp[0] = 1 14 | 15 | for i in 1...s.count { 16 | if s[i - 1] != "0" { 17 | dp[i] += dp[i - 1] 18 | } 19 | 20 | if i > 1 && isValid(s, i - 2, i - 1) { 21 | dp[i] += dp[i - 2] 22 | } 23 | } 24 | 25 | return dp[s.count] 26 | } 27 | 28 | private func isValid(_ s: [Character], _ start: Int, _ end: Int) -> Bool { 29 | guard let num = Int(String(s[start...end])) else { 30 | fatalError() 31 | } 32 | 33 | return num >= 10 && num <= 26 34 | } 35 | } -------------------------------------------------------------------------------- /DP/DungeonGame.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/dungeon-game/ 3 | * Primary idea: Classic DP, current minimum health is decided by right and below minimum health 4 | * 5 | * Time Complexity: O(mn), Space Complexity: O(mn) 6 | */ 7 | 8 | class DungeonGame { 9 | func calculateMinimumHP(_ dungeon: [[Int]]) -> Int { 10 | let m = dungeon.count, n = dungeon[0].count 11 | 12 | guard m > 0, n > 0 else { 13 | return 1 14 | } 15 | 16 | var minHP = Array(repeating: Array(repeating: 1, count: n), count: m) 17 | 18 | for i in (0.. Int { 10 | let aChars = [Character](word1.characters) 11 | let bChars = [Character](word2.characters) 12 | let aLen = aChars.count 13 | let bLen = bChars.count 14 | 15 | var dp = Array(count: aLen + 1, repeatedValue:(Array(count: bLen + 1, repeatedValue: 0))) 16 | 17 | for i in 0...aLen { 18 | for j in 0...bLen { 19 | if i == 0 { 20 | dp[i][j] = j 21 | } else if j == 0 { 22 | dp[i][j] = i 23 | } else if aChars[i - 1] == bChars[j - 1] { 24 | dp[i][j] = dp[i - 1][j - 1] 25 | } else { 26 | dp[i][j] = min(dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]) + 1 27 | } 28 | } 29 | } 30 | 31 | return dp[aLen][bLen] 32 | } 33 | } -------------------------------------------------------------------------------- /DP/FlipGameII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/flip-game-ii/ 3 | * Primary idea: Classic DP, using a map to memorize previous step 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | */ 6 | 7 | class FlipGameII { 8 | func canWin(_ s: String) -> Bool { 9 | var winMap = [String: Bool]() 10 | 11 | return helper(s, &winMap) 12 | } 13 | 14 | func helper(_ s: String, _ winMap: inout [String: Bool]) -> Bool { 15 | guard s.count >= 2 else { 16 | return false 17 | } 18 | 19 | if let sWin = winMap[s] { 20 | return sWin 21 | } 22 | 23 | let sChars = Array(s) 24 | 25 | for i in 0.. [String] { 10 | guard n > 0 else { 11 | return [String]() 12 | } 13 | 14 | var paths = [String](), path = "" 15 | 16 | dfs(&paths, path, n, n) 17 | 18 | return paths 19 | } 20 | 21 | private func dfs(_ paths: inout [String], _ path: String, _ leftRemaining: Int, _ rightRemaining: Int) { 22 | if rightRemaining == 0 { 23 | paths.append(path) 24 | return 25 | } 26 | 27 | if leftRemaining > 0 { 28 | dfs(&paths, path + "(", leftRemaining - 1, rightRemaining) 29 | } 30 | if rightRemaining > leftRemaining { 31 | dfs(&paths, path + ")", leftRemaining, rightRemaining - 1) 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /DP/GuessNumberHigherOrLowerII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/guess-number-higher-or-lower-ii/ 3 | * Primary idea: Typical DP problem 4 | * For each guess: 5 | * 1) Get the worse case of every choice to guarantee the result 6 | * 2) Get the least cost among the guaranteed results 7 | * Time Complexity: O(nlogn), Space Complexity: O(n^2) 8 | */ 9 | 10 | class GuessNumberHigherOrLowerII { 11 | func getMoneyAmount(_ n: Int) -> Int { 12 | var table = [[Int]](repeatElement([Int](repeatElement(0, count: n + 1)), count: n + 1)) 13 | return DP(&table, 1, n) 14 | } 15 | 16 | private func DP(_ table: inout [[Int]], _ s: Int, _ e: Int) -> Int { 17 | if s >= e { 18 | return 0 19 | } 20 | if table[s][e] != 0 { 21 | return table[s][e] 22 | } 23 | var guarantee = Int.max 24 | for i in s.. Int { 10 | var curt = 0, prev = 0 11 | 12 | for num in nums { 13 | (curt, prev) = (max(curt, prev + num), curt) 14 | } 15 | 16 | return curt 17 | } 18 | } -------------------------------------------------------------------------------- /DP/HouseRobberII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/house-robber-ii/ 3 | * Primary idea: Dynamic Programming, dp[i] = max(dp[i - 1], dp[i - 2], + nums[i]) 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | * 6 | */ 7 | 8 | class HouseRobberII { 9 | func rob(_ nums: [Int]) -> Int { 10 | guard nums.count != 1 else { 11 | return nums[0] 12 | } 13 | 14 | return max(helper(nums, 0, nums.count - 2), helper(nums, 1, nums.count - 1)) 15 | } 16 | 17 | fileprivate func helper(_ nums: [Int], _ start: Int, _ end: Int) -> Int { 18 | if start > end { 19 | return 0 20 | } 21 | 22 | var prev = 0, current = 0 23 | 24 | for i in start...end { 25 | (current, prev) = (max(prev + nums[i], current), current) 26 | } 27 | 28 | return current 29 | } 30 | } -------------------------------------------------------------------------------- /DP/JumpGame.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/jump-game/ 3 | * Primary idea: check each position with the previous farest step can reach. If i > last farest step, means cannot reach 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | * 6 | */ 7 | 8 | class JumpGame { 9 | func canJump(_ nums: [Int]) -> Bool { 10 | var maximumIndex = nums[0] 11 | 12 | for (currentIndex, value) in nums.enumerated(){ 13 | 14 | if currentIndex > maximumIndex{ 15 | return false 16 | } 17 | 18 | maximumIndex = max(maximumIndex, currentIndex + value) 19 | } 20 | 21 | return true 22 | } 23 | } 24 | 25 | 26 | -------------------------------------------------------------------------------- /DP/LongestIncreasingSubsequence.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/longest-increasing-subsequence/ 3 | * Primary idea: Dynamic Programming, update the array which ends at current index using binary search 4 | * Time Complexity: O(nlogn), Space Complexity: O(n) 5 | */ 6 | 7 | class LongestIncreasingSubsequence { 8 | func lengthOfLIS(_ nums: [Int]) -> Int { 9 | guard let first = nums.first else { 10 | return 0 11 | } 12 | 13 | var ends = [first] 14 | 15 | for i in 1..= ends.count { 31 | ends.append(nums[i]) 32 | } else { 33 | ends[right] = nums[i] 34 | } 35 | } 36 | 37 | return ends.count 38 | } 39 | } -------------------------------------------------------------------------------- /DP/LongestPalindromicSubstring.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/longest-palindromic-substring/ 3 | * Primary idea: Find the longest palindrome string from every index at the center. 4 | * Time Complexity: O(n^2), Space Complexity: O(1) 5 | * 6 | */ 7 | 8 | class LongestPalindromicSubstring { 9 | func longestPalindrome(_ s: String) -> String { 10 | guard s.count > 1 else { 11 | return s 12 | } 13 | 14 | let sChars = Array(s) 15 | var maxLen = 0, start = 0 16 | 17 | for i in 0..= 0 && r < chars.count && chars[l] == chars[r] { 29 | l -= 1 30 | r += 1 31 | } 32 | 33 | if maxLen < r - l - 1 { 34 | start = l + 1 35 | maxLen = r - l - 1 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /DP/MaximalSquare.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/maximal-square/ 3 | * Primary idea: Dynamic Programming, new one is equal to the min square width plus one 4 | * Time Complexity: O(mn), Space Complexity: O(mn) 5 | */ 6 | 7 | class MaximalSquare { 8 | func maximalSquare(matrix: [[Character]]) -> Int { 9 | guard matrix.count != 0 else { 10 | return 0 11 | } 12 | 13 | let m = matrix.count 14 | let n = matrix[0].count 15 | 16 | var max_global = 0 17 | var maxSquareSide = Array(count: m, repeatedValue: (Array(count: n, repeatedValue: 0))) 18 | 19 | for i in 0.. Int { 9 | var min_soFar = nums[0] 10 | var max_soFar = nums[0] 11 | var max_global = nums[0] 12 | 13 | for i in 1.. Int { 10 | var max_current = nums[0] 11 | var max_global = nums[0] 12 | 13 | for i in 1.. Int { 12 | var dp = [Int](repeating: Int.max, count: cost.count + 1) 13 | (dp[0], dp[1]) = (cost[0], cost[1]) 14 | 15 | for i in 2...cost.count { 16 | if i == cost.count { 17 | dp[i] = min(dp[i - 1], dp[i - 2]) 18 | } else { 19 | dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i] 20 | } 21 | } 22 | 23 | return dp[cost.count] 24 | } 25 | } -------------------------------------------------------------------------------- /DP/MinimumOperationsToReduceXToZero.swift: -------------------------------------------------------------------------------- 1 | class Solution { 2 | func minOperations(_ nums: [Int], _ x: Int) -> Int { 3 | var leftSums = [0: 0] 4 | 5 | var leftSum = 0 6 | for l in 0.. l { 19 | result = min(result, l + nums.count - r) 20 | } 21 | } 22 | 23 | return result < Int.max ? result : -1 24 | } 25 | } -------------------------------------------------------------------------------- /DP/MinimumPathSum.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/minimum-path-sum/ 3 | * Primary idea: Classic Two Dimensionel Dynamic Programming 4 | * Time Complexity: O(mn), Space Complexity: O(mn) 5 | */ 6 | 7 | class MinimumPathSum { 8 | func minPathSum(_ grid: [[Int]]) -> Int { 9 | guard grid.count != 0 && grid[0].count != 0 else{ 10 | return 0 11 | } 12 | 13 | let m = grid.count, n = grid[0].count 14 | var dp = Array(repeating: Array(repeating: 0, count: n), count: m) 15 | 16 | for i in 0.. String { 10 | let m = T.count, n = S.count, sChars = Array(S), tChars = Array(T) 11 | var dp = Array(repeating: Array(repeating: 0, count: n + 1), count: m + 1) 12 | var start = 0, len = n + 1 13 | 14 | for i in 0...n { 15 | dp[0][i] = i + 1 16 | } 17 | 18 | for i in 1...m { 19 | for j in 1...n { 20 | if tChars[i - 1] == sChars[j - 1] { 21 | dp[i][j] = dp[i - 1][j - 1] 22 | } else { 23 | dp[i][j] = dp[i][j - 1] 24 | } 25 | } 26 | } 27 | 28 | for i in 1...n { 29 | if dp[m][i] != 0 { 30 | if i - dp[m][i] + 1 < len { 31 | len = i - dp[m][i] + 1 32 | start = dp[m][i] - 1 33 | } 34 | } 35 | } 36 | 37 | return len == n + 1 ? "" : String(sChars[start.. Int { 11 | if n == 0 || k == 0 { 12 | return 0 13 | } 14 | if n == 1 { 15 | return k 16 | } 17 | 18 | var lastSame = k 19 | var lastDiff = k * (k - 1) 20 | 21 | for i in 2.. Int { 10 | guard let colors = costs.first, !colors.isEmpty else { 11 | return 0 12 | } 13 | 14 | var dp = costs 15 | 16 | for i in 1.. Int { 10 | guard n > 0 else { 11 | return 0 12 | } 13 | 14 | var leastNums = [Int](count: n + 1, repeatedValue: Int.max) 15 | leastNums[0] = 0 16 | 17 | for i in 1...n { 18 | for j in 1...i { 19 | if j * j > i { 20 | break 21 | } 22 | leastNums[i] = min(leastNums[i], leastNums[i - j * j] + 1) 23 | } 24 | } 25 | 26 | return leastNums[n] 27 | } 28 | } -------------------------------------------------------------------------------- /DP/Triangle.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/triangle/ 3 | * Primary idea: Dynamic Programming, start from bottom to top 4 | * Time Complexity: O(2^n), Space Complexity: O(m) 5 | * 6 | */ 7 | 8 | class Triangle { 9 | func minimumTotal(_ triangle: [[Int]]) -> Int { 10 | guard triangle.count > 0 else { 11 | return 0 12 | } 13 | 14 | var dp = triangle.last! 15 | 16 | for i in stride(from: triangle.count - 2, through: 0, by: -1) { 17 | for j in 0...i { 18 | dp[j] = min(dp[j], dp[j + 1]) + triangle[i][j] 19 | } 20 | } 21 | 22 | return dp[0] 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /DP/UniquePaths.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/unique-paths/ 3 | * Primary idea: 2D Dynamic Programming, use a 2D array as a cache to store calculated data 4 | * Time Complexity: O(mn), Space Complexity: O(mn) 5 | * 6 | */ 7 | 8 | class UniquePaths { 9 | func uniquePaths(m: Int, _ n: Int) -> Int { 10 | var pathNums = Array(count: m, repeatedValue: Array(count: n, repeatedValue: 0)) 11 | return _helper(&pathNums, m - 1, n - 1) 12 | } 13 | 14 | private func _helper(inout pathNums: [[Int]], _ m: Int, _ n: Int) -> Int { 15 | if m < 0 || n < 0 { 16 | return 0 17 | } 18 | if m == 0 || n == 0 { 19 | return 1 20 | } 21 | 22 | if pathNums[m][n] != 0 { 23 | return pathNums[m][n] 24 | } 25 | pathNums[m][n] = _helper(&pathNums, m - 1, n) + _helper(&pathNums, m, n - 1) 26 | 27 | return pathNums[m][n] 28 | } 29 | } -------------------------------------------------------------------------------- /DP/UniquePathsII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/unique-paths-ii/ 3 | * Primary idea: 2D Dynamic Programming, use a 2D array as a cache to store calculated data 4 | * Time Complexity: O(mn), Space Complexity: O(mn) 5 | */ 6 | 7 | class UniquePathsII { 8 | func uniquePathsWithObstacles(_ obstacleGrid: [[Int]]) -> Int { 9 | let m = obstacleGrid.count 10 | guard m > 0 else { 11 | return 0 12 | } 13 | 14 | let n = obstacleGrid[0].count 15 | guard n > 0 else { 16 | return 0 17 | } 18 | 19 | var dp = Array(repeating: Array(repeating: -1, count: n), count: m) 20 | 21 | return help(m - 1, n - 1, &dp, obstacleGrid) 22 | } 23 | 24 | fileprivate func help(_ m: Int, _ n: Int, _ dp: inout [[Int]], _ obstacleGrid: [[Int]]) -> Int { 25 | if m < 0 || n < 0 { 26 | return 0 27 | } 28 | if obstacleGrid[m][n] == 1 { 29 | return 0 30 | } 31 | if m == 0 && n == 0 { 32 | return 1 33 | } 34 | if dp[m][n] != -1 { 35 | return dp[m][n] 36 | } 37 | 38 | dp[m][n] = help(m - 1, n, &dp, obstacleGrid) + help(m, n - 1, &dp, obstacleGrid) 39 | return dp[m][n] 40 | } 41 | } -------------------------------------------------------------------------------- /DP/WiggleSubsequence.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/wiggle-subsequence/ 3 | * Primary idea: Classic Dynamic Programming, two variables/arries to track up or down status 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | */ 6 | 7 | class WiggleSubsequence { 8 | func wiggleMaxLength(_ nums: [Int]) -> Int { 9 | guard nums.count >= 2 else { 10 | return nums.count 11 | } 12 | 13 | var up = 1, down = 1 14 | 15 | for i in 1.. nums[i - 1] { 17 | up = down + 1 18 | } else if nums[i] < nums[i - 1] { 19 | down = up + 1 20 | } 21 | } 22 | 23 | return max(up, down) 24 | } 25 | } -------------------------------------------------------------------------------- /Design/ShuffleAnArray.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/shuffle-an-array/ 3 | * Primary idea: Iterate through the array and swap the value at current index 4 | * with that at a random selected index 5 | * Time Complexity: O(n), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class ShuffleAnArray { 10 | var originalNums: [Int] 11 | 12 | init(_ nums: [Int]) { 13 | originalNums = nums 14 | } 15 | 16 | /** Resets the array to its original configuration and return it. */ 17 | func reset() -> [Int] { 18 | return originalNums 19 | } 20 | 21 | /** Returns a random shuffling of the array. */ 22 | func shuffle() -> [Int] { 23 | // note: Apple have an API called shuffled() for an array, complexity is O(n) 24 | 25 | let count = originalNums.count 26 | var nums = originalNums 27 | 28 | for i in 0.. Int { 24 | if hasNext() { 25 | let element = arrays[arrayIdx][elementIdx] 26 | elementIdx += 1 27 | return element 28 | } 29 | 30 | fatalError("Invalid next call") 31 | } 32 | 33 | func hasNext() -> Bool { 34 | findNext() 35 | 36 | return arrayIdx < arrays.count 37 | } 38 | 39 | private func findNext() { 40 | while arrayIdx < arrays.count { 41 | if elementIdx < arrays[arrayIdx].count { 42 | return 43 | } else { 44 | arrayIdx += 1 45 | elementIdx = 0 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Graph/GraphValidTree.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/graph-valid-tree/ 3 | * Primary idea: Classic Union Find, return false encountering a cycle, 4 | * or finally there is more than one link 5 | * 6 | * Time Complexity: O(nlogn), Space Complexity: O(n) 7 | * 8 | */ 9 | 10 | class GraphValidTree { 11 | func validTree(_ n: Int, _ edges: [[Int]]) -> Bool { 12 | guard n > 0 else { 13 | return true 14 | } 15 | 16 | var roots = [Int](0.. Int { 35 | var node = node 36 | 37 | while node != roots[node] { 38 | node = roots[node] 39 | } 40 | 41 | return node 42 | } 43 | } -------------------------------------------------------------------------------- /Graph/NumberConnectedComponentsUndirectedGraph.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/number-of-connected-components-in-an-undirected-graph/ 3 | * Primary idea: Classic Union Find, decrease count when there is a link between two nodes 4 | * 5 | * Time Complexity: O(nlogn), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class NumberConnectedComponentsUndirectedGraph { 10 | func countComponents(_ n: Int, _ edges: [[Int]]) -> Int { 11 | guard n > 0 else { 12 | return 0 13 | } 14 | 15 | var count = n 16 | var roots = [Int](0...n - 1) 17 | 18 | for edge in edges { 19 | let root0 = findRoot(edge[0], roots) 20 | let root1 = findRoot(edge[1], roots) 21 | 22 | if root0 != root1 { 23 | count -= 1 24 | roots[root1] = root0 25 | } 26 | } 27 | 28 | return count 29 | } 30 | 31 | private func findRoot(_ node: Int, _ roots: [Int]) -> Int { 32 | var node = node 33 | 34 | while (node != roots[node]) { 35 | node = roots[node] 36 | } 37 | 38 | return node 39 | } 40 | } -------------------------------------------------------------------------------- /Leetcode_Contributors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TerryHuangHD/LeetCode-Swift-Forked/eed765b4c283932fd8e3b13811d91328768729d4/Leetcode_Contributors.png -------------------------------------------------------------------------------- /License.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Yi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LinkedList/MergeTwoSortedLists.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/merge-two-sorted-lists/ 3 | * Primary idea: Dummy Node to traverse two lists, compare two nodes and point to the right one 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | * 6 | * Definition for singly-linked list. 7 | * public class ListNode { 8 | * public var val: Int 9 | * public var next: ListNode? 10 | * public init(_ val: Int) { 11 | * self.val = val 12 | * self.next = nil 13 | * } 14 | * } 15 | */ 16 | 17 | class MergeTwoSortedLists { 18 | func mergeTwoLists(l1: ListNode?, _ l2: ListNode?) -> ListNode? { 19 | let dummy = ListNode(0) 20 | var node = dummy 21 | 22 | var l1 = l1 23 | var l2 = l2 24 | 25 | while l1 != nil && l2 != nil { 26 | if l1!.val < l2!.val { 27 | node.next = l1 28 | l1 = l1!.next 29 | } else { 30 | node.next = l2 31 | l2 = l2!.next 32 | } 33 | node = node.next! 34 | } 35 | 36 | node.next = l1 ?? l2 37 | 38 | return dummy.next 39 | } 40 | } -------------------------------------------------------------------------------- /LinkedList/OddEvenLinkedList.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/odd-even-linked-list/ 3 | * Primary idea: Prev-post two pointers; change the prev and move both at a time 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | * 6 | * Definition for singly-linked list. 7 | * public class ListNode { 8 | * public var val: Int 9 | * public var next: ListNode? 10 | * public init(_ val: Int) { 11 | * self.val = val 12 | * self.next = nil 13 | * } 14 | * } 15 | */ 16 | 17 | class OddEvenLinkedList { 18 | func oddEvenList(_ head: ListNode?) -> ListNode? { 19 | guard head != nil, head!.next != nil else { 20 | return head 21 | } 22 | 23 | var prev = head, post = head!.next, isEndEven = true 24 | let evenStart = post 25 | 26 | while post!.next != nil { 27 | prev!.next = post!.next 28 | 29 | prev = post 30 | post = post!.next 31 | 32 | isEndEven = !isEndEven 33 | } 34 | 35 | if isEndEven { 36 | prev!.next = evenStart 37 | } else { 38 | prev!.next = nil 39 | post!.next = evenStart 40 | } 41 | 42 | 43 | return head 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /LinkedList/PartitionList.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/partition-list/ 3 | * Primary idea: Tail Insert and merge two lists, use dummy to avoid edge case 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(1) 6 | * Definition for singly-linked list. 7 | * public class ListNode { 8 | * public var val: Int 9 | * public var next: ListNode? 10 | * public init(_ val: Int) { 11 | * self.val = val 12 | * self.next = nil 13 | * } 14 | * } 15 | */ 16 | 17 | class PartitionList { 18 | func partition(_ head: ListNode?, _ x: Int) -> ListNode? { 19 | let prevDummy = ListNode(0), postDummy = ListNode(0) 20 | var prev = prevDummy, post = postDummy 21 | 22 | var node = head 23 | 24 | while node != nil { 25 | let next = node!.next 26 | node!.next = nil 27 | 28 | if node!.val < x { 29 | prev.next = node 30 | prev = prev.next! 31 | } else { 32 | post.next = node 33 | post = post.next! 34 | } 35 | node = next 36 | } 37 | 38 | prev.next = postDummy.next 39 | 40 | return prevDummy.next 41 | } 42 | } -------------------------------------------------------------------------------- /LinkedList/RemoveDuplicatesFromSortedList.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/remove-duplicates-from-sorted-list/ 3 | * Primary idea: Iterate the list, jump over duplicates by replacing next with next.next 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | * 6 | * Definition for singly-linked list. 7 | * public class ListNode { 8 | * public var val: Int 9 | * public var next: ListNode? 10 | * public init(_ val: Int) { 11 | * self.val = val 12 | * self.next = nil 13 | * } 14 | * } 15 | */ 16 | 17 | class RemoveDuplicatesFromSortedList { 18 | func deleteDuplicates(_ head: ListNode?) -> ListNode? { 19 | guard let head = head else { 20 | return nil 21 | } 22 | 23 | var curt = head 24 | 25 | while curt.next != nil { 26 | if curt.next!.val == curt.val { 27 | curt.next = curt.next!.next 28 | } else { 29 | curt = curt.next! 30 | } 31 | } 32 | 33 | return head 34 | } 35 | } -------------------------------------------------------------------------------- /LinkedList/RemoveLinkedListElements.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/remove-linked-list-elements/ 3 | * Primary idea: Iterate the list, jump over vals by replacing next with next.next 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | * 6 | * Definition for singly-linked list. 7 | * public class ListNode { 8 | * public var val: Int 9 | * public var next: ListNode? 10 | * public init(_ val: Int) { 11 | * self.val = val 12 | * self.next = nil 13 | * } 14 | * } 15 | */ 16 | 17 | class RemoveLinkedListElements { 18 | func removeElements(_ head: ListNode?, _ val: Int) -> ListNode? { 19 | let dummy = ListNode(0) 20 | dummy.next = head 21 | var node = dummy 22 | 23 | while node.next != nil { 24 | if node.next!.val == val { 25 | node.next = node.next!.next 26 | } else { 27 | node = node.next! 28 | } 29 | } 30 | 31 | return dummy.next 32 | } 33 | } -------------------------------------------------------------------------------- /LinkedList/RemoveNthFromEnd.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/remove-nth-node-from-end-of-list/ 3 | * Primary idea: Runner Tech 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | * 6 | * Definition for singly-linked list. 7 | * public class ListNode { 8 | * public var val: Int 9 | * public var next: ListNode? 10 | * public init(_ val: Int) { 11 | * self.val = val 12 | * self.next = nil 13 | * } 14 | * } 15 | */ 16 | 17 | class RemoveNthFromEnd { 18 | func removeNthFromEnd(_ head: ListNode?, _ n: Int) -> ListNode? { 19 | let dummy = ListNode(0) 20 | dummy.next = head 21 | var prev: ListNode? = dummy 22 | var post: ListNode? = dummy 23 | 24 | // move post 25 | for _ in 0.. ListNode? { 19 | var temp: ListNode? 20 | var first = head 21 | 22 | while first != nil { 23 | let second = first!.next 24 | 25 | first!.next = temp 26 | 27 | temp = first 28 | first = second 29 | } 30 | 31 | return temp 32 | } 33 | 34 | func reverseList(_ head: ListNode?) -> ListNode? { 35 | guard let h = head, let next = h.next else { 36 | return head 37 | } 38 | 39 | let node = reverseList(next) 40 | 41 | next.next = h 42 | h.next = nil 43 | 44 | return node 45 | } 46 | } -------------------------------------------------------------------------------- /LinkedList/SwapNodesInPairs.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/swap-nodes-in-pairs/ 3 | * Primary idea: Three Pointers, each time change pointers' directions 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | * 6 | * Definition for singly-linked list. 7 | * public class ListNode { 8 | * public var val: Int 9 | * public var next: ListNode? 10 | * public init(_ val: Int) { 11 | * self.val = val 12 | * self.next = nil 13 | * } 14 | * } 15 | */ 16 | 17 | class SwapNodesInPairs { 18 | func swapPairs(head: ListNode?) -> ListNode? { 19 | let dummy = ListNode(0) 20 | dummy.next = head 21 | 22 | var prev: ListNode? = dummy 23 | var current = dummy.next 24 | 25 | while current != nil && current!.next != nil { 26 | let next = current!.next 27 | let post = current!.next!.next 28 | 29 | prev!.next = next 30 | next!.next = current 31 | current!.next = post 32 | 33 | prev = current 34 | current = post 35 | } 36 | 37 | return dummy.next 38 | } 39 | } -------------------------------------------------------------------------------- /Math/AddBinary.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/add-binary/ 3 | * Primary idea: Two pointers: use carry and iterate from last to start 4 | * 5 | * Note: Swift does not have a way to access a character in a string with O(1), 6 | * thus we have to first transfer the string to a character array 7 | * Time Complexity: O(n), Space Complexity: O(n) 8 | * 9 | */ 10 | 11 | class AddBinary { 12 | func addBinary(_ a: String, _ b: String) -> String { 13 | let a = Array(a), b = Array(b) 14 | var res = "", carry = 0, i = a.count - 1, j = b.count - 1 15 | 16 | while i >= 0 || j >= 0 || carry > 0 { 17 | var sum = carry 18 | 19 | if i >= 0 { 20 | sum += Int(String(a[i]))! 21 | i -= 1 22 | } 23 | if j >= 0 { 24 | sum += Int(String(b[j]))! 25 | j -= 1 26 | } 27 | 28 | res = "\(sum % 2)" + res 29 | carry = sum / 2 30 | } 31 | 32 | return res 33 | } 34 | } -------------------------------------------------------------------------------- /Math/AddDigits.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/add-digits/ 3 | * Primary idea: Transform number into array of string and sum the values recursively until the result is achieved 4 | * 5 | * Time Complexity: O(1), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class AddDigits { 10 | func add (num: Int) -> Int { 11 | let numString = String(num) 12 | guard numString.characters.count > 1 else { 13 | return num 14 | } 15 | 16 | let array = Array(numString.characters).map { String($0) } 17 | 18 | let sum = array.reduce(0) { $0.0 + Int($0.1)! } 19 | 20 | return add(num: sum) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Math/AddTwoNumbers.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/add-two-numbers/ 3 | * Primary idea: use carry and iterate through both linked lists 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | * 6 | * Definition for singly-linked list. 7 | * public class ListNode { 8 | * public var val: Int 9 | * public var next: ListNode? 10 | * public init(_ val: Int) { 11 | * self.val = val 12 | * self.next = nil 13 | * } 14 | * } 15 | */ 16 | 17 | class AddTwoNumbers { 18 | func addTwoNumbers(l1: ListNode?, _ l2: ListNode?) -> ListNode? { 19 | guard let l1 = l1 else {return l2} 20 | guard let l2 = l2 else {return l1} 21 | 22 | let outputNode = ListNode((l1.val + l2.val)%10) 23 | if l1.val + l2.val > 9 { 24 | outputNode.next = addTwoNumbers(addTwoNumbers(l1.next, l2.next), 25 | ListNode(1)) 26 | } else { 27 | outputNode.next = addTwoNumbers(l1.next, l2.next) 28 | } 29 | 30 | 31 | return outputNode 32 | } 33 | } -------------------------------------------------------------------------------- /Math/ContainerMostWater.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/container-with-most-water/ 3 | * Primary idea: First given largest width, then go to height-increase direction while width decreases 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | * 6 | */ 7 | 8 | class ContainerMostWater { 9 | func maxArea(_ height: [Int]) -> Int { 10 | var maxRes = 0 11 | var left = 0 12 | var right = height.count - 1 13 | 14 | while left < right { 15 | let minHeight = min(height[left], height[right]) 16 | 17 | maxRes = max(maxRes, (right - left) * minHeight) 18 | 19 | if minHeight == height[left] { 20 | left += 1 21 | } else { 22 | right -= 1 23 | } 24 | } 25 | 26 | return maxRes 27 | } 28 | } -------------------------------------------------------------------------------- /Math/CountPrimes.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/count-primes/ 3 | * Primary idea: Create a boolean array to determine prime or not, 4 | * filter numbers are times of previous number starting from its square 5 | * 6 | * Time Complexity: O(n), Space Complexity: O(n) 7 | */ 8 | 9 | class CountPrimes { 10 | func countPrimes(_ n: Int) -> Int { 11 | guard n > 2 else { 12 | return 0 13 | } 14 | 15 | // init isPrime bool array 16 | var isPrime = Array(repeating: true, count: n) 17 | isPrime[0] = false 18 | isPrime[1] = false 19 | 20 | // count prime number 21 | var count = 0 22 | for num in 2.. [Int] { 11 | guard num > 0 else { 12 | return [0] 13 | } 14 | 15 | var bits = [Int](count: num + 1, repeatedValue: 0) 16 | var x = 1 17 | for i in 1...num { 18 | if i == x { 19 | x = x << 1 20 | bits[i] = 1 21 | } else { 22 | bits[i] = bits[i - (x >> 1)] + 1 23 | } 24 | } 25 | 26 | return bits 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Math/DivideTwoIntegers.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/divide-two-integers/ 3 | * Primary idea: Use left shift and subtraction to get the number of every digit 4 | * Time Complexity: O(logn), Space Complexity: O(1) 5 | * 6 | */ 7 | 8 | class DivideTwoIntegers { 9 | func divide(_ dividend: Int, _ divisor: Int) -> Int { 10 | let isPositive = (dividend < 0) == (divisor < 0) 11 | var dividend = abs(dividend), divisor = abs(divisor), count = 0 12 | 13 | while dividend >= divisor { 14 | var shift = 0 15 | 16 | while dividend >= (divisor << shift) { 17 | shift += 1 18 | } 19 | 20 | dividend -= divisor << (shift - 1) 21 | 22 | count += (1 << (shift - 1)) 23 | } 24 | 25 | return refactorCount(count, isPositive) 26 | } 27 | 28 | private func refactorCount(_ count: Int, _ isPositive: Bool) -> Int { 29 | let INTMAX = 2147483647 30 | var count = count 31 | 32 | if isPositive { 33 | if count > INTMAX { 34 | count = INTMAX 35 | } 36 | } else { 37 | count *= -1 38 | } 39 | 40 | return count 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Math/ExcelSheetColumnNumber.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/excel-sheet-column-number/ 3 | * Primary idea: Classic Math problem, res = res * 26 + current 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | * 6 | */ 7 | 8 | class ExcelSheetColumnNumber { 9 | func titleToNumber(s: String) -> Int { 10 | var result = 0 11 | 12 | for c in s.unicodeScalars { 13 | let value = Int(c.value) - 64 14 | result = (result * 26) + value 15 | } 16 | 17 | return result 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Math/FactorialTrailingZeroes.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/factorial-trailing-zeroes/ 3 | * Primary idea: Calculate how many 5s the number has since it should have more 2 4 | * 5 | * Time Complexity: O(logn), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class FactorialTrailingZeroes { 10 | func trailingZeroes(_ n: Int) -> Int { 11 | return n > 0 ? n / 5 + trailingZeroes(n / 5) : 0 12 | } 13 | } -------------------------------------------------------------------------------- /Math/GaryCode.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/gray-code/ 3 | * Primary idea: the result of n can be derived from (n - 1) by reversing 4 | the order and prepending 1 to each number's binary representation 5 | * 6 | * Time Complexity: O(n), Space Complexity: O(2^n) 7 | * 8 | */ 9 | 10 | class GaryCode { 11 | func grayCode(_ n: Int) -> [Int] { 12 | var codes = [0] 13 | for i in 0.. Int { 10 | var z = x ^ y, count = 0 11 | 12 | while z > 0 { 13 | count += z & 1 14 | z = z >> 1 15 | } 16 | 17 | return count 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Math/HappyNumber.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/happy-number/ 3 | * Primary idea: Use a set to help determine if it goes to a cycle 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | * 6 | */ 7 | 8 | class HappyNumber { 9 | func isHappy(n: Int) -> Bool { 10 | var set = Set() 11 | var num = n 12 | 13 | while num != 1 { 14 | guard !set.contains(num) else { 15 | return false 16 | } 17 | set.insert(num) 18 | 19 | var temp = 0 20 | while num != 0 { 21 | temp += (num % 10) * (num % 10) 22 | num = num / 10 23 | } 24 | num = temp 25 | } 26 | 27 | return true 28 | } 29 | } -------------------------------------------------------------------------------- /Math/IntegerBreak.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/integer-break/ 3 | * Primary idea: Final Result must be split as 2^m * 3^n. Lets say p = p1 + p2 +...+ pn, 4 | * if p1 could be split as 2(p1 - 2), than it would be greater than p1 if p1 > 4. 5 | * same thing for 3(p1 - 3). Thus we spilt the original number to multiple 3s and 2s to 6 | * get the final result 7 | * Time Complexity: O(logn), Space Complexity: O(1) 8 | */ 9 | 10 | class IntegerBreak { 11 | func integerBreak(n: Int) -> Int { 12 | var num = n 13 | var res = 1 14 | 15 | if num == 2 { 16 | return 1 17 | } 18 | if num == 3 { 19 | return 2 20 | } 21 | 22 | while num > 4 { 23 | res *= 3 24 | num -= 3 25 | } 26 | res *= num 27 | 28 | return res 29 | } 30 | } -------------------------------------------------------------------------------- /Math/KthSmallestLexicographicalOrder.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/k-th-smallest-in-lexicographical-order/ 3 | * Primary idea: Image it is a ten-deminsion tree, we only need to calculate the number 4 | * of children for each node, and keep minus until we get the right one 5 | * 6 | * Note: Swift does not have a way to access a character in a string with O(1), 7 | * thus we have to first transfer the string to a character array 8 | * Time Complexity: O(n), Space Complexity: O(1) 9 | * 10 | */ 11 | 12 | class KthSmallestLexicographicalOrder { 13 | func findKthNumber(_ n: Int, _ k: Int) -> Int { 14 | var curt = 1, k = k - 1 15 | 16 | while k > 0 { 17 | var step = 0, first = curt, last = curt + 1 18 | while first <= n { 19 | step += min(n + 1, last) - first 20 | first *= 10 21 | last *= 10 22 | } 23 | if step <= k { 24 | curt += 1 25 | k -= step 26 | } else { 27 | curt *= 10 28 | k -= 1 29 | } 30 | } 31 | 32 | return curt 33 | } 34 | } -------------------------------------------------------------------------------- /Math/LineReflection.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/line-reflection/ 3 | * Primary idea: Find a Line that should be y = (minX + maxX) / 2, then iterate through points and make sure that it has a reflected point in the opposite side. 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(n) 6 | */ 7 | 8 | class LineReflection { 9 | func isReflected(_ points: [[Int]]) -> Bool { 10 | var minX = Int.max, maxX = Int.min 11 | var pointSet = Set<[Int]>() 12 | 13 | for point in points { 14 | pointSet.insert(point) 15 | minX = min(point[0], minX) 16 | maxX = max(point[0], maxX) 17 | } 18 | 19 | let sum = minX + maxX 20 | 21 | for item in pointSet { 22 | if item[0] == sum { 23 | continue 24 | } 25 | 26 | if !pointSet.contains([sum - item[0], item[1]]) { 27 | return false 28 | } 29 | } 30 | 31 | return true 32 | } 33 | } -------------------------------------------------------------------------------- /Math/MinimumMovesEqualArrayElements.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/minimum-moves-to-equal-array-elements/ 3 | * Primary idea: Adding 1 to n - 1 elements is the same as subtracting 1 from one element, 4 | * the best way is to make all the elements equal to the min element. 5 | * 6 | * Time Complexity: O(n), Space Complexity: O(1) 7 | */ 8 | 9 | class MinimumMovesEqualArrayElements { 10 | func minMoves(_ nums: [Int]) -> Int { 11 | let minNum = nums.min()! 12 | 13 | return nums.reduce(0) { total, num in total + num - minNum } 14 | } 15 | } -------------------------------------------------------------------------------- /Math/MissingNumber.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/missing-number/ 3 | * Primary idea: The distinct number is the sum from 0 to expected end number, which is 4 | * exactly the array length, minus the sum of all the values in array 5 | * Time Complexity: O(n), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class MissingNumber { 10 | func missingNumber(_ nums: [Int]) -> Int { 11 | return nums.count * (nums.count + 1) / 2 - nums.reduce(0, +) 12 | } 13 | } -------------------------------------------------------------------------------- /Math/NumberComplement.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/number-complement/ 3 | * Primary idea: Caculate digit by digit, and use offset to left shift 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class NumberComplement { 10 | func findComplement(_ num: Int) -> Int { 11 | var res = 0, num = num, offset = 0 12 | 13 | while num > 0 { 14 | res = res + ((num & 1) ^ 1) << offset 15 | 16 | num = num >> 1 17 | offset += 1 18 | } 19 | 20 | return res 21 | } 22 | } -------------------------------------------------------------------------------- /Math/PalindromeNumber.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/palindrome-number/ 3 | * Primary idea: Negative numbers are not palindromes. 4 | * 5 | * Time Complexity: O(1), Space Complexity: O(1) 6 | */ 7 | 8 | class PalindromeNumber { 9 | func isPalindrome(x: Int) -> Bool { 10 | guard x >= 0 else { 11 | return false 12 | } 13 | 14 | var x = x 15 | var div = 1 16 | 17 | while (x / div >= 10) { 18 | div = div * 10 19 | } 20 | 21 | while (x > 0) { 22 | var left = x / div 23 | var right = x % 10 24 | 25 | if (left != right) { 26 | return false 27 | } 28 | 29 | x = (x % div) / 10 30 | div = div / 100 31 | } 32 | 33 | return true 34 | } 35 | } -------------------------------------------------------------------------------- /Math/PermutationSequence.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/permutation-sequence/ 3 | * Primary idea: Iterate and change the array from last to the first 4 | * 5 | * Time Complexity: O(n^2), Space Complexity: O(1) 6 | */ 7 | 8 | class PermutationSequence { 9 | func getPermutation(_ n: Int, _ k: Int) -> String { 10 | var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9] 11 | 12 | var factorial = 1 13 | for i in 1 ..< n { 14 | factorial *= i 15 | } 16 | 17 | var result = "" 18 | var k = k 19 | var divisor = n - 1 20 | 21 | for i in 0 ..< n { 22 | for (index, number) in numbers.enumerated() { 23 | if k > factorial { 24 | k -= factorial 25 | } else { 26 | result += "\(number)" 27 | numbers.remove(at: index) 28 | break 29 | } 30 | } 31 | if divisor > 1 { 32 | factorial /= divisor 33 | divisor -= 1 34 | } 35 | } 36 | 37 | return result 38 | } 39 | } -------------------------------------------------------------------------------- /Math/PlusOne.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/plus-one/ 3 | * Primary idea: Iterate and change the array from last to the first 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(1) 6 | */ 7 | 8 | class PlusOne { 9 | func plusOne(digits: [Int]) -> [Int] { 10 | var digits = digits 11 | var index = digits.count - 1 12 | 13 | while index >= 0 { 14 | if digits[index] < 9 { 15 | digits[index] += 1 16 | return digits 17 | } 18 | 19 | digits[index] = 0 20 | index -= 1 21 | } 22 | 23 | digits.insert(1, atIndex: 0) 24 | return digits 25 | } 26 | } -------------------------------------------------------------------------------- /Math/Pow.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/powx-n/ 3 | * Primary idea: Classic Recursion and handle positive/negative case at first 4 | * 5 | * Time Complexity: O(logn), Space Complexity: O(1) 6 | */ 7 | 8 | class Pow { 9 | func myPow(x: Double, _ n: Int) -> Double { 10 | var x = x, n = n 11 | 12 | if n < 0 { 13 | x = 1.0 / x 14 | n = -n 15 | } 16 | 17 | var res = 1.0 18 | 19 | while n > 0 { 20 | if n % 2 != 0 { 21 | res *= x 22 | } 23 | x *= x 24 | n /= 2 25 | } 26 | 27 | return res 28 | } 29 | } -------------------------------------------------------------------------------- /Math/PowerThree.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/power-of-three/ 3 | * Primary idea: Use the largest 3^n int number to mod 4 | * Time Complexity: O(1), Space Complexity: O(1) 5 | * 6 | */ 7 | 8 | class PowerThree { 9 | func isPowerOfThree(n: Int) -> Bool { 10 | guard n > 0 else { 11 | return false 12 | } 13 | 14 | return 1162261467 % n == 0 15 | } 16 | } -------------------------------------------------------------------------------- /Math/PowerTwo.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/power-of-two/ 3 | * Primary idea: Use and operation to solve the problem 4 | * Time Complexity: O(1), Space Complexity: O(1) 5 | * 6 | */ 7 | 8 | class PowerTwo { 9 | func isPowerOfTwo(n: Int) -> Bool { 10 | guard n > 0 else { 11 | return false 12 | } 13 | 14 | return n & (n - 1) == 0 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Math/ReachANumber.swift: -------------------------------------------------------------------------------- 1 | class Solution { 2 | func reachNumber(_ target: Int) -> Int { 3 | var target = abs(target) 4 | 5 | var step = 0 6 | while target > 0 { 7 | step += 1 8 | target -= step 9 | } 10 | target = -target 11 | 12 | return (target.isMultiple(of: 2) ? step : (step + 1 + step%2)) 13 | } 14 | } 15 | 16 | /* 17 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21 18 | 1 2 3 4 5 6 19 | 2 3 4 5 6 20 | 3 4 5 6 21 | 3 4 5 6 22 | 4 5 6 23 | 4 5 6 24 | */ 25 | 26 | 27 | -------------------------------------------------------------------------------- /Math/RectangleArea.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/rectangle-area/ 3 | * Primary idea: Add areas of two and minus the overlap one 4 | * Time Complexity: O(1), Space Complexity: O(1) 5 | * 6 | */ 7 | 8 | class RectangleArea { 9 | func computeArea(_ A: Int, _ B: Int, _ C: Int, _ D: Int, _ E: Int, _ F: Int, _ G: Int, _ H: Int) -> Int { 10 | let areaOne = (C - A) * (D - B) 11 | let areaTwo = (G - E) * (H - F) 12 | 13 | return areaOne + areaTwo - _overlap(A, C, E, G) * _overlap(B, D, F, H) 14 | } 15 | 16 | private func _overlap(_ A: Int, _ B: Int, _ C: Int, _ D: Int) -> Int { 17 | if B <= C || A >= D { 18 | return 0 19 | } 20 | 21 | return min(B, D) - max(A, C) 22 | } 23 | } -------------------------------------------------------------------------------- /Math/ReverseInteger.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/reverse-integer/ 3 | * Primary idea: Using % 10 to reversely iterate through digits of the number, 4 | * and use * 10 to update the result accordingly 5 | * Note: Handle integer overflow at proper time 6 | * Time Complexity: O(n), Space Complexity: O(1) 7 | */ 8 | 9 | class ReverseInteger { 10 | func reverse(_ x: Int) -> Int { 11 | var res = 0 12 | var x = x 13 | while x != 0 { 14 | if res > Int(Int32.max) / 10 || res < Int(Int32.min) / 10 { 15 | return 0 16 | } 17 | res = res * 10 + x % 10 18 | x = x / 10 19 | } 20 | return res 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Math/RomanToInteger.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/roman-to-integer/ 3 | * Primary idea: Iterate through end to start, add or minus according to different situations 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | * 6 | */ 7 | 8 | class RomanToInteger { 9 | func romanToInt(s: String) -> Int { 10 | let dict = initDict() 11 | let chars = [Character](s.characters.reverse()) 12 | var res = 0 13 | 14 | for i in 0.. 0 && current < dict[String(chars[i - 1])] { 19 | res -= current 20 | } else { 21 | res += current 22 | } 23 | } 24 | 25 | return res 26 | } 27 | 28 | private func initDict() -> [String: Int] { 29 | var dict = [String: Int]() 30 | 31 | dict["I"] = 1 32 | dict["V"] = 5 33 | dict["X"] = 10 34 | dict["L"] = 50 35 | dict["C"] = 100 36 | dict["D"] = 500 37 | dict["M"] = 1000 38 | 39 | return dict 40 | } 41 | } -------------------------------------------------------------------------------- /Math/SingleNumber.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/single-number/ 3 | * Primary idea: Exclusive or 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | * 6 | */ 7 | 8 | class SingleNumber { 9 | func singleNumber(nums: [Int]) -> Int { 10 | var res = 0 11 | 12 | for num in nums { 13 | res ^= num 14 | } 15 | 16 | return res 17 | } 18 | } -------------------------------------------------------------------------------- /Math/SingleNumberII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/single-number-ii/ 3 | * Primary idea: Every number has 64 bits, for the i-th bit of each number. 4 | * In total, we should have (nums.count) 0s and 1s. 5 | * If the i-th bit of the single number is 1, then we should have (3n + 1) 1s, and (3n) 0s. 6 | * Otherwise, the i-th bit is 0. 7 | * In this way, we can calculate each bit of the single number. 8 | * 9 | * Time Complexity: O(n), Space Complexity: O(1) 10 | * 11 | */ 12 | 13 | class SingleNumberII { 14 | func singleNumber(nums: [Int]) -> Int { 15 | var ans = 0 16 | var sum = 0 17 | 18 | for i in 0..<64 { 19 | sum = 0 20 | let tmp = (1 << i) 21 | for j in 0.. [[Int]] { 10 | let l = A.count, m = B.count, n = B[0].count 11 | 12 | var res = Array(repeating: Array(repeating: 0, count: n), count: l) 13 | 14 | var nonZeroB = Array(repeating: [Int](), count: m) 15 | for i in 0.. Int { 11 | var a = a 12 | var b = b 13 | 14 | while b != 0 { 15 | (a, b) = (a ^ b, (a & b) << 1) 16 | } 17 | return a 18 | } 19 | } -------------------------------------------------------------------------------- /Math/SuperPow.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/super-pow/ 3 | * Primary idea: a * b % k = (a % k) * (b % k) % k 4 | * a ^ b % k = [a ^ (b / 10 * 10) % k] * [a ^ (b % 10) % k] % k 5 | * f(a, b) = f(a, b / 10 * 10) * f(a, b % 10) % k 6 | * = f(f(a, b / 10), 10) * f(a, b % 10) % k 7 | * 8 | * Time Complexity: O(n), Space Complexity: O(1) 9 | */ 10 | 11 | class SuperPow { 12 | let base = 1337 13 | 14 | func superPow(a: Int, _ b: [Int]) -> Int { 15 | return _superPowHelper(a, b, b.count - 1) 16 | } 17 | 18 | private func _pow(a: Int, _ b: Int) -> Int { 19 | var ret = 1 20 | for _ in 0.. Int { 27 | guard idx >= 0 else { 28 | return 1 29 | } 30 | return _pow(_superPowHelper(a, b, idx - 1), 10) * _pow(a, b[idx]) % base 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Math/UglyNumber.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/ugly-number/ 3 | * Primary idea: Divided by 2, 3, 5 until it is equal to 1 4 | * Time Complexity: O(logn), Space Complexity: O(1) 5 | * 6 | */ 7 | 8 | class UglyNumber { 9 | func isUgly(num: Int) -> Bool { 10 | guard num > 0 else { 11 | return false 12 | } 13 | 14 | var num = num 15 | 16 | while num != 1 { 17 | if num % 2 == 0 { 18 | num /= 2 19 | } else if num % 3 == 0 { 20 | num /= 3 21 | } else if num % 5 == 0 { 22 | num /= 5 23 | } else { 24 | return false 25 | } 26 | } 27 | 28 | return true 29 | } 30 | } -------------------------------------------------------------------------------- /Math/UglyNumberII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/ugly-number-ii/ 3 | * Primary idea: Use three indices to build a helper array 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | * 6 | */ 7 | 8 | class UglyNumberII { 9 | func nthUglyNumber(n: Int) -> Int { 10 | guard n > 1 else { 11 | return 1 12 | } 13 | 14 | var uglyNums = [Int](count: n, repeatedValue: 1) 15 | 16 | var index2 = 0 17 | var index3 = 0 18 | var index5 = 0 19 | 20 | for i in 1.. Int { 33 | return storage.removeFirst() 34 | } 35 | 36 | /** Get the front element. */ 37 | func peek() -> Int { 38 | guard let first = storage.first else { return 0} 39 | return first 40 | } 41 | 42 | /** Returns whether the queue is empty. */ 43 | func empty() -> Bool { 44 | return storage.isEmpty 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Search/FindMinimumRotatedSortedArray.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/ 3 | * Primary idea: Classic Binary Search 4 | * 5 | * Time Complexity: O(logn), Space Complexity: O(1) 6 | */ 7 | 8 | class FindMinimumRotatedSortedArray { 9 | func findMin(_ nums: [Int]) -> Int { 10 | var minVal = Int.max 11 | var left = 0 12 | var right = nums.count - 1 13 | 14 | while left <= right { 15 | let mid = (right - left) / 2 + left 16 | if nums[mid] >= nums[left] { 17 | minVal = min(minVal, nums[left]) 18 | left = mid + 1 19 | } else { 20 | minVal = min(minVal, nums[mid]) 21 | right = mid - 1 22 | } 23 | } 24 | 25 | return minVal 26 | } 27 | } -------------------------------------------------------------------------------- /Search/FindMinimumRotatedSortedArrayII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/find-minimum-in-rotated-sorted-array-ii/ 3 | * Primary idea: Classic Binary Search 4 | * 5 | * Time Complexity: O(logn), Space Complexity: O(1) 6 | */ 7 | 8 | class FindMinimumRotatedSortedArrayII { 9 | func findMin(nums: [Int]) -> Int { 10 | var left = 0 11 | var right = nums.count - 1 12 | var mid = 0 13 | var minVal = Int.max 14 | 15 | while left + 1 < right { 16 | mid = (right - left) / 2 + left 17 | if nums[mid] > nums[left] { 18 | minVal = min(nums[left], minVal) 19 | left = mid + 1 20 | } else if nums [mid] < nums[left] { 21 | minVal = min(nums[mid], minVal) 22 | right = mid - 1 23 | } else { 24 | left += 1 25 | } 26 | } 27 | 28 | return min(minVal, nums[left], nums[right]) 29 | } 30 | } -------------------------------------------------------------------------------- /Search/FindPeakElement.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/find-peak-element/ 3 | * Primary idea: Classic Binary Search 4 | * 5 | * Time Complexity: O(logn), Space Complexity: O(1) 6 | */ 7 | 8 | class FindPeakElement { 9 | func findPeakElement(_ nums: [Int]) -> Int { 10 | var left = 0, right = nums.count - 1, mid = 0 11 | 12 | while left < right { 13 | mid = (right - left) / 2 + left 14 | 15 | if nums[mid] > nums[mid + 1] { 16 | right = mid 17 | } else { 18 | left = mid + 1 19 | } 20 | } 21 | 22 | return left 23 | } 24 | } -------------------------------------------------------------------------------- /Search/MinimizeMaxDistanceGasStation.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/minimize-max-distance-to-gas-station/ 3 | * Primary idea: Binary search to track minmax distance that can make, and update 4 | * boundary based on station add number K vs. distance possible stations number 5 | * 6 | * Time Complexity: O(nlogm), Space Complexity: O(1) 7 | */ 8 | 9 | class MinimizeMaxDistanceGasStation { 10 | func minmaxGasDist(_ stations: [Int], _ K: Int) -> Double { 11 | var left = Double(0), right = Double(stations.last! - stations.first!) 12 | 13 | while right - left >= pow(10, -6) { 14 | let mid = left + (right - left) / 2 15 | var count = 0 16 | 17 | for i in 0.. K { 22 | left = mid 23 | } else { 24 | right = mid 25 | } 26 | } 27 | 28 | return right 29 | } 30 | } -------------------------------------------------------------------------------- /Search/PeakIndexMountainArray.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/peak-index-in-a-mountain-array/ 3 | * Primary idea: Classic Binary Search 4 | * 5 | * Time Complexity: O(logn), Space Complexity: O(1) 6 | */ 7 | 8 | 9 | class PeakIndexMountainArray { 10 | func peakIndexInMountainArray(_ A: [Int]) -> Int { 11 | var left = 0, right = A.count - 1, mid = 0 12 | 13 | while left < right { 14 | mid = (right - left) / 2 + left 15 | 16 | if A[mid] > A[mid + 1] { 17 | right = mid 18 | } else { 19 | left = mid + 1 20 | } 21 | } 22 | 23 | return left 24 | } 25 | } -------------------------------------------------------------------------------- /Search/Search2DMatrixII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/search-a-2d-matrix-ii/ 3 | * Primary idea: Start from last element at first row, then move downwards or backwards 4 | * 5 | * Time Complexity: O(m + n), Space Complexity: O(1) 6 | */ 7 | 8 | class Search2DMatrixII { 9 | func searchMatrix(_ matrix: [[Int]], _ target: Int) -> Bool { 10 | guard matrix.count > 0 else { 11 | return false 12 | } 13 | 14 | var row = 0, col = matrix[0].count - 1 15 | 16 | while row < matrix.count && col >= 0 { 17 | if matrix[row][col] == target { 18 | return true 19 | } else if matrix[row][col] < target { 20 | row += 1 21 | } else { 22 | col -= 1 23 | } 24 | } 25 | 26 | return false 27 | } 28 | } -------------------------------------------------------------------------------- /Search/SearchInRotatedSortedArray.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/search-in-rotated-sorted-array/ 3 | * Primary idea: Binary Search, check left or right is sorted, then search in the part 4 | * 5 | * Time Complexity: O(logn), Space Complexity: O(1) 6 | */ 7 | 8 | class SearchInRotatedSortedArray { 9 | func search(nums: [Int], _ target: Int) -> Int { 10 | var left = 0 11 | var right = nums.count - 1 12 | var mid = 0 13 | 14 | while left <= right { 15 | mid = (right - left) / 2 + left 16 | 17 | if nums[mid] == target { 18 | return mid 19 | } 20 | 21 | if nums[mid] >= nums[left] { 22 | if nums[mid] > target && target >= nums[left] { 23 | right = mid - 1 24 | } else { 25 | left = mid + 1 26 | } 27 | } else { 28 | if nums[mid] < target && target <= nums[right] { 29 | left = mid + 1 30 | } else { 31 | right = mid - 1 32 | } 33 | } 34 | } 35 | 36 | return -1 37 | } 38 | } -------------------------------------------------------------------------------- /Search/SearchInsertPosition.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/search-insert-position/ 3 | * Primary idea: Binary Search, until two variables left 4 | * 5 | * Time Complexity: O(logn), Space Complexity: O(1) 6 | */ 7 | 8 | class SearchInsertPosition { 9 | func searchInsert(nums: [Int], _ target: Int) -> Int { 10 | guard nums.count > 0 else { 11 | return 0 12 | } 13 | 14 | var left = 0 15 | var right = nums.count - 1 16 | var mid = 0 17 | 18 | while left + 1 < right { 19 | mid = (right - left) / 2 + left 20 | if nums[mid] == target { 21 | return mid 22 | } else if nums[mid] < target { 23 | left = mid 24 | } else { 25 | right = mid 26 | } 27 | } 28 | 29 | if nums[right] < target { 30 | return right + 1 31 | } 32 | if nums[left] >= target { 33 | return left 34 | } 35 | 36 | return right 37 | } 38 | } -------------------------------------------------------------------------------- /Search/Sqrtx.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/sqrtx/ 3 | * Primary idea: Binary Search, right should start with x / 2 + 1, thus its square is x + x ^ 2 / 4 + 1, 4 | * which is definitely greater than x 5 | * 6 | * Note: please use (right - left) / 2 + left to get mid in case of integer overflow 7 | * 8 | * Time Complexity: O(logn), Space Complexity: O(1) 9 | */ 10 | 11 | class Sqrtx { 12 | func mySqrt(_ x: Int) -> Int { 13 | guard x >= 0 else { 14 | return 0 15 | } 16 | 17 | var left = 0, right = x / 2 + 1 18 | 19 | while left <= right { 20 | let mid = (right - left) / 2 + left 21 | 22 | if mid * mid == x { 23 | return mid 24 | } else if mid * mid < x { 25 | left = mid + 1 26 | } else { 27 | right = mid - 1 28 | } 29 | } 30 | 31 | return right 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Sort/ArrayPartitionI.swift: -------------------------------------------------------------------------------- 1 | class ArrayPartitionI { 2 | func arrayPairSum(_ nums: [Int]) -> Int { 3 | var arr = nums 4 | arr = arr.sorted() 5 | var res = 0 6 | for i in 0.. Int { 17 | return nums.sorted(by: <).enumerated() 18 | .flatMap { $0 % 2 == 0 ? $1 : nil } 19 | .reduce(0) { $0 + $1 } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Sort/KthLargestElementInArray.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/kth-largest-element-in-an-array/ 3 | * Primary idea: Quick sort 4 | * Time Complexity: O(nlogn), Space Complexity: O(n) 5 | */ 6 | 7 | class KthLargestElementInArray { 8 | func findKthLargest(_ nums: [Int], _ k: Int) -> Int { 9 | guard let pivot = nums.first else { 10 | fatalError("Invalid Input") 11 | } 12 | 13 | let leftPart = nums.filter { $0 > pivot } 14 | let middlePart = nums.filter { $0 == pivot} 15 | let rightPart = nums.filter { $0 < pivot } 16 | 17 | if nums.count == middlePart.count { 18 | return pivot 19 | } 20 | 21 | if leftPart.count > k - 1 { 22 | return findKthLargest(leftPart, k) 23 | } else if k - leftPart.count <= middlePart.count { 24 | return findKthLargest(middlePart, k - leftPart.count) 25 | } else { 26 | return findKthLargest(rightPart, k - leftPart.count - middlePart.count) 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /Sort/LargestNumber.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/largest-number/ 3 | * Primary idea: map and sort the array inplace to form the largest number. 4 | * 5 | * Time Complexity: O(nlogn), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class Solution { 10 | func largestNumber(_ A: [Int]) -> String { 11 | let result = A.map { "\($0)" }.sorted(by: { $0 + $1 > $1 + $0 }).joined() 12 | return result.first == "0" ? "0" : result 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Sort/MeetingRooms.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/meeting-rooms/ 3 | * Primary idea: Sort and traverse, find if any conflicts exist 4 | * Time Complexity: O(nlogn), Space Complexity: O(1) 5 | * 6 | * Definition for an interval. 7 | * public class Interval { 8 | * public var start: Int 9 | * public var end: Int 10 | * public init(_ start: Int, _ end: Int) { 11 | * self.start = start 12 | * self.end = end 13 | * } 14 | * } 15 | */ 16 | 17 | class MeetingRooms { 18 | func canAttendMeetings(intervals: [Interval]) -> Bool { 19 | guard intervals.count > 1 else { 20 | return true 21 | } 22 | 23 | var intervals = intervals.sort() { 24 | if $0.start != $1.start { 25 | return $0.start < $1.start 26 | } else { 27 | return $0.end < $1.end 28 | } 29 | } 30 | 31 | for i in 0.. intervals[i + 1].start { 33 | return false 34 | } 35 | } 36 | 37 | return true 38 | } 39 | } -------------------------------------------------------------------------------- /Sort/MeetingRoomsII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/meeting-rooms-ii/ 3 | * Primary idea: Sort start and end separately, then count conflicts 4 | * Time Complexity: O(nlogn), Space Complexity: O(n) 5 | * 6 | * Definition for an interval. 7 | * public class Interval { 8 | * public var start: Int 9 | * public var end: Int 10 | * public init(_ start: Int, _ end: Int) { 11 | * self.start = start 12 | * self.end = end 13 | * } 14 | * } 15 | */ 16 | 17 | class MeetingRoomsII { 18 | func minMeetingRooms(_ intervals: [[Int]]) -> Int { 19 | let startingTimes = intervals.map { interval in interval[0] }.sorted() 20 | let endingTimes = intervals.map { interval in interval[1] }.sorted() 21 | let intervalsCount = intervals.count 22 | 23 | var i = 0, j = 0, meetingRoomsNum = 0 24 | 25 | while i < intervalsCount && j < intervalsCount { 26 | if startingTimes[i] < endingTimes[j] { 27 | meetingRoomsNum += 1 28 | } else { 29 | j += 1 30 | } 31 | 32 | i += 1 33 | } 34 | 35 | return meetingRoomsNum 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Sort/MergeSortedArray.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/merge-sorted-array/ 3 | * Primary idea: Merge from tail to head to avoid override 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | */ 6 | 7 | class MergeSortedArray { 8 | func merge(_ nums1: inout [Int], _ m: Int, _ nums2: [Int], _ n: Int) { 9 | var i = m - 1, j = n - 1 10 | 11 | while i >= 0 || j >= 0 { 12 | if j < 0 || (i >= 0 && nums1[i] > nums2[j]) { 13 | nums1[i + j + 1] = nums1[i] 14 | i -= 1 15 | } else { 16 | nums1[i + j + 1] = nums2[j] 17 | j -= 1 18 | } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /Sort/SortColors.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/sort-colors/ 3 | * Primary idea: Bucket sort 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | */ 6 | 7 | class SortColors { 8 | func sortColors(_ nums: inout [Int]) { 9 | var red = 0, blue = nums.count - 1, i = 0 10 | 11 | while i <= blue { 12 | if nums[i] == 0 { 13 | _swap(&nums, i, red) 14 | red += 1 15 | i += 1 16 | } else if nums[i] == 1 { 17 | i += 1 18 | } else { 19 | _swap(&nums, i, blue) 20 | blue -= 1 21 | } 22 | } 23 | } 24 | 25 | fileprivate func _swap(_ nums: inout [T], _ p: Int, _ q: Int) { 26 | (nums[p], nums[q]) = (nums[q], nums[p]) 27 | } 28 | } -------------------------------------------------------------------------------- /Sort/TopKFrequentElements.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/top-k-frequent-elements/ 3 | * Primary idea: Use a map to track frenquency of each number, then sort keys based on values 4 | * 5 | * Time Complexity: O(nlogn), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class TopKFrequentElements { 10 | func topKFrequent(_ nums: [Int], _ k: Int) -> [Int] { 11 | let numFreq = Dictionary(nums.map { ($0, 1) }, uniquingKeysWith: +) 12 | 13 | let sortedNums = numFreq.keys.sorted { 14 | return numFreq[$0]! > numFreq[$1]! 15 | } 16 | 17 | return Array(sortedNums[0..= 2 else { 10 | return 11 | } 12 | 13 | for i in stride(from: 1, to: nums.count, by: 2) { 14 | let idx = getLargest(nums, i - 1, i , i + 1) 15 | (nums[i], nums[idx]) = (nums[idx], nums[i]) 16 | } 17 | } 18 | 19 | private func getLargest(_ nums: [Int], _ x: Int, _ y: Int, _ z: Int) -> Int { 20 | let len = nums.count 21 | 22 | let xVal = x >= 0 && x < len ? nums[x] : Int.min 23 | let yVal = y >= 0 && y < len ? nums[y] : Int.min 24 | let zVal = z >= 0 && z < len ? nums[z] : Int.min 25 | let maxVal = max(xVal, yVal, zVal) 26 | 27 | if maxVal == xVal { 28 | return x 29 | } else if maxVal == yVal { 30 | return y 31 | } else { 32 | return z 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /Sort/WiggleSortII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/wiggle-sort-ii/ 3 | * Primary idea: Sort and re-arrange the array 4 | * Time Complexity: O(nlogn), Space Complexity: O(n) 5 | */ 6 | 7 | class WiggleSortII { 8 | func wiggleSort(_ nums: inout [Int]) { 9 | let temp = nums.sorted() 10 | 11 | var m = temp.count 12 | var n = (m + 1) / 2 13 | 14 | for i in 0.. Int { 9 | var result = 0 10 | var num = 0 11 | var sign = 1 12 | var stack = [sign] 13 | 14 | for char in s { 15 | switch char { 16 | case "+", "-": 17 | result += num * sign 18 | sign = stack.last! * (char == "+" ? 1 : -1) 19 | num = 0 20 | case "(": 21 | stack.append(sign) 22 | case ")": 23 | stack.removeLast() 24 | case " ": 25 | break 26 | default: 27 | num = num * 10 + char.wholeNumberValue! 28 | } 29 | } 30 | 31 | return result + num * sign 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Stack/ExclusiveTimeFunctions.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/exclusive-time-of-functions/ 3 | * Primary idea: Use a stack to keep task start time, update it when a new task starts. 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | */ 6 | 7 | class ExclusiveTimeFunctions { 8 | func exclusiveTime(_ n: Int, _ logs: [String]) -> [Int] { 9 | var stack = [(Int, Int)](), res = Array(repeating: 0, count: n) 10 | 11 | for log in logs { 12 | // parse log 13 | let logInfo = log.components(separatedBy: ":") 14 | let id = Int(logInfo[0])!, isStart = logInfo[1] == "start", time = Int(logInfo[2])! 15 | 16 | if isStart { 17 | if let last = stack.last { 18 | res[last.0] += time - last.1 19 | } 20 | 21 | stack.append((id, time)) 22 | } else { 23 | let startTime = stack.removeLast().1 24 | 25 | res[id] += time - startTime + 1 26 | 27 | if var last = stack.last { 28 | last.1 = time + 1 29 | stack[stack.count - 1] = last 30 | } 31 | } 32 | } 33 | 34 | return res 35 | } 36 | } -------------------------------------------------------------------------------- /Stack/InorderTraversal.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/binary-tree-inorder-traversal/ 3 | * Primary idea: Use a stack to help iterate the tree 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | * 6 | * Definition for a binary tree node. 7 | * public class TreeNode { 8 | * public var val: Int 9 | * public var left: TreeNode? 10 | * public var right: TreeNode? 11 | * public init(_ val: Int) { 12 | * self.val = val 13 | * self.left = nil 14 | * self.right = nil 15 | * } 16 | * } 17 | */ 18 | class InorderTraversal { 19 | func inorderTraversal(_ root: TreeNode?) -> [Int] { 20 | var res = [Int](), stack = [TreeNode](), node = root 21 | 22 | while node != nil || !stack.isEmpty { 23 | if let currentNode = node { 24 | stack.append(currentNode) 25 | node = currentNode.left 26 | } else { 27 | let prevNode = stack.removeLast() 28 | res.append(prevNode.val) 29 | node = prevNode.right 30 | } 31 | } 32 | 33 | return res 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Stack/LargestRectangleInHistogram.swift: -------------------------------------------------------------------------------- 1 | class Solution { 2 | func largestRectangleArea(_ heights: [Int]) -> Int { 3 | var heights = [heights, [0]].flatMap{ $0 } 4 | var result = 0 5 | var stacks = [Int]() 6 | 7 | for i in 0.. Int { 9 | var stack = [Int](), longest = 0, start = 0 10 | 11 | for (i, char) in s.enumerated() { 12 | if char == "(" { 13 | stack.append(i) 14 | } else { 15 | if !stack.isEmpty { 16 | stack.removeLast() 17 | 18 | if let last = stack.last { 19 | longest = max(longest, i - last) 20 | } else { 21 | longest = max(longest, i - start + 1) 22 | } 23 | } else { 24 | start = i + 1 25 | } 26 | } 27 | } 28 | 29 | return longest 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Stack/MinStack.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/min-stack/ 3 | * Primary idea: Use a helper stack to help save the minimum values -- 4 | * only when the new pushed value is less than the top value, 5 | * and remove values correspond to pop operation 6 | * Time Complexity: O(1), Space Complexity: O(n) 7 | */ 8 | 9 | class MinStack { 10 | var stack: [Int] 11 | var minStack: [Int] 12 | 13 | /** initialize your data structure here. */ 14 | init() { 15 | stack = [Int]() 16 | minStack = [Int]() 17 | } 18 | 19 | func push(_ x: Int) { 20 | stack.append(x) 21 | 22 | if minStack.isEmpty || x <= minStack.last! { 23 | minStack.append(x) 24 | } 25 | } 26 | 27 | func pop() { 28 | guard !stack.isEmpty else { 29 | return 30 | } 31 | 32 | let removedVal = stack.removeLast() 33 | 34 | if let last = minStack.last, last == removedVal { 35 | minStack.removeLast() 36 | } 37 | } 38 | 39 | func top() -> Int { 40 | return stack.isEmpty ? -1 : stack.last! 41 | } 42 | 43 | func getMin() -> Int { 44 | return minStack.isEmpty ? -1 : minStack.last! 45 | } 46 | } -------------------------------------------------------------------------------- /Stack/PostorderTraversal.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/binary-tree-postorder-traversal/ 3 | * Primary idea: Use a stack to help iterate the tree, go right and insert at head 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | * 6 | * Definition for a binary tree node. 7 | * public class TreeNode { 8 | * public var val: Int 9 | * public var left: TreeNode? 10 | * public var right: TreeNode? 11 | * public init(_ val: Int) { 12 | * self.val = val 13 | * self.left = nil 14 | * self.right = nil 15 | * } 16 | * } 17 | */ 18 | 19 | class PostorderTraversal { 20 | func postorderTraversal(root: TreeNode?) -> [Int] { 21 | var res = [Int]() 22 | var stack = [TreeNode]() 23 | var node = root 24 | 25 | while !stack.isEmpty || node != nil { 26 | if node != nil { 27 | res.insert(node!.val, atIndex: 0) 28 | stack.append(node!) 29 | node = node!.right 30 | } else { 31 | node = stack.removeLast().left 32 | } 33 | } 34 | 35 | return res 36 | } 37 | } -------------------------------------------------------------------------------- /Stack/PreorderTraversal.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/binary-tree-preorder-traversal/ 3 | * Primary idea: Use a stack to help iterate the tree 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | * 6 | * Definition for a binary tree node. 7 | * public class TreeNode { 8 | * public var val: Int 9 | * public var left: TreeNode? 10 | * public var right: TreeNode? 11 | * public init(_ val: Int) { 12 | * self.val = val 13 | * self.left = nil 14 | * self.right = nil 15 | * } 16 | * } 17 | */ 18 | 19 | class PreorderTraversal { 20 | func preorderTraversal(root: TreeNode?) -> [Int] { 21 | var res = [Int]() 22 | var stack = [TreeNode]() 23 | var node = root 24 | 25 | while !stack.isEmpty || node != nil { 26 | if node != nil { 27 | res.append(node!.val) 28 | stack.append(node!) 29 | node = node!.left 30 | } else { 31 | node = stack.removeLast().right 32 | } 33 | } 34 | 35 | return res 36 | } 37 | } -------------------------------------------------------------------------------- /Stack/RemoveKDigits.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/remove-k-digits/ 3 | * Primary idea: Keep a stack to ensure its numbers are ascending so that the number 4 | * is the smallest, truncate it to right size and handle edge cases 5 | * Time Complexity: O(n), Space Complexity: O(n) 6 | */ 7 | 8 | class RemoveKDigits { 9 | func removeKdigits(_ num: String, _ k: Int) -> String { 10 | var res = [Character](), k = k 11 | let numChars = String(num).characters, size = numChars.count - k 12 | 13 | for char in numChars { 14 | while k > 0 && res.count > 0 && charToInt(res.last!) > charToInt(char) { 15 | res.removeLast() 16 | k -= 1 17 | } 18 | res.append(char) 19 | } 20 | 21 | res = Array(res[0.. Int { 34 | return Int(String(c))! 35 | } 36 | } -------------------------------------------------------------------------------- /Stack/SimplifyPath.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/simplify-path/ 3 | * Primary idea: Use a stack, normal to push, .. to pop 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | */ 6 | 7 | class SimplifyPath { 8 | func simplifyPath(_ path: String) -> String { 9 | var directories = [String]() 10 | let components = path.split(separator: "/") 11 | for component in components { 12 | switch component { 13 | case "": break // do nothing 14 | case ".": break // do nothing, pointing to the current directory 15 | case "..": 16 | directories.popLast() // if empty, does nothing 17 | default: 18 | directories.append(String(component)) 19 | } 20 | } 21 | return "/" + String(directories.joined(separator: "/")) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Stack/TernaryExpressionParser.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/ternary-expression-parser/ 3 | * Primary idea: Use a stack and go from right to left, pop when peek is "?" 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | */ 6 | 7 | class TernaryExpressionParser { 8 | func parseTernary(_ expression: String) -> String { 9 | var stack = [Character]() 10 | 11 | for char in expression.characters.reversed() { 12 | if !stack.isEmpty && stack.last! == "?" { 13 | stack.removeLast() 14 | let first = stack.removeLast() 15 | stack.removeLast() 16 | let second = stack.removeLast() 17 | 18 | if char == "T" { 19 | stack.append(first) 20 | } else { 21 | stack.append(second) 22 | } 23 | } else { 24 | stack.append(char) 25 | } 26 | } 27 | 28 | 29 | return stack.isEmpty ? "" : String(stack.last!) 30 | } 31 | } -------------------------------------------------------------------------------- /Stack/ValidParentheses.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/valid-parentheses/ 3 | * Primary idea: Use a stack to see whether the peek left brace is correspond to the current right one 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | */ 6 | 7 | class ValidParentheses { 8 | func isValid(_ s: String) -> Bool { 9 | var stack = [Character]() 10 | 11 | for char in s { 12 | if char == "(" || char == "[" || char == "{" { 13 | stack.append(char) 14 | } else if char == ")" { 15 | guard stack.count != 0 && stack.removeLast() == "(" else { 16 | return false 17 | } 18 | } else if char == "]" { 19 | guard stack.count != 0 && stack.removeLast() == "[" else { 20 | return false 21 | } 22 | } else if char == "}" { 23 | guard stack.count != 0 && stack.removeLast() == "{" else { 24 | return false 25 | } 26 | } 27 | } 28 | 29 | return stack.isEmpty 30 | } 31 | } -------------------------------------------------------------------------------- /String/AddStrings.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/add-strings/ 3 | * Primary idea: reverse two strings and add them using sum && carry idea 4 | * 5 | * Note: do not forget to reverse afterwards 6 | * 7 | * Time Complexity: O(n), Space Complexity: O(1) 8 | * 9 | */ 10 | 11 | class AddStrings { 12 | func addStrings(_ num1: String, _ num2: String) -> String { 13 | let num1Chars = Array(num1.characters.reversed()) 14 | let num2Chars = Array(num2.characters.reversed()) 15 | var i = 0, j = 0, sum = 0, carry = 0 16 | var res = "" 17 | 18 | while i < num1Chars.count || j < num2Chars.count || carry != 0 { 19 | sum = carry 20 | 21 | if i < num1Chars.count { 22 | sum += Int(String(num1Chars[i]))! 23 | i += 1 24 | } 25 | if j < num2Chars.count { 26 | sum += Int(String(num2Chars[j]))! 27 | j += 1 28 | } 29 | 30 | carry = sum / 10 31 | sum = sum % 10 32 | 33 | res.append(String(sum)) 34 | } 35 | 36 | return String(res.characters.reversed()) 37 | } 38 | } -------------------------------------------------------------------------------- /String/CountAndSay.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/count-and-say/ 3 | * Primary idea: Recursion to get previous string, then iterate and generate current one. 4 | * 5 | * Time Complexity: O(n^2), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class CountAndSay { 10 | func countAndSay(_ n: Int) -> String { 11 | if n == 1 { 12 | return "1" 13 | } 14 | 15 | let previousStr = countAndSay(n - 1) 16 | var currentChar = previousStr.first!, currentCount = 0, res = "" 17 | 18 | for (i, char) in previousStr.enumerated() { 19 | if char == currentChar { 20 | currentCount += 1 21 | } else { 22 | res += "\(currentCount)\(currentChar)" 23 | 24 | currentCount = 1 25 | currentChar = char 26 | } 27 | } 28 | 29 | res += "\(currentCount)\(currentChar)" 30 | 31 | return res 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /String/DetectCapital.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/detect-capital/ 3 | * Primary idea: Counts uppercased characters then compare to the standards. 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class DetectCapital { 10 | func detectCapitalUse(_ word: String) -> Bool { 11 | var capitalNum = 0, isFirstUpperCased = false 12 | 13 | for char in word { 14 | if char.isUpperCased() { 15 | capitalNum += 1 16 | } 17 | } 18 | 19 | if let firstChar = word.first { 20 | isFirstUpperCased = firstChar.isUpperCased() 21 | } 22 | 23 | return capitalNum == 0 || (capitalNum == 1 && isFirstUpperCased) || capitalNum == word.count 24 | } 25 | } 26 | 27 | fileprivate extension Character { 28 | func isUpperCased() -> Bool { 29 | return String(self).uppercased() == String(self) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /String/DetermineIfTwoStringsAreClose.swift: -------------------------------------------------------------------------------- 1 | class Solution { 2 | func closeStrings(_ word1: String, _ word2: String) -> Bool { 3 | var dic1 = Dictionary(grouping: Array(word1)) { $0 } 4 | var dic2 = Dictionary(grouping: Array(word2)) { $0 } 5 | 6 | return dic1.map { $0.0 }.sorted() == dic2.map { $0.0 }.sorted() 7 | && dic1.map { $1.count }.sorted() == dic2.map { $1.count }.sorted() 8 | } 9 | } -------------------------------------------------------------------------------- /String/FirstUniqueCharacterInString.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/first-unique-character-in-a-string/ 3 | * Primary idea: Keep track of existence of each character in the string 4 | * 5 | * Note: The maximum space of the dictionary is 26, so space complexity is O(1) 6 | * 7 | * Time Complexity: O(n), Space Complexity: O(1) 8 | * 9 | */ 10 | 11 | class FirstUniqueCharacterInString { 12 | func firstUniqChar(_ s: String) -> Int { 13 | var dict = [Character: Bool]() 14 | 15 | for char in s.characters { 16 | if let isDup = dict[char] { 17 | dict[char] = true 18 | } else { 19 | dict[char] = false 20 | } 21 | } 22 | 23 | for (i, char) in Array(s.characters).enumerated() { 24 | if !dict[char]! { 25 | return i 26 | } 27 | } 28 | 29 | return -1 30 | } 31 | } -------------------------------------------------------------------------------- /String/FizzBuzz.swift: -------------------------------------------------------------------------------- 1 | class Solution { 2 | func fizzBuzz(_ n: Int) -> [String] { 3 | var result = [String]() 4 | for x in 1...n { 5 | let m3 = x.isMultiple(of: 3) 6 | let m5 = x.isMultiple(of: 5) 7 | 8 | switch (m3, m5) { 9 | case (true, true): 10 | result.append("FizzBuzz") 11 | case (true, false): 12 | result.append("Fizz") 13 | case (false, true): 14 | result.append("Buzz") 15 | default: 16 | result.append("\(x)") 17 | } 18 | } 19 | 20 | return result 21 | } 22 | } -------------------------------------------------------------------------------- /String/FlipGame.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/flip-game/ 3 | * Primary idea: Iterate the string and change all "++" to "--" 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | */ 6 | 7 | class FlipGame { 8 | func generatePossibleNextMoves(_ s: String) -> [String] { 9 | var res = [String]() 10 | let sChars = Array(s) 11 | 12 | guard sChars.count > 1 else { 13 | return res 14 | } 15 | 16 | for i in 0.. [[String]] { 11 | var sortedStrToStrs = [String: [String]]() 12 | 13 | for str in strs { 14 | let sortedStr = String(str.sorted()) 15 | 16 | sortedStrToStrs[sortedStr, default: []].append(str) 17 | } 18 | 19 | return Array(sortedStrToStrs.values) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /String/IsomorphicStrings.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/isomorphic-strings/ 3 | * Primary idea: Use two dictionaries to help 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | */ 6 | 7 | class IsomorphicStrings { 8 | func isIsomorphic(_ s: String, _ t: String) -> Bool { 9 | guard s.count == t.count else { 10 | return false 11 | } 12 | 13 | var stDict = [Character: Character](), tsDict = [Character: Character]() 14 | let s = Array(s), t = Array(t) 15 | 16 | for (i, sChar) in s.enumerated() { 17 | let tChar = t[i] 18 | 19 | if stDict[sChar] == nil && tsDict[tChar] == nil { 20 | stDict[sChar] = tChar 21 | tsDict[tChar] = sChar 22 | } else if stDict[sChar] != tChar || tsDict[tChar] != sChar { 23 | return false 24 | } 25 | } 26 | 27 | return true 28 | } 29 | } -------------------------------------------------------------------------------- /String/KeyboardRow.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/keyboard-row/ 3 | * Primary idea: Use filter to determine the word is subset or not. 4 | * 5 | * Note: You can also use intersect() or union() functions to solve this problem. 6 | * 7 | * Time Complexity: O(nm), Space Complexity: O(n) 8 | * 9 | */ 10 | 11 | class KeyboardRow { 12 | func findWords(_ words: [String]) -> [String] { 13 | let rowOne = "qwertyuiop", rowTwo = "asdfghjkl", rowThree = "zxcvbnm" 14 | 15 | return words.filter { word in rowOne.contains(word.lowercased()) || rowTwo.contains(word.lowercased()) || rowThree.contains(word.lowercased()) } 16 | } 17 | } 18 | 19 | extension String { 20 | func contains(_ word: String) -> Bool { 21 | return word.filter { c in !self.contains(c) }.count == 0 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /String/LengthLastWord.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/length-of-last-word/ 3 | * Primary idea: Iterate the string in backward direction 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | */ 6 | 7 | class LengthLastWord { 8 | func lengthOfLastWord(s: String) -> Int { 9 | var res = 0 10 | var sChars = [Character](s.characters) 11 | 12 | guard sChars.count != 0 else { 13 | return 0 14 | } 15 | 16 | for i in (0...sChars.count - 1).reverse() { 17 | if res == 0 { 18 | if sChars[i] == " " { 19 | continue 20 | } else { 21 | res += 1 22 | } 23 | } else { 24 | if sChars[i] == " " { 25 | break 26 | } else { 27 | res += 1 28 | } 29 | } 30 | } 31 | 32 | return res 33 | } 34 | } -------------------------------------------------------------------------------- /String/LongestCommonPrefix.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/longest-common-prefix/ 3 | * Primary idea: Use the first string as the result at first, trim it while iterating the array 4 | * Time Complexity: O(nm), Space Complexity: O(m), m stands for the length of longest prefix 5 | */ 6 | 7 | class LongestCommonPrefix { 8 | func longestCommonPrefix(_ strs: [String]) -> String { 9 | guard let firstStr = strs.first else { 10 | return "" 11 | } 12 | 13 | var res = "" 14 | 15 | for (i, char) in firstStr.enumerated() { 16 | // dropFirst(_ k: Int = 1) returns a Substring struct 17 | for str in strs.dropFirst() { 18 | if i == str.count { 19 | return res 20 | } 21 | 22 | // Another easy way: Array(str)[i], time complexity is linear though 23 | let currentStrChar = str[str.index(str.startIndex, offsetBy: i)] 24 | 25 | if char != currentStrChar { 26 | return res 27 | } 28 | } 29 | res.append(char) 30 | } 31 | 32 | return res 33 | } 34 | } -------------------------------------------------------------------------------- /String/LongestSubstringWithoutRepeatingCharacters.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/longest-substring-without-repeating-characters/ 3 | * Primary idea: Use a dictionary to hold the next possible valid position of characters of the non-repeating substring, 4 | * and then iterate the string to update maxLen, dictionary, and startIdx encountering duplicates 5 | * 6 | * Note: Swift does not have a way to access a character in a string with O(1), 7 | * thus we have to first transfer the string to a character array 8 | * Time Complexity: O(n), Space Complexity: O(n) 9 | * 10 | */ 11 | 12 | class LongestSubstringWithoutRepeatingCharacters { 13 | func lengthOfLongestSubstring(_ s: String) -> Int { 14 | var maxLen = 0, startIdx = 0, charToPos = [Character: Int]() 15 | let sChars = Array(s) 16 | 17 | for (i, char) in sChars.enumerated() { 18 | if let pos = charToPos[char] { 19 | startIdx = max(startIdx, pos) 20 | } 21 | 22 | // update to next valid position 23 | charToPos[char] = i + 1 24 | maxLen = max(maxLen, i - startIdx + 1) 25 | } 26 | 27 | return maxLen 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /String/PalindromePermutation.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/palindrome-permutation/ 3 | * Primary idea: Use a dictionary to track each character's frequency 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | */ 6 | 7 | class PalindromePermutation { 8 | func canPermutePalindrome(_ s: String) -> Bool { 9 | var oddNum = 0 10 | 11 | for (_, value) in s.frequencies where value % 2 == 1 { 12 | oddNum += 1 13 | 14 | if oddNum >= 2 { 15 | return false 16 | } 17 | } 18 | 19 | return true 20 | } 21 | } 22 | 23 | extension Sequence where Element: Hashable { 24 | var frequencies: [Element: Int] { 25 | return Dictionary(self.map{ ($0, 1)}, uniquingKeysWith: +) 26 | } 27 | } -------------------------------------------------------------------------------- /String/RansomNote.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/ransom-note/ 3 | * Primary idea: Use a dictionary to calculate the existence of characters in magazine 4 | * and check with the ransom Note 5 | * 6 | * Time Complexity: O(n), Space Complexity: O(n) 7 | */ 8 | 9 | class RansomNote { 10 | func canConstruct(ransomNote: String, _ magazine: String) -> Bool { 11 | var magazineMap = _strToMap(magazine) 12 | 13 | for char in ransomNote.characters { 14 | if magazineMap[char] == nil { 15 | return false 16 | } else if magazineMap[char] == 0 { 17 | return false 18 | } else { 19 | magazineMap[char]! -= 1 20 | } 21 | } 22 | 23 | return true 24 | } 25 | 26 | private func _strToMap(magazine: String) -> [Character: Int] { 27 | var res = [Character: Int]() 28 | 29 | for char in magazine.characters { 30 | if res[char] == nil { 31 | res[char] = 1 32 | } else { 33 | res[char]! += 1 34 | } 35 | } 36 | 37 | return res 38 | } 39 | } -------------------------------------------------------------------------------- /String/ReverseString.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/reverse-string/ 3 | * Primary idea: Use reverse() to help reverse the string 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class ReverseString { 10 | func reverseString(s: String) -> String { 11 | return String(s.reversed()) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /String/ReverseStringII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/reverse-string-ii/ 3 | * Primary idea: Use reversed() to help reverse the string 4 | * 5 | * Note: Avoid index out of range error as k will pass the right edge of the string 6 | * 7 | * Time Complexity: O(n), Space Complexity: O(n) 8 | * 9 | */ 10 | 11 | class ReverseStringII { 12 | func reverseStr(_ s: String, _ k: Int) -> String { 13 | var chars = [Character](s.characters), res = [Character]() 14 | 15 | if k < 0 { 16 | fatalError("Invalid k") 17 | } 18 | 19 | for i in stride(from: 0, to: chars.count, by: 2 * k) { 20 | print(i) 21 | 22 | if chars.count < i + k { 23 | res += chars[i.. String { 12 | var left = 0, right = s.count - 1 13 | var chars = Array(s) 14 | 15 | while left < right { 16 | let isVowelLeft = isVowel(chars[left]), isVowelRight = isVowel(chars[right]) 17 | 18 | if isVowelLeft && isVowelRight { 19 | chars.swapAt(left, right) 20 | left += 1 21 | right -= 1 22 | } else { 23 | if !isVowelLeft { 24 | left += 1 25 | } else { 26 | right -= 1 27 | } 28 | } 29 | } 30 | 31 | return String(chars) 32 | } 33 | 34 | private func isVowel(_ char: Character) -> Bool { 35 | return Set("aeiouAEIOU").contains(char) 36 | } 37 | } -------------------------------------------------------------------------------- /String/ReverseWordsString.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/reverse-words-in-a-string/ 3 | * Primary idea: Trim and split the original string to a string array, 4 | * reverse it and then join strings in the array to a single one. 5 | * 6 | * Time Complexity: O(n), Space Complexity: O(1) 7 | * 8 | */ 9 | 10 | class ReverseWordsString { 11 | func reverseWords(_ s: String) -> String { 12 | return s.split(separator: " ").reversed().joined(separator: " ") 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /String/ReverseWordsStringII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/reverse-words-in-a-string-ii/ 3 | * Primary idea: Reverse the whole string, then reverse every word 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class ReverseWordsStringII { 10 | func reverseWords(_ str: inout [Character]) { 11 | var last = 0 12 | 13 | reverse(&str, 0, str.count - 1) 14 | 15 | for i in 0..(_ array: inout [T], _ startIdx: Int, _ endIdx: Int) { 24 | var (left, right) = (startIdx, endIdx) 25 | 26 | while left < right { 27 | (array[left], array[right]) = (array[right], array[left]) 28 | left += 1 29 | right -= 1 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /String/ReverseWordsStringIII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/reverse-words-in-a-string-iii/ 3 | * Primary idea: Check the empty space to get the previous word, then reverse it 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class ReverseWordsStringIII { 10 | func reverseWords(_ s: String) -> String { 11 | var last = 0, str = Array(s) 12 | 13 | for i in 0..(_ array: inout [T], _ startIdx: Int, _ endIdx: Int) { 24 | var (left, right) = (startIdx, endIdx) 25 | 26 | while left < right { 27 | (array[left], array[right]) = (array[right], array[left]) 28 | left += 1 29 | right -= 1 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /String/ShortestDistanceToACharacter.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/shortest-distance-to-a-character/ 3 | * Primary idea: Iterate through left and right to get min distance by compared between indices of C at two sides. 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class ShortestDistanceToACharacter { 10 | func shortestToChar(_ S: String, _ C: Character) -> [Int] { 11 | var res = Array(repeating: 0, count: S.count), cIndex = -10000, sChars = Array(S) 12 | 13 | for (i, sChar) in sChars.enumerated() { 14 | if sChar == C { 15 | cIndex = i 16 | } 17 | 18 | res[i] = i - cIndex 19 | } 20 | 21 | cIndex = -10000 22 | 23 | for i in (0.. Int { 9 | let hChars = Array(haystack.characters), nChars = Array(needle.characters) 10 | let hLen = hChars.count, nLen = nChars.count 11 | 12 | guard hLen >= nLen else { 13 | return -1 14 | } 15 | guard nLen != 0 else { 16 | return 0 17 | } 18 | 19 | for i in 0...hLen - nLen { 20 | if hChars[i] == nChars[0] { 21 | for j in 0.. Int { 13 | var index = 0, currentCount = 0 14 | 15 | for i in 0.. Bool { 9 | let sCharsFreq = Dictionary(s.map { ($0, 1) }, uniquingKeysWith: +) 10 | let tCharsFreq = Dictionary(t.map { ($0, 1) }, uniquingKeysWith: +) 11 | 12 | return sCharsFreq == tCharsFreq 13 | } 14 | } -------------------------------------------------------------------------------- /String/ValidPalindrome.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/valid-palindrome/ 3 | * Primary idea: For every index in the first half of the String, compare two values at mirroring indices. 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class ValidPalindrome { 10 | func isPalindrome(_ s: String) -> Bool { 11 | var i = 0, j = s.count - 1 12 | let sChars = Array(s.lowercased()) 13 | 14 | while i < j { 15 | while !sChars[i].isAlphanumeric && i < j { 16 | i += 1 17 | } 18 | 19 | while !sChars[j].isAlphanumeric && i < j { 20 | j -= 1 21 | } 22 | 23 | if sChars[i] != sChars[j] { 24 | return false 25 | } else { 26 | i += 1 27 | j -= 1 28 | } 29 | } 30 | 31 | return true 32 | } 33 | } 34 | 35 | extension Character { 36 | var isValid: Bool { 37 | return isLetter || isNumber 38 | } 39 | } -------------------------------------------------------------------------------- /String/ValidPalindromeII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/valid-palindrome-ii/ 3 | * Primary idea: Take advantage of validPalindrome, and jump left and right separately to get correct character should be deleted 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class ValidPalindromeII { 10 | func validPalindrome(_ s: String) -> Bool { 11 | let s = Array(s) 12 | return isValid(true, s) || isValid(false, s) 13 | } 14 | 15 | private func isValid(_ skipLeft: Bool, _ s: [Character]) -> Bool { 16 | var i = 0, j = s.count - 1, alreadySkipped = false 17 | 18 | while i < j { 19 | if s[i] == s[j] { 20 | i += 1 21 | j -= 1 22 | } else { 23 | if alreadySkipped { 24 | return false 25 | } else { 26 | alreadySkipped = true 27 | if skipLeft { 28 | i += 1 29 | } else { 30 | j -= 1 31 | } 32 | } 33 | } 34 | } 35 | 36 | return true 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /String/WordPattern.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/word-pattern/ 3 | * Primary idea: Use two dictionarys to determine if a character is unique to a word 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | */ 6 | 7 | class WordPattern { 8 | func wordPattern(_ pattern: String, _ str: String) -> Bool { 9 | let strs = str.split(separator: " ").map(String.init) 10 | 11 | guard pattern.count == strs.count else { 12 | return false 13 | } 14 | 15 | var patternToWord = [Character: String]() 16 | 17 | for (i, char) in pattern.enumerated() { 18 | let word = strs[i] 19 | 20 | if let charWord = patternToWord[char] { 21 | if charWord != word { 22 | return false 23 | } 24 | } else { 25 | if patternToWord.values.contains(word) { 26 | return false 27 | } else { 28 | patternToWord[char] = word 29 | } 30 | } 31 | } 32 | 33 | return true 34 | } 35 | } -------------------------------------------------------------------------------- /String/ZigZagConverstion.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/zigzag-conversion/ 3 | * 4 | * Primary idea: The first and the last row, loop length is (2 * numRows - 2) 5 | * For each row between them, should insert another number, index = index + 2 * (numRows - i - 1) 6 | * 7 | * Time Complexity: O(log(n + m)), Space Complexity: O(1) 8 | * 9 | */ 10 | 11 | class Solution { 12 | func convert(s: String, _ numRows: Int) -> String { 13 | if numRows == 1 { 14 | return s 15 | } 16 | 17 | var ret: [Character] = [] 18 | var chars: [Character] = [Character](s.characters) 19 | let cnt = chars.count 20 | 21 | 22 | for i in 0.. Bool { 21 | return checkHeight(root) != -1 22 | } 23 | 24 | private func checkHeight(_ root: TreeNode?) -> Int { 25 | guard let root = root else { 26 | return 0 27 | } 28 | 29 | let left = checkHeight(root.left), right = checkHeight(root.right) 30 | 31 | if left == -1 || right == -1 { 32 | return -1 33 | } 34 | 35 | if abs(left - right) > 1 { 36 | return -1 37 | } 38 | 39 | return max(left, right) + 1 40 | } 41 | } -------------------------------------------------------------------------------- /Tree/BinaryTreeUpsideDown.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/binary-tree-upside-down/ 3 | * Primary idea: Mark left one as current node, change its left and right and 4 | * keep going to right until to the leaf 5 | * Time Complexity: O(n), Space Complexity: O(1) 6 | * 7 | * Definition for a binary tree node. 8 | * public class TreeNode { 9 | * public var val: Int 10 | * public var left: TreeNode? 11 | * public var right: TreeNode? 12 | * public init(_ val: Int) { 13 | * self.val = val 14 | * self.left = nil 15 | * self.right = nil 16 | * } 17 | * } 18 | */ 19 | 20 | class BinaryTreeUpsideDown { 21 | func upsideDownBinaryTree(_ root: TreeNode?) -> TreeNode? { 22 | var parent: TreeNode? 23 | var node: TreeNode? = root 24 | var right: TreeNode? 25 | 26 | while node != nil { 27 | let left = node!.left 28 | node!.left = right 29 | right = node!.right 30 | node!.right = parent 31 | parent = node 32 | node = left 33 | } 34 | 35 | return parent 36 | } 37 | } -------------------------------------------------------------------------------- /Tree/ConvertSortedArrayBinarySearchTree.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/convert-sorted-array-to-binary-search-tree/ 3 | * Primary idea: recursion, the root of subtree should always be mid point of the subarray 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | * 6 | * Definition for a binary tree node. 7 | * public class TreeNode { 8 | * public var val: Int 9 | * public var left: TreeNode? 10 | * public var right: TreeNode? 11 | * public init(_ val: Int) { 12 | * self.val = val 13 | * self.left = nil 14 | * self.right = nil 15 | * } 16 | * } 17 | */ 18 | 19 | class ConvertSortedArrayBinarySearchTree { 20 | func sortedArrayToBST(_ nums: [Int]) -> TreeNode? { 21 | return sortedArrayToBST(nums, 0, nums.count - 1) 22 | } 23 | 24 | private func sortedArrayToBST(_ nums: [Int], _ leftIdx: Int, _ rightIdx: Int) -> TreeNode? { 25 | guard leftIdx <= rightIdx else { 26 | return nil 27 | } 28 | 29 | let mid = (rightIdx - leftIdx) / 2 + leftIdx 30 | let root = TreeNode(nums[mid]) 31 | 32 | root.left = sortedArrayToBST(nums, leftIdx, mid - 1) 33 | root.right = sortedArrayToBST(nums, mid + 1, rightIdx) 34 | 35 | return root 36 | } 37 | } -------------------------------------------------------------------------------- /Tree/DiameterBinaryTree.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/diameter-of-binary-tree/ 3 | * Primary idea: recursion, update globel diameter along with maxDepth 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | * 6 | * Definition for a binary tree node. 7 | * public class TreeNode { 8 | * public var val: Int 9 | * public var left: TreeNode? 10 | * public var right: TreeNode? 11 | * public init(_ val: Int) { 12 | * self.val = val 13 | * self.left = nil 14 | * self.right = nil 15 | * } 16 | * } 17 | */ 18 | 19 | class DiameterBinaryTree { 20 | var diameter = 0 21 | 22 | func diameterOfBinaryTree(_ root: TreeNode?) -> Int { 23 | maxDepth(root) 24 | 25 | return diameter 26 | } 27 | 28 | fileprivate func maxDepth(_ node: TreeNode?) -> Int { 29 | guard let node = node else { 30 | return 0 31 | } 32 | 33 | let (left, right) = (maxDepth(node.left), maxDepth(node.right)) 34 | 35 | diameter = max(diameter, left + right) 36 | 37 | return max(left, right) + 1 38 | } 39 | } -------------------------------------------------------------------------------- /Tree/HouseRobberIII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/house-robber-iii/ 3 | * Primary idea: Using two sums to track rob sum starting from current node or not, 4 | * compare and get the maximum one 5 | * Time Complexity: O(n), Space Complexity: O(1) 6 | * 7 | * Definition for a binary tree node. 8 | * public class TreeNode { 9 | * public var val: Int 10 | * public var left: TreeNode? 11 | * public var right: TreeNode? 12 | * public init(_ val: Int) { 13 | * self.val = val 14 | * self.left = nil 15 | * self.right = nil 16 | * } 17 | * } 18 | */ 19 | 20 | class HouseRobberIII { 21 | func rob(_ root: TreeNode?) -> Int { 22 | let (robRoot, notRobRoot) = helper(root) 23 | 24 | return max(robRoot, notRobRoot) 25 | } 26 | 27 | fileprivate func helper(_ node: TreeNode?) -> (Int, Int) { 28 | guard let node = node else { 29 | return (0, 0) 30 | } 31 | 32 | let (robLeft, notRobLeft) = helper(node.left) 33 | let (robRight, notRobRight) = helper(node.right) 34 | 35 | let robNode = notRobLeft + notRobRight + node.val 36 | let notRobNode = max(robLeft, notRobLeft) + max(robRight, notRobRight) 37 | 38 | return (robNode, notRobNode) 39 | } 40 | } -------------------------------------------------------------------------------- /Tree/InvertBinaryTree.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/invert-binary-tree/ 3 | * Primary idea: recursion, swap left and right of current node each time 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | * 6 | * Definition for a binary tree node. 7 | * public class TreeNode { 8 | * public var val: Int 9 | * public var left: TreeNode? 10 | * public var right: TreeNode? 11 | * public init(_ val: Int) { 12 | * self.val = val 13 | * self.left = nil 14 | * self.right = nil 15 | * } 16 | * } 17 | */ 18 | 19 | class InvertBinaryTree { 20 | func invertTree(_ root: TreeNode?) -> TreeNode? { 21 | guard let root = root else { 22 | return nil 23 | } 24 | 25 | (root.left, root.right) = (root.right, root.left) 26 | 27 | invertTree(root.left) 28 | invertTree(root.right) 29 | 30 | return root 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Tree/KthSmallestElementBST.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/kth-smallest-element-in-a-bst/ 3 | * Primary idea: use stack to do inorder traverse and track k to find answer 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | * 6 | * Definition for a binary tree node. 7 | * public class TreeNode { 8 | * public var val: Int 9 | * public var left: TreeNode? 10 | * public var right: TreeNode? 11 | * public init(_ val: Int) { 12 | * self.val = val 13 | * self.left = nil 14 | * self.right = nil 15 | * } 16 | * } 17 | */ 18 | 19 | class KthSmallestElementBST { 20 | func kthSmallest(_ root: TreeNode?, _ k: Int) -> Int { 21 | var stack = [TreeNode](), currentNode = root, k = k 22 | 23 | while !stack.isEmpty || currentNode != nil { 24 | if currentNode != nil { 25 | stack.append(currentNode!) 26 | currentNode = currentNode!.left 27 | } else { 28 | let node = stack.removeLast() 29 | k -= 1 30 | 31 | if k == 0 { 32 | return node.val 33 | } 34 | 35 | currentNode = node.right 36 | } 37 | } 38 | 39 | return -1 40 | } 41 | } -------------------------------------------------------------------------------- /Tree/MaximumDepthOfBinaryTree.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/maximum-depth-of-binary-tree/ 3 | * Primary idea: recursion, return 0 when it is a leaf node 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | * 6 | * Definition for a binary tree node. 7 | * public class TreeNode { 8 | * public var val: Int 9 | * public var left: TreeNode? 10 | * public var right: TreeNode? 11 | * public init(_ val: Int) { 12 | * self.val = val 13 | * self.left = nil 14 | * self.right = nil 15 | * } 16 | * } 17 | */ 18 | 19 | class MaximumDepthOfBinaryTree { 20 | func maxDepth(_ root: TreeNode?) -> Int { 21 | guard let root = root else { 22 | return 0 23 | } 24 | 25 | return max(maxDepth(root.left), maxDepth(root.right)) + 1 26 | } 27 | } -------------------------------------------------------------------------------- /Tree/MergeTwoBinaryTrees.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * public class TreeNode { 4 | * public var val: Int 5 | * public var left: TreeNode? 6 | * public var right: TreeNode? 7 | * public init(_ val: Int) { 8 | * self.val = val 9 | * self.left = nil 10 | * self.right = nil 11 | * } 12 | * } 13 | */ 14 | class MergeTwoBinaryTrees { 15 | func mergeTrees(_ t1: TreeNode?, _ t2: TreeNode?) -> TreeNode? { 16 | guard let t1 = t1 else { 17 | return t2 18 | } 19 | guard let t2 = t2 else { 20 | return t1 21 | } 22 | t1.val += t2.val 23 | t1.left = mergeTrees(t1.left, t2.left) 24 | t1.right = mergeTrees(t1.right, t2.right) 25 | return t1 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Tree/MinimumDepthOfBinaryTree.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/minimum-depth-of-binary-tree/ 3 | * Primary idea: recursion, similar as maximum depth of a binary tree, need handle edge case first 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | * 6 | * Definition for a binary tree node. 7 | * public class TreeNode { 8 | * public var val: Int 9 | * public var left: TreeNode? 10 | * public var right: TreeNode? 11 | * public init(_ val: Int) { 12 | * self.val = val 13 | * self.left = nil 14 | * self.right = nil 15 | * } 16 | * } 17 | */ 18 | 19 | class MinimumDepthOfBinaryTree { 20 | func minDepth(root: TreeNode?) -> Int { 21 | guard let root = root else { 22 | return 0 23 | } 24 | 25 | return _helper(root) 26 | } 27 | 28 | private func _helper(root: TreeNode?) -> Int { 29 | guard let root = root else { 30 | return Int.max 31 | } 32 | 33 | if root.left == nil && root.right == nil { 34 | return 1 35 | } 36 | 37 | return min(_helper(root.left), _helper(root.right)) + 1 38 | } 39 | } -------------------------------------------------------------------------------- /Tree/PathSum.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/path-sum/ 3 | * Primary idea: recursion 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | * 6 | * Definition for a binary tree node. 7 | * public class TreeNode { 8 | * public var val: Int 9 | * public var left: TreeNode? 10 | * public var right: TreeNode? 11 | * public init(_ val: Int) { 12 | * self.val = val 13 | * self.left = nil 14 | * self.right = nil 15 | * } 16 | * } 17 | */ 18 | 19 | class PathSum { 20 | func hasPathSum(_ root: TreeNode?, _ sum: Int) -> Bool { 21 | guard let root = root else { 22 | return false 23 | } 24 | if sum == root.val && root.left == nil && root.right == nil { 25 | return true 26 | } 27 | 28 | return hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Tree/SameTree.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/same-tree/ 3 | * Primary idea: recursion 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | * 6 | * Copyright © 2016 YiGu. All rights reserved. 7 | * 8 | * Definition for a binary tree node. 9 | * public class TreeNode { 10 | * public var val: Int 11 | * public var left: TreeNode? 12 | * public var right: TreeNode? 13 | * public init(_ val: Int) { 14 | * self.val = val 15 | * self.left = nil 16 | * self.right = nil 17 | * } 18 | * } 19 | */ 20 | 21 | class SameTree { 22 | func isSameTree(_ p: TreeNode?, _ q: TreeNode?) -> Bool { 23 | guard let p = p else { 24 | return q == nil 25 | } 26 | guard let q = q else { 27 | return p == nil 28 | } 29 | 30 | if p.val != q.val { 31 | return false 32 | } 33 | 34 | return isSameTree(p.left, q.left) && isSameTree(p.right, q.right) 35 | } 36 | } -------------------------------------------------------------------------------- /Tree/SerializeDeserializeNAryTree.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/serialize-and-deserialize-n-ary-tree/ 3 | * Primary idea: Preorder 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | * 6 | * Definition for a binary tree node. 7 | * public class TreeNode { 8 | * public var val: Int 9 | * public var children: [TreeNode] 10 | 11 | * public init(_ val: Int) { 12 | * self.val = val 13 | * self.children = [TreeNode]() 14 | * } 15 | * } 16 | */ 17 | 18 | class SerializeDeserializeNAryTree { 19 | func serialize(_ root: Node?) -> String { 20 | guard let root = root else { 21 | return "" 22 | } 23 | 24 | return String(root.val) + String(root.children.count) + root.children.map { serialize($0) }.joined() 25 | } 26 | 27 | func deserialize(_ vals: inout String) -> Node? { 28 | guard let rootVal = Int(String(vals.removeFirst())) else { 29 | return nil 30 | } 31 | 32 | let root = Node(rootVal), size = String(vals.removeFirst()) 33 | 34 | for _ in 0.. Int { 21 | guard let root = root else { 22 | return 0 23 | } 24 | 25 | var res = 0 26 | helper(root.left, true, &res) 27 | helper(root.right, false, &res) 28 | 29 | return res 30 | } 31 | 32 | private func helper(_ node: TreeNode?, _ isLeft: Bool, _ res: inout Int) { 33 | guard let node = node else { 34 | return 35 | } 36 | if node.left == nil && node.right == nil && isLeft { 37 | res += node.val 38 | } 39 | 40 | helper(node.left, true, &res) 41 | helper(node.right, false, &res) 42 | } 43 | } -------------------------------------------------------------------------------- /Tree/SymmetricTree.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/symmetric-tree/ 3 | * Primary idea: recursion 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | * 6 | * Definition for a binary tree node. 7 | * public class TreeNode { 8 | * public var val: Int 9 | * public var left: TreeNode? 10 | * public var right: TreeNode? 11 | * public init(_ val: Int) { 12 | * self.val = val 13 | * self.left = nil 14 | * self.right = nil 15 | * } 16 | * } 17 | * 18 | */ 19 | 20 | class SymmetricTree { 21 | func isSymmetric(_ root: TreeNode?) -> Bool { 22 | guard let root = root else { 23 | return true 24 | } 25 | 26 | return isSymmetricHelper(root.left, root.right) 27 | } 28 | 29 | private func isSymmetricHelper(_ left: TreeNode?, _ right: TreeNode?) -> Bool { 30 | if left == nil && right == nil { 31 | return true 32 | } 33 | 34 | if let left = left, let right = right, left.val == right.val { 35 | return isSymmetricHelper(left.left, right.right) && isSymmetricHelper(left.right, right.left) 36 | } else { 37 | return false 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /Tree/UniqueBinarySearchTrees.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/unique-binary-search-trees/ 3 | * Primary idea: Dynamic programming, for each node as root, dp[i] += dp[j] * dp[i - j - 1] 4 | * 5 | * Time Complexity: O(n^2), Space Complexity: O(n) 6 | * 7 | * Definition for a binary tree node. 8 | * public class TreeNode { 9 | * public var val: Int 10 | * public var left: TreeNode? 11 | * public var right: TreeNode? 12 | * public init(_ val: Int) { 13 | * self.val = val 14 | * self.left = nil 15 | * self.right = nil 16 | * } 17 | * } 18 | */ 19 | 20 | class UniqueBinarySearchTrees { 21 | func numTrees(_ n: Int) -> Int { 22 | guard n > 1 else { 23 | return 1 24 | } 25 | 26 | var dp = Array(repeating: 0, count: n + 1) 27 | dp[0] = 1 28 | 29 | for i in 1...n { 30 | for j in 0.. Bool { 21 | return _helper(root, nil, nil) 22 | } 23 | 24 | private func _helper(_ node: TreeNode?, _ min: Int?, _ max: Int?) -> Bool { 25 | guard let node = node else { 26 | return true 27 | } 28 | 29 | if let min = min, node.val <= min { 30 | return false 31 | } 32 | if let max = max, node.val >= max { 33 | return false 34 | } 35 | 36 | return _helper(node.left, min, node.val) && _helper(node.right, node.val, max) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TerryHuangHD/LeetCode-Swift-Forked/eed765b4c283932fd8e3b13811d91328768729d4/logo.png --------------------------------------------------------------------------------