├── logo.png ├── Leetcode_Contributors.png ├── String ├── ReverseString.swift ├── ReverseWordsString.swift ├── ValidAnagram.swift ├── FlipGame.swift ├── PalindromePermutation.swift ├── KeyboardRow.swift ├── FizzBuzz.swift ├── GroupAnagrams.swift ├── FirstUniqueCharacterInString.swift ├── DetectCapital.swift ├── LengthLastWord.swift ├── ReverseWordsStringII.swift ├── ReverseWordsStringIII.swift ├── StrStr.swift ├── ShortestDistanceToACharacter.swift ├── IsomorphicStrings.swift ├── WordPattern.swift ├── ReverseStringII.swift ├── ValidPalindromeII.swift ├── RansomNote.swift ├── AddStrings.swift ├── StringCompression.swift ├── LongestSubstringWithoutRepeatingCharacters.swift ├── LongestCommonPrefix.swift ├── ValidPalindrome.swift ├── ZigZagConverstion.swift ├── OneEditDistance.swift └── FindDuplicateFileInSystem.swift ├── Array ├── ContainsDuplicate.swift ├── IntersectionTwoArrays.swift ├── RemoveElement.swift ├── SortArrayByParity.swift ├── TwoSum.swift ├── MoveZeroes.swift ├── FirstMissingPositive.swift ├── RemoveDuplicatesFromSortedArray.swift ├── MaxConsecutiveOnes.swift ├── Heaters.swift ├── MajorityElement.swift ├── RotateImage.swift ├── RemoveDuplicatesFromSortedArrayII.swift ├── ProductExceptSelf.swift ├── ContainsDuplicateII.swift ├── ShortestWordDistance.swift ├── MaximumSizeSubarraySumEqualsK.swift ├── IslandPerimeter.swift ├── MinimumSizeSubarraySum.swift ├── SummaryRanges.swift ├── MaximizeDistanceToClosestPerson.swift ├── IntersectionTwoArraysII.swift ├── SlidingWindowMaximum.swift ├── TaskScheduler.swift ├── GasStation.swift ├── LongestConsecutiveSequence.swift ├── StrobogrammaticNumber.swift ├── DiagonalTraverse.swift ├── NumberBoomerangs.swift ├── ShortestWordDistanceIII.swift ├── RotateArray.swift ├── ExamRoom.swift ├── AsteroidCollision.swift └── NumMatrix.swift ├── Math ├── PowerTwo.swift ├── PowerThree.swift ├── SingleNumber.swift ├── SumTwoIntegers.swift ├── HammingDistance.swift ├── NumberComplement.swift ├── MinimumMovesEqualArrayElements.swift ├── AddDigits.swift ├── PlusOne.swift ├── ExcelSheetColumnNumber.swift ├── ReverseInteger.swift ├── RectangleArea.swift ├── CountingBits.swift ├── UglyNumber.swift ├── HappyNumber.swift ├── ContainerMostWater.swift ├── PalindromeNumber.swift ├── IntegerBreak.swift ├── CountPrimes.swift ├── DivideTwoIntegers.swift ├── SuperPow.swift ├── Pow.swift ├── SingleNumberII.swift ├── UglyNumberII.swift ├── AddBinary.swift ├── KthSmallestLexicographicalOrder.swift ├── RomanToInteger.swift ├── AddTwoNumbers.swift ├── TrappingRainWater.swift └── SuperUglyNumber.swift ├── DP ├── HouseRobber.swift ├── BestTimeBuySellStockII.swift ├── MaximumSubarray.swift ├── Triangle.swift ├── JumpGame.swift ├── PaintFence.swift ├── WiggleSubsequence.swift ├── BestTimeBuySellStock.swift ├── CoinChangeII.swift ├── MaximumProductSubarray.swift ├── PerfectSquares.swift ├── ClimbingStairs.swift ├── LongestIncreasingSubsequence.swift ├── CombinationSumIV.swift ├── HouseRobberII.swift ├── MinCostClimbingStairs.swift ├── UniquePaths.swift ├── BestTimeBuySellStockCooldown.swift ├── MinimumPathSum.swift ├── CoinChange.swift ├── FlipGameII.swift ├── EditDistance.swift ├── GenerateParentheses.swift ├── DecodeWays.swift ├── BestTimeBuySellStockIII.swift ├── GuessNumberHigherOrLowerII.swift ├── DungeonGame.swift ├── MaximalSquare.swift ├── UniquePathsII.swift ├── MinimumWindowSubsequence.swift ├── BurstBalloons.swift ├── CanIWin.swift └── RegularExpressionMatching.swift ├── Sort ├── ArrayPartitionI.swift ├── WiggleSortII.swift ├── MergeSortedArray.swift ├── SortColors.swift ├── TopKFrequentElements.swift ├── MeetingRoomsII.swift ├── MeetingRooms.swift ├── WiggleSort.swift └── MergeIntervals.swift ├── Search ├── FindPeakElement.swift ├── PeakIndexMountainArray.swift ├── FindMinimumRotatedSortedArray.swift ├── Search2DMatrixII.swift ├── FindMinimumRotatedSortedArrayII.swift ├── Sqrtx.swift ├── SearchInsertPosition.swift ├── MinimizeMaxDistanceGasStation.swift ├── SearchInRotatedSortedArray.swift ├── SearchInRotatedSortedArrayII.swift └── MedianTwoSortedArrays.swift ├── Tree ├── MergeTwoBinaryTrees.swift ├── MaximumDepthOfBinaryTree.swift ├── PathSum.swift ├── InvertBinaryTree.swift ├── SameTree.swift ├── UniqueBinarySearchTrees.swift ├── SymmetricTree.swift ├── DiameterBinaryTree.swift ├── BinaryTreeUpsideDown.swift ├── MinimumDepthOfBinaryTree.swift ├── BalancedBinaryTree.swift ├── ValidateBinarySearchTree.swift ├── SumLeftLeaves.swift ├── KthSmallestElementBST.swift ├── HouseRobberIII.swift ├── BinaryTreeZigzagLevelOrderTraversal.swift ├── FlattenBinaryTreeLinkedList.swift └── PathSumIII.swift ├── DFS ├── Subsets.swift ├── Combinations.swift ├── FactorCombinations.swift ├── SubsetsII.swift ├── Permutations.swift ├── CombinationSum.swift ├── IsGraphBipartite.swift ├── GeneralizedAbbreviation.swift ├── CombinationSumII.swift ├── CombinationSumIII.swift ├── PermutationsII.swift ├── NumberofIslands.swift └── WallsGates.swift ├── Stack ├── SimplifyPath.swift ├── LongestValidParentheses.swift ├── TernaryExpressionParser.swift ├── PreorderTraversal.swift ├── ValidParentheses.swift ├── InorderTraversal.swift ├── PostorderTraversal.swift ├── RemoveKDigits.swift └── EvaluateReversePolishNotation.swift ├── LinkedList ├── RemoveLinkedListElements.swift ├── RemoveDuplicatesFromSortedList.swift ├── RemoveNthFromEnd.swift ├── SwapNodesInPairs.swift ├── MergeTwoSortedLists.swift ├── PartitionList.swift ├── ReverseLinkedList.swift ├── OddEvenLinkedList.swift ├── RotateList.swift ├── RemoveDuplicatesFromSortedListII.swift └── PalindromeLinkedList.swift ├── License.md └── UnionFind ├── NumberConnectedComponentsUndirectedGraph.swift ├── GraphValidTree.swift └── NumberIslandsII.swift /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-interview/LeetCode-Swift/master/logo.png -------------------------------------------------------------------------------- /Leetcode_Contributors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-interview/LeetCode-Swift/master/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 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 | } -------------------------------------------------------------------------------- /Array/IntersectionTwoArrays.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/intersection-of-two-arrays/ 3 | * Primary idea: Use set interact function to help 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class IntersectionTwoArrays { 10 | func intersection(nums1: [Int], _ nums2: [Int]) -> [Int] { 11 | return [Int](Set(nums1).intersect(nums2)) 12 | } 13 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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, add word from end to start 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class ReverseWordsString { 10 | func reverseWords(_ s: String) -> String { 11 | return String(s.split(separator: " ").reversed().reduce("") { total, word in total + word + " "}.dropLast()) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /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/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 | } -------------------------------------------------------------------------------- /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 == 1 ? count + 1 : count 14 | z = z >> 1 15 | } 16 | 17 | return count 18 | } 19 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | var outputArray = [Int]() 12 | for (_,value) in A.enumerated(){ 13 | outputArray.insert(value, at: value % 2 == 0 ? 0 : outputArray.count) 14 | } 15 | 16 | return outputArray 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /Array/MoveZeroes.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/move-zeroes/ 3 | * Primary idea: keep index for element not equal to 0, traverse and set up the index 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class MoveZeroes { 10 | func moveZeroes(_ nums: inout [Int]) { 11 | var idx = 0 12 | 13 | for (i, num) in nums.enumerated() { 14 | if num != 0 { 15 | nums[idx] = num 16 | idx += 1 17 | } 18 | } 19 | 20 | while idx < nums.count { 21 | nums[idx] = 0 22 | idx += 1 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | var set = Set() 11 | 12 | nums.forEach { set.insert($0) } 13 | 14 | for i in 0.. Bool { 9 | guard s.characters.count == t.characters.count else { 10 | return false 11 | } 12 | 13 | return sortStr(s) == sortStr(t) 14 | } 15 | 16 | private func sortStr(s: String) -> [Character] { 17 | var sChars = [Character](s.characters) 18 | sChars.sortInPlace({$0 < $1}) 19 | return sChars 20 | } 21 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /Math/ExcelSheetColumnNumber.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/excel-sheet-column-number/ 3 | * Primary idea: Classic Math problem, res = res * 26 + current 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | * 6 | */ 7 | 8 | class ExcelSheetColumnNumber { 9 | func titleToNumber(s: String) -> Int { 10 | var res = 0 11 | let scalarsOfA = "A".unicodeScalars 12 | 13 | for char in s.characters { 14 | let scalars = String(char).unicodeScalars 15 | let current = Int(scalars[scalars.startIndex].value - scalarsOfA[scalarsOfA.startIndex].value) + 1 16 | res = res * 26 + current 17 | } 18 | 19 | return res 20 | } 21 | } -------------------------------------------------------------------------------- /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 major = nums.first! 12 | var sum = 0 13 | 14 | for num in nums { 15 | if num == major { 16 | sum += 1 17 | } else { 18 | sum -= 1 19 | } 20 | 21 | if sum == 0 { 22 | major = num 23 | sum = 1 24 | } 25 | } 26 | 27 | return major 28 | } 29 | } -------------------------------------------------------------------------------- /DP/WiggleSubsequence.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/wiggle-subsequence/ 3 | * Primary idea: Classic Dynamic Programming, two variables/arries to track up or down status 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | */ 6 | 7 | class WiggleSubsequence { 8 | func wiggleMaxLength(_ nums: [Int]) -> Int { 9 | guard nums.count >= 2 else { 10 | return nums.count 11 | } 12 | 13 | var up = 1, down = 1 14 | 15 | for i in 1.. nums[i - 1] { 17 | up = down + 1 18 | } else if nums[i] < nums[i - 1] { 19 | down = up + 1 20 | } 21 | } 22 | 23 | return max(up, down) 24 | } 25 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 >= 2 else { 12 | return 0 13 | } 14 | 15 | var maxProfit = 0 16 | var lowest = prices[0] 17 | 18 | for price in prices { 19 | maxProfit = max(maxProfit, price - lowest) 20 | lowest = min(lowest, price) 21 | } 22 | 23 | return maxProfit 24 | } 25 | } -------------------------------------------------------------------------------- /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) || rowTwo.contains(word) || rowThree.contains(word) } 16 | } 17 | 18 | extension String { 19 | func contains(_ word: String) -> Bool { 20 | return word.filter { c in !self.contains(c) }.characters.count == 0 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /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..(_ nums: inout [T], _ p: Int, _ q: Int) { 26 | (nums[p], nums[q]) = (nums[q], nums[p]) 27 | } 28 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /DFS/Subsets.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/subsets/ 3 | * Primary idea: Classic Depth-first Search 4 | * 5 | * Time Complexity: O(n^n), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class Subsets { 10 | func subsets(nums: [Int]) -> [[Int]] { 11 | var res = [[Int]]() 12 | var path = [Int]() 13 | 14 | let nums = nums.sorted(by: <) 15 | 16 | _dfs(&res, &path, nums, 0) 17 | 18 | return res 19 | } 20 | 21 | private func _dfs(inout res: [[Int]], inout _ path: [Int], _ nums: [Int], _ index: Int) { 22 | // termination case 23 | 24 | res.append(Array(path)) 25 | 26 | for i in index.. Int { 10 | guard n > 0 else { 11 | return 0 12 | } 13 | 14 | var leastNums = [Int](count: n + 1, repeatedValue: Int.max) 15 | leastNums[0] = 0 16 | 17 | for i in 1...n { 18 | for j in 1...i { 19 | if j * j > i { 20 | break 21 | } 22 | leastNums[i] = min(leastNums[i], leastNums[i - j * j] + 1) 23 | } 24 | } 25 | 26 | return leastNums[n] 27 | } 28 | } -------------------------------------------------------------------------------- /DP/ClimbingStairs.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/climbing-stairs/ 3 | * Primary idea: Dynamic Programming, use array as a cache to store calculated data 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | * 6 | */ 7 | 8 | class ClimbingStairs { 9 | func climbStairs(n: Int) -> Int { 10 | var steps = [Int](count: n + 1, repeatedValue: 0) 11 | return _helper(n, &steps) 12 | } 13 | 14 | private func _helper(n: Int, inout _ steps: [Int]) -> Int { 15 | // termination case 16 | if n < 0 { 17 | return 0 18 | } 19 | if n == 0 { 20 | return 1 21 | } 22 | 23 | if steps[n] != 0 { 24 | return steps[n] 25 | } 26 | 27 | steps[n] = _helper(n - 1, &steps) + _helper(n - 2, &steps) 28 | return steps[n] 29 | } 30 | } -------------------------------------------------------------------------------- /DP/LongestIncreasingSubsequence.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/longest-increasing-subsequence/ 3 | * Primary idea: Dynamic Programming, transition function is len[i] = max(len[i], len[j] + 1) 4 | * Time Complexity: O(n^2), Space Complexity: O(n) 5 | */ 6 | 7 | class LongestIncreasingSubsequence { 8 | func lengthOfLIS(nums: [Int]) -> Int { 9 | var length_global = 0 10 | var length_current = [Int](count: nums.count, repeatedValue: 1) 11 | 12 | for i in 0.. nums[j] { 15 | length_current[i] = max(length_current[i], length_current[j] + 1) 16 | } 17 | } 18 | length_global = max(length_global, length_current[i]) 19 | } 20 | 21 | return length_global 22 | } 23 | } -------------------------------------------------------------------------------- /Math/ContainerMostWater.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/container-with-most-water/ 3 | * Primary idea: First given largest width, then go to height-increase direction while width decreases 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | * 6 | */ 7 | 8 | class ContainerMostWater { 9 | func maxArea(_ height: [Int]) -> Int { 10 | var maxRes = 0 11 | var left = 0 12 | var right = height.count - 1 13 | 14 | while left < right { 15 | let minHeight = min(height[left], height[right]) 16 | 17 | maxRes = max(maxRes, (right - left) * minHeight) 18 | 19 | if minHeight == height[left] { 20 | left += 1 21 | } else { 22 | right -= 1 23 | } 24 | } 25 | 26 | return maxRes 27 | } 28 | } -------------------------------------------------------------------------------- /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.. [Int] { 10 | var res = Array(repeating: 1, count: nums.count) 11 | var right = 1 12 | 13 | guard nums.count > 0 else { 14 | return res 15 | } 16 | 17 | for i in 1.. 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 | } -------------------------------------------------------------------------------- /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 | var map = [Int: Int]() 12 | 13 | for num in nums { 14 | guard let times = map[num] else { 15 | map[num] = 1 16 | continue 17 | } 18 | map[num] = times + 1 19 | } 20 | 21 | var keys = Array(map.keys) 22 | keys.sortInPlace() { 23 | let value1 = map[$0] 24 | let value2 = map[$1] 25 | return value1 > value2 26 | } 27 | 28 | return Array(keys[0.. [[String]] { 11 | var map = [String: [String]]() 12 | 13 | for str in strs { 14 | let sortedStr = String(str.sorted()) 15 | 16 | var anagrams = [String]() 17 | if let list = map[sortedStr] { 18 | anagrams = list 19 | } 20 | anagrams.append(str) 21 | map[sortedStr] = anagrams 22 | } 23 | 24 | return map.values.map { value in value.sorted() } 25 | } 26 | } -------------------------------------------------------------------------------- /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 | // edge case 12 | if nums.count <= 1 { 13 | return false 14 | } 15 | 16 | // key: nums[index], value: index 17 | var dict = [Int: Int]() 18 | 19 | for i in 0.. 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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 distance = Int.max 10 | var firstIndex = -1, secondIndex = -1 11 | 12 | for (i, word) in words.enumerated() { 13 | if word == word1 { 14 | firstIndex = i 15 | } 16 | if word == word2 { 17 | secondIndex = i 18 | } 19 | if firstIndex != -1 && secondIndex != -1 { 20 | distance = min(distance, abs(firstIndex - secondIndex)) 21 | } 22 | } 23 | 24 | return distance 25 | } 26 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 ones 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 | var isPrime = [Bool](repeating: true, count: n) 16 | 17 | for i in 2.. String { 9 | let dirs = path.components(separatedBy: "/") 10 | var stack = [String]() 11 | 12 | for dir in dirs { 13 | if dir == "." { 14 | continue 15 | } else if dir == ".." { 16 | if !stack.isEmpty { 17 | stack.removeLast() 18 | } 19 | } else { 20 | if dir != "" { 21 | stack.append(dir) 22 | } 23 | } 24 | } 25 | 26 | let res = stack.reduce("") { total, dir in "\(total)/\(dir)" } 27 | 28 | return res.isEmpty ? "/" : res 29 | } 30 | } -------------------------------------------------------------------------------- /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(n^n), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class Combinations { 10 | func combine(n: Int, _ k: Int) -> [[Int]] { 11 | var res = [[Int]]() 12 | var path = [Int]() 13 | let nums = [Int](1...n) 14 | 15 | _dfs(nums, &res, &path, 0, k) 16 | 17 | return res 18 | } 19 | 20 | private func _dfs(nums: [Int], inout _ res: [[Int]], inout _ path: [Int], _ index: Int, _ k: Int) { 21 | if path.count == k { 22 | res.append([Int](path)) 23 | return 24 | } 25 | 26 | for i in index.. Int { 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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 invalid 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 | } -------------------------------------------------------------------------------- /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 | if divisor == 0 { 11 | return Int.max 12 | } 13 | 14 | let isNegative = (dividend < 0) != (divisor < 0) 15 | var dividend = abs(dividend), divisor = abs(divisor), count = 0 16 | 17 | while dividend >= divisor { 18 | var shift = 0 19 | 20 | while dividend >= (divisor << shift) { 21 | shift += 1 22 | } 23 | 24 | dividend -= divisor << (shift - 1) 25 | count += 1 << (shift - 1) 26 | } 27 | 28 | return isNegative ? -count : count 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /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.characters { 14 | if char.isUpperCased() { 15 | capitalNum += 1 16 | } 17 | } 18 | 19 | if let firstChar = word.characters.first { 20 | isFirstUpperCased = firstChar.isUpperCased() 21 | } 22 | 23 | return capitalNum == 0 || (capitalNum == 1 && isFirstUpperCased) || capitalNum == word.characters.count 24 | } 25 | } 26 | 27 | fileprivate extension Character { 28 | func isUpperCased() -> Bool { 29 | return String(self).uppercased() == String(self) 30 | } 31 | } -------------------------------------------------------------------------------- /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 | let sChars = Array(s.characters) 10 | var stack = [Int]() 11 | var longest = 0 12 | 13 | for (i, char) in sChars.enumerated() { 14 | if char == "(" || stack.isEmpty || sChars[stack.last!] == ")" { 15 | stack.append(i) 16 | } else { 17 | let _ = stack.removeLast() 18 | if stack.isEmpty { 19 | longest = max(longest, i + 1) 20 | } else { 21 | longest = max(longest, i - stack.last!) 22 | } 23 | } 24 | } 25 | 26 | return longest 27 | } 28 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 res = [[Int]]() 12 | var path = [Int]() 13 | 14 | dfs(&res, &path, n, 2) 15 | 16 | return res 17 | } 18 | 19 | private func dfs(_ res: inout [[Int]], _ path: inout [Int], _ n: Int, _ start: Int) { 20 | if n == 1 { 21 | if path.count > 1 { 22 | res.append(Array(path)) 23 | } 24 | return 25 | } 26 | 27 | if start > n { 28 | return 29 | } 30 | 31 | for i in start...n where n % i == 0 { 32 | path.append(i) 33 | dfs(&res, &path, n / i, i) 34 | path.removeLast() 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /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 | if x <= 0 { 14 | return x 15 | } 16 | 17 | var left = 0 18 | var right = x / 2 + 1 19 | var mid = 0 20 | 21 | while left <= right { 22 | mid = (right - left) / 2 + left 23 | 24 | if mid * mid == x { 25 | return mid 26 | } else if mid * mid < x { 27 | left = mid + 1 28 | } else { 29 | right = mid - 1 30 | } 31 | } 32 | 33 | return right 34 | } 35 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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^n), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class SubsetsII { 10 | func subsetsWithDup(nums: [Int]) -> [[Int]] { 11 | var res = [[Int]]() 12 | var path = [Int]() 13 | 14 | let nums = nums.sorted(by: <) 15 | 16 | _dfs(&res, &path, nums, 0) 17 | 18 | return res 19 | } 20 | 21 | private func _dfs(inout res: [[Int]], inout _ path:[Int], _ nums: [Int], _ index: Int) { 22 | res.append(Array(path)) 23 | 24 | for i in index.. 0 && nums[i] == nums[i - 1] && i != index { 26 | continue 27 | } 28 | 29 | path.append(nums[i]) 30 | _dfs(&res, &path, nums, i + 1) 31 | path.removeLast() 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 | -------------------------------------------------------------------------------- /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 frequencies = Dictionary(nums1.map { ($0, 1) } , uniquingKeysWith: +) 14 | var res = [Int]() 15 | 16 | for num in nums2 { 17 | guard let frequent = frequencies[num] else { 18 | continue 19 | } 20 | 21 | if frequent > 0 { 22 | frequencies[num]! = frequent - 1 23 | res.append(num) 24 | } 25 | } 26 | 27 | return res 28 | } 29 | } -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 { 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 | for sortedTask in sortedTasks { 20 | if taskFreqs[sortedTask] != taskFreqs[sortedTasks[0]] { 21 | break 22 | } 23 | 24 | mostFreqCount += 1 25 | } 26 | 27 | return max(tasks.count, (taskFreqs[sortedTasks[0]]! - 1) * (n + 1) + mostFreqCount) 28 | } 29 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /Stack/TernaryExpressionParser.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/ternary-expression-parser/ 3 | * Primary idea: Use a stack and go from right to left, pop when peek is "?" 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | */ 6 | 7 | class TernaryExpressionParser { 8 | func parseTernary(_ expression: String) -> String { 9 | var stack = [Character]() 10 | 11 | for char in expression.characters.reversed() { 12 | if !stack.isEmpty && stack.last! == "?" { 13 | stack.removeLast() 14 | let first = stack.removeLast() 15 | stack.removeLast() 16 | let second = stack.removeLast() 17 | 18 | if char == "T" { 19 | stack.append(first) 20 | } else { 21 | stack.append(second) 22 | } 23 | } else { 24 | stack.append(char) 25 | } 26 | } 27 | 28 | 29 | return stack.isEmpty ? "" : String(stack.last!) 30 | } 31 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /Tree/SymmetricTree.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/symmetric-tree/ 3 | * Primary idea: recursion 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | * 6 | * Definition for a binary tree node. 7 | * public class TreeNode { 8 | * public var val: Int 9 | * public var left: TreeNode? 10 | * public var right: TreeNode? 11 | * public init(_ val: Int) { 12 | * self.val = val 13 | * self.left = nil 14 | * self.right = nil 15 | * } 16 | * } 17 | * 18 | */ 19 | 20 | class SymmetricTree { 21 | func isSymmetric(root: TreeNode?) -> Bool { 22 | guard let root = root else { 23 | return true 24 | } 25 | return _helper(root.left, root.right) 26 | } 27 | 28 | func _helper(p: TreeNode?, _ q:TreeNode?) -> Bool { 29 | if p == nil && q == nil { 30 | return true 31 | } 32 | if p == nil || q == nil || p!.val != q!.val { 33 | return false 34 | } 35 | return _helper(p!.left, q!.right) && _helper(p!.right, q!.left) 36 | } 37 | } -------------------------------------------------------------------------------- /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(n^n), Space Complexity: O(2^n - 1) 6 | * 7 | */ 8 | 9 | class CombinationSum { 10 | func combinationSum(candidates: [Int], _ target: Int) -> [[Int]] { 11 | var res = [[Int]]() 12 | var path = [Int]() 13 | 14 | _dfs(candidates.sorted(by: <), target, &res, &path, 0) 15 | 16 | return res 17 | } 18 | 19 | private func _dfs(candidates: [Int], _ target: Int, inout _ res: [[Int]], inout _ path: [Int], _ index: Int) { 20 | if target == 0 { 21 | res.append(Array(path)) 22 | return 23 | } 24 | 25 | for i in index.. Double { 10 | guard n != 0 else { 11 | return 1 12 | } 13 | guard x != 0 else { 14 | return 0 15 | } 16 | 17 | var res = _helper(abs(x), abs(n)) 18 | 19 | if n < 0 { 20 | res = 1 / res 21 | } 22 | if n % 2 != 0 && x < 0 { 23 | res = -res 24 | } 25 | 26 | return res 27 | } 28 | 29 | private func _helper(x: Double, _ n: Int) -> Double { 30 | guard n != 0 else { 31 | return 1 32 | } 33 | guard n != 1 else { 34 | return x 35 | } 36 | 37 | if n % 2 == 0 { 38 | return _helper(x * x, n / 2) 39 | } else { 40 | return _helper(x, n - 1) * x 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /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: [Interval]) -> Int { 19 | let starts = intervals.map { interval in interval.start }.sorted() 20 | let ends = intervals.map { interval in interval.end }.sorted() 21 | var i = 0, j = 0, count = 0 22 | 23 | while i < starts.count && j < ends.count { 24 | if starts[i] < ends[j] { 25 | count += 1 26 | i += 1 27 | } else { 28 | i += 1 29 | j += 1 30 | } 31 | } 32 | 33 | return count 34 | } 35 | } -------------------------------------------------------------------------------- /DP/MinimumPathSum.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/minimum-path-sum/ 3 | * Primary idea: Classic Two Dimensionel Dynamic Programming 4 | * Time Complexity: O(mn), Space Complexity: O(mn) 5 | */ 6 | 7 | class MinimumPathSum { 8 | func minPathSum(_ grid: [[Int]]) -> Int { 9 | guard grid.count != 0 && grid[0].count != 0 else{ 10 | return 0 11 | } 12 | 13 | let m = grid.count, n = grid[0].count 14 | var dp = Array(repeating: Array(repeating: 0, count: n), count: m) 15 | 16 | for i in 0.. Int { 11 | var set = Set(nums), longest = 0 12 | 13 | for num in nums { 14 | if set.contains(num) { 15 | set.remove(num) 16 | let distance = 1 + findConsecutive(&set, num, 1) + findConsecutive(&set, num, -1) 17 | longest = max(longest, distance) 18 | } 19 | } 20 | 21 | return longest 22 | } 23 | 24 | fileprivate func findConsecutive(_ set: inout Set, _ num: Int, _ step: Int) -> Int { 25 | var len = 0, num = num + step 26 | 27 | while set.contains(num) { 28 | set.remove(num) 29 | len += 1 30 | num += step 31 | } 32 | 33 | return len 34 | } 35 | } -------------------------------------------------------------------------------- /Math/SingleNumberII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/single-number-ii/ 3 | * Primary idea: Every number has 64 bits, for the i-th bit of each number. 4 | * In total, we should have (nums.count) 0s and 1s. 5 | * If the i-th bit of the single number is 1, then we should have (3n + 1) 1s, and (3n) 0s. 6 | * Otherwise, the i-th bit is 0. 7 | * In this way, we can calculate each bit of the single number. 8 | * 9 | * Time Complexity: O(n), Space Complexity: O(1) 10 | * 11 | */ 12 | 13 | class SingleNumberII { 14 | func singleNumber(nums: [Int]) -> Int { 15 | var ans = 0 16 | var sum = 0 17 | 18 | for i in 0..<64 { 19 | sum = 0 20 | let tmp = (1 << i) 21 | for j in 0.. Int { 10 | 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 | } -------------------------------------------------------------------------------- /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 | // edge case 10 | guard amount != 0 else { 11 | return 0 12 | } 13 | 14 | var minNums = [Int](count: amount + 1, repeatedValue: -1) 15 | 16 | for i in 0...amount { 17 | for coin in coins { 18 | if coin == i { 19 | minNums[i] = 1 20 | break 21 | } 22 | if coin < i && minNums[i - coin] != -1 { 23 | if minNums[i] == -1 { 24 | minNums[i] = minNums[i - coin] + 1 25 | } else { 26 | minNums[i] = min(minNums[i], minNums[i - coin] + 1) 27 | } 28 | } 29 | } 30 | } 31 | 32 | return minNums[amount] 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 | if char == "(" || char == "[" || char == "{" { 13 | stack.append(char) 14 | } else if char == ")" { 15 | guard stack.count != 0 && stack.removeLast() == "(" else { 16 | return false 17 | } 18 | } else if char == "]" { 19 | guard stack.count != 0 && stack.removeLast() == "[" else { 20 | return false 21 | } 22 | } else if char == "}" { 23 | guard stack.count != 0 && stack.removeLast() == "{" else { 24 | return false 25 | } 26 | } 27 | } 28 | 29 | return stack.isEmpty 30 | } 31 | } -------------------------------------------------------------------------------- /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/AddBinary.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/add-binary/ 3 | * Primary idea: 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 | var sum = 0, carry = 0, res = "" 14 | let aChars = Array(a.characters), bChars = Array(b.characters) 15 | var i = aChars.count - 1, j = bChars.count - 1 16 | 17 | while i >= 0 || j >= 0 || carry > 0 { 18 | sum = carry 19 | if i >= 0 { 20 | sum += Int(String(aChars[i]))! 21 | i -= 1 22 | } 23 | if j >= 0 { 24 | sum += Int(String(bChars[j]))! 25 | j -= 1 26 | } 27 | carry = sum / 2 28 | sum = sum % 2 29 | res = String(sum) + res 30 | } 31 | 32 | return res 33 | } 34 | } -------------------------------------------------------------------------------- /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/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 | var stDict = [Character: Character]() 10 | var tsDict = [Character: Character]() 11 | 12 | let sChars = [Character](s.characters) 13 | let tChars = [Character](t.characters) 14 | 15 | guard sChars.count == tChars.count else { 16 | return false 17 | } 18 | 19 | for i in 0.. [Int] { 20 | var stack = [TreeNode]() 21 | var res = [Int]() 22 | var node = root 23 | 24 | while !stack.isEmpty || node != nil { 25 | if node != nil { 26 | stack.append(node!) 27 | node = node!.left 28 | } else { 29 | node = stack.removeLast() 30 | res.append(node!.val) 31 | node = node!.right 32 | } 33 | } 34 | 35 | return res 36 | } 37 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | if charA == charB { 28 | return ["0", "1", "8"].contains(charA) 29 | } else { 30 | if (charA == "6" && charB == "9") || (charA == "9" && charB == "6") { 31 | return true 32 | } else { 33 | return false 34 | } 35 | } 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /Array/DiagonalTraverse.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/diagonal-traverse/ 3 | * Primary idea: use sum to track matrix index, note to set lower and upper bound to avoid duplicates 4 | * 5 | * Time Complexity: O(mn), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class DiagonalTraverse { 10 | func findDiagonalOrder(_ matrix: [[Int]]) -> [Int] { 11 | var res = [Int]() 12 | 13 | guard matrix.count > 0 && matrix[0].count > 0 else { 14 | return res 15 | } 16 | 17 | let m = matrix.count, n = matrix[0].count 18 | var fromTop = false 19 | 20 | for sum in 0...m + n - 2 { 21 | if fromTop { 22 | for i in max(sum - n + 1, 0)...min(m - 1, sum) { 23 | res.append(matrix[i][sum - i]) 24 | } 25 | } else { 26 | for i in (max(sum - n + 1, 0)...min(m - 1, sum)).reversed() { 27 | res.append(matrix[i][sum - i]) 28 | } 29 | } 30 | 31 | fromTop = !fromTop 32 | } 33 | 34 | return res 35 | } 36 | } -------------------------------------------------------------------------------- /Sort/WiggleSort.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/wiggle-sort/ 3 | * Primary idea: Iterate the array and swap the largest one to the middle 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | */ 6 | 7 | class WiggleSort { 8 | func wiggleSort(_ nums: inout [Int]) { 9 | guard nums.count >= 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/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/GeneralizedAbbreviation.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/generalized-abbreviation/ 3 | * Primary idea: Classic Depth-first Search 4 | * 5 | * Time Complexity: O(n^n), Space Complexity: O(2^n) 6 | * 7 | */ 8 | 9 | class GeneralizedAbbreviation { 10 | func generateAbbreviations(_ word: String) -> [String] { 11 | var res = [String]() 12 | let chars = Array(word.characters) 13 | 14 | dfs(chars, &res, "", 0) 15 | 16 | return res 17 | } 18 | 19 | private func dfs(_ word: [Character], _ res: inout [String], _ subset: String, _ index: Int) { 20 | if word.count == index { 21 | res.append(String(subset)) 22 | return 23 | } 24 | 25 | res.append(subset + String(word.count - index)) 26 | 27 | for i in index.. Bool { 11 | let array = Array(s) 12 | return isPalindrome(array, 0, array.count - 1) 13 | } 14 | 15 | fileprivate func isPalindrome(_ array: [Character], _ i: Int, _ j: Int, alreadyRemoved: Bool = false) -> Bool { 16 | var i = i, j = j 17 | while i < j { 18 | if array[i] != array[j] { 19 | if alreadyRemoved { 20 | return false 21 | } else { 22 | return isPalindrome(array, i + 1, j, alreadyRemoved: true) || 23 | isPalindrome(array, i, j - 1, alreadyRemoved: true) 24 | } 25 | } else { 26 | i += 1 27 | j -= 1 28 | } 29 | } 30 | return true 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /DP/FlipGameII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/flip-game-ii/ 3 | * Primary idea: Classic DP, using a map to memorize previous step 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | */ 6 | 7 | class FlipGameII { 8 | func canWin(_ s: String) -> Bool { 9 | var winMap = [String: Bool]() 10 | 11 | return helper(s, &winMap) 12 | } 13 | 14 | func helper(_ s: String, _ winMap: inout [String: Bool]) -> Bool { 15 | guard s.count >= 2 else { 16 | return false 17 | } 18 | 19 | if let sWin = winMap[s] { 20 | return sWin 21 | } 22 | 23 | let sChars = Array(s) 24 | 25 | for i in 0.. [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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /Tree/BalancedBinaryTree.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/balanced-binary-tree/ 3 | * Primary idea: use the idea of maximum depth of a binary tree 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | * 6 | * Definition for a binary tree node. 7 | * public class TreeNode { 8 | * public var val: Int 9 | * public var left: TreeNode? 10 | * public var right: TreeNode? 11 | * public init(_ val: Int) { 12 | * self.val = val 13 | * self.left = nil 14 | * self.right = nil 15 | * } 16 | * } 17 | */ 18 | 19 | class BalancedBinaryTree { 20 | func isBalanced(_ root: TreeNode?) -> 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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /UnionFind/NumberConnectedComponentsUndirectedGraph.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/number-of-connected-components-in-an-undirected-graph/ 3 | * Primary idea: Classic Union Find, decrease count when there is a link between two nodes 4 | * 5 | * Time Complexity: O(nlogn), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class NumberConnectedComponentsUndirectedGraph { 10 | func countComponents(_ n: Int, _ edges: [[Int]]) -> Int { 11 | guard n > 0 else { 12 | return 0 13 | } 14 | 15 | var count = n 16 | var roots = [Int](0...n - 1) 17 | 18 | for edge in edges { 19 | let root0 = findRoot(edge[0], roots) 20 | let root1 = findRoot(edge[1], roots) 21 | 22 | if root0 != root1 { 23 | count -= 1 24 | roots[root1] = root0 25 | } 26 | } 27 | 28 | return count 29 | } 30 | 31 | private func findRoot(_ node: Int, _ roots: [Int]) -> Int { 32 | var node = node 33 | 34 | while (node != roots[node]) { 35 | node = roots[node] 36 | } 37 | 38 | return node 39 | } 40 | } -------------------------------------------------------------------------------- /Stack/RemoveKDigits.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/remove-k-digits/ 3 | * Primary idea: Keep a stack to ensure its numbers are ascending so that the number 4 | * is the smallest, truncate it to right size and handle edge cases 5 | * Time Complexity: O(n), Space Complexity: O(n) 6 | */ 7 | 8 | class RemoveKDigits { 9 | func removeKdigits(_ num: String, _ k: Int) -> String { 10 | var res = [Character](), k = k 11 | let numChars = String(num).characters, size = numChars.count - k 12 | 13 | for char in numChars { 14 | while k > 0 && res.count > 0 && charToInt(res.last!) > charToInt(char) { 15 | res.removeLast() 16 | k -= 1 17 | } 18 | res.append(char) 19 | } 20 | 21 | res = Array(res[0.. Int { 34 | return Int(String(c))! 35 | } 36 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /UnionFind/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 | } -------------------------------------------------------------------------------- /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 | var carry = 0, l1 = l1, l2 = l2 20 | let dummy = ListNode(0) 21 | var node = dummy 22 | 23 | while l1 != nil || l2 != nil || carry != 0 { 24 | if l1 != nil { 25 | carry += l1!.val 26 | l1 = l1!.next 27 | } 28 | if l2 != nil { 29 | carry += l2!.val 30 | l2 = l2!.next 31 | } 32 | 33 | node.next = ListNode(carry % 10) 34 | node = node.next! 35 | 36 | carry = carry / 10 37 | } 38 | 39 | return dummy.next 40 | } 41 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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(n^n), Space Complexity: O(2^n - 2) 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 | } -------------------------------------------------------------------------------- /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 aChars = [Character](word1.characters) 11 | let bChars = [Character](word2.characters) 12 | let aLen = aChars.count 13 | let bLen = bChars.count 14 | 15 | var dp = Array(count: aLen + 1, repeatedValue:(Array(count: bLen + 1, repeatedValue: 0))) 16 | 17 | for i in 0...aLen { 18 | for j in 0...bLen { 19 | if i == 0 { 20 | dp[i][j] = j 21 | } else if j == 0 { 22 | dp[i][j] = i 23 | } else if aChars[i - 1] == bChars[j - 1] { 24 | dp[i][j] = dp[i - 1][j - 1] 25 | } else { 26 | dp[i][j] = min(dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]) + 1 27 | } 28 | } 29 | } 30 | 31 | return dp[aLen][bLen] 32 | } 33 | } -------------------------------------------------------------------------------- /Stack/EvaluateReversePolishNotation.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/evaluate-reverse-polish-notation/ 3 | * Primary idea: Push a number to a stack and pop two for operation when encounters a operator 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | */ 6 | 7 | class EvaluateReversePolishNotation { 8 | func evalRPN(_ tokens: [String]) -> Int { 9 | var stack = [Int]() 10 | 11 | for token in tokens { 12 | if let num = Int(token) { 13 | stack.append(num) 14 | } else { 15 | let post = stack.removeLast() 16 | let prev = stack.removeLast() 17 | 18 | stack.append(operate(prev, post, token)) 19 | } 20 | } 21 | 22 | return stack.first ?? 0 23 | } 24 | 25 | fileprivate func _operate(_ prev: Int, _ post: Int, _ token: String) -> Int{ 26 | switch token { 27 | case "+": 28 | return prev + post 29 | case "-": 30 | return prev - post 31 | case "*": 32 | return prev * post 33 | default: 34 | return prev / post 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /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 | var paths = [String](), path = [Character](repeating: " ", count: 2 * n) 11 | 12 | helper(&paths, &path, n, n, 0) 13 | 14 | return paths 15 | } 16 | 17 | func helper(_ paths: inout [String], _ path: inout [Character], _ leftCount: Int, _ rightCount: Int, _ index: Int) { 18 | if leftCount < 0 || leftCount > rightCount { 19 | return 20 | } 21 | 22 | if leftCount == 0 && rightCount == 0 { 23 | paths.append(String(path)) 24 | return 25 | } 26 | 27 | if leftCount > 0 { 28 | path[index] = "(" 29 | helper(&paths, &path, leftCount - 1, rightCount, index + 1) 30 | } 31 | if rightCount > leftCount { 32 | path[index] = ")" 33 | helper(&paths, &path, leftCount, rightCount - 1, index + 1) 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /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.. Int { 11 | let sChars = Array(s) 12 | var dp = Array(repeating: 0, count: s.count + 1) 13 | dp[0] = 1 14 | 15 | guard s.count >= 1 else { 16 | return 0 17 | } 18 | 19 | for i in 1...s.count { 20 | if String(sChars[i - 1..= 2 && String(sChars[i - 2..= num 43 | } 44 | } -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /Array/RotateArray.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/rotate-array/ 3 | * Primary idea: reverse the whole array, then reverse parts of it seperately 4 | * 5 | * Note: Argument of a function in Swift is let by default, so change it to var if you need to alter the value 6 | * 7 | * Time Complexity: O(n), Space Complexity: O(1) 8 | * 9 | */ 10 | 11 | class RotateArray { 12 | func rotate(_ nums: inout [Int], _ k: Int) { 13 | var k = k % nums.count 14 | 15 | _reverse(&nums, 0, nums.count - 1) 16 | _reverse(&nums, 0, k - 1) 17 | _reverse(&nums, k, nums.count - 1) 18 | } 19 | 20 | private func _reverse(_ nums: inout [Int], _ startIdx: Int, _ endIdx: Int) { 21 | // edge case 22 | if startIdx < 0 || endIdx > nums.count || startIdx >= endIdx { 23 | return 24 | } 25 | 26 | var startIdx = startIdx 27 | var endIdx = endIdx 28 | 29 | while startIdx < endIdx { 30 | _swap(&nums, startIdx, endIdx) 31 | startIdx += 1 32 | endIdx -= 1 33 | } 34 | } 35 | 36 | private func _swap(_ nums: inout Array, _ p: Int, _ q: Int) { 37 | (nums[p], nums[q]) = (nums[q], nums[p]) 38 | } 39 | } -------------------------------------------------------------------------------- /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 { 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]] { 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.. Int { 9 | let m = obstacleGrid.count 10 | guard m > 0 else { 11 | return 0 12 | } 13 | 14 | let n = obstacleGrid[0].count 15 | guard n > 0 else { 16 | return 0 17 | } 18 | 19 | var dp = Array(repeating: Array(repeating: -1, count: n), count: m) 20 | 21 | return help(m - 1, n - 1, &dp, obstacleGrid) 22 | } 23 | 24 | fileprivate func help(_ m: Int, _ n: Int, _ dp: inout [[Int]], _ obstacleGrid: [[Int]]) -> Int { 25 | if m < 0 || n < 0 { 26 | return 0 27 | } 28 | if obstacleGrid[m][n] == 1 { 29 | return 0 30 | } 31 | if m == 0 && n == 0 { 32 | return 1 33 | } 34 | if dp[m][n] != -1 { 35 | return dp[m][n] 36 | } 37 | 38 | dp[m][n] = help(m - 1, n, &dp, obstacleGrid) + help(m, n - 1, &dp, obstacleGrid) 39 | return dp[m][n] 40 | } 41 | } -------------------------------------------------------------------------------- /String/LongestSubstringWithoutRepeatingCharacters.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/longest-substring-without-repeating-characters/ 3 | * Primary idea: Use a set to hold characters and then iterate the string, 4 | * update maxLen, set, 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 longest = 0, left = 0, set = Set() 15 | let sChars = Array(s) 16 | 17 | for (i, char) in sChars.enumerated() { 18 | if set.contains(char) { 19 | 20 | longest = max(longest, i - left) 21 | 22 | while sChars[left] != char { 23 | set.remove(sChars[left]) 24 | left += 1 25 | } 26 | left += 1 27 | 28 | } else { 29 | set.insert(char) 30 | } 31 | } 32 | 33 | return max(longest, sChars.count - left) 34 | } 35 | } -------------------------------------------------------------------------------- /Tree/SumLeftLeaves.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/sum-of-left-leaves/ 3 | * Primary idea: Recursion. Go to left and right and add to res if it is left leaf. 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 SumLeftLeaves { 20 | func sumOfLeftLeaves(_ root: TreeNode?) -> Int { 21 | guard let root = root else { 22 | return 0 23 | } 24 | 25 | var res = 0 26 | helper(root.left, true, &res) 27 | helper(root.right, false, &res) 28 | 29 | return res 30 | } 31 | 32 | private func helper(_ node: TreeNode?, _ isLeft: Bool, _ res: inout Int) { 33 | guard let node = node else { 34 | return 35 | } 36 | if node.left == nil && node.right == nil && isLeft { 37 | res += node.val 38 | } 39 | 40 | helper(node.left, true, &res) 41 | helper(node.right, false, &res) 42 | } 43 | } -------------------------------------------------------------------------------- /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]]() 12 | var path = [Int]() 13 | var visited = [Bool](count: nums.count, repeatedValue: false) 14 | 15 | let nums = nums.sorted(by: <) 16 | 17 | _dfs(&res, &path, nums, &visited) 18 | 19 | return res 20 | } 21 | 22 | private func _dfs(inout res: [[Int]], inout _ path: [Int], _ nums: [Int], inout _ visited: [Bool]) { 23 | // termination case 24 | if path.count == nums.count { 25 | res.append(Array(path)) 26 | return 27 | } 28 | 29 | for i in 0.. 0 && nums[i] == nums[i - 1] && visited[i - 1]) { 31 | continue 32 | } 33 | 34 | path.append(nums[i]) 35 | visited[i] = true 36 | _dfs(&res, &path, nums, &visited) 37 | visited[i] = false 38 | path.removeLast() 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /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 | var longestPrefix = [Character](), index = 0 10 | 11 | guard let firstStr = strs.first else { 12 | return String(longestPrefix) 13 | } 14 | 15 | let firstStrChars = Array(firstStr) 16 | let strsChars = strs.map { Array($0) } 17 | 18 | while index < firstStr.count { 19 | 20 | longestPrefix.append(firstStrChars[index]) 21 | 22 | for str in strsChars { 23 | if index >= str.count { 24 | return String(longestPrefix.dropLast()) 25 | } 26 | 27 | if str[index] != longestPrefix[index] { 28 | return String(longestPrefix.dropLast()) 29 | } 30 | } 31 | 32 | index += 1 33 | } 34 | 35 | return String(longestPrefix) 36 | } 37 | } -------------------------------------------------------------------------------- /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 isAlpha: Bool { 37 | return (Character("a")...Character("z")).contains(self) 38 | } 39 | 40 | var isNumeric: Bool { 41 | return (Character("0")...Character("9")).contains(self) 42 | } 43 | 44 | var isAlphanumeric: Bool { 45 | return isAlpha || isNumeric 46 | } 47 | } -------------------------------------------------------------------------------- /LinkedList/OddEvenLinkedList.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/odd-even-linked-list/ 3 | * Primary idea: Prev-post two pointers; change the prev and move both at a time 4 | * Time Complexity: O(n), Space Complexity: O(1) 5 | * 6 | * Definition for singly-linked list. 7 | * public class ListNode { 8 | * public var val: Int 9 | * public var next: ListNode? 10 | * public init(_ val: Int) { 11 | * self.val = val 12 | * self.next = nil 13 | * } 14 | * } 15 | */ 16 | 17 | class OddEvenLinkedList { 18 | func oddEvenList(_ head: ListNode?) -> ListNode? { 19 | guard head != nil && head!.next != nil else { 20 | return head 21 | } 22 | 23 | let evenHead = head!.next 24 | var p = head 25 | var q = evenHead 26 | var isEndEven = true 27 | 28 | while q!.next != nil { 29 | let node = q!.next 30 | 31 | p!.next = node 32 | 33 | p = q 34 | q = node 35 | isEndEven = !isEndEven 36 | } 37 | 38 | if isEndEven { 39 | p!.next = evenHead 40 | } else { 41 | p!.next = nil 42 | q!.next = evenHead 43 | } 44 | 45 | return head 46 | } 47 | } -------------------------------------------------------------------------------- /String/ZigZagConverstion.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/zigzag-conversion/ 3 | * 4 | * Primary idea: The first and the last row, loop length is (2 * numRows - 2) 5 | * For each row between them, should insert another number, index = index + 2 * (numRows - i - 1) 6 | * 7 | * Time Complexity: O(log(n + m)), Space Complexity: O(1) 8 | * 9 | */ 10 | 11 | class Solution { 12 | func convert(s: String, _ numRows: Int) -> String { 13 | if numRows == 1 { 14 | return s 15 | } 16 | 17 | var ret: [Character] = [] 18 | var chars: [Character] = [Character](s.characters) 19 | let cnt = chars.count 20 | 21 | 22 | for i in 0.. Int { 21 | var stack = [TreeNode](), currentNode = root, k = k 22 | 23 | while !stack.isEmpty || currentNode != nil { 24 | if currentNode != nil { 25 | stack.append(currentNode!) 26 | currentNode = currentNode!.left 27 | } else { 28 | let node = stack.removeLast() 29 | k -= 1 30 | 31 | if k == 0 { 32 | return node.val 33 | } 34 | 35 | currentNode = node.right 36 | } 37 | } 38 | 39 | return -1 40 | } 41 | } -------------------------------------------------------------------------------- /Tree/HouseRobberIII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/house-robber-iii/ 3 | * Primary idea: Using two sums to track rob sum starting from current node or not, 4 | * compare and get the maximum one 5 | * Time Complexity: O(n), Space Complexity: O(1) 6 | * 7 | * Definition for a binary tree node. 8 | * public class TreeNode { 9 | * public var val: Int 10 | * public var left: TreeNode? 11 | * public var right: TreeNode? 12 | * public init(_ val: Int) { 13 | * self.val = val 14 | * self.left = nil 15 | * self.right = nil 16 | * } 17 | * } 18 | */ 19 | 20 | class HouseRobberIII { 21 | func rob(_ root: TreeNode?) -> Int { 22 | let (robRoot, notRobRoot) = helper(root) 23 | 24 | return max(robRoot, notRobRoot) 25 | } 26 | 27 | fileprivate func helper(_ node: TreeNode?) -> (Int, Int) { 28 | guard let node = node else { 29 | return (0, 0) 30 | } 31 | 32 | let (robLeft, notRobLeft) = helper(node.left) 33 | let (robRight, notRobRight) = helper(node.right) 34 | 35 | let robNode = notRobLeft + notRobRight + node.val 36 | let notRobNode = max(robLeft, notRobLeft) + max(robRight, notRobRight) 37 | 38 | return (robNode, notRobNode) 39 | } 40 | } -------------------------------------------------------------------------------- /DP/MinimumWindowSubsequence.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/minimum-window-subsequence/ 3 | * Primary idea: Dynamic Programming, dp[i][j] = dp[i][j - 1] || dp[i - 1][j - 1] 4 | * Time Complexity: O(mn), Space Complexity: O(mn) 5 | * 6 | */ 7 | 8 | class MinimumWindowSubsequence { 9 | func minWindow(_ S: String, _ T: String) -> String { 10 | let m = T.count, n = S.count, sChars = Array(S), tChars = Array(T) 11 | var dp = Array(repeating: Array(repeating: 0, count: n + 1), count: m + 1) 12 | var start = 0, len = n + 1 13 | 14 | for i in 0...n { 15 | dp[0][i] = i + 1 16 | } 17 | 18 | for i in 1...m { 19 | for j in 1...n { 20 | if tChars[i - 1] == sChars[j - 1] { 21 | dp[i][j] = dp[i - 1][j - 1] 22 | } else { 23 | dp[i][j] = dp[i][j - 1] 24 | } 25 | } 26 | } 27 | 28 | for i in 1...n { 29 | if dp[m][i] != 0 { 30 | if i - dp[m][i] + 1 < len { 31 | len = i - dp[m][i] + 1 32 | start = dp[m][i] - 1 33 | } 34 | } 35 | } 36 | 37 | return len == n + 1 ? "" : String(sChars[start.. Bool { 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 true 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 if nums[mid] < nums[left]{ 28 | if nums[mid] < target && target <= nums[right] { 29 | left = mid + 1 30 | } else { 31 | right = mid - 1 32 | } 33 | } else { 34 | left += 1 35 | } 36 | } 37 | 38 | return false 39 | } 40 | } -------------------------------------------------------------------------------- /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: [Interval]) -> [Interval] { 19 | var result = [Interval]() 20 | 21 | let intervals = intervals.sorted { 22 | if $0.start != $1.start { 23 | return $0.start < $1.start 24 | } else { 25 | return $0.end < $1.end 26 | } 27 | } 28 | 29 | for interval in intervals { 30 | guard let last = result.last else { 31 | result.append(interval) 32 | continue 33 | } 34 | 35 | if last.end < interval.start { 36 | result.append(interval) 37 | } else { 38 | last.end = max(last.end, interval.end) 39 | } 40 | } 41 | 42 | return result 43 | } 44 | } -------------------------------------------------------------------------------- /String/OneEditDistance.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/one-edit-distance/ 3 | * Primary idea: Two pointers to determine two strings' mutation 4 | * Time Complexity: O(n), Space Complexity: O(n) 5 | */ 6 | 7 | class OneEditDistance { 8 | func isOneEditDistance(_ s: String, _ t: String) -> Bool { 9 | let sChars = Array(s.characters), tChars = Array(t.characters) 10 | var foundDiff = false, i = 0, j = 0 11 | 12 | let shorter = sChars.count < tChars.count ? sChars : tChars 13 | let longer = sChars.count < tChars.count ? tChars : sChars 14 | 15 | guard longer.count - shorter.count < 2 && s != t else { 16 | return false 17 | } 18 | 19 | while i < shorter.count && j < longer.count { 20 | if shorter[i] != longer[j] { 21 | if foundDiff { 22 | return false 23 | } 24 | 25 | foundDiff = true 26 | if shorter.count < longer.count { 27 | j += 1 28 | } else { 29 | i += 1 30 | j += 1 31 | } 32 | } else { 33 | i += 1 34 | j += 1 35 | } 36 | } 37 | 38 | return true 39 | } 40 | } -------------------------------------------------------------------------------- /DFS/NumberofIslands.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/number-of-islands/ 3 | * Primary idea: Classic Depth-first Search, go up, down, left, right four directions 4 | * 5 | * Time Complexity: O(mn), Space Complexity: O(1) 6 | * 7 | */ 8 | 9 | class NumberofIslands { 10 | func numIslands(grid: [[Character]]) -> Int { 11 | guard grid.count > 0 && grid[0].count > 0 else { 12 | return 0 13 | } 14 | 15 | var grid = grid 16 | let m = grid.count 17 | let n = grid[0].count 18 | var count = 0 19 | 20 | for i in 0..= 0 && i < m && j >= 0 && j < n && String(grid[i][j]) == "1" else { 34 | return 35 | } 36 | 37 | grid[i][j] = Character("0") 38 | 39 | _dfs(&grid, m, n, i + 1, j) 40 | _dfs(&grid, m, n, i - 1, j) 41 | _dfs(&grid, m, n, i, j + 1) 42 | _dfs(&grid, m, n, i, j - 1) 43 | } 44 | } -------------------------------------------------------------------------------- /Array/ExamRoom.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/exam-room/ 3 | * Primary idea: Calculate and compare middle point between two taken seats. 4 | * 5 | * Time Complexity: O(n) for seat(), O(1) for leave(at:), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class ExamRoom { 10 | var seats: [Int] 11 | 12 | init(_ n: Int) { 13 | seats = Array(repeating: 0, count: n) 14 | } 15 | 16 | func seat() -> Int { 17 | var maxDistance = 0, maxIndex = 0, lastOne = -1 18 | 19 | for (i, seat) in seats.enumerated() { 20 | if seat == 1 { 21 | if lastOne == -1 { 22 | if maxDistance < i { 23 | maxDistance = i 24 | maxIndex = 0 25 | } 26 | } else { 27 | if maxDistance < (i - lastOne) / 2 { 28 | maxDistance = (i - lastOne) / 2 29 | maxIndex = lastOne + (i - lastOne) / 2 30 | } 31 | } 32 | } 33 | 34 | lastOne = i 35 | } 36 | 37 | if lastOne != -1 { 38 | if maxDistance < (seats.count - 1 - lastOne) / 2 { 39 | maxIndex = seats.count - 1 40 | } 41 | } 42 | 43 | seats[maxIndex] = 1 44 | 45 | return maxIndex 46 | } 47 | 48 | func leave(_ seat: Int) { 49 | seats[seat] = 0 50 | } 51 | } -------------------------------------------------------------------------------- /DFS/WallsGates.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/walls-and-gates/ 3 | * Primary idea: Classic Depth-first Search, go up, down, left, right four directions 4 | * 5 | * Note: Start from gate to ease complexity, update distance correspondingly 6 | * Time Complexity: O((mn)^2), Space Complexity: O(1) 7 | * 8 | */ 9 | 10 | class WallsGates { 11 | func wallsAndGates(_ rooms: inout [[Int]]) { 12 | guard rooms.count > 0 && rooms[0].count > 0 else { 13 | return 14 | } 15 | 16 | let m = rooms.count 17 | let n = rooms[0].count 18 | 19 | for i in 0..= 0 && i < m && j >= 0 && j < n else { 30 | return 31 | } 32 | 33 | if distance == 0 || distance < rooms[i][j] { 34 | rooms[i][j] = distance 35 | dfs(&rooms, i + 1, j, m, n, distance + 1) 36 | dfs(&rooms, i - 1, j, m, n, distance + 1) 37 | dfs(&rooms, i, j + 1, m, n, distance + 1) 38 | dfs(&rooms, i, j - 1, m, n, distance + 1) 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /DP/BurstBalloons.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/burst-balloons/ 3 | * Primary idea: Dynamic Programming, dp[i][j] represents the max coins from ballon i to j, 4 | * transition function: dp[i][j] = max(dp[i][j], nums[i - 1]*nums[k]*nums[j + 1] + dp[i][k - 1] + dp[k + 1][j]) 5 | * 6 | * Note: for loops should start by length, not by start 7 | * 8 | * Time Complexity: O(n^3), Space Complexity: O(n) 9 | * 10 | */ 11 | 12 | class BurstBalloons { 13 | func maxCoins(_ nums: [Int]) -> Int { 14 | guard nums.count > 0 else { 15 | return 0 16 | } 17 | 18 | let n = nums.count, nums = renderNums(nums) 19 | var dp = Array(repeating: Array(repeating: 0, count: nums.count), count: nums.count) 20 | 21 | for len in 1...n { 22 | for left in 1...n - len + 1 { 23 | let right = left + len - 1 24 | for k in left...right { 25 | dp[left][right] = max(dp[left][right], nums[left - 1] * nums[k] * nums[right + 1] + dp[left][k - 1] + dp[k + 1][right]) 26 | } 27 | } 28 | } 29 | 30 | return dp[1][n] 31 | } 32 | 33 | private func renderNums(_ nums: [Int]) -> [Int] { 34 | var nums = nums 35 | 36 | nums.append(1) 37 | nums.insert(1, at: 0) 38 | 39 | return nums 40 | } 41 | } -------------------------------------------------------------------------------- /Tree/BinaryTreeZigzagLevelOrderTraversal.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/ 3 | * Primary idea: use a queue to help hold TreeNode, and for each level add a new Int array 4 | * 5 | * Note: use a boolean value to determine if needs to be added reversely 6 | * 7 | * Time Complexity: O(n), Space Complexity: O(n) 8 | * 9 | * Definition for a binary tree node. 10 | * public class TreeNode { 11 | * public var val: Int 12 | * public var left: TreeNode? 13 | * public var right: TreeNode? 14 | * public init(_ val: Int) { 15 | * self.val = val 16 | * self.left = nil 17 | * self.right = nil 18 | * } 19 | * } 20 | * 21 | */ 22 | 23 | class BinaryTreeZigzagLevelOrderTraversal { 24 | func zigzagLevelOrder(root: TreeNode?) -> [[Int]] { 25 | guard let root = root else { 26 | return [[Int]]() 27 | } 28 | 29 | var res = [[Int]](), isReverse = false, nodeQ = [root] 30 | 31 | while !nodeQ.isEmpty { 32 | let currentLevel = nodeQ.map { $0.val } 33 | res.append(isReverse ? currentLevel.reversed() : currentLevel) 34 | 35 | isReverse = !isReverse 36 | 37 | nodeQ = nodeQ.flatMap { [$0.left, $0.right].compactMap { $0 } } 38 | } 39 | 40 | return res 41 | } 42 | } -------------------------------------------------------------------------------- /Tree/FlattenBinaryTreeLinkedList.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/flatten-binary-tree-to-linked-list/ 3 | * Primary idea: Reset left to nil and change current node to left child every time 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 FlattenBinaryTreeLinkedList { 20 | func flatten(_ root: TreeNode?) { 21 | helper(root) 22 | } 23 | 24 | private func helper(_ node: TreeNode?) -> TreeNode? { 25 | var node = node 26 | if node == nil { 27 | return node 28 | } 29 | if node!.left == nil && node!.right == nil { 30 | return node 31 | } 32 | 33 | let left = node!.left, right = node!.right 34 | node!.left = nil 35 | 36 | if let left = left { 37 | node!.right = left 38 | node = helper(left) 39 | } 40 | if let right = right { 41 | node!.right = right 42 | node = helper(right) 43 | } 44 | 45 | return node 46 | } 47 | } -------------------------------------------------------------------------------- /Tree/PathSumIII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/path-sum-iii/ 3 | * Primary idea: Get path number of every node as root while iterating the tree 4 | * Time Complexity: O(n^2), 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 PathSumIII { 20 | func pathSum(_ root: TreeNode?, _ sum: Int) -> Int { 21 | guard let root = root else { 22 | return 0 23 | } 24 | 25 | var res = totalPaths(root, sum) 26 | 27 | let left = pathSum(root.left, sum) 28 | let right = pathSum(root.right, sum) 29 | 30 | return res + left + right 31 | } 32 | 33 | func totalPaths(_ root: TreeNode?, _ sum: Int) -> Int { 34 | guard let root = root else { 35 | return 0 36 | } 37 | 38 | var res = 0 39 | if sum == root.val { 40 | res += 1 41 | } 42 | 43 | res += totalPaths(root.left, sum - root.val) 44 | res += totalPaths(root.right, sum - root.val) 45 | 46 | return res 47 | } 48 | } -------------------------------------------------------------------------------- /Math/TrappingRainWater.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/trapping-rain-water/ 3 | * Primary idea: The rain capacity is always determined by the the min value of 4 | * left and right maximum height 5 | * Time Complexity: O(n), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class TrappingRainWater { 10 | func trap(height: [Int]) -> Int { 11 | guard height.count > 0 else { 12 | return 0 13 | } 14 | 15 | var res = 0 16 | var left = _initMaxHeights(height, true) 17 | var right = _initMaxHeights(height, false) 18 | 19 | for i in 0.. [Int] { 27 | var res = [Int](count: height.count, repeatedValue: 0) 28 | var currentMax = 0 29 | 30 | if isLeft { 31 | for i in 0.. Bool { 10 | if maxChoosableInteger >= desiredTotal { 11 | return true 12 | } 13 | if (maxChoosableInteger + 1) * maxChoosableInteger / 2 < desiredTotal { 14 | return false 15 | } 16 | 17 | var memo = [Int: Bool]() 18 | return helper(maxChoosableInteger, desiredTotal, 0, &memo) 19 | } 20 | 21 | fileprivate func helper(_ maxChoosableInteger: Int, _ desiredTotal: Int, _ used: Int, _ memo: inout [Int: Bool]) -> Bool { 22 | if let canWin = memo[used] { 23 | return canWin 24 | } 25 | 26 | for i in 0.. ListNode? { 19 | if head == nil { 20 | return head 21 | } 22 | 23 | var prev = head 24 | var post = head 25 | let len = _getLength(head) 26 | var k = k % len 27 | 28 | while k > 0 { 29 | post = post!.next 30 | k -= 1 31 | } 32 | 33 | while post!.next != nil { 34 | prev = prev!.next 35 | post = post!.next 36 | } 37 | 38 | post!.next = head 39 | post = prev!.next 40 | prev!.next = nil 41 | 42 | return post 43 | } 44 | 45 | private func _getLength(head: ListNode?) -> Int { 46 | var len = 0 47 | var node = head 48 | 49 | while node != nil { 50 | len += 1 51 | node = node!.next 52 | } 53 | 54 | return len 55 | } 56 | } -------------------------------------------------------------------------------- /Search/MedianTwoSortedArrays.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/median-of-two-sorted-arrays/ 3 | * Primary idea: Search kth value of both arrays and then compare, each time 4 | * remove half of them until index is 0 5 | * 6 | * Time Complexity: O(log(m + n)), Space Complexity: O(1) 7 | */ 8 | 9 | class MedianTwoSortedArrays { 10 | func findMedianSortedArrays(_ nums1: [Int], _ nums2: [Int]) -> Double { 11 | let m = nums1.count 12 | let n = nums2.count 13 | 14 | return (findKth(nums1, nums2, (m + n + 1) / 2) + findKth(nums1, nums2, (m + n + 2) / 2)) / 2 15 | } 16 | 17 | private func findKth(_ nums1: [Int], _ nums2: [Int], _ index: Int) -> Double { 18 | let m = nums1.count 19 | let n = nums2.count 20 | 21 | guard m <= n else { 22 | return findKth(nums2, nums1, index) 23 | } 24 | guard m != 0 else { 25 | return Double(nums2[index - 1]) 26 | } 27 | guard index != 1 else { 28 | return Double(min(nums1[0], nums2[0])) 29 | } 30 | 31 | let i = min(index / 2, m) 32 | let j = min(index / 2, n) 33 | 34 | if nums1[i - 1] < nums2[j - 1] { 35 | return findKth(Array(nums1[i.. ListNode? { 22 | if head == nil || head!.next == nil { 23 | return head 24 | } 25 | 26 | let dummy = ListNode(0) 27 | dummy.next = head 28 | var node = dummy 29 | 30 | while node.next != nil && node.next!.next != nil { 31 | if node.next!.val == node.next!.next!.val { 32 | let val = node.next!.val 33 | while node.next != nil && node.next!.val == val { 34 | node.next = node.next!.next 35 | } 36 | } else { 37 | node = node.next! 38 | } 39 | } 40 | 41 | return dummy.next 42 | } 43 | } -------------------------------------------------------------------------------- /Array/AsteroidCollision.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/asteroid-collision/ 3 | * Primary idea: traverse the array and handle positive and negative separately 4 | * 5 | * Time Complexity: O(n), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class AsteroidCollision { 10 | func asteroidCollision(_ asteroids: [Int]) -> [Int] { 11 | var positives = [Int]() 12 | var negatives = [Int]() 13 | 14 | for asteroid in asteroids { 15 | if asteroid > 0 { 16 | positives.append(asteroid) 17 | } else { 18 | var shouldAppendToNegative = true 19 | 20 | while positives.count > 0 { 21 | if positives.last! > -asteroid { 22 | shouldAppendToNegative = false 23 | break 24 | } else { 25 | let last = positives.removeLast() 26 | 27 | if -asteroid == last { 28 | shouldAppendToNegative = false 29 | break 30 | } 31 | } 32 | } 33 | 34 | if shouldAppendToNegative { 35 | negatives.append(asteroid) 36 | } 37 | } 38 | } 39 | 40 | return negatives + positives 41 | } 42 | } -------------------------------------------------------------------------------- /DP/RegularExpressionMatching.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/regular-expression-matching/ 3 | * Primary idea: Classic Two Dimensionel Dynamic Programming 4 | * Time Complexity: O(mn), Space Complexity: O(mn) 5 | */ 6 | 7 | class RegularExpressionMatching { 8 | func isMatch(_ s: String, _ p: String) -> Bool { 9 | let sChars = Array(s), pChars = Array(p) 10 | var dp = Array(repeating: Array(repeating: false, count: pChars.count + 1), count: sChars.count + 1) 11 | dp[0][0] = true 12 | 13 | for i in 0...pChars.count { 14 | // jump over "" vs. "x*" case 15 | dp[0][i] = i == 0 || i > 1 && dp[0][i - 2] && pChars[i - 1] == "*" 16 | } 17 | 18 | for i in 0...sChars.count { 19 | for j in 0...pChars.count { 20 | guard j > 0 else { 21 | continue 22 | } 23 | 24 | let pCurrent = pChars[j - 1] 25 | 26 | if pCurrent != "*" { 27 | dp[i][j] = i > 0 && dp[i - 1][j - 1] && (pCurrent == "." || pCurrent == sChars[i - 1]) 28 | } else { 29 | dp[i][j] = dp[i][j - 2] || i > 0 && j > 1 && (sChars[i - 1] == pChars[j - 2] || pChars[j - 2] == ".") && dp[i - 1][j] 30 | } 31 | } 32 | } 33 | 34 | return dp[sChars.count][pChars.count] 35 | } 36 | } -------------------------------------------------------------------------------- /Array/NumMatrix.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/range-sum-query-2d-immutable/ 3 | * Primary idea: Prebuild a sum matrix by original as top left point and current as bottom right point 4 | * 5 | * Time Complexity: O(mn) for init(), O(1) for sumRegion(), Space Complexity: O(mn) 6 | */ 7 | 8 | class NumMatrix { 9 | fileprivate var sum: [[Int]] 10 | 11 | init(_ matrix: [[Int]]) { 12 | let m = matrix.count, n = matrix[0].count 13 | sum = Array(repeating: Array(repeating: 0, count: n), count: m) 14 | 15 | for i in 0.. Int { 30 | if row1 == 0 && col1 == 0 { 31 | return sum[row2][col2] 32 | } else if row1 == 0 { 33 | return sum[row2][col2] - sum[row2][col1 - 1] 34 | } else if col1 == 0 { 35 | return sum[row2][col2] - sum[row1 - 1][col2] 36 | } else { 37 | return sum[row2][col2] - sum[row2][col1 - 1] - sum[row1 - 1][col2] + sum[row1 - 1][col1 - 1] 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /UnionFind/NumberIslandsII.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/number-of-islands-ii/ 3 | * Primary idea: Classic Union Find, check four directions and update count every time 4 | * 5 | * Time Complexity: O(klogmn), Space Complexity: O(mn) 6 | * 7 | */ 8 | 9 | class NumberIslandsII { 10 | func numOfIslandsII(_ m: Int, _ n: Int, _ positions: [(Int, Int)]) -> [Int] { 11 | var res = [Int](), count = 0, roots = Array(repeating: -1, count: m * n) 12 | 13 | for position in positions { 14 | var pos = position.0 * n + position.1 15 | roots[pos] = pos 16 | count += 1 17 | 18 | for moveDir in [(0, 1), (0, -1), (1, 0), (-1, 0)] { 19 | let i = position.0 + moveDir.0, j = position.1 + moveDir.1 20 | let movePos = i * n + j 21 | 22 | guard i >= 0 && i < m && j >= 0 && j < n && roots[movePos] != -1 else { 23 | continue 24 | } 25 | 26 | let movePosRoot = findRoot(movePos, roots) 27 | 28 | if movePosRoot != pos { 29 | count -= 1 30 | roots[pos] = movePosRoot 31 | pos = movePosRoot 32 | } 33 | } 34 | 35 | res.append(count) 36 | } 37 | 38 | return res 39 | } 40 | 41 | fileprivate func findRoot(_ node: Int, _ roots: [Int]) -> Int { 42 | var node = node 43 | while node != roots[node] { 44 | node = roots[node] 45 | } 46 | return node 47 | } 48 | } -------------------------------------------------------------------------------- /Math/SuperUglyNumber.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/super-ugly-number/ 3 | * Primary idea: Use dict to track indices to build a helper array, 4 | * remember to kill duplicates 5 | * Time Complexity: O(n^2), Space Complexity: O(n) 6 | * 7 | */ 8 | 9 | class SuperUglyNumber { 10 | func nthSuperUglyNumber(n: Int, _ primes: [Int]) -> Int { 11 | var uglyNums = [Int](count: n, repeatedValue: 1) 12 | var dict = _init(primes) 13 | 14 | for i in 1.. [Int: Int] { 22 | var dict = [Int: Int]() 23 | 24 | for prime in primes { 25 | dict[prime] = 0 26 | } 27 | 28 | return dict 29 | } 30 | 31 | private func _getMin(inout dict: [Int: Int], _ uglyNums: [Int], _ previous: Int) -> Int { 32 | var minNum = Int.max 33 | 34 | for prime in dict.keys { 35 | var current = uglyNums[dict[prime]!] * prime 36 | 37 | // kill duplicates 38 | if current == uglyNums[previous] { 39 | dict[prime]! += 1 40 | current = uglyNums[dict[prime]!] * prime 41 | } 42 | minNum = min(current, minNum) 43 | } 44 | 45 | return minNum 46 | } 47 | } -------------------------------------------------------------------------------- /LinkedList/PalindromeLinkedList.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/palindrome-linked-list/ 3 | * Primary idea: Runner tech, reverse the first half linkedlist, then compare it to the next half 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 PalindromeLinkedList { 18 | func isPalindrome(head: ListNode?) -> Bool { 19 | guard head != nil else { 20 | return true 21 | } 22 | 23 | var slow = head 24 | var fast = head 25 | var prev: ListNode? 26 | var post = slow!.next 27 | 28 | while fast != nil && fast!.next != nil { 29 | fast = fast!.next!.next 30 | 31 | slow!.next = prev 32 | prev = slow 33 | slow = post 34 | post = post!.next 35 | } 36 | 37 | if fast != nil { 38 | slow = post 39 | } 40 | 41 | while prev != nil { 42 | if prev!.val != slow!.val { 43 | return false 44 | } 45 | 46 | prev = prev!.next 47 | slow = slow!.next 48 | } 49 | 50 | return true 51 | } 52 | } -------------------------------------------------------------------------------- /String/FindDuplicateFileInSystem.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Question Link: https://leetcode.com/problems/find-duplicate-file-in-system/ 3 | * Primary idea: Iterate the paths array and categories paths with the same content 4 | * 5 | * Time Complexity: O(nm), n stands for number of paths, m stands for file number in a path 6 | * Space Complexity: O(n) 7 | */ 8 | 9 | class FindDuplicateFileInSystem { 10 | func findDuplicate(_ paths: [String]) -> [[String]] { 11 | var contentToFiles = [String: [String]]() 12 | 13 | for path in paths { 14 | let params = path.split(separator: " ") 15 | 16 | guard let dir = params.first else { 17 | continue 18 | } 19 | 20 | for i in 1..= 2 } 35 | } 36 | } 37 | --------------------------------------------------------------------------------