├── Images └── Logo.png ├── Sources ├── Math │ ├── 13_RomanToInteger.swift │ ├── 231_PowerOfTwo.swift │ ├── 136_SingleNumber.swift │ ├── 326_PowerOfThree.swift │ ├── 7_ReverseInteger.swift │ ├── 338_CountingBits.swift │ ├── 263_UglyNumber.swift │ ├── 223_RectangleArea.swift │ ├── 258_AddDigits.swift │ ├── 9_PalindromeNumber.swift │ └── 8_StringToInteger.swift ├── Array │ ├── 217_ContainsDuplicate.swift │ ├── 349_IntersectionOfTwoArrays.swift │ ├── 1_TwoSum.swift │ ├── 27_RemoveElement.swift │ ├── 645_SetMismatch.swift │ ├── 283_MoveZeros.swift │ ├── 400_NthDigit.swift │ ├── 48_RotateImage.swift │ ├── 228_SummaryRange.swift │ ├── 260_SingleNumberIII.swift │ ├── 303_RangeSumQuery.swift │ ├── 36_ValidSudoku.swift │ ├── 26_RemoveDuplicatesFromSortedArray.swift │ ├── 189_RotateArray.swift │ ├── 350_IntersectionOfTwoArraysII.swift │ ├── 621_TaskScheduler.swift │ ├── 340_LongestSubStringWithAtMostKDistinctCharacters.swift │ ├── 388_LongestAbsoluteFilePath.swift │ ├── 80_RemoveDuplicatesFromSortedArrayII.swift │ ├── 457_CircularArrayLoop.swift │ ├── 15_3Sum.swift │ ├── 361_BombEnemy.swift │ ├── 18_4Sum.swift │ └── 304_RangeSumQuery2D.swift ├── String │ ├── 58_LengthOfLastWord.swift │ ├── 344_ReverseString.swift │ ├── 293_FlipGame.swift │ ├── 28_ImplementStrStr.swift │ ├── 205_IsomorphicString.swift │ ├── 14_LongestCommonPrefix.swift │ ├── 242_ValidAnagram.swift │ ├── 345_ReverseVowelsOfAString.swift │ ├── 294_FlipGameII.swift │ ├── 389_FindTheDifference.swift │ ├── 418_SentenceScreenFitting.swift │ ├── 394_DecodeString.swift │ ├── 383_RansomNote.swift │ ├── 3_LongestSubStringWithoutRepeatingCharacters.swift │ ├── 290_WordPattern.swift │ └── 165_CompareVersionNumbers.swift ├── LinkedList │ ├── 206_ReverseLinkedList.swift │ ├── 24_SwapNodesInPairs.swift │ ├── 86_PartitionList.swift │ ├── 61_RotateList.swift │ ├── 143_ReorderList.swift │ ├── 83_RemoveDuplicatesFromSortedList.swift │ └── 2_AddTwoNumbers.swift ├── DynamicProgramming │ ├── 70_ClimbingStairs.swift │ ├── 53_MaximumSubarry.swift │ ├── 121_BestTimeToBuyAndSellStock.swift │ ├── 62_UniquePaths.swift │ ├── 279_PerfectSquares.swift │ ├── 152_MaximumProductSubarray.swift │ ├── 300_LongestIncreasingSubsequence.swift │ ├── 409_LongestPalindrome.swift │ ├── 55_JumpGame.swift │ ├── 322_CoinChange.swift │ ├── 64_MinimumPathSum.swift │ ├── 72_EditDistance.swift │ ├── 198_HouseRobber.swift │ ├── 63_UniquePaths.swift │ ├── 221_MaximalSquare.swift │ ├── 5_LongestPalindromicSubString.swift │ ├── 377_CombinationSumIV.swift │ ├── 139_WordBreak.swift │ └── 213_HouseRobberII.swift ├── Tree │ ├── 98_ValidateBinarySearchTree.swift │ ├── 112_PathSum.swift │ ├── 437_PathSumIII.swift │ ├── 226_InvertBinaryTree.swift │ ├── 100_SameTree.swift │ ├── 110_BalancedBinaryTree.swift │ ├── 450_DeleteNodeInABST.swift │ ├── 102_BinaryTreeLevelOrderTraversal.swift │ ├── 113_PathSumII.swift │ ├── 104_MaximumDepthOfBinaryTree.swift │ ├── 655_PrintBinaryTree.swift │ ├── 111_MinimumDepthOfBinaryTree.swift │ ├── 236_LowestCommonAncestorBinaryTree.swift │ ├── 105_ConstructBinaryTreeFromPreorderAndInorderTraversal.swift │ ├── 107_BinaryTreeLevelOrderTraversalII.swift │ ├── 337_HouseRobberIII.swift │ ├── 106_ConstructBinaryTreeFromInorderAndPostorderTraversal.swift │ ├── 124_BinaryTreeMaximumPathSum.swift │ └── 101_SymmetricTree.swift ├── Stack │ ├── 94_BinaryTreeInorderTraversal.swift │ ├── 20_ValidParentheses.swift │ ├── 144_BinaryTreePreorderTraversal.swift │ └── 145_BinaryTreePostorderTraversal.swift ├── Sort │ ├── 347_TopKFrequentElements.swift │ ├── 56_MergeIntervals.swift │ └── 75_SortColors.swift ├── Search │ ├── 154_FindMinimumInRotatedSortedArrayII.swift │ ├── 35_SearchInsertPosition.swift │ ├── 69_Sqrtx.swift │ ├── 153_FindMinimumInRotatedSortedArray.swift │ ├── 278_FirstBadVersion.swift │ ├── 33_SearchInRotatedSortedArray.swift │ ├── 162_FindAPeakElement.swift │ ├── 74_Search2DMatrix.swift │ ├── 34_SearchForARange.swift │ └── 81_SearchInRotatedSortedArrayII.swift ├── DFS │ ├── 638_ShoppingOffers.swift │ ├── 77_Combinations.swift │ ├── 78_Subsets.swift │ ├── 90_SubSetsII.swift │ ├── 46_Permutations.swift │ ├── 47_PermutationsII.swift │ ├── 212_WordSearchII.swift │ └── 79_WordSearch.swift ├── Heap │ └── 23_MergeKSortedLists.swift ├── Queue │ └── 346_MovingAverage.swift ├── Graph │ └── 207_CourseSchedule.swift ├── 227_BasicCalculatorII.swift ├── Google │ └── 482_LicenseKeyFormatting.swift ├── BFS │ └── 317_ShortestDistanceFromAllBuildings.swift └── 772_BasicCalculatorIII.swift ├── LeetcodeSwiftTests ├── Info.plist ├── QuickMedianTest.swift ├── ArrayExtensionTest.swift ├── LeetcodeSwiftTests.swift └── HeapTest.swift ├── LeetcodeSwiftUITests ├── Info.plist └── LeetcodeSwiftUITests.swift ├── LeetcodeSwift ├── ViewController.swift ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Base.lproj │ ├── Main.storyboard │ └── LaunchScreen.storyboard ├── Info.plist └── AppDelegate.swift ├── LICENSE └── .gitignore /Images/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jindulys/Leetcode_Solutions_Swift/HEAD/Images/Logo.png -------------------------------------------------------------------------------- /Sources/Math/13_RomanToInteger.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 13_RomanToInteger.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-05. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | -------------------------------------------------------------------------------- /Sources/Math/231_PowerOfTwo.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 231_PowerOfTwo.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-05. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:231 Power of Two 13 | URL: https://leetcode.com/problems/power-of-two/ 14 | Space: O(1) 15 | Time: O(1) 16 | */ 17 | 18 | class PowerOfTwo_Solution { 19 | func isPowerOfTwo(_ n: Int) -> Bool { 20 | guard n > 0 else { 21 | return false 22 | } 23 | return n & (n - 1) == 0 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Sources/Math/136_SingleNumber.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 136_SingleNumber.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-05. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:136 Single Number 13 | URL: https://leetcode.com/problems/single-number/ 14 | Space: O(1) 15 | Time: O(n) 16 | */ 17 | 18 | class SingleNumber_Solution { 19 | func singleNumber(_ nums: [Int]) -> Int { 20 | var ret: Int = 0 21 | for i in nums { 22 | ret ^= i 23 | } 24 | return ret 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Sources/Math/326_PowerOfThree.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 326_PowerOfThree.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-05. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:326 Power of Three 13 | URL: https://leetcode.com/problems/power-of-three/ 14 | Space: O(1) 15 | Time: O(1) 16 | */ 17 | 18 | class PowerOfThree_Solution { 19 | 20 | func isPowerOfThree(_ n: Int) -> Bool { 21 | guard n > 0 else { 22 | return false 23 | } 24 | return 3486784401 % n == 0 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Sources/Array/217_ContainsDuplicate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 217_ContainsDuplicate.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-08-27. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:217 Contains Duplicate 13 | URL: https://leetcode.com/problems/contains-duplicate/ 14 | Space: O(n) 15 | Time: O(n) 16 | */ 17 | 18 | class ContainsDuplicate_Solution { 19 | // Use set. 20 | func containsDuplicate(_ nums: [Int]) -> Bool { 21 | let numsSet = Set(nums) 22 | return numsSet.count != nums.count 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Sources/Array/349_IntersectionOfTwoArrays.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 349_IntersectionOfTwoArrays.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-08-27. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:349 Intersection of two arrays 13 | URL: https://leetcode.com/problems/intersection-of-two-arrays/ 14 | Space: O(n) 15 | Time: O(n) 16 | */ 17 | 18 | class IntersectionofTwoArrays_Solution { 19 | func intersection(_ nums1: [Int], _ nums2: [Int]) -> [Int] { 20 | let result = Set(nums1).intersection(nums2) 21 | return Array(result) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Sources/String/58_LengthOfLastWord.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 58_LengthOfLastWord.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-08-27. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:58 Length of Last Word 13 | URL: https://leetcode.com/problems/length-of-last-word/ 14 | Space: O(n) 15 | Time: O(n) 16 | */ 17 | 18 | class LengthOfLastWord_Solution { 19 | func lengthOfLastWord(_ s: String) -> Int { 20 | if let lastWord = s.characters.split(separator: " ").last { 21 | return lastWord.count 22 | } else { 23 | return 0 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Sources/Array/1_TwoSum.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 1_TwoSum.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-08-28. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:1 Two Sum 13 | URL: https://leetcode.com/problems/two-sum/ 14 | Space: O(n) 15 | Time: O(n) 16 | */ 17 | 18 | class TwoSum_Solution { 19 | func twoSum(_ nums: [Int], _ target: Int) -> [Int] { 20 | var expectedDict: [Int: Int] = [:] 21 | for i in 0.. ListNode? { 20 | var temp: ListNode? 21 | var first = head 22 | while let validNode = first { 23 | first = validNode.next 24 | validNode.next = temp 25 | temp = validNode 26 | } 27 | return temp 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Sources/Array/27_RemoveElement.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 27_RemoveElement.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-08-27. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:27 Remove Element 13 | URL: https://leetcode.com/problems/remove-element/ 14 | Space: O(1) 15 | Time: O(n) 16 | */ 17 | 18 | class RemoveElement_Solution { 19 | func removeElement(_ nums: inout [Int], _ val: Int) -> Int { 20 | var len: Int = nums.count 21 | var i: Int = 0 22 | while i < len { 23 | while nums[i] == val && i < len { 24 | len -= 1 25 | nums[i] = nums[len] 26 | } 27 | i += 1 28 | } 29 | return len 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Sources/Math/7_ReverseInteger.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 7_ReverseInteger.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-05. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:7 Reverse Integer 13 | URL: https://leetcode.com/problems/reverse-integer/ 14 | Space: O(1) 15 | Time: O(1) 16 | */ 17 | 18 | class ReverseInteger_Solution { 19 | func reverse(_ x: Int) -> Int { 20 | var loopVariable = x 21 | var res = 0 22 | while loopVariable != 0 { 23 | res = res * 10 + loopVariable % 10 24 | loopVariable = loopVariable / 10 25 | if res > Int(Int32.max) || res < Int(Int32.min) { 26 | return 0 27 | } 28 | } 29 | return res 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Sources/Math/338_CountingBits.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 338_CountingBits.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-11-12. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:338 Counting Bits 13 | URL: https://leetcode.com/problems/counting-bits/ 14 | Space: O(N) 15 | Time: O(N) 16 | */ 17 | 18 | class CountingBits_Solution { 19 | func countBits(_ num: Int) -> [Int] { 20 | guard num > 0 else { 21 | return [0] 22 | } 23 | var result = Array(repeating: 0, count: num + 1) 24 | var x = 1 25 | for i in 1...num { 26 | if i == x { 27 | x = x << 1 28 | result[i] = 1 29 | } else { 30 | result[i] = result[i - (x >> 1)] + 1 31 | } 32 | } 33 | return result 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /LeetcodeSwiftTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /LeetcodeSwiftUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Sources/Math/263_UglyNumber.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 263_UglyNumber.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-05. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:263 Ugly Number 13 | URL: https://leetcode.com/problems/ugly-number/ 14 | Space: O(1) 15 | Time: O(1) 16 | */ 17 | 18 | class UglyNumber_Solution { 19 | func isUgly(_ num: Int) -> Bool { 20 | guard num > 0 else { 21 | return false 22 | } 23 | var loopNum = num 24 | while loopNum != 1 { 25 | if loopNum % 2 == 0 { 26 | loopNum /= 2 27 | } else if loopNum % 3 == 0 { 28 | loopNum /= 3 29 | } else if loopNum % 5 == 0 { 30 | loopNum /= 5 31 | } else { 32 | return false 33 | } 34 | } 35 | return true 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Sources/Math/223_RectangleArea.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 223_RectangleArea.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-11-12. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:223 Rectangle Area 13 | URL: https://leetcode.com/problems/rectangle-area/ 14 | Space: O(1) 15 | Time: O(1) 16 | */ 17 | 18 | class RectangleArea_Solution { 19 | func computeArea(_ A: Int, _ B: Int, _ C: Int, _ D: Int, _ E: Int, _ F: Int, _ G: Int, _ H: Int) -> Int { 20 | let totalArea = (C - A) * (D - B) + (G - E) * (H - F) 21 | if A >= G || C <= E || B >= H || D <= F { 22 | return totalArea 23 | } 24 | let startX = max(A, E) 25 | let endX = min(C, G) 26 | let startY = max(B, F) 27 | let endY = min(D, H) 28 | return totalArea - (endX - startX) * (endY - startY) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Sources/Array/645_SetMismatch.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 645_SetMismatch.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2018-04-22. 6 | // Copyright © 2018 YANSONG LI. All rights reserved. 7 | // 8 | 9 | /** 10 | Title: 645 SetMismatch 11 | URL: https://leetcode.com/problems/set-mismatch/ 12 | Space: O(N) 13 | Time: O(N) 14 | */ 15 | 16 | class SetMismatch { 17 | func findErrorNums(_ nums: [Int]) -> [Int] { 18 | guard nums.count > 0 else { 19 | return [] 20 | } 21 | let n = nums.count 22 | var numsCount = Array(repeatElement(0, count: n)) 23 | for i in 0.. Int { 20 | guard n > 0 else { 21 | return 0 22 | } 23 | var oneStepPrev = 1 24 | var twoStepPrev = 0 25 | var ret = 0 26 | for i in 1...n { 27 | ret = 0 28 | if i - 1 >= 0 { 29 | ret += oneStepPrev 30 | } 31 | if i - 2 >= 0 { 32 | ret += twoStepPrev 33 | } 34 | twoStepPrev = oneStepPrev 35 | oneStepPrev = ret 36 | } 37 | return ret 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Sources/Array/283_MoveZeros.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 283_MoveZeros.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-08-27. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:283 Move Zeroes 13 | URL: https://leetcode.com/problems/move-zeroes/ 14 | Space: O(1) 15 | Time: O(n) 16 | */ 17 | 18 | class MoveZeros_Solution { 19 | func moveZeroes(_ nums: inout [Int]) { 20 | var firstZeroIndex: Int = -1 21 | /// 1 2 3 0 0 1 2 22 | /// 1 2 3 1 0 0 2 23 | for i in 0.. Int { 20 | guard nums.count > 1 else { 21 | if nums.count == 1 { 22 | return nums[0] 23 | } 24 | return 0 25 | } 26 | var maxSums = Array(repeating: 0, count: nums.count) 27 | maxSums[0] = nums[0] 28 | var ret = nums[0] 29 | for i in 1.. 0 ? maxSums[i - 1] : 0) + nums[i] 31 | ret = max(ret, maxSums[i]) 32 | } 33 | return ret 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Sources/DynamicProgramming/121_BestTimeToBuyAndSellStock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 121_BestTimeToBuyAndSellStock.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-22. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:121 Best Time to Buy and Sell Stock 13 | URL: https://leetcode.com/problems/best-time-to-buy-and-sell-stock/ 14 | Space: O(1) 15 | Time: O(N) 16 | */ 17 | 18 | class BestTimeToBuyAndSellStock_Solution { 19 | func maxProfit(_ prices: [Int]) -> Int { 20 | guard prices.count > 1 else { 21 | return 0 22 | } 23 | var currentMin = prices[0] 24 | var bestTrade = 0 25 | for i in 0.. String { 20 | var characters = Array(s.characters) 21 | guard characters.count > 0 else { 22 | return "" 23 | } 24 | var startIndex = 0 25 | var endIndex = characters.count - 1 26 | while startIndex < endIndex { 27 | let tmp = characters[startIndex] 28 | characters[startIndex] = characters[endIndex] 29 | characters[endIndex] = tmp 30 | startIndex += 1 31 | endIndex -= 1 32 | } 33 | return String(characters) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Sources/DynamicProgramming/62_UniquePaths.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 62_UniquePaths.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-12. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:62 Unique Paths 13 | URL: https://leetcode.com/problems/unique-paths/ 14 | Space: O(mn) 15 | Time: O(mn) 16 | */ 17 | 18 | class UniquePaths_Solution { 19 | func uniquePaths(_ m: Int, _ n: Int) -> Int { 20 | var pathsMatrix = Array(repeating: Array(repeating: 0, count: n), count: m) 21 | guard m > 1 || n > 1 else { 22 | return m * n 23 | } 24 | for i in 0.. [String] { 20 | guard s.characters.count > 1 else { 21 | return [] 22 | } 23 | var result: [String] = [] 24 | let characters = [Character](s.characters) 25 | for i in 0..<(characters.count - 1) { 26 | if characters[i] == characters[i + 1], characters[i] == "+" { 27 | var candidate = characters 28 | candidate[i] = "-" 29 | candidate[i + 1] = "-" 30 | result.append(String(candidate)) 31 | } 32 | } 33 | return result 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Sources/Math/258_AddDigits.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 258_AddDigits.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-05. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:258 Add Digits 13 | URL: https://leetcode.com/problems/add-digits/ 14 | Space: O(1) 15 | Time: O(1) 16 | */ 17 | 18 | class AddDigits_Solution { 19 | func addDigits(_ num: Int) -> Int { 20 | var currentDigitsArray = [Int]() 21 | var tenCount: Int = 1 22 | while num / tenCount >= 10 { 23 | tenCount = tenCount * 10 24 | } 25 | var loopNum = num 26 | while loopNum > 0 { 27 | currentDigitsArray.append(loopNum / tenCount) 28 | loopNum = loopNum - (loopNum / tenCount) * tenCount 29 | tenCount = tenCount / 10 30 | } 31 | let sum = currentDigitsArray.reduce(0) { 32 | $0 + $1 33 | } 34 | if sum < 10 { 35 | return sum 36 | } 37 | return addDigits(sum) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Sources/Tree/98_ValidateBinarySearchTree.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 98_ValidateBinarySearchTree.swift 3 | // HRSwift 4 | // 5 | // Created by yansong li on 2016-08-06. 6 | // Copyright © 2016 yansong li. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:98 Validate Binary Search Tree 13 | URL: https://leetcode.com/problems/validate-binary-search-tree/ 14 | Space: O(n) 15 | Time: O(n) 16 | */ 17 | 18 | /// Inorder traversal. 19 | class ValidateBinaryTree_Solution { 20 | func isValidBST(_ root: TreeNode?) -> Bool { 21 | var inorderList: [Int] = [] 22 | inorderTraversal(root, nodeList: &inorderList) 23 | return inorderList.isStrictlyIncreasing 24 | } 25 | 26 | func inorderTraversal(_ root: TreeNode?, nodeList: inout [Int]) { 27 | guard let root = root else { 28 | return 29 | } 30 | inorderTraversal(root.left, nodeList: &nodeList) 31 | nodeList.append(root.val) 32 | inorderTraversal(root.right, nodeList: &nodeList) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Sources/Tree/112_PathSum.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 112_PathSum.swift 3 | // HRSwift 4 | // 5 | // Created by yansong li on 2016-08-06. 6 | // Copyright © 2016 yansong li. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:112 Path Sum 13 | URL: https://leetcode.com/problems/path-sum/ 14 | Space: O(n) 15 | Time: O(n) 16 | */ 17 | 18 | class PathSum_Solution { 19 | 20 | var target: Int = Int.max 21 | 22 | func hasPathSum(_ root: TreeNode?, _ sum: Int) -> Bool { 23 | self.target = sum 24 | return dfsSum(root, prevSum: 0) 25 | } 26 | 27 | fileprivate func dfsSum(_ root: TreeNode?, prevSum: Int) -> Bool { 28 | guard let root = root else { 29 | return false 30 | } 31 | 32 | let currentSum = prevSum + root.val 33 | 34 | if (root.left == nil) && (root.right == nil) && currentSum == target { 35 | return true 36 | } 37 | 38 | return dfsSum(root.left, prevSum: currentSum) || dfsSum(root.right, prevSum: currentSum) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Sources/DynamicProgramming/279_PerfectSquares.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 279_PerfectSquares.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-14. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:279 Unique Paths II 13 | URL: https://leetcode.com/problems/perfect-squares/ 14 | Space: O(n) 15 | Time: O(n^2) 16 | */ 17 | 18 | class PerfectSquares_Solution { 19 | func numSquares(_ n: Int) -> Int { 20 | guard n > 0 else { 21 | return 0 22 | } 23 | // NOTE: perfectNums is an Array, which stores the minimum nums of square numbers 24 | // to sum up for index 'i'. 25 | var perfectNums = Array(repeating: Int.max, count: n + 1) 26 | perfectNums[0] = 0 27 | for i in 1...n { 28 | for j in 1...i { 29 | if j * j > i { 30 | break 31 | } 32 | perfectNums[i] = min(perfectNums[i], perfectNums[i - j * j] + 1) 33 | } 34 | } 35 | return perfectNums[n] 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Sources/DynamicProgramming/152_MaximumProductSubarray.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 152_MaximumProductSubarray.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-18. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:152 Maximum Product Subarray 13 | URL: https://leetcode.com/problems/maximum-product-subarray/ 14 | Space: O(1) 15 | Time: O(n) 16 | */ 17 | 18 | class MaximumProductSubArray_Solution { 19 | func maxProduct(_ nums: [Int]) -> Int { 20 | var ret = nums[0] 21 | // Maximum product at index `i`. 22 | var iMax = nums[0] 23 | // Minimum product at index `i`. 24 | var iMin = nums[0] 25 | for i in 1.. [Int] { 19 | var nodeStack: List = .end 20 | var currentNode = root 21 | var result: [Int] = [] 22 | while currentNode != nil || !nodeStack.isEmpty() { 23 | while let validNode = currentNode { 24 | nodeStack.push(validNode) 25 | currentNode = validNode.left 26 | } 27 | let leftMostNode = nodeStack.pop() 28 | result.append(leftMostNode!.val) 29 | currentNode = leftMostNode?.right 30 | } 31 | return result 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Sources/Sort/347_TopKFrequentElements.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 347_TopKFrequentElements.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-11-21. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:347 Top K Frequent Element 13 | URL: https://leetcode.com/problems/top-k-frequent-elements/ 14 | Space: O(klgk) 15 | Time: O(N) 16 | */ 17 | 18 | class TopKFrequentElements_Solution { 19 | func topKFrequent(_ nums: [Int], _ k: Int) -> [Int] { 20 | var elementCounts = [Int : Int]() 21 | for i in nums { 22 | if let currentCount = elementCounts[i] { 23 | elementCounts[i] = currentCount + 1 24 | } else { 25 | elementCounts[i] = 1 26 | } 27 | } 28 | var keys = [Int](elementCounts.keys) 29 | keys.sort { 30 | let firstCount = elementCounts[$0]! 31 | let secondCount = elementCounts[$1]! 32 | return firstCount > secondCount 33 | } 34 | return Array(keys.prefix(upTo: k)) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Sources/DynamicProgramming/300_LongestIncreasingSubsequence.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 300_LongestIncreasingSubsequence.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-12-10. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:300 Longest Increasing Subsequence 13 | URL: https://leetcode.com/problems/longest-increasing-subsequence/ 14 | Space: O(n) 15 | Time: O(n^2) 16 | */ 17 | 18 | class LongestIncreasingSubSequence_Solution { 19 | func lengthOfLIS(_ nums: [Int]) -> Int { 20 | guard nums.count > 0 else { 21 | return 0 22 | } 23 | let m = nums.count 24 | var longestSubSequenceCounts = Array(repeating: 1, count: m) 25 | for i in 0..() 27 | testMedian.add(10) 28 | testMedian.add(100) 29 | testMedian.add(8) 30 | testMedian.add(18) 31 | testMedian.add(30) 32 | testMedian.add(80) 33 | testMedian.add(26) 34 | XCTAssert(testMedian.popMedian()! == 26) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Sources/Math/9_PalindromeNumber.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 9_PalindromeNumber.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-05. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:9 Palindrome Number 13 | URL: https://leetcode.com/problems/palindrome-number/ 14 | Space: O(1) 15 | Time: O(1) 16 | */ 17 | 18 | class PalindromeNumber_Solution { 19 | func isPalindrome(_ x: Int) -> Bool { 20 | guard x >= 0 else { 21 | return false 22 | } 23 | var tenCount: Int = 1 24 | var loopx = x 25 | while loopx / 10 > 0 { 26 | tenCount *= 10 27 | loopx = loopx / 10 28 | } 29 | var processedX = x 30 | while processedX > 0 { 31 | let left = processedX / tenCount 32 | let right = processedX % 10 33 | if left != right { 34 | return false 35 | } 36 | processedX = processedX % tenCount 37 | processedX = processedX / 10 38 | tenCount /= 100 39 | } 40 | return true 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Sources/DynamicProgramming/409_LongestPalindrome.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 409_LongestPalindrome.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2018-04-15. 6 | // Copyright © 2018 YANSONG LI. All rights reserved. 7 | // 8 | 9 | class LongestPalindrome { 10 | func longestPalindrome(_ s: String) -> Int { 11 | guard s.count > 0 else { 12 | return 0 13 | } 14 | let length = s.count 15 | var maxLength: Int = 0 16 | var dp = 17 | Array(repeatElement(Array(repeatElement(false, count: length + 1)), count: length)) 18 | for i in 0...length { 19 | for j in 0.. maxLength{ 28 | maxLength = i 29 | } 30 | } 31 | } 32 | return maxLength 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Sources/LinkedList/24_SwapNodesInPairs.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 24_SwapNodesInPairs.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-05. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:24 Swap Nodes in Pairs 13 | URL: https://leetcode.com/problems/swap-nodes-in-pairs/ 14 | Space: O(1) 15 | Time: O(n) 16 | */ 17 | 18 | class SwapNodesInPairs_Solution { 19 | func swapPairs(_ head: ListNode?) -> ListNode? { 20 | guard head != nil && head?.next != nil else { 21 | return head 22 | } 23 | let dummy = ListNode(0) 24 | dummy.next = head 25 | var prev: ListNode? = dummy 26 | var first = head 27 | var sec = head?.next 28 | while let validSec = sec { 29 | let next = validSec.next 30 | prev?.next = validSec 31 | validSec.next = first 32 | first?.next = next 33 | if next == nil { 34 | break 35 | } 36 | prev = first 37 | first = next 38 | sec = next?.next 39 | } 40 | return dummy.next 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Sources/Tree/437_PathSumIII.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 437_PathSumIII.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2018-04-17. 6 | // Copyright © 2018 YANSONG LI. All rights reserved. 7 | // 8 | 9 | /** 10 | Title: 437 Path Sum III 11 | URL: https://leetcode.com/problems/path-sum-iii/description/ 12 | Space: O(n) 13 | Time: O(n) 14 | */ 15 | class PathSumIII { 16 | func pathSum(_ root: TreeNode?, _ sum: Int) -> Int { 17 | guard let vRoot = root else { 18 | return 0 19 | } 20 | return pathSumInclude(_:vRoot, _:sum) + pathSum(_:vRoot.left, _:sum) + pathSum(_:vRoot.right, _:sum) 21 | } 22 | 23 | func pathSumInclude(_ root: TreeNode?, _ target: Int) -> Int { 24 | guard let validRoot = root else { 25 | return 0 26 | } 27 | var currentResult: Int = 0 28 | if validRoot.val == target { 29 | currentResult += 1 30 | } 31 | currentResult += pathSumInclude(_:validRoot.left, _: target - validRoot.val) 32 | currentResult += pathSumInclude(_:validRoot.right, _: target - validRoot.val) 33 | return currentResult 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Sources/LinkedList/86_PartitionList.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 83_PartitionList.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-11-07. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:86 Partition List 13 | URL: https://leetcode.com/problems/partition-list/ 14 | Space: O(1) 15 | Time: O(N) 16 | */ 17 | 18 | class PartitionList_Solution { 19 | func partition(_ head: ListNode?, _ x: Int) -> ListNode? { 20 | let prevDummy = ListNode(0) 21 | var prev: ListNode? = prevDummy 22 | let postDummy = ListNode(0) 23 | var post: ListNode? = postDummy 24 | var checkingNode = head 25 | while let validCheckingNode = checkingNode { 26 | checkingNode = validCheckingNode.next 27 | if validCheckingNode.val < x { 28 | prev?.next = validCheckingNode 29 | prev = prev?.next 30 | } else { 31 | post?.next = validCheckingNode 32 | post = post?.next 33 | } 34 | } 35 | post?.next = nil 36 | prev?.next = postDummy.next 37 | return prevDummy.next 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Sources/DynamicProgramming/55_JumpGame.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 55_JumpGame.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-12-10. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:55 Jump Game 13 | URL: https://leetcode.com/problems/jump-game/ 14 | Space: O(n) 15 | Time: O(n) 16 | */ 17 | 18 | class JumpGame_Solution { 19 | func canJump(_ nums: [Int]) -> Bool { 20 | guard nums.count > 0 else { 21 | return false 22 | } 23 | let m = nums.count 24 | // Current max reachable point. 25 | var currentMaxReachable = 0 26 | var canJump = Array(repeating: false, count: m) 27 | canJump[0] = true 28 | for i in 0.. currentMaxReachable { 32 | for j in currentMaxReachable...upperBound { 33 | canJump[j] = true 34 | } 35 | } 36 | currentMaxReachable = upperBound 37 | } 38 | } 39 | return canJump[m - 1] 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Sources/Array/400_NthDigit.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 400_NthDigit.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-11-26. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:400 Nth Digit 13 | URL: https://leetcode.com/problems/nth-digit/ 14 | Space: O(lgN) 15 | Time: O(1) 16 | */ 17 | 18 | class NthDigit_Solution { 19 | func findNthDigit(_ n: Int) -> Int { 20 | // Firstly, find the len for that nth number. 21 | var len = 1 22 | var count = 9 23 | var remainedN = n 24 | var start = 1 25 | while remainedN > len * count { 26 | remainedN -= len * count 27 | len = len + 1 28 | count = count * 10 29 | start = start * 10 30 | } 31 | // Secondly, find the number the Nth digit belongs to. 32 | start += (remainedN - 1) / len 33 | let startString = String(start) 34 | // Thirdly, find the character the Nth digit of that finded number. 35 | let indexedCharacter = [Character](startString.characters)[(remainedN - 1) % len] 36 | return Int(String(indexedCharacter))! 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Sources/Array/48_RotateImage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 48_RotateImage.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-07. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | * Transpose Flip 13 | * 1 2 3 1 4 7 7 4 1 14 | * 4 5 6 ----------> 2 5 8 ----------> 8 5 2 15 | * 7 8 9 3 6 9 9 6 3 16 | */ 17 | 18 | /** 19 | Title:48 Rotate Image 20 | URL: https://leetcode.com/problems/rotate-image/ 21 | Space: O(1) 22 | Time: O(n^2) 23 | */ 24 | 25 | class RotateImage_Solution { 26 | func rotate(_ matrix: inout [[Int]]) { 27 | for i in 0.. Int { 20 | let longCharacters = Array(haystack.characters) 21 | let shortCharacters = Array(needle.characters) 22 | // NOTE: First time I missed this guard. 23 | guard longCharacters.count >= shortCharacters.count else { 24 | return -1 25 | } 26 | for i in 0...(longCharacters.count - shortCharacters.count) { 27 | var found = true 28 | for j in 0.. Bool { 20 | guard s.characters.count > 0 else { 21 | return true 22 | } 23 | var sTotMap: [Character : Character] = [:] 24 | var tTosMap: [Character : Character] = [:] 25 | let sCharacters = Array(s.characters) 26 | let tCharacters = Array(t.characters) 27 | for i in 0.. Int { 20 | guard nums.count > 1 else { 21 | return nums.count == 1 ? nums[0] : -1 22 | } 23 | var left = 0 24 | var right = nums.count - 1 25 | while left + 1 < right { 26 | let mid = left + (right - left) / 2 27 | if nums[mid] > nums[right] { 28 | left = mid 29 | } else if nums[mid] < nums[right]{ 30 | right = mid 31 | } else { 32 | right = right - 1 33 | } 34 | } 35 | if nums[left] > nums[right] { 36 | return nums[right] 37 | } else { 38 | return nums[left] 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Sources/Array/228_SummaryRange.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 228_SummaryRange.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-07. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:228 Summary Ranges 13 | URL: https://leetcode.com/problems/summary-ranges/ 14 | Space: O(n) 15 | Time: O(n) 16 | */ 17 | 18 | class SummaryRanges_Solution { 19 | func summaryRanges(_ nums: [Int]) -> [String] { 20 | guard nums.count > 0 else { 21 | return [] 22 | } 23 | var startIndex = 0 24 | var walkingIndex = startIndex 25 | var ret: [String] = [] 26 | while walkingIndex < nums.count { 27 | if (walkingIndex + 1 < nums.count && 28 | nums[walkingIndex] + 1 != nums[walkingIndex + 1]) || 29 | walkingIndex == nums.count - 1 { 30 | if walkingIndex == startIndex { 31 | ret.append("\(nums[startIndex])") 32 | } else { 33 | ret.append("\(nums[startIndex])->\(nums[walkingIndex])") 34 | } 35 | startIndex = walkingIndex + 1 36 | } 37 | walkingIndex += 1 38 | } 39 | return ret 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Sources/Search/35_SearchInsertPosition.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 35_SearchInsertPosition.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-04. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:35 Search Insert Position 13 | URL: https://leetcode.com/problems/search-insert-position/ 14 | Space: O(1) 15 | Time: O(lgn) 16 | */ 17 | 18 | class SearchInsertPosition_Solution { 19 | func searchInsert(_ nums: [Int], _ target: Int) -> Int { 20 | if nums.count == 1 && nums[0] < target { 21 | return 1 22 | } 23 | if nums.count == 0 { 24 | return 0 25 | } 26 | var start = 0 27 | var end = nums.count - 1 28 | while start + 1 < end { 29 | let mid = start + (end - start) / 2 30 | if nums[mid] == target { 31 | return mid 32 | } 33 | if nums[mid] > target { 34 | end = mid 35 | } else { 36 | start = mid 37 | } 38 | } 39 | if nums[start] >= target { 40 | return start 41 | } 42 | if nums[end] < target { 43 | return end + 1 44 | } 45 | return end 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Sources/DFS/638_ShoppingOffers.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 638_ShoppingOffers.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2018-04-21. 6 | // Copyright © 2018 YANSONG LI. All rights reserved. 7 | // 8 | 9 | /** 10 | Title: 638 Shopping Offers 11 | URL: https://leetcode.com/problems/shopping-offers 12 | Space: O(N) 13 | Time: O(N^2) 14 | */ 15 | 16 | class ShoppingOffers { 17 | func shoppingOffers(_ price: [Int], _ special: [[Int]], _ needs: [Int]) -> Int { 18 | var bestPrice: Int = Int.max 19 | for i in 0.. needs[j] { 24 | isValidOffer = false 25 | break 26 | } 27 | adjustedNeeds[j] = adjustedNeeds[j] - special[i][j] 28 | } 29 | if !isValidOffer { 30 | continue 31 | } 32 | bestPrice = min(bestPrice, shoppingOffers(price, special, adjustedNeeds) + special[i][special[i].count - 1]) 33 | } 34 | let noDiscountPrice = zip(price, needs).reduce(0) { $0 + $1.0 * $1.1} 35 | return min(bestPrice, noDiscountPrice) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Sources/Tree/226_InvertBinaryTree.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 226_InvertBinaryTree.swift 3 | // HRSwift 4 | // 5 | // Created by yansong li on 2016-08-03. 6 | // Copyright © 2016 yansong li. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | * 13 | * Invert a binary tree. 14 | * 15 | * Definition for a binary tree node. 16 | * public class TreeNode { 17 | * public var val: Int 18 | * public var left: TreeNode? 19 | * public var right: TreeNode? 20 | * public init(_ val: Int) { 21 | * self.val = val 22 | * self.left = nil 23 | * self.right = nil 24 | * } 25 | * } 26 | */ 27 | 28 | /** 29 | Swift Knowledge: 30 | 31 | Class 32 | 33 | Algorithem Knowledge: 34 | 35 | Top to bottom 36 | */ 37 | 38 | /** 39 | 226 Invert Binary Tree 40 | https://leetcode.com/problems/invert-binary-tree/ 41 | */ 42 | 43 | class Solution_invertTree { 44 | func invertTree(_ root: TreeNode?) -> TreeNode? { 45 | guard let root = root else { 46 | return nil 47 | } 48 | invertTree(root.left) 49 | invertTree(root.right) 50 | let tmp = root.left 51 | root.left = root.right 52 | root.right = tmp 53 | return root 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Sources/Search/69_Sqrtx.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 69_Sqrtx.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-03. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:69 Sqrt(x) 13 | URL: https://leetcode.com/problems/sqrtx/ 14 | Space: O(1) 15 | Time: O(lgn) 16 | */ 17 | 18 | class Sqrt_Solution { 19 | func mySqrt(_ x: Int) -> Int { 20 | guard x > 1 else { 21 | return x >= 0 ? x : -1 22 | } 23 | var start = 1 24 | var end = x 25 | while start + 1 < end { 26 | let mid = start + (end - start) / 2 27 | if mid * mid == x { 28 | return mid 29 | } else if mid * mid > x { 30 | end = mid 31 | } else { 32 | start = mid 33 | } 34 | } 35 | if start * start == x { 36 | return start 37 | } 38 | if start * start < x && end * end > x { 39 | return start 40 | } 41 | if end * end == x { 42 | return end 43 | } 44 | return -1 45 | } 46 | 47 | func test() { 48 | print(mySqrt(10)) 49 | print(mySqrt(1)) 50 | print(mySqrt(36)) 51 | print(mySqrt(0)) 52 | print(mySqrt(100)) 53 | print(mySqrt(10000)) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Sources/LinkedList/61_RotateList.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 61_RotateList.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-11-06. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:61 Rotate List 13 | URL: https://leetcode.com/problems/rotate-list/ 14 | Space: O(1) 15 | Time: O(N) 16 | */ 17 | 18 | class RotateList_Solution { 19 | func rotateRight(_ head: ListNode?, _ k: Int) -> ListNode? { 20 | guard let validHead = head else { 21 | return nil 22 | } 23 | var totalCount = 1 24 | var currentNode = validHead 25 | while let nextNode = currentNode.next { 26 | totalCount += 1 27 | currentNode = nextNode 28 | } 29 | 30 | var needRotate = k % totalCount 31 | var prevNode: ListNode? = validHead 32 | var postNode: ListNode? = validHead 33 | 34 | while needRotate > 0 { 35 | postNode = postNode?.next 36 | needRotate -= 1 37 | } 38 | 39 | while postNode?.next != nil { 40 | postNode = postNode?.next 41 | prevNode = prevNode?.next 42 | } 43 | 44 | postNode?.next = head 45 | postNode = prevNode?.next 46 | prevNode?.next = nil 47 | return postNode 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Sources/Tree/100_SameTree.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 100_SameTree.swift 3 | // HRSwift 4 | // 5 | // Created by yansong li on 2016-08-02. 6 | // Copyright © 2016 yansong li. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Given two binary trees, write a function to check if they are equal or not. 13 | 14 | Two binary trees are considered equal if they are structurally identical and the nodes have the same value. 15 | */ 16 | 17 | /** 18 | Swift Knowledge: 19 | 20 | Enum Comparison 21 | 22 | Algorithem Knowledge: 23 | 24 | Recursive call. 25 | */ 26 | 27 | /** 28 | 100. Same Tree 29 | https://leetcode.com/problems/same-tree/ 30 | */ 31 | 32 | class Solution_SameTree { 33 | func isSameTree(_ p: TreeNode?, _ q: TreeNode?) -> Bool { 34 | switch(p, q){ 35 | case (let .some(leftRoot), let .some(rightRoot)): 36 | let valEqual = (leftRoot.val == rightRoot.val) 37 | let leftEqual = isSameTree(leftRoot.left, rightRoot.left) 38 | let rightEqual = isSameTree(leftRoot.right, rightRoot.right) 39 | return valEqual && leftEqual && rightEqual 40 | case (.none, .none): 41 | return true 42 | default: 43 | return false 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Sources/Tree/110_BalancedBinaryTree.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 110_BalancedBinaryTree.swift 3 | // HRSwift 4 | // 5 | // Created by yansong li on 2016-08-05. 6 | // Copyright © 2016 yansong li. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:110 Balanced Binary Tree 13 | URL: https://leetcode.com/problems/balanced-binary-tree/ 14 | Space: O(n) 15 | Time: O(n) 16 | */ 17 | 18 | class BalancedBinaryTree_Solution { 19 | func isBalanced(_ root: TreeNode?) -> Bool { 20 | let(ans, _) = balancedAt(root) 21 | return ans 22 | } 23 | 24 | /// Detect whether a treenode is balanced, return the detection result and 25 | /// Depth of the treenode 26 | /// - parameter root: the root treenode. 27 | fileprivate func balancedAt(_ root: TreeNode?) -> (Bool, Int) { 28 | guard let root = root else { 29 | return (true, 0) 30 | } 31 | let (leftBalanced, leftDepth) = balancedAt(root.left) 32 | let (rightBalanced, rightDepth) = balancedAt(root.right) 33 | let subTreeBalanced = leftBalanced && rightBalanced 34 | let noMoreThanOne = abs(leftDepth - rightDepth) <= 1 35 | let depth = max(leftDepth, rightDepth) 36 | return (subTreeBalanced && noMoreThanOne, depth + 1) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Sources/Search/153_FindMinimumInRotatedSortedArray.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 151_FindMinimumInRotatedSortedArray.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-03. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:153 Find Minimum in Rotated Sorted Array 13 | URL: https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/ 14 | Space: O(1) 15 | Time: O(lgn) 16 | */ 17 | 18 | class FindMinimumInRotatedSortedArray_Solution { 19 | // Set the right most element as this rotated sorted array's target. 20 | // Then we want to find the first element that less that right most element. 21 | func findMin(_ nums: [Int]) -> Int { 22 | guard nums.count > 1 else { 23 | return nums.count == 1 ? nums[0] : -1 24 | } 25 | var left = 0 26 | var right = nums.count - 1 27 | let target = nums[right] 28 | while left + 1 < right { 29 | let mid = left + (right - left) / 2 30 | if nums[mid] > target { 31 | left = mid 32 | } else { 33 | right = mid 34 | } 35 | } 36 | if nums[left] > nums[right] { 37 | return nums[right] 38 | } else { 39 | return nums[left] 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Sources/Search/278_FirstBadVersion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 278_FirstBadVersion.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-05. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:278 First Bad Version 13 | URL: https://leetcode.com/problems/first-bad-version/ 14 | Space: O(1) 15 | Time: O(lgn) 16 | */ 17 | 18 | class FirstBadVersion_Solution { 19 | func isBadVersion(_ version: Int) -> Bool { 20 | return version >= 1801 21 | } 22 | func solution(_ version: Int) -> Int { 23 | guard version > 1 else { 24 | return version 25 | } 26 | var start = 1 27 | var end = version 28 | 29 | while start + 1 < end { 30 | let mid = start + (end - start) / 2 31 | if isBadVersion(mid) { 32 | end = mid 33 | } else { 34 | start = mid 35 | } 36 | } 37 | if isBadVersion(start) { 38 | return start 39 | } 40 | if isBadVersion(end) { 41 | return end 42 | } 43 | return -1 44 | } 45 | 46 | func test() { 47 | let result = solution(10000) 48 | if result == 1801 { 49 | print("Pass") 50 | } else { 51 | print("Failed") 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Sources/DynamicProgramming/322_CoinChange.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 322_CoinChange.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-14. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:322 Coin Change 13 | URL: https://leetcode.com/problems/coin-change/ 14 | Space: O(n^2) 15 | Time: O(n) 16 | */ 17 | 18 | class CoinChange_Solution { 19 | func coinChange(_ coins: [Int], _ amount: Int) -> Int { 20 | guard let minimumDenomination = coins.min() , minimumDenomination <= amount else { 21 | return amount == 0 ? 0 : -1 22 | } 23 | var coinsNum = Array(repeating: -1, count: amount + 1) 24 | for i in 1...amount { 25 | for j in coins where j <= i { 26 | if j == i { 27 | coinsNum[i] = 1 28 | break 29 | } else if coinsNum[i - j] != -1 { 30 | if coinsNum[i] == -1 { 31 | coinsNum[i] = coinsNum[i - j] + 1 32 | } else { 33 | coinsNum[i] = min(coinsNum[i], coinsNum[i - j] + 1) 34 | } 35 | } 36 | } 37 | } 38 | return coinsNum[amount] 39 | } 40 | 41 | func test() { 42 | let test1 = coinChange([1], 0) 43 | print(test1) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Sources/DynamicProgramming/64_MinimumPathSum.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 64_MinimumPathSum.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-12-10. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:64 Minimum Path Sum 13 | URL: https://leetcode.com/problems/minimum-path-sum/ 14 | Space: O(mn) 15 | Time: O(mn) 16 | */ 17 | 18 | class MinimumPathSum_Solution { 19 | func minPathSum(_ grid: [[Int]]) -> Int { 20 | guard grid.count > 0 else { 21 | return 0 22 | } 23 | let m = grid.count 24 | let n = grid[0].count 25 | // NOTE: minimumGrid means the minimum path sum at point (i, j). 26 | var minimumGird = 27 | Array(repeating: Array(repeating: Int.max, count: n), count: m) 28 | minimumGird[0][0] = grid[0][0] 29 | for j in 1.. String { 20 | guard strs.count > 0 else { 21 | return "" 22 | } 23 | let count = strs.map { 24 | $0.characters.count 25 | }.reduce(Int.max) { 26 | min($0, $1) 27 | } 28 | guard count > 0 else { 29 | return "" 30 | } 31 | let strsCharacters = strs.map { 32 | Array($0.characters) 33 | } 34 | var currentSatisfiedCount = 0 35 | for i in 0.. [Int] { 17 | // var result: Set = [] 18 | // var found: Int = 0 19 | // for i in nums { 20 | // if result.contains(i) { 21 | // result.remove(i) 22 | // } else { 23 | // result.insert(i) 24 | // } 25 | // } 26 | // return Array(result) 27 | // } 28 | 29 | func singleNumber(_ nums: [Int]) -> [Int] { 30 | var result = Array(repeatElement(0, count: 2)) 31 | var tmp: Int = 0 32 | for num in nums { 33 | tmp = tmp ^ num 34 | } 35 | // Find num's any position that is 1, for our case we can 36 | // find the first 1 from right to left by following trick. 37 | let mask = tmp & -tmp 38 | for num in nums { 39 | if num & mask == 0 { 40 | result[0] = result[0] ^ num 41 | } else { 42 | result[1] = result[1] ^ num 43 | } 44 | } 45 | return result 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Sources/DynamicProgramming/72_EditDistance.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 72_EditDistance.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-25. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:72 Edit Distance 13 | URL: https://leetcode.com/problems/edit-distance/ 14 | Space: O(NM) 15 | Time: O(NM) 16 | */ 17 | 18 | class EditDistance_Solution { 19 | func minDistance(_ word1: String, _ word2: String) -> Int { 20 | let word1Characters = [Character](word1.characters) 21 | let word2Characters = [Character](word2.characters) 22 | let word1Len = word1Characters.count 23 | let word2Len = word2Characters.count 24 | 25 | var dp = Array(repeating: Array(repeating: 0, count: word2Len + 1), count: word1Len + 1) 26 | 27 | for i in 0...word1Len { 28 | for j in 0...word2Len { 29 | if i == 0 { 30 | dp[i][j] = j 31 | } else if j == 0{ 32 | dp[i][j] = i 33 | } else if word1Characters[i - 1] == word2Characters[j - 1] { 34 | dp[i][j] = dp[i - 1][j - 1] 35 | } else { 36 | dp[i][j] = min(dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]) + 1 37 | } 38 | } 39 | } 40 | return dp[word1Len][word2Len] 41 | } 42 | 43 | func test() { 44 | let test1 = minDistance("abc", "cfb") 45 | print(test1) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Sources/Tree/450_DeleteNodeInABST.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 450_DeleteNodeInABST.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2018-04-18. 6 | // Copyright © 2018 YANSONG LI. All rights reserved. 7 | // 8 | 9 | /** 10 | Title: 450 Delete Node in A BST 11 | URL: https://leetcode.com/problems/delete-node-in-a-bst/description/ 12 | Space: O(1) 13 | Time: O(lgn) 14 | */ 15 | class DeleteNodeInABST { 16 | func deleteNode(_ root: TreeNode?, _ key: Int) -> TreeNode? { 17 | guard let validRoot = root else { 18 | return nil 19 | } 20 | if validRoot.val < key { 21 | validRoot.right = deleteNode(validRoot.right, key) 22 | } else if validRoot.val > key { 23 | validRoot.left = deleteNode(validRoot.left, key) 24 | } else { 25 | if validRoot.left == nil || validRoot.right == nil { 26 | return validRoot.left == nil ? validRoot.right : validRoot.left 27 | } else { 28 | var checkingNode = validRoot.right 29 | var theSmallest = checkingNode!.val 30 | while let validNode = checkingNode { 31 | theSmallest = validNode.val 32 | checkingNode = validNode.left 33 | } 34 | validRoot.val = theSmallest 35 | validRoot.right = deleteNode(validRoot.right, theSmallest) 36 | } 37 | } 38 | return validRoot 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Sources/Tree/102_BinaryTreeLevelOrderTraversal.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 102_BinaryTreeLevelOrderTraversal.swift 3 | // HRSwift 4 | // 5 | // Created by yansong li on 2016-08-04. 6 | // Copyright © 2016 yansong li. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Swift Knowledge: 13 | 14 | Queue, Array 15 | 16 | Algorithem Knowledge: 17 | 18 | BFS 19 | */ 20 | 21 | /** 22 | 102. Binary Tree Level Order Traversal 23 | https://leetcode.com/problems/binary-tree-level-order-traversal/ 24 | */ 25 | 26 | class BinaryTreeLevelOrderTraversal_Solution { 27 | func levelOrder(_ root: TreeNode?) -> [[Int]] { 28 | guard let node = root else { 29 | return [] 30 | } 31 | var result: [[Int]] = [] 32 | var queue = Queue<(TreeNode, Int)>() 33 | queue.enqueue((node, 0)) 34 | while !queue.isEmpty() { 35 | let (currentNode, currentLevel) = queue.dequeue()! 36 | if currentLevel >= result.count { 37 | result.append([]) 38 | } 39 | result[currentLevel].append(currentNode.val) 40 | if let left = currentNode.left { 41 | queue.enqueue((left, currentLevel + 1)) 42 | } 43 | if let right = currentNode.right { 44 | queue.enqueue((right, currentLevel + 1)) 45 | } 46 | } 47 | return result 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Sources/String/242_ValidAnagram.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 242_ValidAnagram.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-08-11. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:242 Valid Anagram 13 | URL: https://leetcode.com/problems/valid-anagram/ 14 | Space: O(n) 15 | Time: O(n) 16 | */ 17 | 18 | class ValidAnagram_Solution { 19 | func isAnagram(_ s: String, _ t: String) -> Bool { 20 | guard s.characters.count == t.characters.count else { 21 | return false 22 | } 23 | let sCharacters = Array(s.characters) 24 | let tCharacters = Array(t.characters) 25 | var sDict:[Character : Int] = [:] 26 | var tDict:[Character : Int] = [:] 27 | for c in sCharacters { 28 | if let currentCount = sDict[c] { 29 | sDict[c] = currentCount + 1 30 | } else { 31 | sDict[c] = 1 32 | } 33 | } 34 | for c in tCharacters { 35 | if let currentCount = tDict[c] { 36 | tDict[c] = currentCount + 1 37 | } else { 38 | tDict[c] = 1 39 | } 40 | } 41 | var result = true 42 | for (key, value) in sDict { 43 | if let tCount = tDict[key] { 44 | result = result && (tCount == value) 45 | } else { 46 | return false 47 | } 48 | } 49 | return result 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Sources/Heap/23_MergeKSortedLists.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 23_MergeKSortedLists.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-11-09. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:23 Merge K Sorted Lists 13 | URL: https://leetcode.com/problems/merge-k-sorted-lists/ 14 | Space: O(N) 15 | Time: O(Nlgk) 16 | */ 17 | 18 | class MergeKSortedLists_Solution { 19 | func mergeKLists(_ lists: [ListNode?]) -> ListNode? { 20 | var listNodeHeap = Heap { 21 | $0.val < $1.val 22 | } 23 | for l in lists { 24 | if let validList = l { 25 | listNodeHeap.insert(validList) 26 | } 27 | } 28 | if listNodeHeap.isEmpty { 29 | return nil 30 | } 31 | let dummyNode = ListNode(0) 32 | var prev: ListNode? = dummyNode 33 | while let checkingNode = listNodeHeap.peak() { 34 | prev?.next = ListNode(checkingNode.val) 35 | prev = prev?.next 36 | if let validNext = checkingNode.next { 37 | if validNext.val == checkingNode.val { 38 | listNodeHeap.replaceHead(value: validNext) 39 | } else { 40 | listNodeHeap.remove() 41 | listNodeHeap.insert(validNext) 42 | } 43 | } else { 44 | listNodeHeap.remove() 45 | } 46 | } 47 | return dummyNode.next 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Sources/String/345_ReverseVowelsOfAString.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 345_ReverseVowelsOfAString.swift 3 | // HRSwift 4 | // 5 | // Created by yansong li on 2016-08-06. 6 | // Copyright © 2016 yansong li. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:345 Reverse Vowels of a String 13 | URL: https://leetcode.com/problems/reverse-vowels-of-a-string/ 14 | Space: O(n) 15 | Time: O(n) 16 | */ 17 | 18 | class ReverseVowels_Solution { 19 | func reverseVowels(_ s: String) -> String { 20 | let vowels:[Character] = ["a","A", "e","E", "i","I", "o","O", "u", "U"] 21 | var characters = Array(s.characters) 22 | var start = 0 23 | var end = characters.count - 1 24 | while start < end { 25 | for i in start...end { 26 | start = i 27 | if vowels.contains(characters[i]) { 28 | break 29 | } 30 | } 31 | if start == end { 32 | break 33 | } 34 | for i in SRange(start: end, end: start-1, step: -1) { 35 | end = i 36 | if vowels.contains(characters[i]) { 37 | break 38 | } 39 | } 40 | if start == end { 41 | break 42 | } 43 | let tmp = characters[start] 44 | characters[start] = characters[end] 45 | characters[end] = tmp 46 | start += 1 47 | end -= 1 48 | } 49 | return String(characters) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Sources/DFS/77_Combinations.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 77_Combinations.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-11-16. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:77 Combinations 13 | URL: https://leetcode.com/problems/combinations/ 14 | Space: O(N^K) 15 | Time: O(K*N^K) 16 | */ 17 | 18 | class Combinations_Solution { 19 | func combine(_ n: Int, _ k: Int) -> [[Int]] { 20 | if n < k || k == 0 { 21 | return [] 22 | } 23 | var result: [[Int]] = [] 24 | dfs(result: &result, start: 1, n: n, currentCombination: [], remained: k) 25 | return result 26 | } 27 | 28 | func dfs(result: inout [[Int]], 29 | start: Int, 30 | n: Int, 31 | currentCombination: [Int], 32 | remained: Int) { 33 | if remained == 0 { 34 | result.append(currentCombination) 35 | return 36 | } 37 | if start > n { 38 | return 39 | } 40 | for i in start...n { 41 | var newCombination = currentCombination 42 | newCombination.append(i) 43 | dfs(result: &result, 44 | start: i + 1, 45 | n: n, 46 | currentCombination: newCombination, 47 | remained: remained - 1) 48 | } 49 | } 50 | 51 | func test() { 52 | let result = combine(4, 2) 53 | print(result) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Sources/String/294_FlipGameII.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 294_FlipGameII.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-11-26. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:294 Flip Game 13 | URL: https://leetcode.com/problems/flip-game-ii/ 14 | Space: O(2^(n/2)) 15 | Time: O(2^(n/2)) 16 | */ 17 | 18 | class FlipGameII_Solution { 19 | var canWinDict: [String : Bool] = [:] 20 | func canWin(_ s: String) -> Bool { 21 | guard s.characters.count > 1 else { 22 | return false 23 | } 24 | let characters = [Character](s.characters) 25 | return canWin(characters) 26 | } 27 | 28 | func canWin(_ c: [Character]) -> Bool { 29 | let currentString = String(c) 30 | if let validResult = self.canWinDict[currentString] { 31 | return validResult 32 | } 33 | for i in 0.. [[Int]] { 20 | if nums.count == 0 { 21 | return [] 22 | } 23 | var result: [[Int]] = [[]] 24 | generateSubSets(result: &result, 25 | currentSubSet: [], 26 | startIndex: 0, 27 | nums: nums) 28 | return result 29 | } 30 | 31 | // Why we need startIndex, because it is a [1, 2] and [2, 1] is the same, 32 | // we need a way to guarantee that the way we choose element is irreversible. 33 | func generateSubSets(result: inout [[Int]], 34 | currentSubSet: [Int], 35 | startIndex: Int, 36 | nums: [Int]) { 37 | if startIndex == nums.count { 38 | return 39 | } 40 | for i in startIndex.. Character { 20 | var sDict: [Character : Int] = [:] 21 | var tDict: [Character : Int] = [:] 22 | for sc in s.characters { 23 | if let sCount = sDict[sc] { 24 | sDict[sc] = sCount + 1 25 | } else { 26 | sDict[sc] = 1 27 | } 28 | } 29 | for tc in t.characters { 30 | if let tCount = tDict[tc] { 31 | tDict[tc] = tCount + 1 32 | } else { 33 | tDict[tc] = 1 34 | } 35 | } 36 | for (c, _) in tDict { 37 | if sDict[c] != nil { 38 | continue 39 | } else { 40 | return c 41 | } 42 | } 43 | return "*" 44 | } 45 | 46 | func test() { 47 | let result = solution("abcd", t: "abcde") 48 | let correctResult = "e" 49 | if result == correctResult[correctResult.startIndex] { 50 | print("Find the difference Pass") 51 | } else { 52 | print("Find the difference Failed") 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /LeetcodeSwift/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /LeetcodeSwiftUITests/LeetcodeSwiftUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LeetcodeSwiftUITests.swift 3 | // LeetcodeSwiftUITests 4 | // 5 | // Created by yansong li on 2016-08-07. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class LeetcodeSwiftUITests: XCTestCase { 12 | 13 | override func setUp() { 14 | super.setUp() 15 | 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | 18 | // In UI tests it is usually best to stop immediately when a failure occurs. 19 | continueAfterFailure = false 20 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 21 | XCUIApplication().launch() 22 | 23 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 24 | } 25 | 26 | override func tearDown() { 27 | // Put teardown code here. This method is called after the invocation of each test method in the class. 28 | super.tearDown() 29 | } 30 | 31 | func testExample() { 32 | // Use recording to get started writing UI tests. 33 | // Use XCTAssert and related functions to verify your tests produce the correct results. 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Sources/Array/303_RangeSumQuery.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 303_RangeSumQuery.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-11-27. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:303 Range Sum Query - Immutable 13 | URL: https://leetcode.com/problems/range-sum-query-immutable/ 14 | Space: O(N) 15 | Time: O(N) 16 | */ 17 | 18 | class RangeSumQuery_Solution { 19 | 20 | /// The sum array. 21 | var sumArray: [Int]? 22 | 23 | 24 | func queryWithArray(_ array: [Int], start: Int, end: Int) -> Int { 25 | guard array.count > 0 && 26 | start >= 0 && 27 | end <= array.count - 1 else { 28 | return 0 29 | } 30 | self.constructSumArray(array) 31 | if start == 0 { 32 | return self.sumArray![end] 33 | } 34 | return self.sumArray![end] - self.sumArray![start] 35 | } 36 | 37 | func constructSumArray(_ array: [Int]) { 38 | var computedArray = Array(repeating: 0, count: array.count) 39 | computedArray[0] = array[0] 40 | for i in 1.. Int { 20 | guard sentence.count > 0 && rows > 0 && cols > 0 else { 21 | return 0 22 | } 23 | var formattedSentence = sentence.joined(separator: " ") 24 | formattedSentence += " " 25 | let characters = Array(formattedSentence.characters) 26 | var start = 0 27 | for _ in 0.. 0 in case col is small and stop when start = 0 34 | while start > 0 && characters[(start - 1) % characters.count] != " " { 35 | start -= 1 36 | } 37 | } 38 | } 39 | return start / characters.count 40 | } 41 | 42 | func test() { 43 | let sentence = ["hello"] 44 | let result = wordsTyping(sentence, 10, 1) 45 | print(result) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /LeetcodeSwiftTests/ArrayExtensionTest.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ArrayExtensionTest.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-25. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import LeetcodeSwift 11 | 12 | class ArrayExtensionTest: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testLongestCommonSubsequence() { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | let testStringX = ["X", "M", "J", "Y", "A", "U", "Z"] 28 | var testStringY = ["X", "M", "J", "Y", "A", "U", "Z"] 29 | XCTAssert(testStringX.LCS(testStringY) == ["X", "M", "J", "Y", "A", "U", "Z"], "Pass") 30 | testStringY = ["M", "Z", "J", "A", "W", "X", "U"] 31 | XCTAssert(testStringX.LCS(testStringY) == ["M", "J", "A", "U"], "Pass") 32 | } 33 | 34 | func testPerformanceExample() { 35 | // This is an example of a performance test case. 36 | self.measure { 37 | // Put the code you want to measure the time of here. 38 | } 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /LeetcodeSwiftTests/LeetcodeSwiftTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LeetcodeSwiftTests.swift 3 | // LeetcodeSwiftTests 4 | // 5 | // Created by yansong li on 2016-08-07. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import LeetcodeSwift 11 | 12 | class LeetcodeSwiftTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measure { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | func testSequenceSubTract() { 37 | let testArray = [1, 2, 6] 38 | let toRemove = [2] 39 | let normalResult = testArray.subtract(toRemove) 40 | XCTAssert(normalResult == [1, 6], "Pass") 41 | let emptyArray: [Int] = [] 42 | let emptyResult = testArray.subtract(emptyArray) 43 | XCTAssert(emptyResult == [1, 2, 6] , "Pass") 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /Sources/Search/33_SearchInRotatedSortedArray.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 33_SearchInRotatedSortedArray.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-03. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:33 Search in rotated sorted array 13 | URL: https://leetcode.com/problems/search-in-rotated-sorted-array/ 14 | Space: O(1) 15 | Time: O(lgn) 16 | */ 17 | 18 | class RotatedSortedArray_Solution { 19 | func search(_ nums: [Int], _ target: Int) -> Int { 20 | guard nums.count > 1 else { 21 | return nums.count == 1 ? (nums[0] == target ? 0 : -1 ) : -1 22 | } 23 | var left = 0 24 | var right = nums.count - 1 25 | while left + 1 < right { 26 | let mid = left + (right - left) / 2 27 | if nums[mid] == target { 28 | return mid 29 | } 30 | if nums[mid] > nums[left] { 31 | // Note: target should take care of equaling to left situation. 32 | if target < nums[mid] && target >= nums[left] { 33 | right = mid 34 | } else { 35 | left = mid 36 | } 37 | } else { 38 | if target > nums[mid] && target <= nums[right] { 39 | left = mid 40 | } else { 41 | right = mid 42 | } 43 | } 44 | } 45 | if nums[left] == target { 46 | return left 47 | } 48 | if nums[right] == target { 49 | return right 50 | } 51 | return -1 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Sources/DynamicProgramming/198_HouseRobber.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 198_HouseRobber.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-15. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:198 House Robber 13 | URL: https://leetcode.com/problems/house-robber/ 14 | Space: O(n) 15 | Time: O(n) 16 | */ 17 | 18 | class HouseRobber_Solution { 19 | func rob(_ nums: [Int]) -> Int { 20 | guard nums.count > 0 else { 21 | return 0 22 | } 23 | // NOTE: The maximum value by robbing current room. 24 | var robCurrentRoom = Array(repeating: 0, count: nums.count) 25 | for i in 0.. Int { 45 | var robCurrent = 0 46 | var robPre = 0 47 | var robPrePre = 0 48 | for num in nums { 49 | robCurrent = max(robPre, robPrePre + num) 50 | robPrePre = robPre 51 | robPre = robCurrent 52 | } 53 | return robCurrent 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Sources/DynamicProgramming/63_UniquePaths.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 63_UniquePaths.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-12. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:63 Unique Paths II 13 | URL: https://leetcode.com/problems/unique-paths-ii/ 14 | Space: O(mn) 15 | Time: O(mn) 16 | */ 17 | 18 | class UniquePathsII_Solution { 19 | func uniquePathsWithObstacles(_ obstacleGrid: [[Int]]) -> Int { 20 | let m = obstacleGrid.count 21 | let n = obstacleGrid[0].count 22 | guard m > 1 || n > 1 else { 23 | if obstacleGrid[m - 1][n - 1] == 1 { 24 | return 0 25 | } else { 26 | return 1 27 | } 28 | } 29 | var pathsMatrix = Array(repeating: Array(repeating: 0, count: n), count: m) 30 | for i in 0.. 0 && pathsMatrix[i - 1][j] == 0 || 34 | obstacleGrid[i][j] == 1 || 35 | (j > 0 && pathsMatrix[i][j - 1] == 0) { 36 | pathsMatrix[i][j] = 0 37 | } else { 38 | pathsMatrix[i][j] = 1 39 | } 40 | } else { 41 | if obstacleGrid[i][j] == 1 { 42 | pathsMatrix[i][j] = 0 43 | } else { 44 | pathsMatrix[i][j] = pathsMatrix[i][j - 1] + pathsMatrix[i - 1][j] 45 | } 46 | } 47 | } 48 | } 49 | return pathsMatrix[m - 1][n - 1] 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Sources/Array/36_ValidSudoku.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 39_ValidSudoku.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-08-31. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:36 Valid Sudoku 13 | URL: https://leetcode.com/problems/valid-sudoku/ 14 | Space: O(1) 15 | Time: O(1) 16 | */ 17 | 18 | class ValidSudoku_Solution { 19 | func isValidSudoku(_ board: [[Character]]) -> Bool { 20 | let emptyArray = Array(repeating: 0, count: 9) 21 | var rowCheck = Array(repeating: emptyArray, count: 9) 22 | var colCheck = Array(repeating: emptyArray, count: 9) 23 | var blockCheck = Array(repeating: emptyArray, count: 9) 24 | for i in 0..<9 { 25 | for j in 0..<9 { 26 | let currentCharacter = board[i][j] 27 | if let currentElement = Int(String(currentCharacter)) { 28 | if rowCheck[i][currentElement - 1] != 0 { 29 | return false 30 | } else { 31 | rowCheck[i][currentElement - 1] = 1 32 | } 33 | if colCheck[j][currentElement - 1] != 0 { 34 | return false 35 | } else { 36 | colCheck[j][currentElement - 1] = 1 37 | } 38 | if blockCheck[(i/3) * 3 + j/3][currentElement - 1] != 0 { 39 | return false 40 | } else { 41 | blockCheck[(i/3) * 3 + j/3][currentElement - 1] = 1 42 | } 43 | } 44 | } 45 | } 46 | return true 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Sources/Array/26_RemoveDuplicatesFromSortedArray.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 26_RemoveDuplicatesFromSortedArray.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-11-05. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:26 Remove Duplicates from sorted array 13 | URL: https://leetcode.com/problems/remove-duplicates-from-sorted-array/ 14 | Space: O(N) 15 | Time: O(N) 16 | */ 17 | 18 | class RemoveDuplicatesFromSortedArray_Solution { 19 | func removeDuplicates(_ nums: inout [Int]) -> Int { 20 | guard nums.count > 1 else { 21 | return nums.count 22 | } 23 | 24 | var lastFoundUnrepeatedIndex = 0 25 | // Add in a local tmp to reduce array index query and improve performance. 26 | var currentComparisonElement = nums[lastFoundUnrepeatedIndex] 27 | for num in nums { 28 | if num != currentComparisonElement { 29 | lastFoundUnrepeatedIndex += 1 30 | nums[lastFoundUnrepeatedIndex] = num 31 | currentComparisonElement = num 32 | } 33 | } 34 | return lastFoundUnrepeatedIndex + 1 35 | } 36 | 37 | 38 | func brilliant(_ nums: inout [Int]) -> Int { 39 | guard nums.count > 1 else { 40 | return nums.count 41 | } 42 | 43 | var i = 0 44 | var lastValid = nums[0] 45 | for num in nums { 46 | if i < 1 || num > lastValid { 47 | nums[i] = num 48 | i += 1 49 | lastValid = num 50 | } 51 | } 52 | return i 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Sources/DFS/90_SubSetsII.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 90_SubSetsII.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-11-16. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:90 Subsets II 13 | URL: https://leetcode.com/problems/subsets-ii/ 14 | Space: O(2^N) 15 | Time: O(2^N) 16 | */ 17 | 18 | class SubSetII_Solution { 19 | func subsetsWithDup(_ nums: [Int]) -> [[Int]] { 20 | if nums.count == 0 { 21 | return [] 22 | } 23 | var result: [[Int]] = [] 24 | result.append([]) 25 | let newNums = nums.sorted() 26 | generateSubsetsWith(result: &result, currentSubSet: [], startIndex: 0, nums: newNums) 27 | return result 28 | } 29 | 30 | func generateSubsetsWith(result: inout [[Int]], 31 | currentSubSet: [Int], 32 | startIndex: Int, 33 | nums: [Int]) { 34 | for i in startIndex.. 0 && nums[i] == nums[i - 1] && i != startIndex) { 37 | continue 38 | } 39 | var newSubSet = currentSubSet 40 | newSubSet.append(nums[i]) 41 | result.append(newSubSet) 42 | generateSubsetsWith(result: &result, 43 | currentSubSet: newSubSet, 44 | startIndex: i + 1, 45 | nums: nums) 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Sources/Array/189_RotateArray.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 189_RotateArray.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-08-28. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:189 Rotate Array 13 | URL: https://leetcode.com/problems/rotate-array/ 14 | Space: O(1) 15 | Time: O(n) 16 | */ 17 | 18 | class RotateArray_Solution { 19 | func rotate(_ nums: inout [Int], _ k: Int) { 20 | let k = k % nums.count 21 | reverse(&nums, startIndex: 0, endIndex: nums.count - 1) 22 | reverse(&nums, startIndex: 0, endIndex: k - 1) 23 | reverse(&nums, startIndex: k, endIndex: nums.count - 1) 24 | } 25 | 26 | func reverse(_ nums: inout [Int], startIndex: Int, endIndex: Int) { 27 | if startIndex < 0 || endIndex >= nums.count || startIndex >= endIndex { 28 | return 29 | } 30 | var currentStartIndex = startIndex 31 | var currentEndIndex = endIndex 32 | while currentStartIndex < currentEndIndex { 33 | let tmp = nums[currentEndIndex] 34 | nums[currentEndIndex] = nums[startIndex] 35 | nums[startIndex] = tmp 36 | currentEndIndex -= 1 37 | currentStartIndex += 1 38 | } 39 | } 40 | 41 | func test() { 42 | var testArray = [1, 2, 3, 4, 5, 6, 7] 43 | rotate(&testArray, 3) 44 | print(testArray) 45 | testArray = [1, 2, 3, 4, 5, 6] 46 | rotate(&testArray, 2) 47 | print(testArray) 48 | testArray = [1, 2] 49 | rotate(&testArray, 1) 50 | print(testArray) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Sources/Stack/20_ValidParentheses.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 20_ValidParentheses.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-11-24. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:20 Valid Parentheses 13 | URL: https://leetcode.com/problems/valid-parentheses/ 14 | Space: O(N) 15 | Time: O(N) 16 | */ 17 | 18 | class ValidParentheses_Solution { 19 | func isValid(_ s: String) -> Bool { 20 | let characters = [Character](s.characters) 21 | let validInput = "([{" 22 | var characterStack = [Character]() 23 | for i in characters { 24 | if validInput.characters.contains(i) { 25 | characterStack.push(i) 26 | continue 27 | } 28 | switch i { 29 | case ")": 30 | if let firstPop = characterStack.pop() { 31 | if firstPop != "(" { 32 | return false 33 | } 34 | } else { 35 | return false 36 | } 37 | case "]": 38 | if let firstPop = characterStack.pop() { 39 | if firstPop != "[" { 40 | return false 41 | } 42 | } else { 43 | return false 44 | } 45 | case "}": 46 | if let firstPop = characterStack.pop() { 47 | if firstPop != "{" { 48 | return false 49 | } 50 | } else { 51 | return false 52 | } 53 | default: 54 | return false 55 | } 56 | } 57 | return characterStack.isEmpty 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Sources/Array/350_IntersectionOfTwoArraysII.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 350_IntersectionOfTwoArraysII.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-08-27. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:350 Intersection of two arrays II 13 | URL: https://leetcode.com/problems/intersection-of-two-arrays-ii/ 14 | Space: O(n) 15 | Time: O(n) Hsn 16 | */ 17 | 18 | class IntersectionOfTwoArraysII_Solution { 19 | func intersect(_ nums1: [Int], _ nums2: [Int]) -> [Int] { 20 | var result: [Int] = [] 21 | let nums1Dict = nums1.generateCountDict() 22 | let nums2Dict = nums2.generateCountDict() 23 | for (element, occuranceCount) in nums1Dict { 24 | if let nums2OccuranceCount = nums2Dict[element] { 25 | result.append(contentsOf: Array(repeating: element, 26 | count: min(occuranceCount, nums2OccuranceCount))) 27 | } 28 | } 29 | return result 30 | } 31 | } 32 | 33 | // TODO(simonli): move to `LeetCodeKit`. 34 | extension Array where Element: Hashable { 35 | /// generate count dict. 36 | /// - key : the element in the array. 37 | /// - value: the occurance count of this array. 38 | public func generateCountDict() -> [Element: Int] { 39 | var dict: [Element: Int] = [:] 40 | for element in self { 41 | if let occuranceCount = dict[element] { 42 | dict[element] = occuranceCount + 1 43 | } else { 44 | dict[element] = 1 45 | } 46 | } 47 | return dict 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Sources/Tree/113_PathSumII.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 113_PathSumII.swift 3 | // HRSwift 4 | // 5 | // Created by yansong li on 2016-08-06. 6 | // Copyright © 2016 yansong li. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:113 Path Sum II 13 | URL: https://leetcode.com/problems/path-sum-ii/ 14 | Space: O(n) 15 | Time: O(n) 16 | */ 17 | 18 | /** 19 | Swift Knowledge: 20 | 21 | Inout Parameter 22 | 23 | Algorithem Knowledge: 24 | 25 | Stack, DFS 26 | */ 27 | 28 | class PathSumII_Solution { 29 | var satisfiedRouts: [[Int]] = [] 30 | var target: Int = 0 31 | func pathSum(_ root: TreeNode?, _ sum: Int) -> [[Int]] { 32 | self.target = sum 33 | var routeStack:[Int] = [] 34 | DFSSum(root, prevSum: 0, routeStack: &routeStack) 35 | return satisfiedRouts 36 | } 37 | 38 | fileprivate func DFSSum(_ root: TreeNode?, prevSum: Int, routeStack: inout [Int]) { 39 | guard let root = root else { 40 | return 41 | } 42 | let currentSum = root.val + prevSum 43 | routeStack.append(root.val) 44 | if root.left == nil && root.right == nil { 45 | if currentSum == self.target { 46 | self.satisfiedRouts.append(routeStack) 47 | } 48 | routeStack.removeLast() 49 | print(routeStack) 50 | return 51 | } 52 | DFSSum(root.left, prevSum: currentSum, routeStack: &routeStack) 53 | DFSSum(root.right, prevSum: currentSum, routeStack: &routeStack) 54 | // Note: remove here since we have finished this node's check. 55 | routeStack.removeLast() 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Sources/String/394_DecodeString.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 394_DecodeString.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-11-27. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:394 Decode String 13 | URL: https://leetcode.com/problems/decode-string/ 14 | Space: O(N) 15 | Time: O(N) 16 | */ 17 | 18 | class DecodeString_Solution { 19 | func decodeString(_ s: String) -> String { 20 | guard s.characters.count > 0 else { 21 | return "" 22 | } 23 | var numberStack: [Int] = [] 24 | var prefixStringStack: [String] = [] 25 | let characters = Array(s.characters) 26 | var currentPrefix = "" 27 | var currentNumber = "" 28 | let numbers: [Character] = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"] 29 | for i in 0.. Int { 20 | var characterCounts: [Int] = Array(repeatElement(0, count: 26)) 21 | var maxCount: Int = 0 22 | var maxAppearance: Int = 0 23 | for cha in tasks { 24 | let currentIndex = cha.unicodeScalarCodePoint() - "A".unicodeScalarCodePoint() 25 | let currentCount = characterCounts[currentIndex] 26 | characterCounts[currentIndex] = currentCount + 1 27 | if characterCounts[currentIndex] > maxCount { 28 | maxCount = characterCounts[currentIndex] 29 | maxAppearance = 1 30 | } else if characterCounts[currentIndex] == maxCount { 31 | maxAppearance += 1 32 | } 33 | } 34 | let taskCount = tasks.count 35 | let occupiedCount = maxCount * maxAppearance 36 | let emptySpotsCount = (maxCount - 1) * (n + 1 - maxAppearance) 37 | let idleCounts = max(0, emptySpotsCount - (taskCount - occupiedCount)) 38 | return taskCount + idleCounts 39 | } 40 | } 41 | 42 | extension String { 43 | func unicodeScalarCodePoint() -> Int { 44 | let scalars = self.unicodeScalars 45 | return Int(scalars[scalars.startIndex].value) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Sources/String/383_RansomNote.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 383_RansomNote.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-08-27. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:383 Ransom Note 13 | URL: https://leetcode.com/problems/ransom-note/ 14 | Space: O(n) 15 | Time: O(n) 16 | */ 17 | 18 | class RansomeNote_Solution { 19 | // My thoughts: 20 | // 1. construct the dictionary(character: count) for both `ransomNote` and `magazine`. 21 | // 2. make sure each key exist in magazine dictionary and count is less than its counterpart. 22 | func canConstruct(_ ransomNote: String, _ magazine: String) -> Bool { 23 | // Construct ransomNote Dictionary 24 | let noteDict = generateCharacterDictFrom(ransomNote) 25 | let magazineDict = generateCharacterDictFrom(magazine) 26 | var contained: Bool = true 27 | for (currentCharacter, count) in noteDict { 28 | if let magazineCount = magazineDict[currentCharacter] { 29 | if magazineCount < count { 30 | contained = false 31 | break 32 | } 33 | } else { 34 | contained = false 35 | break 36 | } 37 | } 38 | return contained 39 | } 40 | 41 | func generateCharacterDictFrom(_ string: String) -> [Character: Int] { 42 | var dict: [Character: Int] = [:] 43 | for rc in string.characters { 44 | if let rcCount = dict[rc] { 45 | dict[rc] = rcCount + 1 46 | } else { 47 | dict[rc] = 1 48 | } 49 | } 50 | return dict 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Sources/Search/162_FindAPeakElement.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 162_FindAPeakElement.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-03. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:162 Find Peak Element 13 | URL: https://leetcode.com/problems/find-peak-element/ 14 | Space: O(1) 15 | Time: O(lgn) 16 | */ 17 | 18 | class FindPeakElement_Solution { 19 | // My solution loop through. 20 | func MyfindPeakElement(_ nums: [Int]) -> Int { 21 | guard nums.count > 1 else { 22 | return nums.count == 1 ? 0 : -1 23 | } 24 | if nums[0] > nums[1]{ 25 | return 0 26 | } 27 | if nums[nums.count - 1] > nums[nums.count - 2] { 28 | return nums.count - 1 29 | } 30 | for i in 1.. nums[i - 1] && nums[i] > nums[i + 1] { 32 | return i 33 | } 34 | } 35 | return -1 36 | } 37 | 38 | func findPeakElement(_ nums: [Int]) -> Int { 39 | guard nums.count > 1 else { 40 | return nums.count == 1 ? 0 : -1 41 | } 42 | var left = 0 43 | var right = nums.count - 1 44 | while left + 1 < right { 45 | let mid = left + (right - left) / 2 46 | if nums[mid] > nums[mid - 1] && nums[mid] > nums[mid + 1] { 47 | return mid 48 | } 49 | if nums[mid] > nums[mid + 1] { 50 | right = mid 51 | } else { 52 | left = mid 53 | } 54 | } 55 | if nums[left] > nums[right] { 56 | return left 57 | } else { 58 | return right 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Sources/Stack/144_BinaryTreePreorderTraversal.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 144_BinaryTreePreorderTraversal.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-11-07. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:144 Binary Tree Preorder Traversal 13 | URL: https://leetcode.com/problems/binary-tree-preorder-traversal/ 14 | Space: O(N) 15 | Time: O(N) 16 | */ 17 | 18 | class BinarySolution { 19 | func preorderTraversal(_ root: TreeNode?) -> [Int] { 20 | var stack: List = .end 21 | var result: [Int] = [] 22 | guard let validRoot = root else { 23 | return result 24 | } 25 | stack.push(validRoot) 26 | while let checkingNode = stack.pop() { 27 | result.append(checkingNode.val) 28 | if let rightNode = checkingNode.right { 29 | stack.push(rightNode) 30 | } 31 | if let leftNode = checkingNode.left { 32 | stack.push(leftNode) 33 | } 34 | } 35 | return result 36 | } 37 | 38 | func preorderTraversal_Array(_ root: TreeNode?) -> [Int] { 39 | var stack: [TreeNode] = [] 40 | var result: [Int] = [] 41 | guard let validRoot = root else { 42 | return result 43 | } 44 | stack.push(validRoot) 45 | while let checkingNode = stack.pop() { 46 | result.append(checkingNode.val) 47 | if let rightNode = checkingNode.right { 48 | stack.push(rightNode) 49 | } 50 | if let leftNode = checkingNode.left { 51 | stack.push(leftNode) 52 | } 53 | } 54 | return result 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Sources/String/3_LongestSubStringWithoutRepeatingCharacters.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 3_LongestSubStringWithoutRepeatingCharacters.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-08-27. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:3 Longest Substring without repeating characters 13 | URL: https://leetcode.com/problems/longest-substring-without-repeating-characters/ 14 | Space: O(n) 15 | Time: O(n) 16 | */ 17 | 18 | class longestSubstringWithoutRepeatingCharacters_Solution { 19 | /// My Solution 20 | /// 1. we could keep walk through this string, keep max count we meet for now. 21 | /// 2. use a array to keep the record of currently non-repeated substring.remove 22 | /// previous array if find any. 23 | func lengthOfLongestSubstring(_ s: String) -> Int { 24 | guard s.characters.count > 0 else { 25 | return 0 26 | } 27 | var maxCount = 0 28 | var nonRepeatedSubCharacters: [Character] = [] 29 | for c in s.characters { 30 | if let findedIndex = nonRepeatedSubCharacters.index(of: c) { 31 | // Remove elements before (included) findedIndex to include new 32 | // character and continue search. 33 | nonRepeatedSubCharacters.removeSubrange(0.. maxCount { 38 | maxCount = nonRepeatedSubCharacters.count 39 | } 40 | } 41 | } 42 | return maxCount 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Sources/Search/74_Search2DMatrix.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 74_Search2DMatrix.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2018-04-15. 6 | // Copyright © 2018 YANSONG LI. All rights reserved. 7 | // 8 | 9 | /** 10 | Title: 74 Search a 2D Matrix 11 | URL: https://leetcode.com/problems/search-a-2d-matrix/description/ 12 | Space: O(m) 13 | Time: O(lgm + lgn) 14 | */ 15 | 16 | class Search2DMatrix { 17 | func searchMatrix(_ matrix: [[Int]], _ target: Int) -> Bool { 18 | guard matrix.count > 0 && matrix[0].count > 0 else { 19 | return false 20 | } 21 | var headArray: [Int] = [] 22 | let m = matrix.count 23 | 24 | for i in 0.. target } 30 | var toExamine: [Int] = [] 31 | if let rowIndex = minimumIndexGreaterThanTarget, rowIndex != 0 { 32 | // Our row should be the previous one if exists. 33 | toExamine = matrix[rowIndex - 1] 34 | } else if minimumIndexGreaterThanTarget == nil { 35 | // Or perhaps on the last row. 36 | toExamine = matrix[m - 1] 37 | } 38 | 39 | var start = 0 40 | var end = toExamine.count 41 | while start < end { 42 | let mid = start + (end - start) / 2 43 | if toExamine[mid] == target { 44 | return true 45 | } else if toExamine[mid] < target { 46 | start = mid + 1 47 | } else { 48 | end = mid 49 | } 50 | } 51 | 52 | return false 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Sources/Queue/346_MovingAverage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 346_MovingAverage.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-11-30. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:346 Moving Average from Data Stream 13 | URL: https://leetcode.com/problems/moving-average-from-data-stream/ 14 | Space: O(1) 15 | Time: O(N) 16 | */ 17 | 18 | class MovingAverage_Solution { 19 | // The size for this moving average. 20 | let size: Int 21 | 22 | // The queue to use. 23 | var queue: Queue 24 | 25 | var previousSum: Int 26 | 27 | init(size: Int) { 28 | self.size = size 29 | queue = Queue() 30 | previousSum = 0 31 | } 32 | 33 | // Provide a next value to this object then return the average value for this object. 34 | func next(_ next: Int) -> Int { 35 | var change: Int = 0 36 | if queue.size < self.size { 37 | queue.enqueue(next) 38 | previousSum += next 39 | } else { 40 | let previous = queue.dequeue()! 41 | queue.enqueue(next) 42 | change = next - previous 43 | } 44 | previousSum = previousSum + change 45 | return previousSum / (queue.size < self.size ? queue.size : self.size) 46 | } 47 | 48 | class func test() { 49 | let testMoving = MovingAverage_Solution(size: 3) 50 | let r1 = testMoving.next(1) 51 | let r2 = testMoving.next(10) 52 | let r3 = testMoving.next(3) 53 | let r4 = testMoving.next(5) 54 | if r1 == 1 && r2 == 5 && r3 == 4 && r4 == 6 { 55 | print("Pass") 56 | } else { 57 | print("Not pass") 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Sources/LinkedList/143_ReorderList.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 143_ReorderList.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-11-07. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:141 Reorder List 13 | URL: https://leetcode.com/problems/reorder-list/ 14 | Space: O(1) 15 | Time: O(N) 16 | */ 17 | 18 | class ReorderList_Solution { 19 | func reorderList(_ head: ListNode?) { 20 | guard head != nil && head?.next != nil else { 21 | return 22 | } 23 | var prev: ListNode? = head 24 | var post: ListNode? = head?.next 25 | while post != nil && post?.next != nil { 26 | prev = prev?.next 27 | post = post?.next?.next 28 | } 29 | 30 | post = prev?.next 31 | prev?.next = nil 32 | post = self.reverseNode(post) 33 | prev = head 34 | 35 | // NOTE: here post could be nil, prev could be nil or has value 36 | // but not the way around, because if post is not nil prev will always preceed to next. 37 | while post != nil && prev != nil { 38 | let postNext = post?.next 39 | let prevNext = prev?.next 40 | 41 | prev?.next = post 42 | post?.next = prevNext 43 | 44 | post = postNext 45 | prev = prevNext 46 | } 47 | } 48 | 49 | func reverseNode(_ head: ListNode?) -> ListNode? { 50 | var checkingNode = head 51 | var newNext: ListNode? = nil 52 | while let validCheckingNode = checkingNode { 53 | checkingNode = validCheckingNode.next 54 | validCheckingNode.next = newNext 55 | newNext = validCheckingNode 56 | } 57 | return newNext 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Sources/Tree/104_MaximumDepthOfBinaryTree.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 104_MaximumDepthOfBinaryTree.swift 3 | // HRSwift 4 | // 5 | // Created by yansong li on 2016-08-03. 6 | // Copyright © 2016 yansong li. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Given a binary tree, find its maximum depth. 13 | 14 | The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node. 15 | */ 16 | 17 | /** 18 | Swift Knowledge: 19 | 20 | Generic, custom struct, tuple, optional 21 | 22 | Algorithem Knowledge: 23 | 24 | 1) How to define meaningful helper object like nodeQueue maximumDepth means we need 25 | to treverse all elements according to the level. 26 | 2) Breadth first treverse. 27 | 3) Queue. 28 | */ 29 | 30 | /** 31 | 104. Maximum Depth of Binary Tree 32 | https://leetcode.com/problems/maximum-depth-of-binary-tree/ 33 | */ 34 | 35 | class MaximumDepthOfBinaryTree_Solution { 36 | func maxDepth(_ root: TreeNode?) -> Int { 37 | guard let root = root else { return 0 } 38 | var nodeQueue = Queue<(TreeNode, Int)>() 39 | nodeQueue.enqueue((root, 1)) 40 | var maxLevel = 1 41 | while !nodeQueue.isEmpty() { 42 | let (currentNode, currentLevel) = nodeQueue.dequeue()! 43 | maxLevel = currentLevel 44 | let currentLeft = currentNode.left 45 | let currentRight = currentNode.right 46 | if let left = currentLeft { 47 | nodeQueue.enqueue((left, currentLevel + 1)) 48 | } 49 | if let right = currentRight { 50 | nodeQueue.enqueue((right, currentLevel + 1)) 51 | } 52 | } 53 | return maxLevel 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Sources/Array/340_LongestSubStringWithAtMostKDistinctCharacters.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 340_LongestSubStringWithAtMostKDistinctCharacters.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-12-04. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:340 Longest SubString with At Most K Distinct Characters 13 | URL: https://leetcode.com/problems/longest-substring-with-at-most-k-distinct-characters/ 14 | Space: O(1) 15 | Time: O(N) 16 | */ 17 | 18 | class LongestSubStringWithAtMostKDistinctCharacters_Solution { 19 | func lengthOfLongestSubstringKDistinct(_ s: String, _ k: Int) -> Int { 20 | let characters = Array(s.characters) 21 | if characters.count == 0 || k == 0 { 22 | return 0 23 | } 24 | var characterDict = [Character : Int]() 25 | var lowerBound = 0 26 | var result = 0 27 | for i in 0.. k { 34 | if let count = characterDict[characters[lowerBound]] { 35 | characterDict[characters[lowerBound]] = count - 1 36 | if count == 1 { 37 | characterDict.removeValue(forKey: characters[lowerBound]) 38 | } 39 | } 40 | lowerBound += 1 41 | } 42 | result = max(result, i - lowerBound + 1) 43 | } 44 | return result 45 | } 46 | 47 | func test() { 48 | let result = lengthOfLongestSubstringKDistinct("aba", 1) 49 | print(result) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /LeetcodeSwift/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Sources/Array/388_LongestAbsoluteFilePath.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 388_LongestAbsoluteFilePath.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-12-03. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:388 Longest Absolute File Path Solution 13 | URL: https://leetcode.com/problems/longest-absolute-file-path/ 14 | Space: O(N) 15 | Time: O(N) 16 | */ 17 | 18 | class LongestAbsoluteFilePath_Solution { 19 | func lengthLongestPath(_ input: String) -> Int { 20 | guard input.characters.count > 0 else { 21 | return 0 22 | } 23 | let splitedCharacters: [[Character]] = 24 | input.characters.split(separator: "\n").map { 25 | Array(String($0).characters) 26 | } 27 | // 0 as a dummy index, so we could no need to worry about borders. 28 | var depthDictionary: [Int : Int] = [0 : 0] 29 | var maxLength = 0 30 | for characters in splitedCharacters { 31 | let totalCharacterCount = characters.count 32 | var tabCount = 0 33 | var currentIsFile = false 34 | for i in 0.. 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /Sources/Sort/56_MergeIntervals.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 56_MergeIntervals.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-11-21. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:56 Merge Intervals 13 | URL: https://leetcode.com/problems/merge-intervals/ 14 | Space: O(NlgN) 15 | Time: O(N) 16 | */ 17 | 18 | class MergeIntervals_Solution { 19 | /// Primary idea use binary search. 20 | func merge(_ intervals: [Interval]) -> [Interval] { 21 | guard intervals.count > 0 else { 22 | return [] 23 | } 24 | let sortedIntervals = intervals.sorted { 25 | if $0.start == $1.start { 26 | return $0.end <= $1.end 27 | } 28 | return $0.start < $1.start 29 | } 30 | var merged = [sortedIntervals[0]] 31 | for i in 1.. Int { 20 | let totalCount = nums.count 21 | guard totalCount > 2 else { 22 | return totalCount 23 | } 24 | 25 | // This time we need to treat the first item differently. 26 | var currentRepeatTolerance = 0 27 | var lastFoundValidElementIndex = -1 28 | var lastValidElement = nums[0] 29 | 30 | for num in nums { 31 | if num != lastValidElement { 32 | lastFoundValidElementIndex += 1 33 | nums[lastFoundValidElementIndex] = num 34 | currentRepeatTolerance = 1 35 | lastValidElement = num 36 | } else if currentRepeatTolerance < 2 { 37 | lastFoundValidElementIndex += 1 38 | nums[lastFoundValidElementIndex] = num 39 | currentRepeatTolerance += 1 40 | } 41 | } 42 | return lastFoundValidElementIndex + 1 43 | } 44 | 45 | func brilliantSolution(_ nums: inout [Int]) -> Int { 46 | var lastValidIndex = 0 47 | for num in nums { 48 | if lastValidIndex < 2 || num > nums[lastValidIndex - 2] { 49 | nums[lastValidIndex] = num 50 | lastValidIndex += 1 51 | } 52 | } 53 | return lastValidIndex 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Sources/LinkedList/83_RemoveDuplicatesFromSortedList.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 83_RemoveDuplicatesFromSortedList.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-11-05. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:83 Remove Duplicates From Sorted List 13 | URL: https://leetcode.com/problems/remove-duplicates-from-sorted-list/ 14 | Space: O(1) 15 | Time: O(N) 16 | */ 17 | 18 | class RemoveDuplicatesFromSortedList_Solution { 19 | func deleteDuplicates(_ head: ListNode?) -> ListNode? { 20 | guard var validHead = head else { 21 | return nil 22 | } 23 | var checkingNode: ListNode? = ListNode(validHead.val) 24 | let result = checkingNode 25 | while let validNext = validHead.next { 26 | validHead = validNext 27 | if let val = checkingNode?.val, val == validNext.val { 28 | continue 29 | } 30 | checkingNode?.next = ListNode(validNext.val) 31 | checkingNode = checkingNode?.next 32 | } 33 | return result 34 | } 35 | 36 | func deleteDuplicatesInPlaceSolution(_ head: ListNode?) -> ListNode? { 37 | guard var validHead = head else { 38 | return nil 39 | } 40 | var checkingNode: ListNode = validHead 41 | while let validNext = validHead.next { 42 | validHead = validNext 43 | if validNext.val == checkingNode.val { 44 | continue 45 | } 46 | checkingNode.next = validNext 47 | checkingNode = validNext 48 | } 49 | // NOTE: set checing Node next to nil to get rid of those stale data when there 50 | // are no new data come in for the last few items. 51 | checkingNode.next = nil 52 | return head 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Sources/DynamicProgramming/221_MaximalSquare.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 221_MaximalSquare.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-18. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class MaximalSquare_Solution { 12 | /** 13 | Title:221 Maximal Square 14 | URL: https://leetcode.com/problems/maximal-square/ 15 | Space: O(MN) 16 | Time: O(MN) 17 | */ 18 | func maximalSquare(_ matrix: [[Int]]) -> Int { 19 | guard matrix.count > 0, matrix[0].count > 0 else { 20 | return 0 21 | } 22 | var ret: Int = Int.min 23 | let rowCount = matrix.count 24 | let colCount = matrix[0].count 25 | var sizeMatrix = Array(repeating: Array(repeating:0, count: colCount), count: rowCount) 26 | for i in 0.. [[Int]] { 20 | guard nums.count > 0 else { 21 | return [] 22 | } 23 | var result: [[Int]] = [] 24 | traversePermutationWithResults(result: &result, 25 | currentPermutation: [], 26 | currentSet: [], 27 | nums: nums) 28 | return result 29 | } 30 | 31 | // MARK: - Private 32 | func traversePermutationWithResults(result: inout [[Int]], 33 | currentPermutation: [Int], 34 | currentSet: Set, 35 | nums: [Int]) { 36 | // We have find a result append it. 37 | if currentPermutation.count == nums.count { 38 | result.append(currentPermutation) 39 | return 40 | } 41 | for i in nums { 42 | if currentSet.contains(i) { 43 | continue 44 | } 45 | let nextPermutation = currentPermutation + [i] 46 | var nextSet = currentSet 47 | nextSet.insert(i) 48 | traversePermutationWithResults(result: &result, 49 | currentPermutation: nextPermutation, 50 | currentSet: nextSet, 51 | nums: nums) 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Sources/Graph/207_CourseSchedule.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 207_CourseSchedule.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2018-04-15. 6 | // Copyright © 2018 YANSONG LI. All rights reserved. 7 | // 8 | 9 | /** 10 | Title: 207 Course Schedule 11 | URL: https://leetcode.com/problems/course-schedule 12 | Space: O(|E| + |V|) 13 | Time: O(|E| + |V|) 14 | */ 15 | 16 | class CourseSchedule { 17 | func canFinish(_ numCourses: Int, _ prerequisites: [[Int]]) -> Bool { 18 | guard numCourses > 0 else { 19 | return true 20 | } 21 | // Graph represents current index is a prerequisity of which other courses. 22 | var graph: [[Int]] = Array(repeatElement([], count: numCourses)) 23 | var prerequisitesCount: [Int] = Array(repeatElement(0, count: numCourses)) 24 | for requirements in prerequisites { 25 | if requirements.count > 0 { 26 | let currentCourse = requirements[0] 27 | prerequisitesCount[currentCourse] += requirements.count - 1 28 | for i in 1.. [Int] { 20 | guard nums.count > 1 else { 21 | if nums.count == 1 && nums[0] == target { 22 | return [0, 0] 23 | } 24 | return [-1, -1] 25 | } 26 | var start = 0 27 | var end = nums.count - 1 28 | // Firstly, find the last element that equals to target. 29 | while start + 1 < end { 30 | let mid = start + (end - start) / 2 31 | if nums[mid] >= target { 32 | end = mid 33 | } else { 34 | start = mid 35 | } 36 | } 37 | var leftBound: Int = -1 38 | if nums[end] == target { 39 | leftBound = end 40 | } 41 | if nums[start] == target { 42 | leftBound = start 43 | } 44 | if leftBound == -1 { 45 | return [-1, -1] 46 | } 47 | start = 0 48 | end = nums.count - 1 49 | // Secondly, find the first element that equals to target. 50 | while start + 1 < end { 51 | let mid = start + (end - start) / 2 52 | if nums[mid] <= target { 53 | start = mid 54 | } else { 55 | end = mid 56 | } 57 | } 58 | var rightBound: Int = -1 59 | if nums[start] == target { 60 | rightBound = start 61 | } 62 | if nums[end] == target { 63 | rightBound = end 64 | } 65 | return [leftBound, rightBound] 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Sources/Tree/655_PrintBinaryTree.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 655_PrintBinaryTree.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2018-04-22. 6 | // Copyright © 2018 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title: 655 Print Binary Tree 13 | URL: https://leetcode.com/problems/print-binary-tree 14 | Space: O(n) 15 | Time: O(n) 16 | */ 17 | 18 | class PrintBinaryTree { 19 | func printTree(_ root: TreeNode?) -> [[String]] { 20 | let (treeDepth, treeWidth) = findTreeDimension(root) 21 | var matrix = 22 | Array(repeatElement(Array(repeatElement("", count: treeWidth)), count: treeDepth)) 23 | fillNode(root, 0, 0, treeWidth, &matrix) 24 | return matrix 25 | } 26 | 27 | private func fillNode(_ node: TreeNode?, 28 | _ level: Int, 29 | _ startIndex: Int, 30 | _ endIndex: Int, 31 | _ matrix: inout [[String]]) { 32 | guard let vNode = node else { 33 | return 34 | } 35 | let middleIndex = startIndex + (endIndex - startIndex) / 2 36 | matrix[level][middleIndex] = String(vNode.val) 37 | fillNode(vNode.left, level + 1, startIndex, middleIndex, &matrix) 38 | fillNode(vNode.right, level + 1, middleIndex + 1, endIndex, &matrix) 39 | } 40 | 41 | private func findTreeDimension(_ root: TreeNode?) -> (Int, Int) { 42 | guard let vRoot = root else { 43 | return (0, 0) 44 | } 45 | let (leftDepth, leftWidth) = findTreeDimension(vRoot.left) 46 | let (rightDepth, rightWidth) = findTreeDimension(vRoot.right) 47 | let childDepth = max(leftDepth, rightDepth) 48 | let childWidth = max(leftWidth, rightWidth) 49 | return (childDepth + 1, childWidth * 2 + 1) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /LeetcodeSwiftTests/HeapTest.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HeapTest.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-11-09. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | @testable import LeetcodeSwift 12 | 13 | class HeapTest: XCTestCase { 14 | 15 | override func setUp() { 16 | super.setUp() 17 | // Put setup code here. This method is called before the invocation of each test method in the class. 18 | } 19 | 20 | override func tearDown() { 21 | // Put teardown code here. This method is called after the invocation of each test method in the class. 22 | super.tearDown() 23 | } 24 | 25 | func testPeak() { 26 | var testMaxHeap = Heap(sort: >) 27 | testMaxHeap.insert(10) 28 | testMaxHeap.insert(1) 29 | testMaxHeap.insert(100) 30 | XCTAssert(testMaxHeap.peak()! == 100) 31 | } 32 | 33 | func testRemove() { 34 | var testMaxHeap = Heap(sort: >) 35 | testMaxHeap.insert(10) 36 | testMaxHeap.insert(1) 37 | testMaxHeap.insert(100) 38 | XCTAssert(testMaxHeap.remove()! == 100) 39 | XCTAssert(testMaxHeap.remove()! == 10) 40 | XCTAssert(testMaxHeap.remove()! == 1) 41 | XCTAssert(testMaxHeap.remove() == nil) 42 | } 43 | 44 | func testHeapCheck() { 45 | let testMaxHeapArray = [10, 7, 2, 5, 1] 46 | XCTAssert(Heap.arrayIsMaxHeap(testMaxHeapArray)) 47 | let testNonMaxHeapArray = [1, 2, 3, 4, 5] 48 | XCTAssert(!Heap.arrayIsMaxHeap(testNonMaxHeapArray)) 49 | } 50 | 51 | func testPerformanceExample() { 52 | // This is an example of a performance test case. 53 | self.measure { 54 | // Put the code you want to measure the time of here. 55 | } 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /LeetcodeSwift/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Sources/Search/81_SearchInRotatedSortedArrayII.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 81_SearchInRotatedSortedArrayII.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-03. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title: 81 Search in rotated sorted array II 13 | URL: https://leetcode.com/problems/search-in-rotated-sorted-array-ii/ 14 | Space: O(1) 15 | Time: O(n) 16 | */ 17 | 18 | class SearchInRotatedSortedArrayII_Solution { 19 | func search(_ nums: [Int], _ target: Int) -> Bool { 20 | guard nums.count > 1 else { 21 | return nums.count == 1 ? (nums[0] == target ? true : false ) : false 22 | } 23 | var left = 0 24 | var right = nums.count - 1 25 | while left + 1 < right { 26 | let mid = left + (right - left) / 2 27 | if nums[mid] == target { 28 | return true 29 | } 30 | if nums[mid] > nums[left] { 31 | // Note: target should take care of equaling to left situation. 32 | if target < nums[mid] && target >= nums[left] { 33 | right = mid 34 | } else { 35 | left = mid 36 | } 37 | } else if nums[mid] < nums[left] { 38 | if target > nums[mid] && target <= nums[right] { 39 | left = mid 40 | } else { 41 | right = mid 42 | } 43 | } else { 44 | left += 1 45 | } 46 | } 47 | if nums[left] == target { 48 | return true 49 | } 50 | if nums[right] == target { 51 | return true 52 | } 53 | return false 54 | } 55 | 56 | func test() { 57 | let testArray = [1, 1, 1, 1, 1, 1, 1, 1, 58 | 1, 1, 1, 1, 1, 1, 1, 1, 59 | 1, 1, 3, 1, 1, 1, 1, 1] 60 | search(testArray, 3) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Sources/Tree/111_MinimumDepthOfBinaryTree.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 111_MinimumDepthOfBinaryTree.swift 3 | // HRSwift 4 | // 5 | // Created by yansong li on 2016-08-03. 6 | // Copyright © 2016 yansong li. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Given a binary tree, find its minimum depth. 13 | 14 | The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node. 15 | */ 16 | 17 | /** 18 | Swift Knowledge: 19 | 20 | Generic, custom struct, tuple, optional 21 | 22 | Algorithem Knowledge: 23 | 24 | 1) How to define meaningful helper object like nonLeafQueue means you will store 25 | node that is not a leaf. 26 | 2) Breadth first treverse. 27 | 3) Queue 28 | */ 29 | 30 | /** 31 | 111. Minimum Depth of Binary Tree 32 | https://leetcode.com/problems/minimum-depth-of-binary-tree/ 33 | */ 34 | 35 | class MinimumDepthOfBinaryTree_Solution { 36 | func minDepth(_ root: TreeNode?) -> Int { 37 | if let root = root { 38 | var nonLeafQueue = Queue<(TreeNode, Int)>() 39 | nonLeafQueue.enqueue((root, 1)) 40 | var (currentNode, currentLevel) = nonLeafQueue.dequeue()! 41 | while currentNode.left != nil || currentNode.right != nil { 42 | if let left = currentNode.left, let right = currentNode.right { 43 | nonLeafQueue.enqueue((left, (currentLevel + 1))) 44 | nonLeafQueue.enqueue((right, (currentLevel + 1))) 45 | } else if let left = currentNode.left { 46 | nonLeafQueue.enqueue((left, (currentLevel + 1))) 47 | } else { 48 | nonLeafQueue.enqueue((currentNode.right!, (currentLevel + 1))) 49 | } 50 | (currentNode, currentLevel) = nonLeafQueue.dequeue()! 51 | } 52 | return currentLevel 53 | } 54 | return 0 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | # Ignore files build by xcode 21 | *.mode*v* 22 | *.pbxuser 23 | *.xcbkptlist 24 | *.xcscheme 25 | *.xcworkspacedata 26 | *.xcuserstate 27 | 28 | ## Other 29 | *.moved-aside 30 | *.xcuserstate 31 | 32 | ## Obj-C/Swift specific 33 | *.hmap 34 | *.ipa 35 | *.dSYM.zip 36 | *.dSYM 37 | 38 | ## Playgrounds 39 | timeline.xctimeline 40 | playground.xcworkspace 41 | 42 | # Swift Package Manager 43 | # 44 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 45 | # Packages/ 46 | .build/ 47 | 48 | # CocoaPods 49 | # 50 | # We recommend against adding the Pods directory to your .gitignore. However 51 | # you should judge for yourself, the pros and cons are mentioned at: 52 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 53 | # 54 | # Pods/ 55 | 56 | # Carthage 57 | # 58 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 59 | # Carthage/Checkouts 60 | 61 | Carthage/Build 62 | 63 | # fastlane 64 | # 65 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 66 | # screenshots whenever they are needed. 67 | # For more information about the recommended setup visit: 68 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 69 | 70 | fastlane/report.xml 71 | fastlane/Preview.html 72 | fastlane/screenshots 73 | fastlane/test_output 74 | -------------------------------------------------------------------------------- /Sources/LinkedList/2_AddTwoNumbers.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 2_AddTwoNumbers.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-05. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:2 Add Two Numbers 13 | URL: https://leetcode.com/submissions/detail/73064342/ 14 | Space: O(n) 15 | Time: O(n) 16 | */ 17 | 18 | class AddTwoNumbers_Solution { 19 | var currentLastNode: ListNode? 20 | 21 | func addTwoNumbers(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? { 22 | var currentL1 = l1 23 | var currentL2 = l2 24 | var currentCarry: Int = 0 25 | var result: ListNode? 26 | while let computedL1 = currentL1, let computedL2 = currentL2 { 27 | helper(computedL1.val, val2: computedL2.val, carray: ¤tCarry, result: &result) 28 | currentL1 = computedL1.next 29 | currentL2 = computedL2.next 30 | } 31 | // we still have L1 32 | while let computedL1 = currentL1 { 33 | helper(computedL1.val, val2: 0, carray: ¤tCarry, result: &result) 34 | currentL1 = computedL1.next 35 | } 36 | // we still have L2 37 | while let computedL2 = currentL2 { 38 | helper(0, val2: computedL2.val, carray: ¤tCarry, result: &result) 39 | currentL2 = computedL2.next 40 | } 41 | if currentCarry > 0 { 42 | helper(0, val2: 0, carray: ¤tCarry, result: &result) 43 | } 44 | return result 45 | } 46 | 47 | func helper(_ val1: Int, val2: Int, carray: inout Int, result: inout ListNode?) { 48 | let currentVal = (val1 + val2 + carray) % 10 49 | carray = (val1 + val2 + carray) / 10 50 | if let tmp = currentLastNode { 51 | tmp.next = ListNode(currentVal) 52 | currentLastNode = tmp.next 53 | } else { 54 | result = ListNode(currentVal) 55 | currentLastNode = result 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Sources/Math/8_StringToInteger.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 8_StringToInteger.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-06. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:8 String to Integer(atoi) 13 | URL: https://leetcode.com/problems/string-to-integer-atoi/ 14 | Space: O(n) 15 | Time: O(1) 16 | */ 17 | 18 | class StringToInteger_Solution { 19 | func myAtoi(_ str: String) -> Int { 20 | var ret = 0 21 | var flag = 1 22 | var index = 0 23 | let zeroScalar = "0".unicodeScalars 24 | let maxIntRemained = String(Int.max % 10) 25 | let maxRemained = maxIntRemained[maxIntRemained.startIndex] 26 | let maxInt = Int(Int32.max) 27 | let minInt = Int(Int32.min) 28 | let characters = Array(str.characters) 29 | guard characters.count > 0 else { 30 | return ret 31 | } 32 | while characters[index] == " " { 33 | index += 1 34 | } 35 | if characters[index] == "-" || characters[index] == "+" { 36 | flag = 1 - 2 * (characters[index] == "-" ? 1 : 0) 37 | index += 1 38 | } 39 | while index <= characters.count - 1 && 40 | characters[index] >= "0" && characters[index] <= "9" { 41 | if ret > maxInt / 10 || 42 | (ret == maxInt / 10 && characters[index] > maxRemained) { 43 | if flag == 1 { 44 | return maxInt 45 | } else { 46 | return minInt 47 | } 48 | } 49 | // convert to unicode scalar value. 50 | let currentString = String(characters[index]) 51 | let currentScalar = currentString.unicodeScalars 52 | ret = ret * 10 + 53 | Int(currentScalar[currentScalar.startIndex].value) - 54 | Int(zeroScalar[zeroScalar.startIndex].value) 55 | index += 1 56 | } 57 | return ret * flag 58 | } 59 | 60 | func test() { 61 | let test1 = myAtoi("2147483648") 62 | print(test1) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Sources/DynamicProgramming/5_LongestPalindromicSubString.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 5_LongestPalindromicSubString.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-05. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | * Dynamic Programmin 13 | * if s[i] == s[j], then we need to check whether or not s[i+1,..,j-1] is 14 | * palindrome. 15 | */ 16 | 17 | /** 18 | Title:5 Longest Palindromic Substring 19 | URL: https://leetcode.com/problems/longest-palindromic-substring/ 20 | Space: O(n^2) 21 | Time: O(n^2) 22 | */ 23 | 24 | class LongestPalindromicSubString_Solution { 25 | func longestPalindrome(_ s: String) -> String { 26 | guard s.characters.count > 1 else { 27 | return s 28 | } 29 | let characters = Array(s.characters) 30 | let totalLength = characters.count 31 | var maxStartIndex: Int = 0 32 | var maxLength: Int = 1 33 | var palindromicTable = 34 | Array(repeating: Array(repeating: false, count: totalLength), 35 | count: totalLength) 36 | for i in 0..= 3 { 49 | for length in 3...totalLength { 50 | for i in 0...(totalLength - length) { 51 | if characters[i] == characters[i + length - 1] 52 | && palindromicTable[i + 1][i + length - 2] == true { 53 | palindromicTable[i][i + length - 1] = true 54 | maxStartIndex = i 55 | maxLength = length 56 | } 57 | } 58 | } 59 | } 60 | return String(characters[maxStartIndex...(maxStartIndex + maxLength - 1)]) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Sources/DynamicProgramming/377_CombinationSumIV.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 377_CombinationSumIV.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-11-24. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:377 Combination Sum IV 13 | URL: https://leetcode.com/problems/combination-sum-iv/ 14 | Space: O(n^(target/min(n))) 15 | Time: O(N) 16 | */ 17 | 18 | class CombinationSumIV_Solution { 19 | // NOTE: For this solution I will use memoization way. 20 | // This is a top-down approach. 21 | func combinationSum4(_ nums: [Int], _ target: Int) -> Int { 22 | guard nums.count > 0 else { 23 | return 0 24 | } 25 | let sortedNums = nums.sorted() 26 | let minElement = sortedNums[0] 27 | let combinationFunction: (Int) -> Int = memoize { (combinationFunction, x) -> Int in 28 | if x == 0 { 29 | return 1 30 | } 31 | if x < minElement { 32 | return 0 33 | } 34 | var result: Int = 0 35 | for current in nums { 36 | if combinationFunction(x - current) != -1 { 37 | result += combinationFunction(x - current) 38 | } 39 | } 40 | return result 41 | } 42 | return combinationFunction(target) 43 | } 44 | 45 | func combinationSum4_bottomUp(_ nums: [Int], _ target: Int) -> Int { 46 | guard nums.count > 0 else { 47 | return 0 48 | } 49 | let sortedNums = nums.sorted() 50 | var dp = Array(repeating: 0, count: target + 1) 51 | dp[0] = 1 52 | for i in 1...target { 53 | for num in sortedNums { 54 | if i < num { 55 | break 56 | } 57 | if dp[i - num] > Int.max - dp[i] { 58 | continue 59 | } 60 | dp[i] += dp[i - num] 61 | } 62 | } 63 | return dp[target] 64 | } 65 | 66 | func test() { 67 | let result = combinationSum4_bottomUp([3, 33, 333], 10000) 68 | print(result) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Sources/Array/457_CircularArrayLoop.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 457_CircularArrayLoop.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2018-04-21. 6 | // Copyright © 2018 YANSONG LI. All rights reserved. 7 | // 8 | 9 | /** 10 | Title: 457 Circular Array Loop 11 | URL: https://leetcode.com/problems/circular-array-loop 12 | Space: O(1) 13 | Time: O(N) 14 | */ 15 | class CircularArrayLoop { 16 | func circularArrayLoop(_ nums: [Int]) -> Bool { 17 | guard nums.count > 0 else { 18 | return false 19 | } 20 | var checkingNums = nums 21 | let n = nums.count 22 | for i in 0.. 0 && 32 | checkingNums[getNextIndex(k, nums: nums)] * checkingNums[i] > 0 { 33 | if j == k { 34 | // Single node loop is not what we want. 35 | if j == getNextIndex(j, nums: nums) { 36 | break 37 | } 38 | return true 39 | } 40 | j = getNextIndex(j, nums: nums) 41 | k = getNextIndex(k, nums: nums, repeated: 2) 42 | } 43 | j = i 44 | let val = checkingNums[i] 45 | while checkingNums[j] * val > 0 { 46 | // Clean up all the info that on the same direction. 47 | let next = getNextIndex(j, nums: nums) 48 | checkingNums[j] = 0 49 | j = next 50 | } 51 | } 52 | return false 53 | } 54 | 55 | func getNextIndex(_ i: Int, nums: [Int], repeated: Int = 1) -> Int { 56 | let n = nums.count 57 | var cal = i 58 | if repeated > 1 { 59 | cal = getNextIndex(i, nums: nums, repeated: repeated - 1) 60 | } 61 | return cal + nums[cal] >= 0 ? (cal + nums[cal]) % n : n + (cal + nums[cal]) % n 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Sources/Array/15_3Sum.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 15_3Sum.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-06. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:15 3Sum 13 | URL: https://leetcode.com/problems/3sum/ 14 | Space: O(n) 15 | Time: O(n^2) 16 | */ 17 | 18 | class ThreeSum_Solution { 19 | func threeSum(_ nums: [Int]) -> [[Int]] { 20 | guard nums.count >= 3 else { 21 | return [] 22 | } 23 | let nums = nums.sorted() 24 | var ret: [[Int]] = [] 25 | for i in 0..= 0 && nums[i] == nums[i - 1] { 29 | continue 30 | } 31 | // Two pointers. 32 | var left = i + 1 33 | var right = nums.count - 1 34 | while left < right { 35 | let sum = nums[i] + nums[left] + nums[right] 36 | if sum == 0 { 37 | ret.append([nums[i], nums[left], nums[right]]) 38 | // NOTE: here we add 1 first, so that left will always be the one 39 | // we want to check. same for right. 40 | left += 1 41 | while left < right && nums[left] == nums[left - 1] { 42 | left += 1 43 | } 44 | right -= 1 45 | while right > left && nums[right] == nums[right + 1] { 46 | right -= 1 47 | } 48 | } else if (sum < 0) { 49 | left += 1 50 | while left < right && nums[left] == nums[left - 1] { 51 | left += 1 52 | } 53 | } else { 54 | right -= 1 55 | while left < right && nums[right] == nums[right + 1] { 56 | right -= 1 57 | } 58 | } 59 | } 60 | } 61 | return ret 62 | } 63 | 64 | func test() { 65 | let test1 = threeSum([-1, 0, 1, 2, -1, -4]) 66 | print(test1) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Sources/DynamicProgramming/139_WordBreak.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 139_WordBreak.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-11. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:139 Word Break 13 | URL: https://leetcode.com/problems/word-break/ 14 | Space: O(n) 15 | Time: O(nL^2) 16 | */ 17 | 18 | class WordBreak_Solution { 19 | func wordBreak(_ s: String, wordSet:Set) -> Bool { 20 | guard s.characters.count > 0 || wordSet.count > 0 else { 21 | return true 22 | } 23 | let longestWordLength = wordSet.reduce(0) { 24 | return max($0, $1.characters.count) 25 | } 26 | // Query Array means the first 'x' elements could be broken by word set. 27 | var queryArray = Array(repeating: false, count: s.characters.count + 1) 28 | queryArray[0] = true 29 | for i in 1...s.characters.count { 30 | queryArray[i] = false 31 | for currentWordLength in 1...longestWordLength { 32 | if i < currentWordLength { 33 | break 34 | } 35 | if !queryArray[i - currentWordLength] { 36 | continue 37 | } 38 | let currentRange = s.characters.index(s.startIndex, offsetBy: i - currentWordLength).. [[Int]] { 20 | guard nums.count > 0 else { 21 | return [] 22 | } 23 | var result: [[Int]] = [] 24 | let sortedNum = nums.sorted() 25 | let visited = Array(repeating: false, count: nums.count) 26 | traversePermutationWithResults(result: &result, 27 | currentPermutation: [], 28 | visited: visited, 29 | nums: sortedNum) 30 | return result 31 | } 32 | 33 | // MARK: - Private 34 | func traversePermutationWithResults(result: inout [[Int]], 35 | currentPermutation: [Int], 36 | visited: [Bool], 37 | nums: [Int]) { 38 | // We have find a result append it. 39 | if currentPermutation.count == nums.count { 40 | result.append(currentPermutation) 41 | return 42 | } 43 | for i in 0.. 0 && nums[i] == nums[i - 1] && !visited[i - 1]) { 45 | continue 46 | } 47 | let nextPermutation = currentPermutation + [nums[i]] 48 | var nextVisited = visited 49 | nextVisited[i] = true 50 | traversePermutationWithResults(result: &result, 51 | currentPermutation: nextPermutation, 52 | visited: nextVisited, 53 | nums: nums) 54 | } 55 | } 56 | 57 | func test() { 58 | let nums = [1,1, 1, 2] 59 | let ret = self.permuteUnique(nums) 60 | print(ret) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Sources/Tree/236_LowestCommonAncestorBinaryTree.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 236_LowestCommonAncestorBinaryTree.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2018-03-28. 6 | // Copyright © 2018 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:236 Lowest Common Ancestor of a Binary Tree 13 | URL: https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/description/ 14 | Space: O(n) 15 | Time: O(n) 16 | */ 17 | 18 | func lowestCommonAncestorForRoot(_ root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode? { 19 | let (resultNode, count) = lowestCommonAncestorForRootHelper(root, p: p, q: q, found: 0) 20 | if count == 2 { 21 | return resultNode 22 | } 23 | return nil 24 | } 25 | 26 | func lowestCommonAncestorForRootHelper(_ root: TreeNode, 27 | p: TreeNode, 28 | q: TreeNode, 29 | found: Int) -> (TreeNode?, Int) { 30 | var currentFound: Int = 0 31 | if root.val == p.val || root.val == q.val { 32 | if found == 1 { 33 | return (root, 2) 34 | } 35 | currentFound = 1 36 | } 37 | var leftResult: TreeNode? 38 | var leftFound: Int = 0 39 | var rightResult: TreeNode? 40 | var rightFound: Int = 0 41 | if let left = root.left { 42 | (leftResult, leftFound) = lowestCommonAncestorForRootHelper(left, p: p, q: q, found: currentFound) 43 | if leftFound == 2 { 44 | return (leftResult, leftFound) 45 | } 46 | } 47 | if let right = root.right { 48 | (rightResult, rightFound) = lowestCommonAncestorForRootHelper(right, p: p , q: q, found: currentFound) 49 | if rightFound == 2 { 50 | return (rightResult, rightFound) 51 | } 52 | } 53 | if (currentFound + leftFound + rightFound) == 2 { 54 | return (root, 2) 55 | } 56 | if leftFound == 1 { 57 | return (leftResult, 1) 58 | } 59 | if rightFound == 1 { 60 | return (rightResult, 1) 61 | } 62 | if currentFound == 1 { 63 | return (root, 1) 64 | } 65 | return (nil, 0) 66 | } 67 | -------------------------------------------------------------------------------- /Sources/Array/361_BombEnemy.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 361_BombEnemy.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-11-27. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:361 Bomb Enemy 13 | URL: https://leetcode.com/problems/bomb-enemy/ 14 | Space: O(MN) 15 | Time: O(N) 16 | */ 17 | 18 | class BombEnemySolution { 19 | func maxKilledEnemies(_ grid: [[Character]]) -> Int { 20 | guard grid.count > 0 else { 21 | return 0 22 | } 23 | let rowCount = grid.count 24 | let colCount = grid[0].count 25 | var currentRow = 0 26 | var cols = Array(repeating: 0, count: colCount) 27 | var result = 0 28 | 29 | for i in 0.. result ? currentRow + cols[j] : result 62 | } 63 | } 64 | } 65 | return result 66 | } 67 | 68 | func test() { 69 | let t1 = Array("0E00".characters) 70 | let t2 = Array("E0WE".characters) 71 | let t3 = Array("0E00".characters) 72 | let testCase = [t1, t2, t3] 73 | let result = maxKilledEnemies(testCase) 74 | print(result) 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Sources/227_BasicCalculatorII.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 227_BasicCalculatorII.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2018-04-14. 6 | // Copyright © 2018 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:227 Basic Calculator II 13 | URL: https://leetcode.com/problems/basic-calculator-ii/description/ 14 | Space: O(n) 15 | Time: O(n) 16 | */ 17 | class BasicCalculatorII { 18 | func calculate(_ s: String) -> Int { 19 | guard s.count > 0 else { 20 | return 0 21 | } 22 | var numbers: [Int] = [] 23 | var signs: [Character] = [] 24 | var index = s.startIndex 25 | while index < s.endIndex { 26 | if s[index] == "+" { 27 | signs.append("+") 28 | } else if s[index] == "-" { 29 | signs.append("-") 30 | } else if s[index] == "*" { 31 | signs.append("*") 32 | } else if s[index] == "/" { 33 | signs.append("/") 34 | } else if s[index] != " " { 35 | var localIndex = index 36 | var numberString = "" 37 | while localIndex < s.endIndex && s[localIndex] >= "0" && s[localIndex] <= "9" { 38 | numberString += String(s[localIndex]) 39 | localIndex = s.index(after: localIndex) 40 | } 41 | let number = Int(numberString)! 42 | if signs.count > 0 { 43 | let previousSign = signs.removeLast() 44 | if previousSign == "+" { 45 | numbers.append(number) 46 | } else if previousSign == "-" { 47 | numbers.append(number * -1) 48 | } else if previousSign == "*" { 49 | let previous = numbers.removeLast() 50 | numbers.append(previous * number) 51 | } else if previousSign == "/" { 52 | let previous = numbers.removeLast() 53 | numbers.append(previous / number) 54 | } 55 | } else { 56 | numbers.append(Int(numberString)!) 57 | } 58 | index = s.index(before: localIndex) 59 | } 60 | index = s.index(after: index) 61 | } 62 | return numbers.reduce(0){ $0 + $1 } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Sources/Array/18_4Sum.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 18_4Sum.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-11-02. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:18 4 Sum 13 | URL: https://leetcode.com/problems/4sum/ 14 | Space: O(N^2) 15 | Time: O(N^4) 16 | */ 17 | 18 | class FourSum_Solution { 19 | func fourSum(_ nums: [Int], _ target: Int) -> [[Int]] { 20 | guard nums.count > 3 else { 21 | return [] 22 | } 23 | let nums = nums.sorted() 24 | var ret: [[Int]] = [] 25 | for i in 0..= 0 && nums[i] == nums[i - 1] { 27 | continue 28 | } 29 | var left = i + 1 30 | while left < nums.count - 2 { 31 | var leftMiddle: Int = left + 1 32 | var right = nums.count - 1 33 | while leftMiddle < right { 34 | if nums[i] + nums[left] + nums[leftMiddle] + nums[right] == target { 35 | ret.append([nums[i], nums[left], nums[leftMiddle], nums[right]]) 36 | leftMiddle += 1 37 | while leftMiddle < right && nums[leftMiddle] == nums[leftMiddle - 1] { 38 | leftMiddle += 1 39 | } 40 | right -= 1 41 | while leftMiddle < right && nums[right] == nums[right + 1] { 42 | right -= 1 43 | } 44 | } else if nums[i] + nums[left] + nums[leftMiddle] + nums[right] < target { 45 | leftMiddle += 1 46 | while leftMiddle < right && nums[leftMiddle] == nums[leftMiddle - 1] { 47 | leftMiddle += 1 48 | } 49 | } else { 50 | right -= 1 51 | while leftMiddle < right && nums[right] == nums[right + 1] { 52 | right -= 1 53 | } 54 | } 55 | } 56 | left += 1 57 | while left < nums.count - 1 && nums[left] == nums[left - 1] { 58 | left += 1 59 | } 60 | } 61 | } 62 | return ret 63 | } 64 | 65 | func test() { 66 | let result = fourSum([-1, -5, -5, -3, 2, 5, 0, 4], -7) 67 | print(result) 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Sources/String/290_WordPattern.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 290_WordPattern.swift 3 | // HRSwift 4 | // 5 | // Created by yansong li on 2016-08-06. 6 | // Copyright © 2016 yansong li. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:290 Word Pattern 13 | URL: 7 14 | Space: O(n) 15 | Time: O(n) 16 | */ 17 | 18 | class WordPattern_Solution { 19 | /// This is correct but with ugly logic 20 | func wordPattern_initial(_ pattern: String, _ str: String) -> Bool { 21 | var dict: [Character : String] = [:] 22 | var wordIndexedDict: [String: Character] = [:] 23 | let keys:[Character] = Array(pattern.characters) 24 | let words = str.characters.split(separator: " ").map { String($0) } 25 | guard words.count == keys.count else { 26 | return false 27 | } 28 | for i in 0.. Bool { 47 | var characterIndexedDict: [Character : String] = [:] 48 | var wordIndexedDict: [String: Character] = [:] 49 | let keys:[Character] = Array(pattern.characters) 50 | let words = str.characters.split(separator: " ").map { String($0) } 51 | guard words.count == keys.count else { 52 | return false 53 | } 54 | for i in 0.. String { 20 | // O(n) 21 | let reversedCharacters = Array(S.characters).reversed() 22 | var groups: [[Character]] = [] 23 | var currentGroup: [Character] = [] 24 | for character in reversedCharacters { 25 | if currentGroup.count == K { 26 | groups.append(currentGroup) 27 | currentGroup = [] 28 | } 29 | if character == "-" { 30 | continue 31 | } 32 | currentGroup.append(character) 33 | } 34 | if currentGroup.count > 0 { 35 | groups.append(currentGroup) 36 | } 37 | groups = groups.reversed() 38 | return groups.map { String($0.reversed()).uppercased() }.reduce("") { current, nextGroup in 39 | if current == "" { 40 | return nextGroup 41 | } else { 42 | return current + "-" + nextGroup 43 | } 44 | } 45 | } 46 | 47 | func licenseKeyFormatting_simplified(_ S: String, _ K: Int) -> String { 48 | // O(n) 49 | let reversedCharacters = Array(S.characters).reversed() 50 | var characters: [Character] = [] 51 | var count = 0 52 | for character in reversedCharacters { 53 | if character == "-" { 54 | continue 55 | } 56 | if count == K { 57 | characters.append("-") 58 | count = 0 59 | } 60 | characters.append(character) 61 | count += 1 62 | } 63 | if let last = characters.last, last == "-" { 64 | characters.removeLast() 65 | } 66 | return String(characters.reversed()).uppercased() 67 | } 68 | 69 | static func test() { 70 | let solution = LicenseKeyFormattingSolution() 71 | let result = solution.licenseKeyFormatting("2-4A0r7-4k", 4) 72 | if result == "24A0-R74K" { 73 | print("Pass") 74 | } else { 75 | print("Failed") 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /Sources/Array/304_RangeSumQuery2D.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 304_RangeSumQuery2D.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-11-27. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:304 Range Sum Query 2D - Immutable 13 | URL: https://leetcode.com/problems/range-sum-query-2d-immutable/ 14 | Space: O(N^2) 15 | Time: O(N^2) 16 | */ 17 | 18 | class Range2DSumQuery_Solution { 19 | var sumMatrix: [[Int]]? 20 | func queryWithArray(_ array: [[Int]], 21 | startRow: Int, 22 | startCol: Int, 23 | endRow: Int, 24 | endCol: Int) -> Int { 25 | guard array.count > 0 && 26 | startRow < endRow && 27 | startCol < endCol && 28 | startRow >= 0 && 29 | endRow < array.count && 30 | startCol >= 0 && 31 | endCol < array[0].count else { 32 | return 0 33 | } 34 | self.constructSumMatrix(array: array) 35 | let topRightSum = sumMatrix![startRow][endCol + 1] 36 | let bottomLeft = sumMatrix![endRow + 1][startCol] 37 | let commonPart = sumMatrix![startRow][startCol] 38 | let total = sumMatrix![endRow + 1][endCol + 1] 39 | return total - topRightSum - bottomLeft + commonPart 40 | } 41 | 42 | func constructSumMatrix(array: [[Int]]) { 43 | var computedSumMatrix = 44 | Array(repeating: Array(repeating: 0, count:array[0].count + 1), count: array.count + 1) 45 | for i in 1..(lhs: T?, rhs: T?) -> Bool { 11 | switch (lhs, rhs) { 12 | case let (l?, r?): 13 | return l < r 14 | case (nil, _?): 15 | return true 16 | default: 17 | return false 18 | } 19 | } 20 | 21 | fileprivate func > (lhs: T?, rhs: T?) -> Bool { 22 | switch (lhs, rhs) { 23 | case let (l?, r?): 24 | return l > r 25 | default: 26 | return rhs < lhs 27 | } 28 | } 29 | 30 | 31 | /** 32 | Title:165 Compare Version Numbers 33 | URL: https://leetcode.com/problems/compare-version-numbers/ 34 | Space: O(n) 35 | Time: O(n) 36 | */ 37 | 38 | class CompareVersionNumbers_Solution { 39 | func compareVersion(_ version1: String, _ version2: String) -> Int { 40 | let version1Number = version1.characters.split(separator: ".").map { 41 | Int(String($0)) 42 | } 43 | let version2Number = version2.characters.split(separator: ".").map { 44 | Int(String($0)) 45 | } 46 | var loopCount: Int = 0 47 | for i in 0.. version2Number[i] { 49 | return 1 50 | } else if version1Number[i] < version2Number[i] { 51 | return -1 52 | } 53 | loopCount += 1 54 | } 55 | if version1Number.count >= loopCount + 1 { 56 | let remained = version1Number[loopCount...(version1Number.count - 1)] 57 | let remainedCount = Array(remained).reduce(0) { 58 | $0 + $1! 59 | } 60 | if remainedCount > 0 { 61 | return 1 62 | } 63 | } else if version2Number.count >= loopCount + 1 { 64 | let remained = version2Number[loopCount...(version2Number.count - 1)] 65 | let remainedCount = Array(remained).reduce(0) { 66 | $0 + $1! 67 | } 68 | if remainedCount > 0 { 69 | return -1 70 | } 71 | } 72 | return 0 73 | } 74 | 75 | func test() { 76 | let test1 = compareVersion("1", "1.1") 77 | if test1 == -1 { 78 | print("Compared Version Numbers Pass") 79 | } else { 80 | print("Failed") 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /LeetcodeSwift/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-08-07. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | let solution = PermutationsII_Solution() 20 | solution.test() 21 | return true 22 | } 23 | 24 | func applicationWillResignActive(_ application: UIApplication) { 25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 26 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 27 | } 28 | 29 | func applicationDidEnterBackground(_ application: UIApplication) { 30 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 31 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 32 | } 33 | 34 | func applicationWillEnterForeground(_ application: UIApplication) { 35 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 36 | } 37 | 38 | func applicationDidBecomeActive(_ application: UIApplication) { 39 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 40 | } 41 | 42 | func applicationWillTerminate(_ application: UIApplication) { 43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 44 | } 45 | 46 | 47 | } 48 | 49 | -------------------------------------------------------------------------------- /Sources/DynamicProgramming/213_HouseRobberII.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 213_HouseRobberII.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-16. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:213 House Robber II 13 | URL: https://leetcode.com/problems/house-robber-ii/ 14 | Space: O(n) 15 | Time: O(n) 16 | */ 17 | 18 | class HouseRobberII_Solution { 19 | func rob(_ nums: [Int]) -> Int { 20 | guard nums.count > 1 else { 21 | if nums.count == 1 { 22 | return nums[0] 23 | } else { 24 | return 0 25 | } 26 | } 27 | let robFirst = robHelper(nums, left: 0, right: nums.count - 2) 28 | let robLast = robHelper(nums, left: 1, right: nums.count - 1) 29 | return max(robFirst, robLast) 30 | } 31 | 32 | /// rob a row of house with \a left, \a right. 33 | func robHelper(_ nums: [Int], left: Int, right: Int) -> Int { 34 | guard nums.count > 0 && 35 | left <= right && 36 | left >= 0 && 37 | right <= nums.count - 1 else { 38 | return 0 39 | } 40 | // NOTE: The maximum value by robbing current room. 41 | var robCurrentRoom = Array(repeating: 0, count: right - left + 1) 42 | for i in left...right { 43 | if i == left { 44 | robCurrentRoom[i - left] = nums[i] 45 | } else if i == left + 1 { 46 | robCurrentRoom[i - left] = max(nums[i - 1], nums[i]) 47 | } else { 48 | robCurrentRoom[i - left] 49 | = max(robCurrentRoom[i - left - 2] + nums[i], robCurrentRoom[i - left - 1]) 50 | } 51 | } 52 | return robCurrentRoom[right - left] 53 | } 54 | 55 | func rob1(_ nums: [Int]) -> Int { 56 | guard nums.count > 1 else { 57 | if nums.count == 1 { 58 | return nums[0] 59 | } else { 60 | return 0 61 | } 62 | } 63 | let robFirst = coolRob(nums, left: 0, right: nums.count - 2) 64 | let robLast = coolRob(nums, left: 1, right: nums.count - 1) 65 | return max(robFirst, robLast) 66 | } 67 | 68 | func coolRob(_ nums: [Int], left: Int, right: Int) -> Int { 69 | var robCurrent = 0 70 | var robPre = 0 71 | var robPrePre = 0 72 | for i in left...right { 73 | robCurrent = max(robPre, robPrePre + nums[i]) 74 | robPrePre = robPre 75 | robPre = robCurrent 76 | } 77 | return robCurrent 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Sources/Stack/145_BinaryTreePostorderTraversal.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 145_BinaryTreePostorderTraversal.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-11-09. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:145 Binary Tree Post Order Traversal 13 | URL: https://leetcode.com/problems/binary-tree-postorder-traversal/ 14 | Space: O(N) 15 | Time: O(N) 16 | */ 17 | 18 | class BinaryTreePostOrderTraversal_Solution { 19 | func postorderTraversal(_ root: TreeNode?) -> [Int] { 20 | var stack: [TreeNode] = [] 21 | var resultList: ListNode? = ListNode(0) 22 | let dummyFirst = resultList 23 | guard let validRoot = root else { 24 | return [] 25 | } 26 | stack.push(validRoot) 27 | while let checkingNode = stack.pop() { 28 | resultList?.next = ListNode(checkingNode.val) 29 | resultList = resultList?.next 30 | if let leftNode = checkingNode.left { 31 | stack.push(leftNode) 32 | } 33 | if let rightNode = checkingNode.right { 34 | stack.push(rightNode) 35 | } 36 | } 37 | let correctResult = self.reverseList(dummyFirst?.next) 38 | return self.listNodeToArray(correctResult) 39 | } 40 | 41 | func reverseList(_ head: ListNode?) -> ListNode? { 42 | var temp: ListNode? 43 | var first = head 44 | while let validNode = first { 45 | first = validNode.next 46 | validNode.next = temp 47 | temp = validNode 48 | } 49 | return temp 50 | } 51 | 52 | func listNodeToArray(_ head: ListNode?) -> [Int] { 53 | var result: [Int] = [] 54 | var realHead = head 55 | while realHead != nil { 56 | result.append(realHead!.val) 57 | realHead = realHead?.next 58 | } 59 | return result 60 | } 61 | 62 | func postorderTraversalSlow(_ root: TreeNode?) -> [Int] { 63 | var stack: [TreeNode] = [] 64 | var resultList: ListNode? = ListNode(0) 65 | let dummyFirst = resultList 66 | guard let validRoot = root else { 67 | return [] 68 | } 69 | stack.push(validRoot) 70 | while let checkingNode = stack.pop() { 71 | resultList?.next = ListNode(checkingNode.val) 72 | resultList = resultList?.next 73 | if let leftNode = checkingNode.left { 74 | stack.push(leftNode) 75 | } 76 | if let rightNode = checkingNode.right { 77 | stack.push(rightNode) 78 | } 79 | } 80 | let correctResult = self.reverseList(dummyFirst?.next) 81 | return self.listNodeToArray(correctResult) 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Sources/BFS/317_ShortestDistanceFromAllBuildings.swift: -------------------------------------------------------------------------------- 1 | // 2 | // File.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-12-01. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:317 Shortest Distance from All Buildings 13 | URL: https://leetcode.com/problems/shortest-distance-from-all-buildings/ 14 | Space: O(KMN) 15 | Time: O(MN) 16 | */ 17 | 18 | class ShortestDistanceFromAllBuildings_Solution { 19 | 20 | /// Min distance so far. 21 | var minDistance = -1 22 | 23 | /// Step directions. 24 | let stepDirections = [0, 1, 0, -1, 0] 25 | 26 | func shortestDistance(_ grid: [[Int]]) -> Int { 27 | guard grid.count > 0 else { 28 | return -1 29 | } 30 | var walkGrid = grid 31 | var dist = 32 | Array(repeating: Array(repeating: 0, count: grid[0].count), count: grid.count) 33 | var currentWalk = 0 34 | for i in 0..() 47 | scanQueue.enqueue((start, end, 0)) 48 | minDistance = -1 49 | while !scanQueue.isEmpty() { 50 | let currentPoint = scanQueue.dequeue()! 51 | let depth = currentPoint.2 52 | for i in 0..= 0 && 56 | newCheckPoint.0 <= grid.count - 1 && 57 | newCheckPoint.1 >= 0 && 58 | newCheckPoint.1 <= grid[0].count - 1 && 59 | grid[newCheckPoint.0][newCheckPoint.1] == walk ) { 60 | grid[newCheckPoint.0][newCheckPoint.1] = walk - 1 61 | scanQueue.enqueue((newCheckPoint.0, newCheckPoint.1, depth + 1)) 62 | dist[newCheckPoint.0][newCheckPoint.1] += depth + 1 63 | if (minDistance == -1 || minDistance > dist[newCheckPoint.0][newCheckPoint.1]) { 64 | minDistance = dist[newCheckPoint.0][newCheckPoint.1] 65 | } 66 | } 67 | } 68 | } 69 | } 70 | 71 | func test() { 72 | let testGrid = [[1, 0, 2, 0, 1], [0, 0, 0, 0, 0], [0, 0, 1, 0, 0]] 73 | let result = shortestDistance(testGrid) 74 | print(result) 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Sources/Tree/105_ConstructBinaryTreeFromPreorderAndInorderTraversal.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 105_ConstructBinaryTreeFromPreorderAndInorderTraversal.swift 3 | // HRSwift 4 | // 5 | // Created by yansong li on 2016-08-06. 6 | // Copyright © 2016 yansong li. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:105 Construct Binary Tree From Preorder and Ignorer Traversal 13 | URL: https://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/ 14 | Space: O(n) 15 | Time: O(n) 16 | */ 17 | 18 | class TreeBuildPreorderInorder_Solution { 19 | func buildTree(_ preorder: [Int], _ inorder: [Int]) -> TreeNode? { 20 | guard preorder.count > 0 && 21 | inorder.count > 0 && 22 | preorder.count == inorder.count else { 23 | return nil 24 | } 25 | return treeBuildHelper(preorder, 26 | preStartIndex: 0, 27 | preEndIndex: preorder.count - 1, 28 | inorder: inorder, 29 | inorderStartIndex: 0, 30 | inorderEndIndex: inorder.count - 1) 31 | } 32 | func treeBuildHelper(_ preorder: [Int], 33 | preStartIndex: Int, 34 | preEndIndex: Int, 35 | inorder: [Int], 36 | inorderStartIndex: Int, 37 | inorderEndIndex: Int) -> TreeNode? { 38 | guard preStartIndex <= preEndIndex && 39 | inorderStartIndex <= inorderEndIndex else { 40 | return nil 41 | } 42 | let rootVal = preorder[preStartIndex] 43 | let currentRoot = TreeNode(rootVal) 44 | var mid: Int = 0 45 | for i in inorderStartIndex...inorderEndIndex { 46 | if inorder[i] == rootVal { 47 | mid = i 48 | break 49 | } 50 | } 51 | currentRoot.left = treeBuildHelper(preorder, 52 | preStartIndex: preStartIndex + 1, 53 | preEndIndex: preStartIndex + mid - inorderStartIndex, 54 | inorder: inorder, 55 | inorderStartIndex: inorderStartIndex, 56 | inorderEndIndex: mid - 1) 57 | currentRoot.right = treeBuildHelper(preorder, 58 | preStartIndex: preStartIndex + mid - inorderStartIndex + 1, 59 | preEndIndex: preEndIndex, 60 | inorder: inorder, 61 | inorderStartIndex: mid + 1, 62 | inorderEndIndex: inorderEndIndex) 63 | return currentRoot 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Sources/Tree/107_BinaryTreeLevelOrderTraversalII.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 107_BinaryTreeLevelOrderTraversalII.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-12-04. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:107 Binary Tree Level Order Traversal II 13 | URL: https://leetcode.com/problems/binary-tree-level-order-traversal-ii/ 14 | Space: O(N) 15 | Time: O(N) 16 | */ 17 | 18 | class BinaryTreeLevelOrderTraversalII_Solution { 19 | func levelOrderBottom(_ root: TreeNode?) -> [[Int]] { 20 | guard let validRoot = root else { 21 | return [] 22 | } 23 | var traversalQueue = Queue<(TreeNode, Int)>() 24 | var result: [[Int]] = [] 25 | var lastLevel = 0 26 | var currentLevelNodes: [Int] = [] 27 | traversalQueue.enqueue((validRoot, 0)) 28 | while !traversalQueue.isEmpty() { 29 | let (currentTreeNode, currentLevel) = traversalQueue.dequeue()! 30 | if let leftTreeNode = currentTreeNode.left { 31 | traversalQueue.enqueue((leftTreeNode, currentLevel + 1)) 32 | } 33 | if let rightTreeNode = currentTreeNode.right { 34 | traversalQueue.enqueue((rightTreeNode, currentLevel + 1)) 35 | } 36 | if currentLevel == lastLevel { 37 | currentLevelNodes.append(currentTreeNode.val) 38 | } else { 39 | result.insert(currentLevelNodes, at: 0) 40 | currentLevelNodes = [currentTreeNode.val] 41 | lastLevel = currentLevel 42 | } 43 | } 44 | if currentLevelNodes.count > 0 { 45 | result.insert(currentLevelNodes, at: 0) 46 | } 47 | return result 48 | } 49 | 50 | func DFSSolution(_ root: TreeNode?) -> [[Int]] { 51 | guard let validRoot = root else { 52 | return [] 53 | } 54 | var result = [[Int]]() 55 | dfs(&result, node: validRoot, level: 0) 56 | return result 57 | } 58 | 59 | func dfs(_ matrix: inout [[Int]], node: TreeNode?, level: Int) { 60 | guard let validNode = node else { 61 | return 62 | } 63 | if matrix.count < level + 1 { 64 | matrix.insert([], at: 0) 65 | } 66 | dfs(&matrix, node: validNode.left, level: level + 1) 67 | dfs(&matrix, node: validNode.right, level: level + 1) 68 | var currentLevel = matrix[matrix.count - (level + 1)] 69 | currentLevel.append(validNode.val) 70 | matrix[matrix.count - (level + 1)] = currentLevel 71 | } 72 | 73 | func test() { 74 | let root = TreeNode(3) 75 | let l1 = TreeNode(9) 76 | let r1 = TreeNode(20) 77 | let l2 = TreeNode(15) 78 | let r2 = TreeNode(7) 79 | root.left = l1 80 | root.right = r1 81 | r1.left = l2 82 | r1.right = r2 83 | let result = self.DFSSolution(root) 84 | print(result) 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /Sources/Tree/337_HouseRobberIII.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 337_HouseRobberIII.swift 3 | // HRSwift 4 | // 5 | // Created by yansong li on 2016-08-04. 6 | // Copyright © 2016 yansong li. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Swift Knowledge: 13 | 14 | Hashable, Equality, Memoization(awesome!), Functional Programming 15 | 16 | Algorithem Knowledge: 17 | 18 | DFS Traverse, DP Programming 19 | */ 20 | 21 | /** 22 | public func memoize( body:((T)->U, T)->U ) -> (T)->U { 23 | var memo = Dictionary() 24 | var result: ((T)->U)! 25 | result = { x in 26 | if let q = memo[x] { return q } 27 | let r = body(result, x) 28 | memo[x] = r 29 | return r 30 | } 31 | return result 32 | } 33 | */ 34 | 35 | /** 36 | 337. House Robber III 37 | https://leetcode.com/problems/house-robber-iii/ 38 | */ 39 | 40 | class HouseRobberIII_Solution { 41 | func rob(_ root: TreeNode?) -> Int { 42 | guard let root = root else { 43 | return 0 44 | } 45 | let hashableRoot = HashableTreeNode.buildHashableTreeWith(root) 46 | let ans: (HashableTreeNode) -> Int = memoize { (ans, currentNode) -> Int in 47 | var robRoot = currentNode.val 48 | var robNonRoot = 0 49 | if let left = currentNode.left { 50 | if let leftLeft = left.left { 51 | robRoot += ans(leftLeft) 52 | } 53 | if let leftRight = left.right { 54 | robRoot += ans(leftRight) 55 | } 56 | robNonRoot += ans(left) 57 | } 58 | if let right = currentNode.right { 59 | if let rightLeft = right.left { 60 | robRoot += ans(rightLeft) 61 | } 62 | if let rightRight = right.right { 63 | robRoot += ans(rightRight) 64 | } 65 | robNonRoot += ans(right) 66 | } 67 | return max(robRoot, robNonRoot) 68 | } 69 | return ans(hashableRoot!) 70 | } 71 | 72 | /// Second solution. A little better than first one. 73 | func robII(_ root: TreeNode?) -> Int { 74 | let ans = subRob(root) 75 | return max(ans[0], ans[1]) 76 | } 77 | 78 | /// SubRob will calculate from the root and return an Array of 2. 79 | /// A[0]: The maximum money if root is Robbed. 80 | /// A[1]: The maximum money if root is not Robbed. 81 | fileprivate func subRob(_ root: TreeNode?) -> [Int] { 82 | guard let root = root else { 83 | return [0, 0] 84 | } 85 | let leftProfit = subRob(root.left) 86 | let rightProfit = subRob(root.right) 87 | // If root is rob then left, right must not be robbed. 88 | let robRootProfit = root.val + leftProfit[1] + rightProfit[1] 89 | let robNonRootProfit = 90 | max(leftProfit[0], leftProfit[1]) + max(rightProfit[0], rightProfit[1]) 91 | return [robRootProfit, robNonRootProfit] 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /Sources/772_BasicCalculatorIII.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 772_BasicCalculatorIII.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2018-04-15. 6 | // Copyright © 2018 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:772 Basic Calculator III 13 | URL: https://leetcode.com/problems/basic-calculator-iii/description/ 14 | Space: O(n) 15 | Time: O(n) 16 | */ 17 | class BasicCalculatorIII { 18 | func calculate(_ s: String) -> Int { 19 | guard s.count > 0 else { 20 | return 0 21 | } 22 | let (result, _) = calculate(s, startIndex: s.startIndex) 23 | return result 24 | } 25 | 26 | func calculate(_ s: String, startIndex: String.Index) -> (Int, String.Index) { 27 | guard s.count > 0 && startIndex < s.endIndex else { 28 | return (0, s.startIndex) 29 | } 30 | var numbers: [Int] = [] 31 | var signs: [Character] = [] 32 | var index: String.Index = startIndex 33 | 34 | while index < s.endIndex { 35 | if s[index] == "+" { 36 | signs.append("+") 37 | } else if s[index] == "-" { 38 | signs.append("-") 39 | } else if s[index] == "*" { 40 | signs.append("*") 41 | } else if s[index] == "/" { 42 | signs.append("/") 43 | } else if s[index] == "(" { 44 | let (result, updatedIndex) = calculate(s, startIndex: s.index(after:index)) 45 | handleResult(result, signs: &signs, numbers: &numbers) 46 | index = updatedIndex 47 | } else if s[index] == ")" { 48 | return (numbers.reduce(0){ $0 + $1 }, index) 49 | } else if s[index] != " " { 50 | var localIndex = index 51 | var numberString = "" 52 | while localIndex < s.endIndex && s[localIndex] >= "0" && s[localIndex] <= "9" { 53 | numberString += String(s[localIndex]) 54 | localIndex = s.index(after: localIndex) 55 | } 56 | let number = Int(numberString)! 57 | handleResult(number, signs: &signs, numbers: &numbers) 58 | index = s.index(before: localIndex) 59 | } 60 | index = s.index(after: index) 61 | } 62 | return (numbers.reduce(0){ $0 + $1 }, index) 63 | } 64 | 65 | func handleResult(_ number: Int, signs: inout [Character], numbers: inout [Int]) { 66 | if signs.count > 0 { 67 | let previousSign = signs.removeLast() 68 | if previousSign == "+" { 69 | numbers.append(number) 70 | } else if previousSign == "-" { 71 | numbers.append(number * -1) 72 | } else if previousSign == "*" { 73 | let previous = numbers.removeLast() 74 | numbers.append(previous * number) 75 | } else if previousSign == "/" { 76 | let previous = numbers.removeLast() 77 | numbers.append(previous / number) 78 | } 79 | } else { 80 | numbers.append(number) 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Sources/Tree/106_ConstructBinaryTreeFromInorderAndPostorderTraversal.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 106_ConstructBinaryTreeFromInorderAndPostorderTraversal.swift 3 | // HRSwift 4 | // 5 | // Created by yansong li on 2016-08-06. 6 | // Copyright © 2016 yansong li. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:106 Construct Binary Tree From Inorder and Postorder Traversal 13 | URL: https://leetcode.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/ 14 | Space: O(n) 15 | Time: O(n) 16 | */ 17 | 18 | class BuildTreeInorderPostOrder_Solution { 19 | func buildTree(_ inorder: [Int], _ postorder: [Int]) -> TreeNode? { 20 | guard inorder.count > 0 && postorder.count > 0 && inorder.count == postorder.count else { 21 | return nil 22 | } 23 | return treeBuildHelper(inorder, 24 | inorderStart: 0, 25 | inorderEnd: inorder.count - 1, 26 | postorder: postorder, 27 | postStart: 0, 28 | postEnd: postorder.count - 1) 29 | } 30 | 31 | fileprivate func treeBuildHelper(_ inorder: [Int], 32 | inorderStart: Int, 33 | inorderEnd: Int, 34 | postorder: [Int], 35 | postStart: Int, 36 | postEnd: Int) -> TreeNode? { 37 | guard inorderStart <= inorderEnd && postStart <= postEnd else { 38 | return nil 39 | } 40 | var mid: Int = 0 41 | let rootVal = postorder[postEnd] 42 | let rootNode = TreeNode(rootVal) 43 | for i in inorderStart...inorderEnd { 44 | if inorder[i] == rootVal { 45 | mid = i 46 | break 47 | } 48 | } 49 | // Note: when calculate postEnd we use the following formula: 50 | // X - postStart : is how many elements between those two index 51 | // mid - inorderStart = left tree element counts 52 | // X - postStart + 1(the first element) == mid - inorderStart 53 | rootNode.left = treeBuildHelper(inorder, 54 | inorderStart: inorderStart, 55 | inorderEnd: mid - 1, 56 | postorder: postorder, 57 | postStart: postStart, 58 | postEnd: postStart + mid - inorderStart - 1) 59 | rootNode.right = treeBuildHelper(inorder, 60 | inorderStart: mid + 1, 61 | inorderEnd: inorderEnd, 62 | postorder: postorder, 63 | postStart: postStart + mid - inorderStart, 64 | postEnd: postEnd - 1) 65 | return rootNode 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Sources/Tree/124_BinaryTreeMaximumPathSum.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 124_BinaryTreeMaximumPathSum.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-09-04. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:124 Binary Tree Maximum Path Sum 13 | URL: https://leetcode.com/problems/binary-tree-maximum-path-sum/ 14 | Space: O(n) 15 | Time: O(n^2) 16 | */ 17 | 18 | class BinaryTreeMaximumPathSum_Solution { 19 | func maxPathSum(_ root: TreeNode?) -> Int { 20 | let (_, anyMax) = maxPathSumHelper(root) 21 | return anyMax 22 | } 23 | 24 | fileprivate func maxPathSumHelper(_ root: TreeNode?) -> (Int, Int) { 25 | guard let root = root else { 26 | return (0, Int.min) 27 | } 28 | let (leftRootMax, leftAnyMax) = maxPathSumHelper(root.left) 29 | let (rightRootMax, rightAnyMax) = maxPathSumHelper(root.right) 30 | var currentRootMax = max(leftRootMax, rightRootMax) + root.val 31 | currentRootMax = max(currentRootMax, 0) 32 | var currentAnyMax = max(leftAnyMax, rightAnyMax) 33 | currentAnyMax = max(currentAnyMax, leftRootMax + rightRootMax + root.val) 34 | return (currentRootMax, currentAnyMax) 35 | } 36 | 37 | func maxPathSum_Memoized(_ root: TreeNode?) -> Int { 38 | let hashableTreeRoot = HashableTreeNode.buildHashableTreeWith(root) 39 | let (_, anyMax) = maxPathSumMemoized(hashableTreeRoot) 40 | return anyMax 41 | } 42 | 43 | fileprivate func maxPathSumMemoized(_ root: HashableTreeNode?) -> (Int, Int) { 44 | guard let root = root else { 45 | return (0, Int.min) 46 | } 47 | let ans:(HashableTreeNode) -> (Int, Int) = memoize { (ans: (HashableTreeNode) -> (Int, Int), currentNode: HashableTreeNode) -> (Int, Int) in 48 | var leftResult: (Int, Int) 49 | if let left = currentNode.left { 50 | leftResult = ans(left) 51 | } else { 52 | leftResult = (0, Int.min) 53 | } 54 | var rightResult: (Int, Int) 55 | if let right = currentNode.right { 56 | rightResult = ans(right) 57 | } else { 58 | rightResult = (0, Int.min) 59 | } 60 | var currentRootMax = max(leftResult.0, rightResult.0) + currentNode.val 61 | currentRootMax = max(currentRootMax, 0) 62 | var currentAnyMax = max(leftResult.1, rightResult.1) 63 | currentAnyMax = max(currentAnyMax, leftResult.0 + rightResult.0 + currentNode.val) 64 | return (currentRootMax, currentAnyMax) 65 | } 66 | return ans(root) 67 | } 68 | 69 | 70 | func test() { 71 | let node1 = TreeNode(1) 72 | let node2 = TreeNode(2) 73 | let node3 = TreeNode(3) 74 | node1.left = node2 75 | node1.right = node3 76 | let result = maxPathSum(node1) 77 | if result == 6 { 78 | print("Pass") 79 | } else { 80 | print("Fail") 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Sources/DFS/212_WordSearchII.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 212_WordSearchII.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-11-20. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:212 Word Search II 13 | URL: https://leetcode.com/problems/word-search-ii/ 14 | Space: O(N*3^N) 15 | Time: O(N^2) 16 | */ 17 | 18 | class WordSearchII_Solution { 19 | func findWords(_ board: [[Character]], _ words: [String]) -> [String] { 20 | guard board.count > 0 && words.count > 0 else { 21 | return [] 22 | } 23 | let wordsTrie = Trie() 24 | for word in words { 25 | wordsTrie.insert(word: word) 26 | } 27 | var result: [String] = [] 28 | let visitedBoard: [[Bool]] = 29 | Array(repeating: Array(repeating:false, count:board[0].count), count: board.count) 30 | for i in 0.. 0 && visitedBoard[rowIndex - 1][colIndex] == false { 65 | potentioalNextStep.append((rowIndex - 1, colIndex)) 66 | } 67 | if colIndex < board[0].count - 1 && visitedBoard[rowIndex][colIndex + 1] == false { 68 | potentioalNextStep.append((rowIndex, colIndex + 1)) 69 | } 70 | if colIndex > 0 && visitedBoard[rowIndex][colIndex - 1] == false { 71 | potentioalNextStep.append((rowIndex, colIndex - 1)) 72 | } 73 | var currentVisited = visitedBoard 74 | currentVisited[rowIndex][colIndex] = true 75 | for pos in potentioalNextStep { 76 | dfs(rowIndex: pos.0, 77 | colIndex: pos.1, 78 | board: board, 79 | trie: trie, 80 | visitedBoard: currentVisited, 81 | result: &result, 82 | trackedString: newCheckString) 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Sources/DFS/79_WordSearch.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 79_WordSearch.swift 3 | // LeetcodeSwift 4 | // 5 | // Created by yansong li on 2016-11-19. 6 | // Copyright © 2016 YANSONG LI. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:79 Word Search 13 | URL: https://leetcode.com/problems/word-search/ 14 | Space: O(3^N) 15 | Time: O(N^2) 16 | */ 17 | 18 | class WordSearch_Solution { 19 | func exist(_ board: [[Character]], _ word: String) -> Bool { 20 | guard board.count > 0 && board.count * board[0].count >= word.characters.count else { 21 | return false 22 | } 23 | guard word.characters.count > 0 else { 24 | return true 25 | } 26 | let visitedBoard: [[Bool]] = 27 | Array(repeating: Array(repeating:false, count:board[0].count), count: board.count) 28 | let word: [Character] = Array(word.characters) 29 | for i in 0.. Bool { 50 | if board[rowIndex][colIndex] != word[currentIndex] { 51 | return false 52 | } 53 | if currentIndex == word.count - 1 { 54 | return true 55 | } 56 | var potentioalNextStep: [(Int, Int)] = [] 57 | if rowIndex < board.count - 1 && visitedBoard[rowIndex + 1][colIndex] == false { 58 | potentioalNextStep.append((rowIndex + 1, colIndex)) 59 | } 60 | if rowIndex > 0 && visitedBoard[rowIndex - 1][colIndex] == false { 61 | potentioalNextStep.append((rowIndex - 1, colIndex)) 62 | } 63 | if colIndex < board[0].count - 1 && visitedBoard[rowIndex][colIndex + 1] == false { 64 | potentioalNextStep.append((rowIndex, colIndex + 1)) 65 | } 66 | if colIndex > 0 && visitedBoard[rowIndex][colIndex - 1] == false { 67 | potentioalNextStep.append((rowIndex, colIndex - 1)) 68 | } 69 | var currentVisited = visitedBoard 70 | currentVisited[rowIndex][colIndex] = true 71 | for pos in potentioalNextStep { 72 | if dfs(rowIndex: pos.0, 73 | colIndex: pos.1, 74 | board: board, 75 | word: word, 76 | currentIndex: currentIndex + 1, 77 | visitedBoard: currentVisited) { 78 | return true 79 | } 80 | } 81 | return false 82 | } 83 | func test() { 84 | let l1 = "aaaa" 85 | let l2 = "aaaa" 86 | let l3 = "aaaa" 87 | let l4 = "aaaa" 88 | let l5 = "aaab" 89 | let board = [Array(l1.characters), Array(l2.characters),Array(l3.characters), Array(l4.characters),Array(l5.characters)] 90 | let toFind = "aaaaaaaaaaaaaaaaaaaa" 91 | if exist(board, toFind) { 92 | print("Exist") 93 | } else { 94 | print("Not Exist") 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Sources/Tree/101_SymmetricTree.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 101_SymmetricTree.swift 3 | // HRSwift 4 | // 5 | // Created by yansong li on 2016-08-06. 6 | // Copyright © 2016 yansong li. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Title:101 Symmetric Tree 13 | URL: https://leetcode.com/problems/symmetric-tree/ 14 | Space: O(n) 15 | Time: O(n) 16 | */ 17 | 18 | class SymmetricTree_Solution { 19 | /// Bonus points: Iterative 20 | func isSymmetric(_ root: TreeNode?) -> Bool { 21 | guard let root = root else { 22 | return true 23 | } 24 | let original = self.treeToArray(root) 25 | let switchedRoot = self.switchSubTree(root) 26 | let switched = self.treeToArray(switchedRoot) 27 | let comparison = zip(original, switched).map { 28 | return $0 == $1 29 | }.reduce(true) { 30 | $0 && $1 31 | } 32 | return comparison 33 | } 34 | 35 | fileprivate func switchSubTree(_ root: TreeNode) -> TreeNode { 36 | var switchedLeft: TreeNode? 37 | var switchedRight: TreeNode? 38 | if let left = root.left { 39 | switchedLeft = switchSubTree(left) 40 | } 41 | if let right = root.right { 42 | switchedRight = switchSubTree(right) 43 | } 44 | root.left = switchedRight 45 | root.right = switchedLeft 46 | return root 47 | } 48 | 49 | /// Use a queue to convert a tree to an array. 50 | fileprivate func treeToArray(_ root: TreeNode?) -> [TreeValue] { 51 | guard let root = root else { 52 | return [TreeValue.empty] 53 | } 54 | var traversalQueue = Queue() 55 | var retVal: [TreeValue] = [.valid(root.val)] 56 | traversalQueue.enqueue(root) 57 | while !traversalQueue.isEmpty() { 58 | let currentNode = traversalQueue.dequeue()! 59 | if let left = currentNode.left { 60 | retVal.append(.valid(left.val)) 61 | traversalQueue.enqueue(left) 62 | } else { 63 | retVal.append(.empty) 64 | } 65 | if let right = currentNode.right { 66 | retVal.append(.valid(right.val)) 67 | traversalQueue.enqueue(right) 68 | } else { 69 | retVal.append(.empty) 70 | } 71 | } 72 | return retVal 73 | } 74 | 75 | /// A simpler solution, recursive 76 | func solutionTwo(_ root: TreeNode?) -> Bool { 77 | guard let root = root else { 78 | return true 79 | } 80 | return symmetricHelper(root.left, q: root.right) 81 | } 82 | 83 | fileprivate func symmetricHelper(_ p: TreeNode?, q: TreeNode?) -> Bool { 84 | if p == nil && q == nil { 85 | return true 86 | } 87 | if p == nil || q == nil || p?.val != q?.val { 88 | return false 89 | } 90 | return symmetricHelper(p?.left, q: q?.right) && symmetricHelper(p?.right, q: q?.left) 91 | } 92 | } 93 | 94 | enum TreeValue { 95 | case valid(Int) 96 | case empty 97 | } 98 | 99 | extension TreeValue: Equatable { } 100 | 101 | func ==(lhs: TreeValue, rhs: TreeValue) -> Bool { 102 | switch (lhs, rhs) { 103 | case (.valid(let lval), .valid(let rval)): 104 | return lval == rval 105 | case (.empty, .empty): 106 | return true 107 | default: 108 | return false 109 | } 110 | } 111 | --------------------------------------------------------------------------------