├── logo.png ├── Leetcode_Contributors.png ├── String ├── ReverseString.swift ├── ReverseWordsString.swift ├── ValidAnagram.swift ├── GroupAnagrams.swift ├── MinimumStepsMakeTwoStringsAnagram.swift ├── FlipGame.swift ├── PalindromePermutation.swift ├── KeyboardRow.swift ├── FizzBuzz.swift ├── ShortestWayFormString.swift ├── DetectCapital.swift ├── FirstUniqueCharacterInString.swift ├── IsomorphicStrings.swift ├── LengthLastWord.swift ├── CountAndSay.swift ├── ReverseWordsStringII.swift ├── ReverseWordsStringIII.swift ├── StrStr.swift ├── ValidPalindrome.swift ├── StudentAttendanceRecordI.swift ├── ShortestDistanceToACharacter.swift ├── WordPattern.swift ├── LicenseKeyFormatting.swift ├── ReverseStringII.swift ├── RansomNote.swift ├── AddStrings.swift ├── LongestCommonPrefix.swift ├── ReverseVowelsOfAString.swift └── StringCompression.swift ├── Array ├── ContainsDuplicate.swift ├── RemoveElement.swift ├── SortArrayByParity.swift ├── TwoSum.swift ├── FirstMissingPositive.swift ├── MoveZeroes.swift ├── MajorityElement.swift ├── RemoveDuplicatesFromSortedArray.swift ├── MaxConsecutiveOnes.swift ├── Heaters.swift ├── RotateImage.swift ├── IntersectionTwoArrays.swift ├── FindDisappearedNumbers.swift ├── ContainsDuplicateII.swift ├── IncreasingTripletSubsequence.swift ├── RemoveDuplicatesFromSortedArrayII.swift ├── TwoSumII.swift ├── IntersectionTwoArraysII.swift ├── MaximumSizeSubarraySumEqualsK.swift ├── IslandPerimeter.swift ├── SquaresSortedArray.swift ├── MinimumSizeSubarraySum.swift ├── TwoSumLessThanK.swift ├── SummaryRanges.swift ├── MaximizeDistanceToClosestPerson.swift ├── ShortestWordDistance.swift ├── LongestConsecutiveSequence.swift ├── GasStation.swift ├── DiagonalTraverse.swift ├── StrobogrammaticNumber.swift ├── MissingRanges.swift ├── TwoSumIII.swift ├── NumberBoomerangs.swift ├── ShortestWordDistanceIII.swift ├── ShortestWordDistanceII.swift └── TaskScheduler.swift ├── Math ├── PowerTwo.swift ├── PowerThree.swift ├── SingleNumber.swift ├── FactorialTrailingZeroes.swift ├── MissingNumber.swift ├── HammingDistance.swift ├── SumTwoIntegers.swift ├── GaryCode.swift ├── ExcelSheetColumnNumber.swift ├── NumberComplement.swift ├── MinimumMovesEqualArrayElements.swift ├── Pow.swift ├── AddDigits.swift ├── PlusOne.swift ├── ReverseInteger.swift ├── RectangleArea.swift ├── CountingBits.swift ├── UglyNumber.swift ├── HappyNumber.swift ├── MaximumSplitPositiveEvenIntegers.swift ├── ContainerMostWater.swift ├── PalindromeNumber.swift ├── IntegerBreak.swift ├── SuperPow.swift ├── AddBinary.swift ├── LineReflection.swift ├── AddTwoNumbers.swift ├── CountPrimes.swift ├── SingleNumberII.swift ├── UglyNumberII.swift ├── PermutationSequence.swift ├── KthSmallestLexicographicalOrder.swift ├── RomanToInteger.swift ├── SparseMatrixMultiplication.swift └── DivideTwoIntegers.swift ├── Sort ├── LargestNumber.swift ├── ArrayPartitionI.swift ├── TopKFrequentElements.swift ├── WiggleSortII.swift ├── MergeSortedArray.swift ├── SortColors.swift ├── KthLargestElementInArray.swift ├── MergeIntervals.swift ├── MeetingRooms.swift ├── WiggleSort.swift └── MeetingRoomsII.swift ├── DP ├── HouseRobber.swift ├── BestTimeBuySellStockII.swift ├── MaximumSubarray.swift ├── Triangle.swift ├── ClimbingStairs.swift ├── JumpGame.swift ├── PaintFence.swift ├── PaintHouse.swift ├── WiggleSubsequence.swift ├── CoinChangeII.swift ├── MaximumProductSubarray.swift ├── BestTimeBuySellStock.swift ├── PerfectSquares.swift ├── CombinationSumIV.swift ├── WordBreak.swift ├── HouseRobberII.swift ├── MinimumPathSum.swift ├── MinCostClimbingStairs.swift ├── UniquePaths.swift ├── LongestCommonSubsequence.swift ├── BestTimeBuySellStockCooldown.swift ├── CoinChange.swift ├── DecodeWays.swift ├── GenerateParentheses.swift ├── FlipGameII.swift ├── LongestIncreasingSubsequence.swift ├── UniquePathsII.swift ├── EditDistance.swift ├── WildcardMatching.swift ├── MaximumNumberPointsCost.swift ├── LongestPalindromicSubstring.swift ├── BestTimeBuySellStockIII.swift ├── GuessNumberHigherOrLowerII.swift ├── DungeonGame.swift ├── MaximalSquare.swift └── RegularExpressionMatching.swift ├── Search ├── FindPeakElement.swift ├── PeakIndexMountainArray.swift ├── FindMinimumRotatedSortedArray.swift ├── Search2DMatrixII.swift ├── FindMinimumRotatedSortedArrayII.swift ├── Sqrtx.swift ├── SearchInsertPosition.swift ├── MinimizeMaxDistanceGasStation.swift └── SearchInRotatedSortedArray.swift ├── DFS ├── Subsets.swift ├── Combinations.swift ├── SubsetsII.swift ├── FactorCombinations.swift ├── Permutations.swift ├── IsGraphBipartite.swift ├── WordBreakII.swift ├── CombinationSum.swift ├── GeneralizedAbbreviation.swift ├── CombinationSumII.swift ├── PermutationsII.swift └── CombinationSumIII.swift ├── Tree ├── MergeTwoBinaryTrees.swift ├── MaximumDepthOfBinaryTree.swift ├── PathSum.swift ├── InvertBinaryTree.swift ├── SameTree.swift ├── UniqueBinarySearchTrees.swift ├── DiameterBinaryTree.swift ├── BinaryTreeUpsideDown.swift ├── MinimumDepthOfBinaryTree.swift ├── BalancedBinaryTree.swift ├── ValidateBinarySearchTree.swift └── SymmetricTree.swift ├── SlidingWindow ├── FrequencyMostFrequentElement.swift ├── SlidingWindowMaximum.swift └── LongestSubstringWithoutRepeatingCharacters.swift ├── Stack ├── SimplifyPath.swift ├── BasicCalculator.swift ├── ValidParentheses.swift ├── LongestValidParentheses.swift ├── TernaryExpressionParser.swift ├── PreorderTraversal.swift ├── InorderTraversal.swift ├── PostorderTraversal.swift ├── RemoveKDigits.swift └── MinStack.swift ├── Design ├── SnapshotArray.swift ├── ShuffleAnArray.swift └── Vector2D.swift ├── LinkedList ├── RemoveLinkedListElements.swift ├── RemoveDuplicatesFromSortedList.swift ├── RemoveNthFromEnd.swift ├── SwapNodesInPairs.swift ├── MergeTwoSortedLists.swift ├── PartitionList.swift └── ReverseLinkedList.swift ├── License.md ├── Graph ├── CourseScheduleII.swift ├── NumberConnectedComponentsUndirectedGraph.swift ├── GraphValidTree.swift ├── CourseSchedule.swift └── EarliestMomentFriends.swift └── Queue └── ImplementQueueUsingStacks.swift /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soapyigu/LeetCode-Swift/HEAD/logo.png -------------------------------------------------------------------------------- /Leetcode_Contributors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soapyigu/LeetCode-Swift/HEAD/Leetcode_Contributors.png -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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/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/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/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 | } -------------------------------------------------------------------------------- /Array/RemoveElement.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/remove-element/ 3 | * Primary idea: keep a index, compare the element at that index with val while moving forward 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | * 6 | */ 7 | 8 | class RemoveElement { 9 | func removeElement(inout nums: [Int], _ val: Int) -> Int { 10 | nums = nums.filter { (num) in num != val } 11 | return nums.count 12 | } 13 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /DP/HouseRobber.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/house-robber/ 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 HouseRobber { 9 | func rob(nums: [Int]) -> 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 | } -------------------------------------------------------------------------------- /Math/HammingDistance.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/hamming-distance/ 3 | * Primary idea: Bit manipulation, use xor and right shift 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(1) 6 | */ 7 | 8 | class HammingDistance { 9 | func hammingDistance(_ x: Int, _ y: Int) -> 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/SumTwoIntegers.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/sum-of-two-integers/ 3 | * Primary idea: Add is based on xor, and carry is left shift by one, add carry until it is zero 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class SumTwoIntegers { 10 | func getSum(a: Int, _ b: Int) -> 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 | } -------------------------------------------------------------------------------- /String/ValidAnagram.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/valid-anagram/ 3 | * Primary idea: Compare two strings' characters' frequency 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | */ 6 | 7 | class ValidAnagram { 8 | func isAnagram(s: String, _ t: String) -> 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/GroupAnagrams.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/anagrams/ 3 | * Primary idea: Iterate the string array and categories strings with the same sorted one 4 | * 5 | * Time Complexity: O(nmlogm), n stands for number of words, m stands for the length of a word 6 | * Space Complexity: O(n) 7 | */ 8 | 9 | class GroupAnagrams { 10 | func groupAnagrams(_ strs: [String]) -> [[String]] { 11 | return Array(Dictionary(strs.map { (String($0.sorted()), [$0]) }, uniquingKeysWith: +).values) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /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 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 { 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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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.. 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 | } -------------------------------------------------------------------------------- /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 { 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 | } -------------------------------------------------------------------------------- /String/MinimumStepsMakeTwoStringsAnagram.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/minimum-number-of-steps-to-make-two-strings-anagram/ 3 | * Primary idea: Check character frequency in the original string and replace all redundant ones. 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | */ 6 | 7 | class MinimumStepsMakeTwoStringsAnagram { 8 | func minSteps(_ s: String, _ t: String) -> Int { 9 | var tFreq = Dictionary(t.map { ($0, 1) }, uniquingKeysWith: +) 10 | 11 | for char in s { 12 | tFreq[char, default: 0] -= 1 13 | } 14 | 15 | return tFreq.values.filter { $0 > 0 }.reduce(0) { $0 + $1 } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /DP/MaximumSubarray.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/maximum-subarray/ 3 | * Primary idea: Dynamic Programming, each character should be either with previous sequence or 4 | * start a new sequence as the maximum one 5 | * Time Complexity: O(n), Space Complexity: O(1) 6 | */ 7 | 8 | class MaximumSubarray { 9 | func maxSubArray(nums: [Int]) -> Int { 10 | var max_current = nums[0] 11 | var max_global = nums[0] 12 | 13 | for i in 1.. 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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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.. 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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /DP/PaintFence.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/paint-fence/ 3 | * Primary idea: Dynamic Programming, the current ways are either same as of different than previous one 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class PaintFence { 10 | func numWays(_ n: Int, _ k: Int) -> 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]] { 11 | var res = [[Int]](), path = [Int]() 12 | 13 | dfs(&res, &path, 0, nums) 14 | 15 | return res 16 | } 17 | 18 | private func dfs(_ res: inout [[Int]], _ path: inout [Int], _ idx: Int, _ nums: [Int]) { 19 | res.append(path) 20 | 21 | for i in idx.. 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 { 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 | } -------------------------------------------------------------------------------- /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/CountingBits.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/counting-bits/ 3 | * Primary idea: 4 | * bits[i] = bits[i - p] + 1, while p is the largest power of two that smaller than i; 5 | * 6 | * Time Complexity: O(n), Space Complexity: O(n) 7 | */ 8 | 9 | class CountingBits { 10 | func countBits(num: Int) -> [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/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/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 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 { 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 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /DP/MaximumProductSubarray.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/maximum-product-subarray/ 3 | * Primary idea: Dynamic Programming, track max and min at the same time 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | */ 6 | 7 | class MaximumProductSubarray { 8 | func maxProduct(nums: [Int]) -> 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] { 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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /Math/MaximumSplitPositiveEvenIntegers.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/maximum-split-of-positive-even-integers/ 3 | * Primary idea: Greedy. The most split should contain numbers as small as possible. 4 | * Time Complexity: O(logn), Space Complexity: O(1) 5 | * 6 | */ 7 | 8 | class MaximumSplitPositiveEvenIntegers { 9 | func maximumEvenSplit(_ finalSum: Int) -> [Int] { 10 | guard finalSum % 2 == 0 else { 11 | return [] 12 | } 13 | 14 | var res = [Int](), candidate = 2, currentSum = 0 15 | 16 | while (currentSum + candidate) <= finalSum { 17 | res.append(candidate) 18 | currentSum += candidate 19 | candidate += 2 20 | } 21 | res[res.count - 1] += finalSum - currentSum 22 | 23 | return res 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /SlidingWindow/FrequencyMostFrequentElement.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/frequency-of-the-most-frequent-element/ 3 | * Primary idea: Slding window, sort the nums and move left if k cannot make current window even. 4 | * 5 | * Time Complexity: O(nlogn), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class FrequencyMostFrequentElement { 10 | func maxFrequency(_ nums: [Int], _ k: Int) -> Int { 11 | let nums = nums.sorted() 12 | var left = 0, res = 1, sum = 0 13 | 14 | for (i, num) in nums.enumerated() { 15 | sum += num 16 | 17 | while (i - left + 1) * num - sum > k { 18 | sum -= nums[left] 19 | left += 1 20 | } 21 | 22 | res = max(res, i - left + 1) 23 | } 24 | 25 | return res 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /String/FizzBuzz.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/fizz-buzz/ 3 | * Primary idea: Iterate the array and handle multiples of 3 or 5 separately. 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class FizzBuzz { 10 | func fizzBuzz(_ n: Int) -> [String] { 11 | var res = [String]() 12 | 13 | if n < 0 { 14 | return res 15 | } 16 | 17 | for i in 1...n { 18 | if i % 3 == 0 && i % 5 == 0 { 19 | res.append("FizzBuzz") 20 | } else if i % 3 == 0 { 21 | res.append("Fizz") 22 | } else if i % 5 == 0 { 23 | res.append("Buzz") 24 | } else { 25 | res.append("\(i)") 26 | } 27 | } 28 | 29 | return res 30 | } 31 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /DP/PerfectSquares.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/perfect-squares/ 3 | * Primary idea: Dynamic Programming, transition function is 4 | * nums[i] = min(nums[i], nums[i - j * j] + 1) 5 | * Time Complexity: O(n^2), Space Complexity: O(n) 6 | */ 7 | 8 | class PerfectSquares { 9 | func numSquares(n: Int) -> 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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /DFS/Combinations.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/combinations/ 3 | * Primary idea: Classic Depth-first Search, another version of Subsets 4 | * 5 | * Time Complexity: O(2^n), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class Combinations { 10 | func combine(_ n: Int, _ k: Int) -> [[Int]] { 11 | var res = [[Int]](), path = [Int]() 12 | 13 | dfs(&res, &path, 0, Array(1...n), k) 14 | 15 | return res 16 | } 17 | 18 | private func dfs(_ res: inout [[Int]], _ path: inout [Int], _ idx: Int, _ nums: [Int], _ k: Int) { 19 | if path.count == k { 20 | res.append(path) 21 | } 22 | 23 | for i in idx.. 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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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.. 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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /DP/WordBreak.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/word-break/ 3 | * Primary idea: DP. dp[i] = dp[j] && dict.contains(s[j.. Bool { 9 | let dict = Set(wordDict), s = Array(s) 10 | var dp = Array(repeating: false, count: s.count + 1) 11 | dp[0] = true 12 | 13 | for i in 1...s.count { 14 | for j in 0.. [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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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/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 | let m = grid.count, n = grid[0].count 10 | var dp = grid 11 | 12 | for i in 0.. Int { 9 | var res = 0, idx = 0 10 | let s = Array(source), t = Array(target) 11 | 12 | while idx < t.count { 13 | let pre = idx 14 | 15 | for i in 0.. Int { 24 | snapshotArrayMap[count] = array 25 | count += 1 26 | 27 | return count - 1 28 | } 29 | 30 | func get(_ index: Int, _ snap_id: Int) -> Int { 31 | return snapshotArrayMap[snap_id]?[index] ?? 0 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /DP/MinCostClimbingStairs.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/min-cost-climbing-stairs/description/ 3 | * Primary idea: Dynamic Programming, dp[i] represents the current element will be 4 | * added to previous smallest sum, so the Bellman equation is 5 | * dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i] 6 | * Time Complexity: O(n), Space Complexity: O(n) 7 | * 8 | */ 9 | 10 | class MinCostClimbingStairs { 11 | func minCostClimbingStairs(_ cost: [Int]) -> 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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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/SquaresSortedArray.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/squares-of-a-sorted-array/ 3 | * Primary idea: Two pointers. Compare absolute value and assign the bigger one to the right most index of the result. 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | * 6 | */ 7 | 8 | class SquaresSortedArray { 9 | func sortedSquares(_ nums: [Int]) -> [Int] { 10 | var left = 0, right = nums.count - 1, res = Array(repeating: 0, count: nums.count) 11 | var square = 0, idx = nums.count - 1 12 | 13 | while left <= right { 14 | 15 | if abs(nums[left]) < abs(nums[right]) { 16 | square = nums[right] 17 | right -= 1 18 | } else { 19 | square = nums[left] 20 | left += 1 21 | } 22 | 23 | res[idx] = square * square 24 | idx -= 1 25 | } 26 | 27 | return res 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 redIdx = 0, blueIdx = nums.count - 1, currentIdx = 0 10 | 11 | while currentIdx <= blueIdx { 12 | let num = nums[currentIdx] 13 | 14 | if num == 0 { 15 | swap(&nums, redIdx, currentIdx) 16 | redIdx += 1 17 | } else if num == 2 { 18 | swap(&nums, currentIdx, blueIdx) 19 | blueIdx -= 1 20 | currentIdx -= 1 21 | } 22 | 23 | currentIdx += 1 24 | } 25 | } 26 | 27 | private func swap(_ nums: inout [Int], _ left: Int, _ right: Int) { 28 | (nums[left], nums[right]) = (nums[right], nums[left]) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /DFS/SubsetsII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/subsets-ii/ 3 | * Primary idea: Classic Depth-first Search, avoid duplicates by adopting the first occurrence 4 | * 5 | * Time Complexity: O(n * 2^n), Space Complexity: O(n * 2^n) 6 | * 7 | */ 8 | 9 | class SubsetsII { 10 | func subsetsWithDup(_ nums: [Int]) -> [[Int]] { 11 | var res = [[Int]](), path = [Int]() 12 | 13 | dfs(&res, &path, 0, nums.sorted()) 14 | 15 | return res 16 | } 17 | 18 | private func dfs(_ res: inout [[Int]], _ path: inout [Int], _ idx: Int, _ nums: [Int]) { 19 | res.append(path) 20 | 21 | for i in idx.. 0 && nums[i] == nums[i - 1] && i != idx { 23 | continue 24 | } 25 | 26 | path.append(nums[i]) 27 | dfs(&res, &path, i + 1, nums) 28 | path.removeLast() 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /DFS/FactorCombinations.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/factor-combinations/ 3 | * Primary idea: Classic Depth-first Search 4 | * 5 | * Time Complexity: O(n^n), Space Complexity: O(2^n - 1) 6 | * 7 | */ 8 | 9 | class FactorCombinations { 10 | func getFactors(_ n: Int) -> [[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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /DP/LongestCommonSubsequence.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/longest-common-subsequence/ 3 | * Primary idea: Dynamic Programming, dp[i][j] = dp[i - 1][j - 1] + 1 or max(dp[i - 1][j], dp[i][j - 1]) 4 | * 5 | * Time Complexity: O(mn), Space Complexity: O(1) 6 | */ 7 | 8 | class LongestCommonSubsequence { 9 | func longestCommonSubsequence(_ text1: String, _ text2: String) -> Int { 10 | let text1Chars = Array(text1), text2Chars = Array(text2) 11 | let m = text1.count, n = text2.count 12 | var dp = Array(repeating: Array(repeating: 0, count: n + 1), count: m + 1) 13 | 14 | for i in 1...m { 15 | for j in 1...n { 16 | if text1Chars[i - 1] == text2Chars[j - 1] { 17 | dp[i][j] = dp[i - 1][j - 1] + 1 18 | } else { 19 | dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) 20 | } 21 | } 22 | } 23 | 24 | return dp[m][n] 25 | } 26 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /Array/ShortestWordDistance.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/shortest-word-distance/ 3 | * Primary idea: Iterate and update index and distance when encounter word1 or word2 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | */ 6 | 7 | class ShortestWordDistance { 8 | func shortestDistance(_ words: [String], _ word1: String, _ word2: String) -> 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 | } -------------------------------------------------------------------------------- /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/StrStr.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/implement-strstr/ 3 | * Primary idea: Iterate two strings 4 | * Time Complexity: O(nm), Space Complexity: O(n) 5 | */ 6 | 7 | class StrStr { 8 | func strStr(_ haystack: String, _ needle: String) -> 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 { 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/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 | switch char { 13 | case "(", "[", "{": 14 | stack.append(char) 15 | case ")": 16 | if stack.popLast() != "(" { 17 | return false 18 | } 19 | case "]": 20 | if stack.popLast() != "[" { 21 | return false 22 | } 23 | case "}": 24 | if stack.popLast() != "{" { 25 | return false 26 | } 27 | default: 28 | continue 29 | } 30 | } 31 | 32 | return stack.isEmpty 33 | } 34 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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/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 | } -------------------------------------------------------------------------------- /SlidingWindow/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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /Stack/LongestValidParentheses.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/longest-valid-parentheses/ 3 | * Primary idea: Push index to a stack and pop encountering ")" 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | */ 6 | 7 | class LongestValidParentheses { 8 | func longestValidParentheses(_ s: String) -> 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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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.. 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 | } -------------------------------------------------------------------------------- /Array/GasStation.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/gas-station/ 3 | * Primary idea: use currentSum and total to keep track of the gas and cost, 4 | * change start index when currentSum is less than 0 5 | * 6 | * Time Complexity: O(n), Space Complexity: O(1) 7 | * 8 | */ 9 | 10 | class GasStation { 11 | func canCompleteCircuit(_ gas: [Int], _ cost: [Int]) -> 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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /Sort/MergeIntervals.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/merge-intervals/ 3 | * Primary idea: Sort the original intervals and then append them one by one 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 MergeIntervals { 18 | func merge(_ intervals: [[Int]]) -> [[Int]] { 19 | let intervals = intervals.sorted { return $0[0] < $1[0] } 20 | var res = [intervals[0]] 21 | 22 | for interval in intervals[1.. 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 | } -------------------------------------------------------------------------------- /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 isAlphanumeric: Bool { 37 | return isLetter || isNumber 38 | } 39 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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/DecodeWays.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/decode-ways/ 3 | * Primary idea: Dynamic Programming, dp[i] = dp[i - 1] + dp[i - 2], 4 | * determine if current one or two characters are number at first 5 | * Time Complexity: O(n), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class DecodeWays { 10 | func numDecodings(_ s: String) -> 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/GenerateParentheses.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/generate-parentheses/ 3 | * Primary idea: Insert left and right parentheses and ensure they are valid 4 | * Time Complexity: O(2^n), Space Complexity: O(n) 5 | * 6 | */ 7 | 8 | class GenerateParentheses { 9 | func generateParenthesis(_ n: Int) -> [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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /String/StudentAttendanceRecordI.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/student-attendance-record-i/ 3 | * Primary idea: Iterate the string and check late & absent counts to check the eligibility. 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class StudentAttendanceRecordI { 10 | func checkRecord(_ s: String) -> Bool { 11 | var ACount = 0, LCount = 0 12 | let sChars = Array(s) 13 | 14 | for i in 0..= 2 { 19 | return false 20 | } 21 | } else if sChars[i] == "L" { 22 | if i > 0 && sChars[i - 1] == "L" { 23 | LCount += 1 24 | 25 | if LCount >= 3 { 26 | return false 27 | } 28 | } else { 29 | LCount = 1 30 | } 31 | } 32 | } 33 | 34 | return true 35 | } 36 | } -------------------------------------------------------------------------------- /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 { 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 | 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] { 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] { 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 | } -------------------------------------------------------------------------------- /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.. 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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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] { 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/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 | -------------------------------------------------------------------------------- /DFS/WordBreakII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/word-break-ii/ 3 | * Primary idea: DFS. Termination case is index hits the end of the string 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class WordBreakII { 10 | func wordBreak(_ s: String, _ wordDict: [String]) -> [String] { 11 | var res = [String](), path = [String]() 12 | 13 | dfs(&res, &path, Array(s), Set(wordDict), 0) 14 | 15 | return res 16 | } 17 | 18 | private func dfs(_ res: inout [String], _ path: inout [String], _ s: [Character], _ dict: Set, _ idx: Int) { 19 | if idx >= s.count { 20 | res.append(path.joined(separator: " ")) 21 | return 22 | } 23 | 24 | for i in idx..= 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 | } -------------------------------------------------------------------------------- /String/LicenseKeyFormatting.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/license-key-formatting/ 3 | * Primary idea: traverse the array formatted string from end. Insert the dash into the String as per given K, else insert the elements at index 0. 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class LicenseKeyFormatting { 10 | func licenseKeyFormatting(_ S: String, _ K: Int) -> String { 11 | guard S.count > 0 && K > 0 else{ 12 | return "" 13 | } 14 | 15 | let upperCaseString = Array(S.uppercased()) 16 | var result = [Character](), n = K 17 | 18 | for i in stride(from: S.count - 1, through: 0, by: -1){ 19 | let aCharacter = upperCaseString[i] 20 | guard aCharacter != "-" else{ 21 | continue 22 | } 23 | 24 | if n == 0{ 25 | result.insert("-", at: 0) 26 | n = K 27 | } 28 | 29 | result.insert(aCharacter, at: 0) 30 | n -= 1 31 | } 32 | 33 | return String(result) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /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.. 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 | } -------------------------------------------------------------------------------- /DFS/CombinationSum.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/combination-sum/ 3 | * Primary idea: Classic Depth-first Search 4 | * 5 | * Time Complexity: O(2^n), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class CombinationSum { 10 | func combinationSum(_ candidates: [Int], _ target: Int) -> [[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.. [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.. [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 | -------------------------------------------------------------------------------- /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.. [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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | var res = [nums[0]] 10 | 11 | for i in 1.. Int { 23 | var l = 0, r = res.count - 1 24 | 25 | while l < r { 26 | let mid = (r - l) / 2 + l 27 | 28 | if res[mid] == num { 29 | return mid 30 | } else if res[mid] > num { 31 | r = mid 32 | } else { 33 | l = mid + 1 34 | } 35 | } 36 | 37 | return l 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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/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 | } -------------------------------------------------------------------------------- /Graph/CourseScheduleII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/course-schedule-ii/ 3 | * Primary idea: Topological sort, use indegree of a graph and BFS to solve the problem 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class CourseScheduleII { 10 | func findOrder(_ numCourses: Int, _ prerequisites: [[Int]]) -> [Int] { 11 | var indegrees = Array(repeating: 0, count: numCourses), toCourses = [Int: [Int]]() 12 | 13 | for pres in prerequisites { 14 | indegrees[pres[0]] += 1 15 | toCourses[pres[1], default: []].append(pres[0]) 16 | } 17 | 18 | var queue = (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 | } -------------------------------------------------------------------------------- /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, n = obstacleGrid[0].count 10 | 11 | var dp = Array(repeating: Array(repeating: 0, count: n), count: m) 12 | 13 | for i in 0.. 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 | } -------------------------------------------------------------------------------- /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/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 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /DP/EditDistance.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/edit-distance/ 3 | * Primary idea: 2D Dynamic Programming, find minimum step from 4 | * inserting, deleting, or replacing a character 5 | * Time Complexity: O(mn), Space Complexity: O(mn) 6 | */ 7 | 8 | class EditDistance { 9 | func minDistance(word1: String, _ word2: String) -> Int { 10 | let word1Chars = Array(word1), word2Chars = Array(word2), m = word1.count, n = word2.count 11 | var distances = Array(repeating: Array(repeating: 0, count: n + 1), count: m + 1) 12 | 13 | for i in 0...m { 14 | for j in 0...n { 15 | if i == 0 { 16 | distances[i][j] = j 17 | } else if j == 0 { 18 | distances[i][j] = i 19 | } else if word1Chars[i - 1] == word2Chars[j - 1] { 20 | distances[i][j] = distances[i - 1][j - 1] 21 | } else { 22 | distances[i][j] = min(distances[i - 1][j - 1], distances[i - 1][j], distances[i][j - 1]) + 1 23 | } 24 | 25 | } 26 | } 27 | 28 | return distances[m][n] 29 | } 30 | } -------------------------------------------------------------------------------- /Math/SparseMatrixMultiplication.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/sparse-matrix-multiplication/ 3 | * Primary idea: Use a matrix to mark indices of an matrix where is not zero to optimize the multiplication 4 | * 5 | * Time Complexity: O(n^3), Space Complexity: O(n^2) 6 | */ 7 | 8 | class SparseMatrixMultiplication { 9 | func multiply(_ A: [[Int]], _ B: [[Int]]) -> [[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.. 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 | } -------------------------------------------------------------------------------- /Tree/ValidateBinarySearchTree.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/validate-binary-search-tree/ 3 | * Primary idea: Keep min to go right and keep max to go left 4 | * Time Complexity: O(n), Space Complexity: O(log 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 ValidateBinarySearchTree { 20 | func isValidBST(root: TreeNode?) -> 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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /DP/WildcardMatching.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/wildcard-matching/ 3 | * Primary idea: Classic Two Dimensionel Dynamic Programming 4 | * Time Complexity: O(mn), Space Complexity: O(mn) 5 | */ 6 | 7 | class WildcardMatching { 8 | func isMatch(_ s: String, _ p: String) -> Bool { 9 | let s = Array(s), p = Array(p), m = s.count, n = p.count 10 | var dp = Array(repeating: Array(repeating: false, count: n + 1), count: m + 1) 11 | 12 | for j in 0...n { 13 | dp[0][j] = j == 0 || (dp[0][j - 1] && p[j - 1] == "*") 14 | } 15 | 16 | if m < 1 || n < 1 { 17 | return dp[m][n] 18 | } 19 | 20 | for i in 1...m { 21 | for j in 1...n { 22 | if p[j - 1] != "*" { 23 | if p[j - 1] == s[i - 1] || p[j - 1] == "?" { 24 | dp[i][j] = dp[i - 1][j - 1] 25 | } else { 26 | dp[i][j] = false 27 | } 28 | } else { 29 | dp[i][j] = dp[i][j - 1] || dp[i - 1][j] 30 | } 31 | } 32 | } 33 | 34 | return dp[m][n] 35 | } 36 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /DFS/CombinationSumII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/combination-sum-ii/ 3 | * Primary idea: Classic Depth-first Search 4 | * 5 | * Time Complexity: O(2^n), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class CombinationSumII { 10 | func combinationSum2(candidates: [Int], _ target: Int) -> [[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/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 | dfs(&res, &path, &visited, nums.sorted()) 14 | 15 | return res 16 | } 17 | 18 | private func dfs(_ res: inout [[Int]], _ path: inout [Int], _ isVisited: inout [Bool], _ nums: [Int]) { 19 | if path.count == nums.count { 20 | res.append(path) 21 | return 22 | } 23 | 24 | for (i, num) in nums.enumerated() where !isVisited[i] { 25 | if i > 0 && nums[i] == nums[i - 1] && !isVisited[i - 1] { 26 | continue 27 | } 28 | 29 | path.append(num) 30 | isVisited[i] = true 31 | dfs(&res, &path, &isVisited, nums) 32 | isVisited[i] = false 33 | path.removeLast() 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /DP/MaximumNumberPointsCost.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/maximum-number-of-points-with-cost/ 3 | * Primary idea: DP. dp[i][j] is the maximum number of points we can have if points[i][j] is the most recent cell we picked. 4 | * Optimization: Keeps track the current row is enough. Update current row max by traversing from left and right. 5 | * Time Complexity: O(mn), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class MaximumNumberPointsCost { 10 | func maxPoints(_ points: [[Int]]) -> Int { 11 | 12 | let m = points.count, n = points[0].count 13 | var rowMaxes = points[0] 14 | 15 | for i in 1.. 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 | } -------------------------------------------------------------------------------- /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/ReverseVowelsOfAString.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/reverse-vowels-of-a-string/ 3 | * Primary idea: Two pointers, iterate the string and swap two characters each time, 4 | * 5 | * Note: the input String is case sensitive; thus "aA" should be transferred to "Aa" 6 | * Time Complexity: O(n), Space Complexity: O(n) 7 | * 8 | */ 9 | 10 | class ReverseVowelsOfAString { 11 | func reverseVowels(_ s: String) -> 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/StringCompression.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/string-compression/ 3 | * Primary idea: Compare two consecutive characters, set character at index and count of it afterwards 4 | * 5 | * Note: do not forget to handle edge case when hit the end of array 6 | * 7 | * Time Complexity: O(n), Space Complexity: O(1) 8 | * 9 | */ 10 | 11 | class StringCompression { 12 | func compress(_ chars: inout [Character]) -> Int { 13 | var index = 0, currentCount = 0 14 | 15 | for i in 0.. Bool { 11 | var inDegrees = Array(repeating: 0, count: numCourses), toCourses = [Int: [Int]]() 12 | 13 | for courses in prerequisites { 14 | inDegrees[courses[0]] += 1 15 | toCourses[courses[1], default:[]].append(courses[0]) 16 | } 17 | 18 | var queue = (0.. 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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /SlidingWindow/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 | -------------------------------------------------------------------------------- /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 { 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 | -------------------------------------------------------------------------------- /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 { 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 | -------------------------------------------------------------------------------- /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(2^n), Space Complexity: O(n) 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.. 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 | } -------------------------------------------------------------------------------- /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 { 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.. Bool { 9 | let s = Array(s), p = Array(p), m = s.count, n = p.count 10 | var dp = Array(repeating: Array(repeating: false, count: n + 1), count: m + 1) 11 | 12 | for j in 0...n { 13 | dp[0][j] = j == 0 || (j > 1 && dp[0][j - 2] && p[j - 1] == "*") 14 | } 15 | 16 | for i in 1...m { 17 | for j in 1...n { 18 | if p[j - 1] != "*" { 19 | if p[j - 1] == s[i - 1] || p[j - 1] == "." { 20 | dp[i][j] = dp[i - 1][j - 1] 21 | } else { 22 | dp[i][j] = false 23 | } 24 | } else { 25 | if j > 1 { 26 | dp[i][j] = dp[i][j - 2] || ((p[j - 2] == s[i - 1] || p[j - 2] == ".") && dp[i - 1][j]) 27 | } 28 | } 29 | } 30 | } 31 | 32 | return dp[m][n] 33 | } 34 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /Graph/EarliestMomentFriends.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/the-earliest-moment-when-everyone-become-friends/ 3 | * Primary idea: Classic Union Find, union every node until the count drops down to 1. 4 | * 5 | * Time Complexity: O(nlogn), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class EarliestMomentFriends { 10 | func earliestAcq(_ logs: [[Int]], _ n: Int) -> Int { 11 | let logs = logs.sorted { $0[0] < $1[0] } 12 | 13 | var roots = Array(0.. Int { 35 | var node = node 36 | 37 | while node != roots[node] { 38 | node = roots[node] 39 | } 40 | 41 | return node 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Queue/ImplementQueueUsingStacks.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/implement-queue-using-stacks/ 3 | * Primary idea: queue 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | * 6 | * Copyright © 2019 Ilyar Mnazhdin. All rights reserved. 7 | 8 | * Your MyQueue object will be instantiated and called as such: 9 | * let obj = MyQueue() 10 | * obj.push(x) 11 | * let ret_2: Int = obj.pop() 12 | * let ret_3: Int = obj.peek() 13 | * let ret_4: Bool = obj.empty() 14 | */ 15 | 16 | import Foundation 17 | 18 | class MyQueue { 19 | var storage = [Int]() 20 | 21 | /** Initialize your data structure here. */ 22 | init() { 23 | 24 | } 25 | 26 | /** Push element x to the back of queue. */ 27 | func push(_ x: Int) { 28 | storage.append(x) 29 | } 30 | 31 | /** Removes the element from in front of queue and returns that element. */ 32 | func pop() -> 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 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------