├── .gitignore ├── LICENSE ├── LeetCodeChallenge ├── ChallengeTests │ ├── Info.plist │ ├── TestExtensions.swift │ ├── TestsAprilWeek1.swift │ ├── TestsAprilWeek2.swift │ ├── TestsAprilWeek3.swift │ ├── TestsAprilWeek4.swift │ ├── TestsAprilWeek5.swift │ ├── TestsMayWeek1.swift │ ├── TestsMayWeek2.swift │ ├── TestsMayWeek3.swift │ ├── TestsMayWeek4.swift │ └── TestsMayWeek5.swift ├── LeetCodeChallenge.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── LeetCodeChallenge.xcscheme └── LeetCodeChallenge │ ├── AprilWeek1 │ ├── AprilSolDay1.swift │ ├── AprilSolDay2.swift │ ├── AprilSolDay3.swift │ ├── AprilSolDay4.swift │ ├── AprilSolDay5.swift │ ├── AprilSolDay6.swift │ └── AprilSolDay7.swift │ ├── AprilWeek2 │ ├── AprilSolDay10.swift │ ├── AprilSolDay11.swift │ ├── AprilSolDay12.swift │ ├── AprilSolDay13.swift │ ├── AprilSolDay14.swift │ ├── AprilSolDay8.swift │ └── AprilSolDay9.swift │ ├── AprilWeek3 │ ├── AprilSolDay15.swift │ ├── AprilSolDay16.swift │ ├── AprilSolDay17.swift │ ├── AprilSolDay18.swift │ ├── AprilSolDay19.swift │ ├── AprilSolDay20.swift │ └── AprilSolDay21.swift │ ├── AprilWeek4 │ ├── AprilSolDay22.swift │ ├── AprilSolDay23.swift │ ├── AprilSolDay24.swift │ ├── AprilSolDay25.swift │ ├── AprilSolDay26.swift │ ├── AprilSolDay27.swift │ └── AprilSolDay28.swift │ ├── AprilWeek5 │ ├── SolutionDay29.swift │ └── SolutionDay30.swift │ ├── MayWeek1 │ ├── MaySolDay1.swift │ ├── MaySolDay2.swift │ ├── MaySolDay3.swift │ ├── MaySolDay4.swift │ ├── MaySolDay5.swift │ ├── MaySolDay6.swift │ └── MaySolDay7.swift │ ├── MayWeek2 │ ├── MaySolDay10.swift │ ├── MaySolDay11.swift │ ├── MaySolDay12.swift │ ├── MaySolDay13.swift │ ├── MaySolDay14.swift │ ├── MaySolDay8.swift │ └── MaySolDay9.swift │ ├── MayWeek3 │ ├── MaySolDay15.swift │ ├── MaySolDay16.swift │ ├── MaySolDay17.swift │ ├── MaySolDay18.swift │ ├── MaySolDay19.swift │ ├── MaySolDay20.swift │ └── MaySolDay21.swift │ ├── MayWeek4 │ ├── MaySolDay22.swift │ ├── MaySolDay23.swift │ ├── MaySolDay24.swift │ ├── MaySolDay25.swift │ ├── MaySolDay26.swift │ ├── MaySolDay27.swift │ └── MaySolDay28.swift │ ├── MayWeek5 │ ├── MaySolDay29.swift │ ├── MaySolDay30.swift │ └── MaySolDay31.swift │ ├── Shared │ ├── DataModels.swift │ └── Extensions.swift │ └── main.swift └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## User settings 6 | xcuserdata/ 7 | 8 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) 9 | *.xcscmblueprint 10 | *.xccheckout 11 | 12 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) 13 | build/ 14 | DerivedData/ 15 | *.moved-aside 16 | *.pbxuser 17 | !default.pbxuser 18 | *.mode1v3 19 | !default.mode1v3 20 | *.mode2v3 21 | !default.mode2v3 22 | *.perspectivev3 23 | !default.perspectivev3 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | 28 | ## App packaging 29 | *.ipa 30 | *.dSYM.zip 31 | *.dSYM 32 | 33 | ## Playgrounds 34 | timeline.xctimeline 35 | playground.xcworkspace 36 | 37 | # Swift Package Manager 38 | # 39 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 40 | # Packages/ 41 | # Package.pins 42 | # Package.resolved 43 | # *.xcodeproj 44 | # 45 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata 46 | # hence it is not needed unless you have added a package configuration file to your project 47 | # .swiftpm 48 | 49 | .build/ 50 | 51 | # CocoaPods 52 | # 53 | # We recommend against adding the Pods directory to your .gitignore. However 54 | # you should judge for yourself, the pros and cons are mentioned at: 55 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 56 | # 57 | # Pods/ 58 | # 59 | # Add this line if you want to avoid checking in source code from the Xcode workspace 60 | # *.xcworkspace 61 | 62 | # Carthage 63 | # 64 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 65 | # Carthage/Checkouts 66 | 67 | Carthage/Build/ 68 | 69 | # Accio dependency management 70 | Dependencies/ 71 | .accio/ 72 | 73 | # fastlane 74 | # 75 | # It is recommended to not store the screenshots in the git repo. 76 | # Instead, use fastlane to re-generate the screenshots whenever they are needed. 77 | # For more information about the recommended setup visit: 78 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 79 | 80 | fastlane/report.xml 81 | fastlane/Preview.html 82 | fastlane/screenshots/**/*.png 83 | fastlane/test_output 84 | 85 | # Code Injection 86 | # 87 | # After new code Injection tools there's a generated folder /iOSInjectionProject 88 | # https://github.com/johnno1962/injectionforxcode 89 | 90 | iOSInjectionProject/ 91 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Michael T. Ho 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LeetCodeChallenge/ChallengeTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /LeetCodeChallenge/ChallengeTests/TestExtensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TestExtensions.swift 3 | // ChallengeTests 4 | // 5 | // Created by Michael Ho on 4/14/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension Array where Element: Collection, Element.Element: Comparable { 12 | 13 | func compareTo2DArrayIgnoreOrder(_ otherArray: [Element]) -> Bool { 14 | guard self.count == otherArray.count else { return false } 15 | 16 | let thisSorted = self.sorted(by: { $0.count > $1.count }) 17 | let otherSorted = otherArray.sorted(by: { $0.count > $1.count }) 18 | 19 | return thisSorted.elementsEqual(otherSorted) { (subArray, otherSubArray) -> Bool in 20 | subArray.sorted(by: >).elementsEqual(otherSubArray.sorted(by: >)) 21 | } 22 | } 23 | } 24 | 25 | extension SinglyListNode { 26 | 27 | func isEqualToLinkedList(_ otherHead: SinglyListNode?) -> Bool { 28 | guard otherHead != nil else { 29 | return false 30 | } 31 | 32 | var otherNode = otherHead 33 | var node: SinglyListNode? = self 34 | 35 | while node != nil { 36 | if otherNode == nil || (node?.val)! != (otherNode?.val)! { 37 | return false 38 | } 39 | otherNode = otherNode?.next 40 | node = node?.next 41 | } 42 | 43 | return true 44 | } 45 | } 46 | 47 | class TestBinaryMatrix: BinaryMatrix { 48 | private var getCallCount = 0 49 | 50 | override init(matrix: [[Int]]) { 51 | super.init(matrix: matrix) 52 | self.getCallCount = 0 53 | } 54 | 55 | override func get(_ x: Int, _ y: Int) -> Int { 56 | if getCallCount == 100 { 57 | assertionFailure("Error. 100 API calls limit reached.") 58 | } 59 | 60 | getCallCount += 1 61 | return super.get(x, y) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /LeetCodeChallenge/ChallengeTests/TestsAprilWeek1.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TestsWeek1.swift 3 | // ChallengeTests 4 | // 5 | // Created by Michael Ho on 4/14/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | // April Edition 12 | class TestsAprilWeek1: XCTestCase { 13 | let sol1 = AprilSolDay1() 14 | let sol2 = AprilSolDay2() 15 | let sol3 = AprilSolDay3() 16 | let sol4 = AprilSolDay4() 17 | let sol5 = AprilSolDay5() 18 | let sol6 = AprilSolDay6() 19 | let sol7 = AprilSolDay7() 20 | 21 | // MARK: - Day 1: Single Number Tests 22 | func testSingleNumber1() { 23 | let input = [2, 2, 1] 24 | let expected = 1 25 | XCTAssertEqual(sol1.singleNumber(input), expected) 26 | } 27 | 28 | func testSingleNumber2() { 29 | let input = [4, 1, 2, 1, 2] 30 | let expected = 4 31 | XCTAssertEqual(sol1.singleNumber(input), expected) 32 | } 33 | 34 | // MARK: - Day 2: Happy Number Tests 35 | func testHappyNumber1() { 36 | let input = 19 37 | /** 38 | 1^2 + 9^2 = 82 39 | 8^2 + 2^2 = 68 40 | 6^2 + 8^2 = 100 41 | 1^2 + 0^2 + 0^2 = 1 42 | */ 43 | XCTAssertTrue(sol2.isHappy(input)) 44 | } 45 | 46 | func testHappyNumber2() { 47 | let input = 7 48 | /** 49 | 7^2 = 49 50 | 4^2 + 9^2 = 97 51 | 9^2 + 7^2 = 130 52 | 1^2 + 3^2 + 0^2 = 10 53 | 1^2 + 0^2 = 1 54 | */ 55 | XCTAssertTrue(sol2.isHappy(input)) 56 | } 57 | 58 | func testHappyNumber3() { 59 | let input = 9 60 | /** 61 | 9^2 = 81 62 | 8^2 + 1^2 = 65 63 | 6^2 + 5^2 = 61 64 | 6^2 + 1^2 = 37 65 | 3^2 + 7^2 = 58 66 | 5^2 + 8^2 = 89 67 | 8*2 + 9^2 = 145 68 | 1^2 + 4^2 + 5^2 = 42 69 | 4^2 + 2^2 = 20 70 | 2^2 + 0^2 = 4 71 | 4^2 = 16 (duplicate, which has the same result as 61. Cycle detected) 72 | */ 73 | XCTAssertFalse(sol2.isHappy(input)) 74 | } 75 | 76 | // MARK: - Day 3: Maximum Subarray Tests 77 | func testMaxSubArray1() { 78 | let input = [-2, 1, -3, 4, -1, 2, 1, -5, 4] 79 | // Explanation: [4,-1,2,1] has the largest sum = 6. 80 | let expected = 6 81 | XCTAssertEqual(sol3.maxSubArray(input), expected) 82 | } 83 | 84 | func testMaxSubArray2() { 85 | let input = [1, 2, 7, -8, -4, 3, 85, -32, 20] 86 | let expected = 88 87 | XCTAssertEqual(sol3.maxSubArray(input), expected) 88 | } 89 | 90 | // MARK: - Day 4: Maximum Subarray Tests 91 | func testMoveZeroes1() { 92 | var input = [0, 1, 0, 3, 12] 93 | let expected = [1, 3, 12, 0, 0] 94 | sol4.moveZeroes(&input) 95 | XCTAssertEqual(input, expected) 96 | } 97 | 98 | func testMoveZeroes2() { 99 | var input = [0, 0, 0, 0, 0, 1] 100 | let expected = [1, 0, 0, 0, 0, 0] 101 | sol4.moveZeroes(&input) 102 | XCTAssertEqual(input, expected) 103 | } 104 | 105 | // MARK: - Day 5: Best Time to Buy and Sell Stock II 106 | func testMakeProfit1() { 107 | let input = [7, 1, 5, 3, 6, 4] 108 | let expected = 7 109 | XCTAssertEqual(sol5.maxProfit(input), expected) 110 | } 111 | 112 | func testMakeProfit2() { 113 | let input = [1, 2, 3, 4, 5] 114 | let expected = 4 115 | XCTAssertEqual(sol5.maxProfit(input), expected) 116 | } 117 | 118 | // MARK: - Day 6: Group Anagrams 119 | func testGroupAnagrams1() { 120 | let input = ["eat", "tea", "tan", "ate", "nat", "bat"] 121 | let expected = [ 122 | ["ate","eat","tea"], 123 | ["nat","tan"], 124 | ["bat"] 125 | ] 126 | XCTAssertTrue(expected.compareTo2DArrayIgnoreOrder(sol6.groupAnagrams(input))) 127 | } 128 | 129 | func testGroupAnagrams2() { 130 | let input = ["","",""] 131 | let expected = [ 132 | ["","",""] 133 | ] 134 | XCTAssertTrue(expected.compareTo2DArrayIgnoreOrder(sol6.groupAnagrams(input))) 135 | } 136 | 137 | // MARK: - Day 7: Counting Elements 138 | func testCountingElements1() { 139 | let input = [1, 2, 3] 140 | let expected = 2 141 | XCTAssertEqual(expected, sol7.countElements(input)) 142 | } 143 | 144 | func testCountingElements2() { 145 | let input = [1, 1, 3, 3, 5, 5, 7, 7] 146 | let expected = 0 147 | XCTAssertEqual(expected, sol7.countElements(input)) 148 | } 149 | 150 | func testCountingElements3() { 151 | let input = [1, 3, 2, 3, 5, 0] 152 | let expected = 3 153 | XCTAssertEqual(expected, sol7.countElements(input)) 154 | } 155 | 156 | func testCountingElements4() { 157 | let input = [1, 1, 2, 2] 158 | let expected = 2 159 | XCTAssertEqual(expected, sol7.countElements(input)) 160 | } 161 | 162 | // TODO: Performance tests comes later 163 | func testPerformanceExample() throws { 164 | // This is an example of a performance test case. 165 | self.measure { 166 | // Put the code you want to measure the time of here. 167 | } 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /LeetCodeChallenge/ChallengeTests/TestsAprilWeek2.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TestsWeek2.swift 3 | // ChallengeTests 4 | // 5 | // Created by Michael Ho on 4/15/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | // April Edition 12 | class TestsAprilWeek2: XCTestCase { 13 | let sol8 = AprilSolDay8() 14 | let sol9 = AprilSolDay9() 15 | let sol11 = AprilSolDay11() 16 | let sol12 = AprilSolDay12() 17 | let sol13 = AprilSolDay13() 18 | let sol14 = AprilSolDay14() 19 | 20 | // MARK: - Day 8: Middle of the Linked List 21 | func testMiddleNode1() { 22 | let input = [1, 2, 3, 4, 5].convertToLinkedList() 23 | let expected = [3, 4, 5].convertToLinkedList() 24 | let output = sol8.middleNode(input) 25 | 26 | XCTAssertNotNil(output) 27 | XCTAssertTrue(output!.isEqualToLinkedList(expected)) 28 | } 29 | 30 | func testMiddleNode2() { 31 | let input = [2, 4, 6, 8, 10, 12].convertToLinkedList() 32 | let expected = [8, 10, 12].convertToLinkedList() 33 | let output = sol8.middleNode(input) 34 | 35 | XCTAssertNotNil(output) 36 | XCTAssertTrue(output!.isEqualToLinkedList(expected)) 37 | } 38 | 39 | // MARK: - Day 9: Backspace String Compare 40 | func testBackspaceStringCompare1() { 41 | let input = (S: "ab#c", T: "ad#c") 42 | XCTAssertTrue(sol9.backspaceCompare(input.S, input.T)) 43 | } 44 | 45 | func testBackspaceStringCompare2() { 46 | let input = (S: "a##c", T: "#a#c") 47 | XCTAssertTrue(sol9.backspaceCompare(input.S, input.T)) 48 | } 49 | 50 | func testBackspaceStringCompare3() { 51 | let input = (S: "ab##", T: "c#d#") 52 | XCTAssertTrue(sol9.backspaceCompare(input.S, input.T)) 53 | } 54 | 55 | func testBackspaceStringCompare4() { 56 | let input = (S: "a#c", T: "b") 57 | XCTAssertFalse(sol9.backspaceCompare(input.S, input.T)) 58 | } 59 | 60 | // MARK: - Day 10: Min Stack 61 | func testMinStack1() { 62 | let minStack = AprilSolDay10.MinStack() 63 | minStack.push(-2) 64 | minStack.push(0) 65 | minStack.push(-3) 66 | minStack.push(-6) 67 | minStack.push(3) 68 | minStack.push(7) 69 | XCTAssertEqual(-6, minStack.getMin()) 70 | 71 | minStack.pop() 72 | XCTAssertEqual(3, minStack.top()) 73 | 74 | minStack.pop() 75 | minStack.pop() 76 | XCTAssertEqual(-3, minStack.getMin()) 77 | } 78 | 79 | func testMinStack2() { 80 | let minStack = AprilSolDay10.MinStack() 81 | minStack.push(-2) 82 | minStack.push(-13) 83 | minStack.push(8) 84 | XCTAssertEqual(8, minStack.top()) 85 | 86 | minStack.push(-20) 87 | XCTAssertEqual(-20, minStack.getMin()) 88 | 89 | minStack.pop() 90 | XCTAssertEqual(-13, minStack.getMin()) 91 | 92 | minStack.pop() 93 | minStack.pop() 94 | XCTAssertEqual(-2, minStack.getMin()) 95 | } 96 | 97 | // MARK: - Day 11: Diameter of Binary Tree 98 | func testDiameterOfBinaryTree1() { 99 | /** 100 | Tree structure 101 | 1 102 | / \ 103 | 2 3 104 | / \ 105 | 4 5 106 | */ 107 | let tree = [ 108 | 1, 109 | 2, 3, 110 | 4, 5, nil, nil 111 | ].convertToBinaryTree() 112 | let expected = 3 113 | XCTAssertEqual(expected, sol11.diameterOfBinaryTree(tree)) 114 | } 115 | 116 | func testDiameterOfBinaryTree2() { 117 | /** 118 | Tree structure 119 | 4 120 | / \ 121 | 7 3 122 | / \ 123 | 9 3 124 | / \ / 125 | 9 7 4 126 | / / \ 127 | 6 6 6 128 | / \ / / 129 | 0 6 5 9 130 | */ 131 | let tree = [ 132 | 4, 133 | 7, 3, 134 | nil, nil, 9, 3, 135 | nil, nil, nil, nil, 9, 7, 4, nil, 136 | nil, nil, nil, nil, nil, nil, nil, nil, 6, nil, 6, 6, nil, nil, nil, nil, 137 | nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 6, nil, nil, 5, nil, 9, nil, nil, nil, nil, nil, nil, nil, nil, nil 138 | ].convertToBinaryTree() 139 | let expected = 6 140 | XCTAssertEqual(expected, sol11.diameterOfBinaryTree(tree)) 141 | } 142 | 143 | // MARK: - Day 12: Last Stone Weight 144 | func testLastStoneWeight1() { 145 | let input = [2, 7, 4, 1, 8, 1] 146 | let expected = 1 147 | XCTAssertEqual(expected, sol12.lastStoneWeight(input)) 148 | } 149 | 150 | func testLastStoneWeight2() { 151 | let input = [10, 5, 7, 23, 11, 12, 27, 19] 152 | let expected = 0 153 | XCTAssertEqual(expected, sol12.lastStoneWeight(input)) 154 | } 155 | 156 | // MARK: - Day 13: Contiguous Array 157 | func testContiguousArray1() { 158 | let input = [0, 1] 159 | let expected = 2 160 | XCTAssertEqual(expected, sol13.findMaxLength(input)) 161 | } 162 | 163 | func testContiguousArray2() { 164 | let input = [0, 1, 0] 165 | let expected = 2 166 | XCTAssertEqual(expected, sol13.findMaxLength(input)) 167 | } 168 | 169 | func testContiguousArray3() { 170 | let input = [0, 1, 0, 0, 1, 0, 1, 1, 0, 0] 171 | let expected = 8 172 | XCTAssertEqual(expected, sol13.findMaxLength(input)) 173 | } 174 | 175 | func testContiguousArray4() { 176 | let input = [0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0] 177 | let expected = 12 178 | XCTAssertEqual(expected, sol13.findMaxLength(input)) 179 | } 180 | 181 | // MARK: - Day 14: Perform String Shifts 182 | func testPerformStringShifts1() { 183 | let input = (s: "abc", shift: [[0,1], [1,2]]) 184 | let expected = "cab" 185 | XCTAssertEqual(expected, sol14.stringShift(input.s, input.shift)) 186 | } 187 | 188 | func testPerformStringShifts2() { 189 | let input = (s: "abcdefg", shift: [[1, 1], [1, 1], [0, 2], [1, 3]]) 190 | let expected = "efgabcd" 191 | XCTAssertEqual(expected, sol14.stringShift(input.s, input.shift)) 192 | } 193 | 194 | func testPerformStringShifts3() { 195 | let input = (s: "michaelh", shift: [[1, 1], [1, 1], [1, 8], [0, 6], [1, 17]]) 196 | let expected = "haelhmic" 197 | XCTAssertEqual(expected, sol14.stringShift(input.s, input.shift)) 198 | } 199 | 200 | // TODO: Performance tests comes later 201 | func testPerformanceExample() throws { 202 | // This is an example of a performance test case. 203 | self.measure { 204 | // Put the code you want to measure the time of here. 205 | } 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /LeetCodeChallenge/ChallengeTests/TestsAprilWeek3.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TestsWeek3.swift 3 | // ChallengeTests 4 | // 5 | // Created by Michael Ho on 4/20/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | // April Edition 12 | class TestsAprilWeek3: XCTestCase { 13 | let sol15 = AprilSolDay15() 14 | let sol16 = AprilSolDay16() 15 | let sol17 = AprilSolDay17() 16 | let sol18 = AprilSolDay18() 17 | let sol19 = AprilSolDay19() 18 | let sol20 = AprilSolDay20() 19 | let sol21 = AprilSolDay21() 20 | 21 | // MARK: - Day 15: Product of Array Except Self 22 | func testProductExceptSelf1() { 23 | let input = [1, 2, 3, 4] 24 | let expected = [24,12,8,6] 25 | 26 | XCTAssertEqual(expected, sol15.productExceptSelf(input)) 27 | } 28 | 29 | func testMiddleNode2() { 30 | let input = [0, 0] 31 | let expected = [0, 0] 32 | 33 | XCTAssertEqual(expected, sol15.productExceptSelf(input)) 34 | } 35 | 36 | // MARK: - Day 16: Valid Parenthesis String 37 | func testValidParenthesisString1() { 38 | let input = "()" 39 | XCTAssertTrue(sol16.checkValidString(input)) 40 | } 41 | 42 | func testValidParenthesisString2() { 43 | let input = "(*))" 44 | XCTAssertTrue(sol16.checkValidString(input)) 45 | } 46 | 47 | func testValidParenthesisString3() { 48 | let input = "(*()" 49 | XCTAssertTrue(sol16.checkValidString(input)) 50 | } 51 | 52 | func testValidParenthesisString4() { 53 | let input = "(" 54 | XCTAssertFalse(sol16.checkValidString(input)) 55 | } 56 | 57 | func testValidParenthesisString5() { 58 | let input = "(*)" 59 | XCTAssertTrue(sol16.checkValidString(input)) 60 | } 61 | 62 | func testValidParenthesisString6() { 63 | let input = "(())((())()()(*)(*()(())())())()()((()())((()))(*" 64 | XCTAssertFalse(sol16.checkValidString(input)) 65 | } 66 | 67 | func testValidParenthesisString7() { 68 | let input = "(()(())()())*((()(())))*()(*)()()(*((()((*(*))))()*()(()((()(*((()))*(((())(())))*))(()*))(()*)" 69 | XCTAssertTrue(sol16.checkValidString(input)) 70 | } 71 | 72 | // MARK: - Day 17: Number of Islands 73 | func testNumberOfIslands1() { 74 | let input: [[Character]] = [ 75 | ["1", "1", "0", "0", "0"], 76 | ["1", "1", "0", "0", "0"], 77 | ["0", "0", "1", "0", "0"], 78 | ["0", "0", "0", "1", "1"] 79 | ] 80 | let expected = 3 81 | XCTAssertEqual(expected, sol17.numIslands(input)) 82 | } 83 | 84 | func testNumberOfIslands2() { 85 | let input: [[Character]] = [ 86 | ["1", "1", "1", "1", "0"], 87 | ["1", "1", "0", "1", "0"], 88 | ["1", "1", "0", "0", "0"], 89 | ["0", "0", "0", "0", "0"] 90 | ] 91 | let expected = 1 92 | XCTAssertEqual(expected, sol17.numIslands(input)) 93 | } 94 | 95 | func testNumberOfIslands3() { 96 | let input: [[Character]] = [ 97 | ["0", "0", "0", "0", "0"], 98 | ["0", "1", "1", "1", "0"], 99 | ["0", "0", "0", "0", "0"], 100 | ["0", "0", "0", "0", "0"] 101 | ] 102 | let expected = 1 103 | XCTAssertEqual(expected, sol17.numIslands(input)) 104 | } 105 | 106 | // MARK: - Day 18: Minimum Path Sum 107 | func testMinimumPathSum1() { 108 | let input = [ 109 | [1, 3, 1], 110 | [1, 5, 1], 111 | [4, 2, 1] 112 | ] 113 | let expected = 7 114 | XCTAssertEqual(expected, sol18.minPathSum(input)) 115 | } 116 | 117 | func testMinimumPathSum2() { 118 | let input = [ 119 | [1, 2, 5], 120 | [3, 2, 1] 121 | ] 122 | let expected = 6 123 | XCTAssertEqual(expected, sol18.minPathSum(input)) 124 | } 125 | 126 | // MARK: - Day 19: Search in Rotated Sorted Array 127 | func testSearchRotatedSortedArray1() { 128 | let input = (nums: [4, 5, 6, 7, 0, 1, 2], target: 0) 129 | let expected = 4 130 | XCTAssertEqual(expected, sol19.search(input.nums, input.target)) 131 | } 132 | 133 | func testSearchRotatedSortedArray2() { 134 | let input = (nums: [4, 5, 6, 7, 0, 1, 2], target: 3) 135 | let expected = -1 136 | XCTAssertEqual(expected, sol19.search(input.nums, input.target)) 137 | } 138 | 139 | func testSearchRotatedSortedArray3() { 140 | let input = (nums: [Int](), target: 5) 141 | let expected = -1 142 | XCTAssertEqual(expected, sol19.search(input.nums, input.target)) 143 | } 144 | 145 | func testSearchRotatedSortedArray4() { 146 | let input = (nums: [3, 1], target: 1) 147 | let expected = 1 148 | XCTAssertEqual(expected, sol19.search(input.nums, input.target)) 149 | } 150 | 151 | // MARK: - Day 20: Construct Binary Search Tree from Preorder Traversal 152 | func testConstructBSTFromPreorderTraversal1() { 153 | let input = [8, 5, 1, 7, 10, 12] 154 | /** 155 | Tree structure 156 | 8 157 | / \ 158 | 5 10 159 | / \ \ 160 | 1 7 12 161 | */ 162 | let expected = [ 163 | 8, 164 | 5, 10, 165 | 1, 7, nil, 12 166 | ].convertToBinaryTree() 167 | 168 | let output = BinarySearchTree(root: sol20.bstFromPreorder(input)) 169 | XCTAssertTrue(output.isEqualToOtherTree(expected)) 170 | } 171 | 172 | func testConstructBSTFromPreorderTraversal2() { 173 | let input = [9, 5, 3, 8, 10, 15, 13, 19, 25] 174 | /** 175 | Tree structure 176 | 9 177 | / \ 178 | 5 10 179 | / \ \ 180 | 3 8 15 181 | / \ 182 | 13 19 183 | \ 184 | 25 185 | */ 186 | let expected = [ 187 | 9, 188 | 5, 10, 189 | 3, 8, nil, 15, 190 | nil, nil, nil, nil, nil, nil, 13, 19, 191 | nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 25 192 | ].convertToBinaryTree() 193 | 194 | let output = BinarySearchTree(root: sol20.bstFromPreorder(input)) 195 | XCTAssertTrue(output.isEqualToOtherTree(expected)) 196 | } 197 | 198 | // MARK: - Day 21: Leftmost Column with at Least a One 199 | func testLeftmostColumnWithAtLeastOne1() { 200 | let input = [ 201 | [0, 0, 0, 1], 202 | [0, 0, 1, 1], 203 | [0, 1, 1, 1] 204 | ] 205 | let expected = 1 206 | let bm = TestBinaryMatrix(matrix: input) 207 | XCTAssertEqual(expected, sol21.leftMostColumnWithOne(bm)) 208 | } 209 | 210 | func testLeftmostColumnWithAtLeastOne2() { 211 | let input = [ 212 | [0, 0], 213 | [0, 0] 214 | ] 215 | let expected = -1 216 | let bm = TestBinaryMatrix(matrix: input) 217 | XCTAssertEqual(expected, sol21.leftMostColumnWithOne(bm)) 218 | } 219 | 220 | func testLeftmostColumnWithAtLeastOne3() { 221 | let input = [ 222 | [0, 0, 0, 0, 1], 223 | [0, 0, 1, 1, 1], 224 | [0, 0, 0, 1, 1], 225 | [0, 1, 1, 1, 1], 226 | [0, 0, 0, 0, 0], 227 | [1, 1, 1, 1, 1], 228 | ] 229 | let expected = 0 230 | let bm = TestBinaryMatrix(matrix: input) 231 | XCTAssertEqual(expected, sol21.leftMostColumnWithOne(bm)) 232 | } 233 | 234 | 235 | // TODO: Performance tests comes later 236 | func testPerformanceExample() throws { 237 | // This is an example of a performance test case. 238 | self.measure { 239 | // Put the code you want to measure the time of here. 240 | } 241 | } 242 | } 243 | 244 | /** 245 | [ 246 | [0,0,1,1,1,1,1,1], 247 | [0,0,0,0,0,1,1,1], 248 | [0,0,0,1,1,1,1,1], 249 | [0,0,0,0,0,1,1,1], 250 | [0,0,0,1,1,1,1,1], 251 | [0,0,1,1,1,1,1,1], 252 | [0,0,0,0,1,1,1,1], 253 | [0,1,1,1,1,1,1,1] 254 | ] 255 | */ 256 | 257 | -------------------------------------------------------------------------------- /LeetCodeChallenge/ChallengeTests/TestsAprilWeek4.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TestsWeek4.swift 3 | // ChallengeTests 4 | // 5 | // Created by Michael Ho on 4/27/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | // April Edition 12 | class TestsAprilWeek4: XCTestCase { 13 | let sol22 = AprilSolDay22() 14 | let sol23 = AprilSolDay23() 15 | let sol25 = AprilSolDay25() 16 | let sol26 = AprilSolDay26() 17 | let sol27 = AprilSolDay27() 18 | 19 | // MARK: - Day 22: Subarray Sum Equals K 20 | func testSubarraySumEqualsK1() { 21 | let input = (nums: [1, 1, 1, 3, 8, 9], k: 5) 22 | let expected = 1 23 | 24 | XCTAssertEqual(expected, sol22.subarraySum(input.nums, input.k)) 25 | } 26 | 27 | func testSubarraySumEqualsK2() { 28 | let input = (nums: [1, 1, 1], k: 2) 29 | let expected = 2 30 | 31 | XCTAssertEqual(expected, sol22.subarraySum(input.nums, input.k)) 32 | } 33 | 34 | // MARK: - Day 23: Bitwise AND of Numbers Range 35 | func testBitwiseANDOfNumbersRange1() { 36 | let input = (5, 7) 37 | let expected = 4 38 | XCTAssertEqual(expected, sol23.rangeBitwiseAnd(input.0, input.1)) 39 | } 40 | 41 | func testBitwiseANDOfNumbersRange2() { 42 | let input = (0, 1) 43 | let expected = 0 44 | XCTAssertEqual(expected, sol23.rangeBitwiseAnd(input.0, input.1)) 45 | } 46 | 47 | // MARK: - Day 24: LRU Cache 48 | func testLRUCache1() { 49 | let cache = AprilSolDay24.LRUCache(2) 50 | cache.put(1, 1) 51 | cache.put(2, 2) 52 | XCTAssertEqual(1, cache.get(1)) 53 | 54 | cache.put(3, 3) 55 | XCTAssertEqual(-1, cache.get(2)) 56 | 57 | cache.put(4, 4) 58 | XCTAssertEqual(-1, cache.get(1)) 59 | XCTAssertEqual(3, cache.get(3)) 60 | XCTAssertEqual(4, cache.get(4)) 61 | } 62 | 63 | func testLRUCache2() { 64 | let cache = AprilSolDay24.LRUCache(5) 65 | cache.put(1, 10) 66 | cache.put(2, 20) 67 | cache.put(3, 30) 68 | cache.put(4, 40) 69 | cache.put(5, 50) 70 | cache.put(4, 41) 71 | XCTAssertEqual(10, cache.get(1)) 72 | 73 | cache.put(6, 60) 74 | XCTAssertEqual(-1, cache.get(2)) 75 | 76 | cache.put(7, 70) 77 | XCTAssertEqual(-1, cache.get(3)) 78 | XCTAssertEqual(41, cache.get(4)) 79 | XCTAssertEqual(60, cache.get(6)) 80 | } 81 | 82 | // MARK: - Day 25: Jump Game 83 | func testJumpGame1() { 84 | let input = [2, 3, 1, 1, 4] 85 | XCTAssertTrue(sol25.canJump(input)) 86 | } 87 | 88 | func testJumpGame2() { 89 | let input = [3, 2, 1, 0, 4] 90 | XCTAssertFalse(sol25.canJump(input)) 91 | } 92 | 93 | func testJumpGame3() { 94 | let input = [1, 2, 3] 95 | XCTAssertTrue(sol25.canJump(input)) 96 | } 97 | 98 | // MARK: - Day 26: Longest Common Subsequence 99 | func testLongestCommonSubsequence1() { 100 | let input = ("abcde", "ace") 101 | let expected = 3 102 | XCTAssertEqual(expected, sol26.longestCommonSubsequence(input.0, input.1)) 103 | } 104 | 105 | func testLongestCommonSubsequence2() { 106 | let input = ("abc", "def") 107 | let expected = 0 108 | XCTAssertEqual(expected, sol26.longestCommonSubsequence(input.0, input.1)) 109 | } 110 | 111 | func testLongestCommonSubsequence3() { 112 | let input = ("abc", "abc") 113 | let expected = 3 114 | XCTAssertEqual(expected, sol26.longestCommonSubsequence(input.0, input.1)) 115 | } 116 | 117 | func testLongestCommonSubsequence4() { 118 | let input = ("pmjghexybyrgzczy", "hafcdqbgncrcbihkd") 119 | let expected = 4 120 | XCTAssertEqual(expected, sol26.longestCommonSubsequence(input.0, input.1)) 121 | } 122 | 123 | func testLongestCommonSubsequence5() { 124 | let input = ("hofubmnylkra", "pqhgxgdofcvmr") 125 | let expected = 5 126 | XCTAssertEqual(expected, sol26.longestCommonSubsequence(input.0, input.1)) 127 | } 128 | 129 | // MARK: - Day 27: Maximal Square 130 | func testMaximalSquare1() { 131 | let input: [[Character]] = [ 132 | ["1", "0", "1", "0", "0"], 133 | ["1", "0", "1", "1", "1"], 134 | ["1", "1", "1", "1", "1"], 135 | ["1", "0", "0", "1", "0"] 136 | ] 137 | let expected = 4 138 | XCTAssertEqual(expected, sol27.maximalSquare(input)) 139 | } 140 | 141 | func testMaximalSquare2() { 142 | let input: [[Character]] = [ 143 | ["1", "0", "0", "1", "0"], 144 | ["1", "1", "1", "1", "1"], 145 | ["1", "1", "1", "1", "1"], 146 | ["1", "1", "1", "1", "0"] 147 | ] 148 | let expected = 9 149 | XCTAssertEqual(expected, sol27.maximalSquare(input)) 150 | } 151 | 152 | // MARK: - Day 28: First Unique Number 153 | func testFirstUniqueNumber1() { 154 | let firstUnique = AprilSolDay28.FirstUnique([2, 3, 5]) 155 | XCTAssertEqual(2, firstUnique.showFirstUnique()) 156 | firstUnique.add(5) 157 | XCTAssertEqual(2, firstUnique.showFirstUnique()) 158 | firstUnique.add(2) 159 | XCTAssertEqual(3, firstUnique.showFirstUnique()) 160 | firstUnique.add(3) 161 | XCTAssertEqual(-1, firstUnique.showFirstUnique()) 162 | } 163 | 164 | func testFirstUniqueNumber2() { 165 | let firstUnique = AprilSolDay28.FirstUnique([7, 7, 7, 7, 7, 7]) 166 | XCTAssertEqual(-1, firstUnique.showFirstUnique()) 167 | firstUnique.add(7) 168 | firstUnique.add(3) 169 | firstUnique.add(3) 170 | firstUnique.add(17) 171 | XCTAssertEqual(17, firstUnique.showFirstUnique()) 172 | } 173 | 174 | func testFirstUniqueNumber3() { 175 | let firstUnique = AprilSolDay28.FirstUnique([809]) 176 | XCTAssertEqual(809, firstUnique.showFirstUnique()) 177 | firstUnique.add(809) 178 | XCTAssertEqual(-1, firstUnique.showFirstUnique()) 179 | } 180 | 181 | func testPerformanceExample() throws { 182 | // This is an example of a performance test case. 183 | self.measure { 184 | // Put the code you want to measure the time of here. 185 | } 186 | } 187 | 188 | } 189 | -------------------------------------------------------------------------------- /LeetCodeChallenge/ChallengeTests/TestsAprilWeek5.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TestsWeek5.swift 3 | // ChallengeTests 4 | // 5 | // Created by Michael Ho on 5/1/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | // April Edition 12 | class TestsAprilWeek5: XCTestCase { 13 | let sol29 = AprilSolDay29() 14 | let sol30 = AprilSolDay30() 15 | 16 | // MARK: - Day 29: Binary Tree Maximum Path Sum 17 | func testBinaryTreeMaximumPathSum1() { 18 | /** 19 | Tree structure 20 | 1 21 | / \ 22 | 2 3 23 | */ 24 | let tree = [ 25 | 1, 26 | 2, 3 27 | ].convertToBinaryTree() 28 | let expected = 6 29 | XCTAssertEqual(expected, sol29.maxPathSum(tree)) 30 | } 31 | 32 | func testBinaryTreeMaximumPathSum2() { 33 | /** 34 | Tree structure 35 | -10 36 | / \ 37 | 9 20 38 | / \ 39 | 15 7 40 | */ 41 | let tree = [ 42 | -10, 43 | 9, 20, 44 | nil, nil, 15, 7 45 | ].convertToBinaryTree() 46 | let expected = 42 47 | XCTAssertEqual(expected, sol29.maxPathSum(tree)) 48 | } 49 | 50 | func testBinaryTreeMaximumPathSum3() { 51 | /** 52 | Tree structure 53 | 5 54 | / \ 55 | 4 8 56 | / / \ 57 | 11 13 4 58 | / \ \ 59 | 7 2 1 60 | */ 61 | let tree = [ 62 | 5, 63 | 4, 8, 64 | 11, nil, 13, 4, 65 | 7, 2, nil, nil, nil, nil, nil, 1 66 | ].convertToBinaryTree() 67 | let expected = 48 68 | XCTAssertEqual(expected, sol29.maxPathSum(tree)) 69 | } 70 | 71 | // MARK: - Day 30: Check If a String Is a Valid Sequence from Root to Leaves Path in a Binary Tree 72 | func testIsValidSequenceInTree1() { 73 | /** 74 | Tree structure 75 | 0 76 | / \ 77 | 1 0 78 | / \ / 79 | 0 1 0 80 | \ / \ 81 | 1 0 0 82 | */ 83 | let tree = [ 84 | 0, 85 | 1, 0, 86 | 0, 1, 0, nil, 87 | nil, 1, 0, 0, nil, nil, nil, nil 88 | ].convertToBinaryTree() 89 | let arr = [0, 1, 0, 1] 90 | XCTAssertTrue(sol30.isValidSequence(tree, arr)) 91 | } 92 | 93 | func testIsValidSequenceInTree2() { 94 | /** 95 | Tree structure 96 | 0 97 | / \ 98 | 1 0 99 | / \ / 100 | 0 1 0 101 | \ / \ 102 | 1 0 0 103 | */ 104 | let tree = [ 105 | 0, 106 | 1, 0, 107 | 0, 1, 0, nil, 108 | nil, 1, 0, 0, nil, nil, nil, nil 109 | ].convertToBinaryTree() 110 | let arr = [0, 0, 1] 111 | XCTAssertFalse(sol30.isValidSequence(tree, arr)) 112 | } 113 | 114 | func testIsValidSequenceInTree3() { 115 | /** 116 | Tree structure 117 | 0 118 | / \ 119 | 1 0 120 | / \ / 121 | 0 1 0 122 | \ / \ 123 | 1 0 0 124 | */ 125 | let tree = [ 126 | 0, 127 | 1, 0, 128 | 0, 1, 0, nil, 129 | nil, 1, 0, 0, nil, nil, nil, nil 130 | ].convertToBinaryTree() 131 | let arr = [0, 1, 1] 132 | XCTAssertFalse(sol30.isValidSequence(tree, arr)) 133 | } 134 | 135 | func testPerformanceExample() throws { 136 | // This is an example of a performance test case. 137 | self.measure { 138 | // Put the code you want to measure the time of here. 139 | } 140 | } 141 | 142 | } 143 | -------------------------------------------------------------------------------- /LeetCodeChallenge/ChallengeTests/TestsMayWeek1.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TestsMayWeek1.swift 3 | // ChallengeTests 4 | // 5 | // Created by Michael Ho on 5/3/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | // May Edition 12 | class TestsMayWeek1: XCTestCase { 13 | let sol1 = MaySolDay1() 14 | let sol2 = MaySolDay2() 15 | let sol3 = MaySolDay3() 16 | let sol4 = MaySolDay4() 17 | let sol5 = MaySolDay5() 18 | let sol6 = MaySolDay6() 19 | let sol7 = MaySolDay7() 20 | 21 | // MARK: - Day 1: First Bad Version 22 | func testFirstBadVersion1() { 23 | let expected = 4 24 | sol1.setBadVersion(expected) 25 | let input = 5 26 | XCTAssertEqual(expected, sol1.firstBadVersion(input)) 27 | } 28 | 29 | func testFirstBadVersion2() { 30 | let expected = 37 31 | sol1.setBadVersion(expected) 32 | let input = 50 33 | XCTAssertEqual(expected, sol1.firstBadVersion(input)) 34 | } 35 | 36 | // MARK: - Day 2: Jewels and Stones 37 | func testJewelsAndStones1() { 38 | let input = (J: "aA", S: "aAAbbbb") 39 | let expected = 3 40 | XCTAssertEqual(expected, sol2.numJewelsInStones(input.J, input.S)) 41 | } 42 | 43 | func testJewelsAndStones2() { 44 | let input = (J: "z", S: "ZZ") 45 | let expected = 0 46 | XCTAssertEqual(expected, sol2.numJewelsInStones(input.J, input.S)) 47 | } 48 | 49 | // MARK: - Day 3: Ransom Note 50 | func testRansomNote1() { 51 | let input = (ransomNote: "a", magazine: "b") 52 | XCTAssertFalse(sol3.canConstruct(input.ransomNote, input.magazine)) 53 | } 54 | 55 | func testRansomNote2() { 56 | let input = (ransomNote: "aa", magazine: "ab") 57 | XCTAssertFalse(sol3.canConstruct(input.ransomNote, input.magazine)) 58 | } 59 | 60 | func testRansomNote3() { 61 | let input = (ransomNote: "aa", magazine: "aab") 62 | XCTAssertTrue(sol3.canConstruct(input.ransomNote, input.magazine)) 63 | } 64 | 65 | // MARK: - Day 4: Number Complement 66 | func testNumberComplement1() { 67 | let input = 5 68 | let expected = 2 69 | XCTAssertEqual(expected, sol4.findComplement(input)) 70 | } 71 | 72 | func testNumberComplement2() { 73 | let input = 1 74 | let expected = 0 75 | XCTAssertEqual(expected, sol4.findComplement(input)) 76 | } 77 | 78 | // MARK: - Day 5: First Unique Character in a String 79 | func testFirstUniqueCharacterInString1() { 80 | let input = "leetcode" 81 | let expected = 0 82 | XCTAssertEqual(expected, sol5.firstUniqChar(input)) 83 | } 84 | 85 | func testFirstUniqueCharacterInString2() { 86 | let input = "loveleetcode" 87 | let expected = 2 88 | XCTAssertEqual(expected, sol5.firstUniqChar(input)) 89 | } 90 | 91 | // MARK: - Day 6: Majority Element 92 | func testMajorityElement1() { 93 | let input = [3, 2, 3] 94 | let expected = 3 95 | XCTAssertEqual(expected, sol6.majorityElement(input)) 96 | } 97 | 98 | func testMajorityElement2() { 99 | let input = [2, 2, 1, 1, 1, 2, 2] 100 | let expected = 2 101 | XCTAssertEqual(expected, sol6.majorityElement(input)) 102 | } 103 | 104 | // MARK: - Day 7: Cousins in Binary Tree 105 | func testCousinsInBinaryTree1() { 106 | /** 107 | Tree structure 108 | 1 109 | / \ 110 | 2 3 111 | / 112 | 4 113 | */ 114 | let tree = [ 115 | 1, 116 | 2, 3, 117 | 4, nil, nil, nil 118 | ].convertToBinaryTree() 119 | let input = (x: 4, y: 3) 120 | XCTAssertFalse(sol7.isCousins(tree, input.x, input.y)) 121 | } 122 | 123 | func testCousinsInBinaryTree2() { 124 | /** 125 | Tree structure 126 | 1 127 | / \ 128 | 2 3 129 | \ \ 130 | 4 5 131 | */ 132 | let tree = [ 133 | 1, 134 | 2, 3, 135 | nil, 4, nil, 5 136 | ].convertToBinaryTree() 137 | let input = (x: 5, y: 4) 138 | XCTAssertTrue(sol7.isCousins(tree, input.x, input.y)) 139 | } 140 | 141 | func testCousinsInBinaryTree3() { 142 | /** 143 | Tree structure 144 | 1 145 | / \ 146 | 2 3 147 | \ 148 | 4 149 | */ 150 | let tree = [ 151 | 1, 152 | 2, 3, 153 | nil, 4, nil, nil 154 | ].convertToBinaryTree() 155 | let input = (x: 2, y: 3) 156 | XCTAssertFalse(sol7.isCousins(tree, input.x, input.y)) 157 | } 158 | 159 | func testPerformanceExample() throws { 160 | // This is an example of a performance test case. 161 | self.measure { 162 | // Put the code you want to measure the time of here. 163 | } 164 | } 165 | 166 | } 167 | -------------------------------------------------------------------------------- /LeetCodeChallenge/ChallengeTests/TestsMayWeek2.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TestsMayWeek2.swift 3 | // ChallengeTests 4 | // 5 | // Created by Michael Ho on 5/14/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class TestsMayWeek2: XCTestCase { 12 | let sol8 = MaySolDay8() 13 | let sol9 = MaySolDay9() 14 | let sol10 = MaySolDay10() 15 | let sol11 = MaySolDay11() 16 | let sol12 = MaySolDay12() 17 | let sol13 = MaySolDay13() 18 | 19 | // MARK: - Day 8: Check If It Is a Straight Line 20 | func testCheckStraightLine1() { 21 | let input = [[1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7]] 22 | XCTAssertTrue(sol8.checkStraightLine(input)) 23 | } 24 | 25 | func testCheckStraightLine2() { 26 | let input = [[1, 1], [2, 2], [3, 4], [4, 5], [5, 6], [7, 7]] 27 | XCTAssertFalse(sol8.checkStraightLine(input)) 28 | } 29 | 30 | func testCheckStraightLine3() { 31 | let input = [[-3, -2], [-1, -2], [2, -2], [-2, -2], [0, -2]] 32 | XCTAssertTrue(sol8.checkStraightLine(input)) 33 | } 34 | 35 | // MARK: - Day 9: Valid Perfect Square 36 | func testIsPerfectSquare1() { 37 | let input = 16 38 | XCTAssertTrue(sol9.isPerfectSquare(input)) 39 | } 40 | 41 | func testIsPerfectSquare2() { 42 | let input = 7 43 | XCTAssertFalse(sol9.isPerfectSquare(input)) 44 | } 45 | 46 | func testIsPerfectSquare3() { 47 | let input = 100 48 | XCTAssertTrue(sol9.isPerfectSquare(input)) 49 | } 50 | 51 | // MARK: - Day 10: Find the Town Judge 52 | func testFindJudge1() { 53 | let input = (N: 2, trust: [[1, 2]]) 54 | XCTAssertEqual(2, sol10.findJudge(input.N, input.trust)) 55 | } 56 | 57 | func testFindJudge2() { 58 | let input = (N: 3, trust: [[1, 3], [2, 3]]) 59 | XCTAssertEqual(3, sol10.findJudge(input.N, input.trust)) 60 | } 61 | 62 | func testFindJudge3() { 63 | let input = (N: 3, trust: [[1, 3], [2, 3], [3, 1]]) 64 | XCTAssertEqual(-1, sol10.findJudge(input.N, input.trust)) 65 | } 66 | 67 | func testFindJudge4() { 68 | let input = (N: 3, trust: [[1, 2], [2, 3]]) 69 | XCTAssertEqual(-1, sol10.findJudge(input.N, input.trust)) 70 | } 71 | 72 | func testFindJudge5() { 73 | let input = (N: 4, trust: [[1, 3], [1, 4], [2, 3], [2, 4], [4, 3]]) 74 | XCTAssertEqual(3, sol10.findJudge(input.N, input.trust)) 75 | } 76 | 77 | // MARK: - Day 11: Flood Fill 78 | func testFloodFill1() { 79 | let input = (image: [[1, 1, 1], [1, 1, 0], [1, 0, 1]], sr: 1, sc: 1, newColor: 2) 80 | let expected = [[2, 2, 2], [2, 2, 0], [2, 0,1 ]] 81 | XCTAssertEqual(expected, sol11.floodFill(input.image, input.sr, input.sc, input.newColor)) 82 | } 83 | 84 | func testFloodFill2() { 85 | let input = (image: [[0,0,0],[0,0,0]], sr: 0, sc: 0, newColor: 2) 86 | let expected = [[2, 2, 2], [2, 2, 2]] 87 | XCTAssertEqual(expected, sol11.floodFill(input.image, input.sr, input.sc, input.newColor)) 88 | } 89 | 90 | // MARK: - Day 12: Single Element in a Sorted Array 91 | func testSingleNonDuplicate1() { 92 | let input = [1, 1, 2, 3, 3, 4, 4, 8, 8] 93 | let expected = 2 94 | XCTAssertEqual(expected, sol12.singleNonDuplicate(input)) 95 | } 96 | 97 | func testSingleNonDuplicate2() { 98 | let input = [3, 3, 7, 7, 10, 11, 11] 99 | let expected = 10 100 | XCTAssertEqual(expected, sol12.singleNonDuplicate(input)) 101 | } 102 | 103 | // MARK: - Day 13: Remove K Digits 104 | func testRemoveKDigits1() { 105 | let input = (num: "1432219", k: 3) 106 | let expected = "1219" 107 | XCTAssertEqual(expected, sol13.removeKdigits(input.num, input.k)) 108 | } 109 | 110 | func testRemoveKDigits2() { 111 | let input = (num: "10200", k: 1) 112 | let expected = "200" 113 | XCTAssertEqual(expected, sol13.removeKdigits(input.num, input.k)) 114 | } 115 | 116 | func testRemoveKDigits3() { 117 | let input = (num: "10", k: 2) 118 | let expected = "0" 119 | XCTAssertEqual(expected, sol13.removeKdigits(input.num, input.k)) 120 | } 121 | 122 | func testRemoveKDigits4() { 123 | let input = (num: "1234567890", k: 9) 124 | let expected = "0" 125 | XCTAssertEqual(expected, sol13.removeKdigits(input.num, input.k)) 126 | } 127 | 128 | // MARK: - Day 14: Implement Trie (Prefix Tree) 129 | func testTrie1() { 130 | let trie = MaySolDay14.Trie() 131 | 132 | trie.insert("apple") 133 | 134 | XCTAssertTrue(trie.search("apple")) 135 | XCTAssertFalse(trie.search("app")) 136 | 137 | XCTAssertTrue(trie.startsWith("apple")) 138 | XCTAssertTrue(trie.startsWith("app")) 139 | XCTAssertFalse(trie.startsWith("pp")) 140 | } 141 | 142 | func testTrie2() { 143 | let trie = MaySolDay14.Trie() 144 | 145 | trie.insert("app") 146 | trie.insert("apple") 147 | trie.insert("beer") 148 | trie.insert("add") 149 | trie.insert("jam") 150 | trie.insert("rental") 151 | 152 | XCTAssertFalse(trie.search("apps")) 153 | XCTAssertTrue(trie.search("app")) 154 | XCTAssertFalse(trie.search("apps")) 155 | XCTAssertFalse(trie.search("ad")) 156 | XCTAssertFalse(trie.search("applepie")) 157 | XCTAssertFalse(trie.search("jan")) 158 | XCTAssertFalse(trie.search("rent")) 159 | XCTAssertTrue(trie.search("beer")) 160 | XCTAssertTrue(trie.search("jam")) 161 | 162 | XCTAssertFalse(trie.startsWith("apps")) 163 | XCTAssertTrue(trie.startsWith("app")) 164 | XCTAssertTrue(trie.startsWith("ad")) 165 | XCTAssertFalse(trie.startsWith("applepie")) 166 | XCTAssertFalse(trie.startsWith("rest")) 167 | XCTAssertFalse(trie.startsWith("jan")) 168 | XCTAssertTrue(trie.startsWith("rent")) 169 | XCTAssertTrue(trie.startsWith("beer")) 170 | XCTAssertTrue(trie.startsWith("jam")) 171 | } 172 | 173 | func testPerformanceExample() throws { 174 | // This is an example of a performance test case. 175 | self.measure { 176 | // Put the code you want to measure the time of here. 177 | } 178 | } 179 | 180 | } 181 | -------------------------------------------------------------------------------- /LeetCodeChallenge/ChallengeTests/TestsMayWeek3.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TestsMayWeek3.swift 3 | // ChallengeTests 4 | // 5 | // Created by Michael Ho on 5/30/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class TestsMayWeek3: XCTestCase { 12 | let sol15 = MaySolDay15() 13 | let sol16 = MaySolDay16() 14 | let sol17 = MaySolDay17() 15 | let sol20 = MaySolDay20() 16 | let sol21 = MaySolDay21() 17 | 18 | // MARK: - Day 15: Maximum Sum Circular Subarray 19 | func testMaxSubarraySumCircular1() { 20 | let input = [1,-2,3,-2] 21 | let expected = 3 22 | XCTAssertEqual(expected, sol15.maxSubarraySumCircular(input)) 23 | } 24 | 25 | func testMaxSubarraySumCircular2() { 26 | let input = [5, -3, 5] 27 | let expected = 10 28 | XCTAssertEqual(expected, sol15.maxSubarraySumCircular(input)) 29 | } 30 | 31 | func testMaxSubarraySumCircular3() { 32 | let input = [3, -1, 2, -1] 33 | let expected = 4 34 | XCTAssertEqual(expected, sol15.maxSubarraySumCircular(input)) 35 | } 36 | 37 | func testMaxSubarraySumCircular4() { 38 | let input = [9, -4, -7, 9] 39 | let expected = 18 40 | XCTAssertEqual(expected, sol15.maxSubarraySumCircular(input)) 41 | } 42 | 43 | func testMaxSubarraySumCircular5() { 44 | let input = [2, -2, 2, 7, 8, 0] 45 | let expected = 19 46 | XCTAssertEqual(expected, sol15.maxSubarraySumCircular(input)) 47 | } 48 | 49 | // MARK: - Day 16: Odd Even Linked List 50 | func testOddEvenLinkedList1() { 51 | let input = [1, 2, 3, 4, 5].convertToLinkedList() 52 | let expected = [1, 3, 5, 2, 4].convertToLinkedList() 53 | XCTAssertTrue(sol16.oddEvenList(input)!.isEqualToLinkedList(expected)) 54 | } 55 | 56 | func testOddEvenLinkedList2() { 57 | let input = [2, 1, 3, 5, 6, 4, 7].convertToLinkedList() 58 | let expected = [2, 3, 6, 7, 1, 5, 4].convertToLinkedList() 59 | XCTAssertTrue(sol16.oddEvenList(input)!.isEqualToLinkedList(expected)) 60 | } 61 | 62 | // MARK: - Day 17: Find All Anagrams in a String 63 | func testFindAllAnagramsInString1() { 64 | let input = (s: "cbaebabacd", p: "abc") 65 | let expected = [0, 6] 66 | XCTAssertEqual(expected, sol17.findAnagrams(input.s, input.p)) 67 | } 68 | 69 | func testFindAllAnagramsInString2() { 70 | let input = (s: "abab", p: "ab") 71 | let expected = [0, 1, 2] 72 | XCTAssertEqual(expected, sol17.findAnagrams(input.s, input.p)) 73 | } 74 | 75 | // MARK: - Day 18: Permutation in String 76 | 77 | // MARK: - Day 19: Online Stock Span 78 | func testOnlineStockSpan1() { 79 | let stockSpanner = MaySolDay19.StockSpanner() 80 | XCTAssertEqual(1, stockSpanner.next(100)) 81 | XCTAssertEqual(1, stockSpanner.next(80)) 82 | XCTAssertEqual(1, stockSpanner.next(60)) 83 | XCTAssertEqual(2, stockSpanner.next(70)) 84 | XCTAssertEqual(1, stockSpanner.next(60)) 85 | XCTAssertEqual(4, stockSpanner.next(75)) 86 | XCTAssertEqual(6, stockSpanner.next(85)) 87 | } 88 | 89 | // MARK: - Day 20: Kth Smallest Element in a BST 90 | func testKthSmallest1() { 91 | let input = ( 92 | tree: [ 93 | 3, 94 | 1, 4, 95 | nil, 2, nil, nil 96 | ].convertToBinaryTree(), 97 | k: 1 98 | ) 99 | let expected = 1 100 | XCTAssertEqual(expected, sol20.kthSmallest(input.tree, input.k)) 101 | } 102 | 103 | func testKthSmallest2() { 104 | let input = ( 105 | tree: [ 106 | 5, 107 | 3, 6, 108 | 2, 4, nil, nil, 109 | 1, nil, nil, nil, nil, nil, nil, nil 110 | ].convertToBinaryTree(), 111 | k: 3 112 | ) 113 | let expected = 3 114 | XCTAssertEqual(expected, sol20.kthSmallest(input.tree, input.k)) 115 | } 116 | 117 | // MARK: - Day 21: Count Square Submatrices with All Ones 118 | func testCountSquares1() { 119 | let input = [ 120 | [0, 1, 1, 1], 121 | [1, 1, 1, 1], 122 | [0, 1, 1, 1] 123 | ] 124 | let expected = 15 125 | XCTAssertEqual(expected, sol21.countSquares(input)) 126 | } 127 | 128 | func testCountSquares2() { 129 | let input = [ 130 | [1, 0, 1], 131 | [1, 1, 0], 132 | [1, 1, 0] 133 | ] 134 | let expected = 7 135 | XCTAssertEqual(expected, sol21.countSquares(input)) 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /LeetCodeChallenge/ChallengeTests/TestsMayWeek4.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TestsMayWeek4.swift 3 | // ChallengeTests 4 | // 5 | // Created by Michael Ho on 5/31/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class TestsMayWeek4: XCTestCase { 12 | let sol22 = MaySolDay22() 13 | let sol23 = MaySolDay23() 14 | let sol24 = MaySolDay24() 15 | let sol25 = MaySolDay25() 16 | let sol26 = MaySolDay26() 17 | let sol27 = MaySolDay27() 18 | let sol28 = MaySolDay28() 19 | 20 | // MARK: - Day 22: Sort Characters By Frequency 21 | func testFrequencySort1() { 22 | let input = "tree" 23 | let expected1 = "eetr" 24 | let expected2 = "eert" 25 | let output = sol22.frequencySort(input) 26 | XCTAssertTrue(output == expected1 || output == expected2) 27 | } 28 | 29 | func testFrequencySort2() { 30 | let input = "cccaaa" 31 | let expected1 = "aaaccc" 32 | let expected2 = "cccaaa" 33 | let output = sol22.frequencySort(input) 34 | XCTAssertTrue(output == expected1 || output == expected2) 35 | } 36 | 37 | func testFrequencySort3() { 38 | let input = "Aabb" 39 | let expected1 = "bbAa" 40 | let expected2 = "bbaA" 41 | let output = sol22.frequencySort(input) 42 | XCTAssertTrue(output == expected1 || output == expected2) 43 | } 44 | 45 | // MARK: - Day 23: Interval List Intersections 46 | func testIntervalIntersection1() { 47 | let input = (A: [[0, 2],[5, 10], [13, 23], [24, 25]], B: [[1, 5], [8, 12], [15, 24], [25, 26]]) 48 | let expected = [[1, 2], [5, 5], [8, 10], [15, 23], [24, 24], [25, 25]] 49 | XCTAssertEqual(expected, sol23.intervalIntersection(input.A, input.B)) 50 | } 51 | 52 | func testIntervalIntersection2() { 53 | let input = (A: [[4, 6], [7, 8], [10, 17]], B: [[5, 10]]) 54 | let expected = [[5, 6], [7, 8], [10, 10]] 55 | XCTAssertEqual(expected, sol23.intervalIntersection(input.A, input.B)) 56 | } 57 | 58 | func testIntervalIntersection3() { 59 | let input = (A: [[1, 3], [5, 9]], B: [[Int]]()) 60 | let expected = [[Int]]() 61 | XCTAssertEqual(expected, sol23.intervalIntersection(input.A, input.B)) 62 | } 63 | 64 | // MARK: - Day 24: Construct Binary Search Tree from Preorder Traversal 65 | func testConstructBSTFromPreorderTraversal1() { 66 | let input = [8, 5, 1, 7, 10, 12] 67 | /** 68 | Tree structure 69 | 8 70 | / \ 71 | 5 10 72 | / \ \ 73 | 1 7 12 74 | */ 75 | let expected = [ 76 | 8, 77 | 5, 10, 78 | 1, 7, nil, 12 79 | ].convertToBinaryTree() 80 | 81 | let output = BinarySearchTree(root: sol24.bstFromPreorder(input)) 82 | XCTAssertTrue(output.isEqualToOtherTree(expected)) 83 | } 84 | 85 | func testConstructBSTFromPreorderTraversal2() { 86 | let input = [9, 5, 3, 8, 10, 15, 13, 19, 25] 87 | /** 88 | Tree structure 89 | 9 90 | / \ 91 | 5 10 92 | / \ \ 93 | 3 8 15 94 | / \ 95 | 13 19 96 | \ 97 | 25 98 | */ 99 | let expected = [ 100 | 9, 101 | 5, 10, 102 | 3, 8, nil, 15, 103 | nil, nil, nil, nil, nil, nil, 13, 19, 104 | nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 25 105 | ].convertToBinaryTree() 106 | 107 | let output = BinarySearchTree(root: sol24.bstFromPreorder(input)) 108 | XCTAssertTrue(output.isEqualToOtherTree(expected)) 109 | } 110 | 111 | // MARK: - Day 25: Uncrossed Lines 112 | func testMaxUncrossedLines1() { 113 | let input = (A: [1, 4, 2], B: [1, 2, 4]) 114 | let expected = 2 115 | XCTAssertEqual(expected, sol25.maxUncrossedLines(input.A, input.B)) 116 | } 117 | 118 | func testMaxUncrossedLines2() { 119 | let input = (A: [2, 5, 1, 2, 5], B: [10, 5, 2, 1, 5, 2]) 120 | let expected = 3 121 | XCTAssertEqual(expected, sol25.maxUncrossedLines(input.A, input.B)) 122 | } 123 | 124 | func testMaxUncrossedLines3() { 125 | let input = (A: [1, 3, 7, 1, 7, 5], B: [1, 9, 2, 5, 1]) 126 | let expected = 2 127 | XCTAssertEqual(expected, sol25.maxUncrossedLines(input.A, input.B)) 128 | } 129 | 130 | // MARK: - Day 26: Contiguous Array 131 | func testContiguousArray1() { 132 | let input = [0, 1] 133 | let expected = 2 134 | XCTAssertEqual(expected, sol26.findMaxLength(input)) 135 | } 136 | 137 | func testContiguousArray2() { 138 | let input = [0, 1, 0] 139 | let expected = 2 140 | XCTAssertEqual(expected, sol26.findMaxLength(input)) 141 | } 142 | 143 | func testContiguousArray3() { 144 | let input = [0, 1, 0, 0, 1, 0, 1, 1, 0, 0] 145 | let expected = 8 146 | XCTAssertEqual(expected, sol26.findMaxLength(input)) 147 | } 148 | 149 | func testContiguousArray4() { 150 | let input = [0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0] 151 | let expected = 12 152 | XCTAssertEqual(expected, sol26.findMaxLength(input)) 153 | } 154 | 155 | // MARK: - Day 27: Possible Bipartition 156 | func testPossibleBipartition1() { 157 | let input = (N: 4, dislikes: [[1, 2], [1, 3], [2, 4]]) 158 | XCTAssertTrue(sol27.possibleBipartition(input.N, input.dislikes)) 159 | } 160 | 161 | func testPossibleBipartition2() { 162 | let input = (N: 3, dislikes: [[1, 2], [1, 3], [2, 3]]) 163 | XCTAssertFalse(sol27.possibleBipartition(input.N, input.dislikes)) 164 | } 165 | 166 | func testPossibleBipartition3() { 167 | let input = (N: 5, dislikes: [[1, 2], [2, 3], [3, 4], [4, 5], [1, 5]]) 168 | XCTAssertFalse(sol27.possibleBipartition(input.N, input.dislikes)) 169 | } 170 | 171 | // MARK: - Day 28: Counting Bits 172 | func testCountingBits1() { 173 | let input = 2 174 | let expected = [0, 1, 1] 175 | XCTAssertEqual(expected, sol28.countBits(input)) 176 | } 177 | 178 | func testCountingBits2() { 179 | let input = 5 180 | let expected = [0, 1, 1, 2, 1, 2] 181 | XCTAssertEqual(expected, sol28.countBits(input)) 182 | } 183 | } 184 | 185 | -------------------------------------------------------------------------------- /LeetCodeChallenge/ChallengeTests/TestsMayWeek5.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TestsMayWeek5.swift 3 | // ChallengeTests 4 | // 5 | // Created by Michael Ho on 6/3/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class TestsMayWeek5: XCTestCase { 12 | let sol29 = MaySolDay29() 13 | let sol30 = MaySolDay30() 14 | let sol31 = MaySolDay31() 15 | 16 | // MARK: - Day 29: Course Schedule 17 | func testCourseSchedule1() { 18 | let input = (numCourses: 2, prerequisites: [[1, 0]]) 19 | XCTAssertTrue(sol29.canFinish(input.numCourses, input.prerequisites)) 20 | } 21 | 22 | func testCourseSchedule2() { 23 | let input = (numCourses: 2, prerequisites: [[1, 0], [0, 1]]) 24 | XCTAssertFalse(sol29.canFinish(input.numCourses, input.prerequisites)) 25 | } 26 | 27 | func testCourseSchedule3() { 28 | let input = (numCourses: 8, prerequisites: [[1, 0], [2, 6], [1, 7], [6, 4], [7, 0], [0, 5], [7, 6]]) 29 | XCTAssertTrue(sol29.canFinish(input.numCourses, input.prerequisites)) 30 | } 31 | 32 | func testCourseSchedule4() { 33 | let input = (numCourses: 4, prerequisites: [[1, 0], [2, 0], [3, 1], [3, 2], [1, 3]]) 34 | XCTAssertFalse(sol29.canFinish(input.numCourses, input.prerequisites)) 35 | } 36 | 37 | // MARK: - Day 30: K Closest Points to Origin 38 | func testKClosest1() { 39 | let input = (points: [[1, 3], [-2, 2]], K: 1) 40 | let expected = [[-2, 2]] 41 | XCTAssertEqual(expected, sol30.kClosest(input.points, input.K)) 42 | } 43 | 44 | func testKClosest2() { 45 | let input = (points: [[3, 3], [5, -1], [-2, 4]], K: 2) 46 | let expected = [[3, 3], [-2, 4]] 47 | XCTAssertEqual(expected, sol30.kClosest(input.points, input.K)) 48 | } 49 | 50 | // MARK: - Day 31: Edit Distance 51 | func testEditDistance1() { 52 | let input = (word1: "horse", word2: "ros") 53 | let expected = 3 54 | XCTAssertEqual(expected, sol31.minDistance(input.word1, input.word2)) 55 | } 56 | 57 | func testEditDistance2() { 58 | let input = (word1: "intention", word2: "execution") 59 | let expected = 5 60 | XCTAssertEqual(expected, sol31.minDistance(input.word1, input.word2)) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge.xcodeproj/xcshareddata/xcschemes/LeetCodeChallenge.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 53 | 55 | 61 | 62 | 63 | 64 | 70 | 72 | 78 | 79 | 80 | 81 | 83 | 84 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/AprilWeek1/AprilSolDay1.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AprilSolDay1.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 4/14/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/single-number/ 10 | class AprilSolDay1 { 11 | 12 | func singleNumber(_ nums: [Int]) -> Int { 13 | var dict = [Int:Bool]() 14 | for num in nums { 15 | if (dict[num] != nil) { 16 | dict[num] = false 17 | } else { 18 | dict[num] = true 19 | } 20 | } 21 | 22 | for key in dict.keys { 23 | if (dict[key] != false) { 24 | return key 25 | } 26 | } 27 | 28 | return -1 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/AprilWeek1/AprilSolDay2.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AprilSolDay2.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 4/14/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/happy-number/ 10 | class AprilSolDay2 { 11 | 12 | func isHappy(_ n: Int) -> Bool { 13 | var set = Set() 14 | var current = n 15 | while current > 0, !set.contains(current) { 16 | current = operateHappyNum(current, &set) 17 | } 18 | return current == 1 19 | } 20 | 21 | func operateHappyNum(_ num: Int, _ set: inout Set) -> Int { 22 | var num = num 23 | while (num % 10 == 0) { 24 | num = num / 10 25 | } 26 | set.insert(num) 27 | 28 | var sum = 0 29 | while (num > 0) { 30 | let last = num % 10 31 | sum += last * last 32 | num = num / 10 33 | } 34 | return sum 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/AprilWeek1/AprilSolDay3.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AprilSolDay3.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 4/14/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/maximum-subarray/ 10 | class AprilSolDay3 { 11 | 12 | func maxSubArray(_ nums: [Int]) -> Int { 13 | guard nums.count > 0 else { return 0 } 14 | 15 | if nums.count == 1 { 16 | return nums[0] 17 | } 18 | 19 | var localMax = nums[0] 20 | var result = localMax 21 | for idx in 1...nums.count - 1 { 22 | localMax = max(nums[idx] + localMax, nums[idx]) 23 | result = max(localMax, result) 24 | } 25 | return result 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/AprilWeek1/AprilSolDay4.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AprilSolDay4.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 4/14/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/move-zeroes/ 10 | class AprilSolDay4 { 11 | 12 | func moveZeroes(_ nums: inout [Int]) { 13 | var idx = 0 14 | var count = 0 15 | while idx < nums.count, count < nums.count { 16 | if nums[idx] == 0 { 17 | nums.remove(at: idx) 18 | nums.append(0) 19 | } else { 20 | idx += 1 21 | } 22 | count += 1 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/AprilWeek1/AprilSolDay5.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AprilSolDay5.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 4/14/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/ 10 | class AprilSolDay5 { 11 | 12 | func maxProfit(_ prices: [Int]) -> Int { 13 | guard prices.count > 1 else { return 0 } 14 | 15 | var preVal = prices[0] 16 | var val = 0 17 | for idx in 1...prices.count-1 { 18 | if prices[idx] > preVal { 19 | val += prices[idx] - preVal 20 | } 21 | preVal = prices[idx] 22 | } 23 | return val 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/AprilWeek1/AprilSolDay6.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AprilSolDay6.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 4/14/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // https://leetcode.com/problems/group-anagrams/ 10 | class AprilSolDay6 { 11 | 12 | func groupAnagrams(_ strs: [String]) -> [[String]] { 13 | var dict = [String:[String]]() 14 | for str in strs { 15 | let key = String(str.sorted()) 16 | if dict[key] != nil { 17 | dict[key]!.append(str) 18 | } else { 19 | dict[key] = [str] 20 | } 21 | } 22 | var output = [[String]]() 23 | for key in dict.keys { 24 | output.append(dict[key]!) 25 | } 26 | return output 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/AprilWeek1/AprilSolDay7.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AprilSolDay7.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 4/14/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/explore/featured/card/30-day-leetcoding-challenge/528/week-1/3289/ 10 | class AprilSolDay7 { 11 | 12 | func countElements(_ arr: [Int]) -> Int { 13 | let set = Set(arr) 14 | var output = 0 15 | for num in arr { 16 | if set.contains(num + 1) { 17 | output += 1 18 | } 19 | } 20 | return output 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/AprilWeek2/AprilSolDay10.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AprilSolDay10.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 4/15/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/min-stack/ 10 | class AprilSolDay10 { 11 | 12 | class MinStack: MinStackProtocol { 13 | var stack: [Node] 14 | 15 | /** initialize your data structure here. */ 16 | init() { 17 | stack = [Node]() 18 | } 19 | 20 | func push(_ x: Int) { 21 | stack.append(Node(x, min(x, getMin()))) 22 | } 23 | 24 | func pop() { 25 | stack.removeLast() 26 | } 27 | 28 | func top() -> Int { 29 | guard let last = stack.last else { return -1 } 30 | return last.val 31 | } 32 | 33 | func getMin() -> Int { 34 | guard let last = stack.last else { return Int.max } 35 | return last.minVal 36 | } 37 | } 38 | 39 | class Node { 40 | var val: Int 41 | var minVal: Int 42 | 43 | init(_ value: Int, _ minVal: Int) { 44 | self.val = value 45 | self.minVal = minVal 46 | } 47 | } 48 | } 49 | 50 | protocol MinStackProtocol { 51 | // Push element x onto stack. 52 | func push(_ x: Int) 53 | // Removes the element on top of the stack. 54 | func pop() 55 | // Get the top element. 56 | func top() -> Int 57 | // Retrieve the minimum element in the stack. 58 | func getMin() -> Int 59 | } 60 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/AprilWeek2/AprilSolDay11.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AprilSolDay11.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 4/15/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/diameter-of-binary-tree/ 10 | class AprilSolDay11 { 11 | 12 | func diameterOfBinaryTree(_ root: TreeNode?) -> Int { 13 | guard let root = root else { return 0 } 14 | 15 | var output = 0 16 | let _ = calculateLocalMaxLength(root, &output) 17 | return output - 1 18 | } 19 | /** 20 | This function solves the problem of calculating the longest one-way 21 | length that associated with a tree node. Let's define a leg as the 22 | one-way path that does not pass the root. 23 | 24 | - Parameter root: The root node to start with. 25 | - Parameter output: The output tracks the longest path in the entire tree. 26 | */ 27 | func calculateLocalMaxLength(_ root: TreeNode?, _ output: inout Int) -> Int { 28 | guard let root = root else { return 0 } 29 | 30 | // A local longest path is calculcated by adding up its longest left and right legs. 31 | let left = calculateLocalMaxLength(root.left, &output) 32 | let right = calculateLocalMaxLength(root.right, &output) 33 | let localLongestPath = left + right + 1 34 | 35 | // This helps obtain the longest path of the tree by comparing each caculation. 36 | output = max(output, localLongestPath) 37 | 38 | // A leg is caclulated by adding itself to its longer leg. 39 | // Note: The leg is defined to not pass its root node. 40 | return 1 + max(left, right) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/AprilWeek2/AprilSolDay12.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AprilSolDay12.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 4/15/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/last-stone-weight/ 10 | class AprilSolDay12 { 11 | /* 12 | Note: 13 | 14 | 1. 1 <= stones.length <= 30 15 | 2. 1 <= stones[i] <= 1000 16 | */ 17 | func lastStoneWeight(_ stones: [Int]) -> Int { 18 | var sorted = stones.sorted() 19 | 20 | while sorted.count > 1 { 21 | let last1 = sorted.removeLast() 22 | let last2 = sorted.removeLast() 23 | 24 | if last1 != last2 { 25 | sorted.append(last1 - last2) 26 | sorted.sort() 27 | } 28 | } 29 | 30 | return sorted.count > 0 ? sorted[0] : 0 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/AprilWeek2/AprilSolDay13.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AprilSolDay13.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 4/15/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/contiguous-array/ 10 | class AprilSolDay13 { 11 | 12 | func findMaxLength(_ nums: [Int]) -> Int { 13 | /** 14 | The count before we enter the array is 0. The index 15 | before we enter the array is noted as -1. 16 | */ 17 | var dict = [0 : -1] // [count:index] 18 | var count = 0 19 | 20 | // The maximum length (longest) is set to 0 initially. 21 | var maxLength = 0 22 | for idx in 0.. String { 22 | var totalShift = 0 23 | for move in shift { 24 | if move[0] == 0 { 25 | totalShift -= move[1] 26 | } else if move[0] == 1 { 27 | totalShift += move[1] 28 | } 29 | } 30 | var output = Array(s) 31 | totalShift = totalShift%s.count 32 | if totalShift > 0 { 33 | output = Array(output[output.count - totalShift.. SinglyListNode? { 13 | guard head != nil else { return nil } 14 | 15 | var slowNode: SinglyListNode? = head 16 | var fastNode: SinglyListNode? = head 17 | 18 | while fastNode?.next != nil { 19 | slowNode = slowNode?.next 20 | fastNode = fastNode?.next?.next 21 | } 22 | 23 | return slowNode 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/AprilWeek2/AprilSolDay9.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AprilSolDay9.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 4/15/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/backspace-string-compare/ 10 | class AprilSolDay9 { 11 | 12 | func backspaceCompare(_ S: String, _ T: String) -> Bool { 13 | return formatString(S) == formatString(T) 14 | } 15 | 16 | func formatString(_ s: String) -> String { 17 | let arr = Array(s) 18 | var output = "" 19 | var back = 0 20 | for idx in 0.. 0{ 26 | back -= 1 27 | } else { 28 | output += String(arr[lastIdx]) 29 | } 30 | } 31 | } 32 | return output 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/AprilWeek3/AprilSolDay15.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AprilSolDay15.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 4/20/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/product-of-array-except-self/ 10 | class AprilSolDay15 { 11 | 12 | func productExceptSelf(_ nums: [Int]) -> [Int] { 13 | var foundFirstZero = false 14 | var total = 1 15 | for num in nums { 16 | if !foundFirstZero && num == 0 { 17 | foundFirstZero = true 18 | } else { 19 | total = total * num 20 | } 21 | } 22 | 23 | var output = [Int]() 24 | if foundFirstZero && total == 0 { 25 | return Array(repeating: 0, count: nums.count) 26 | } 27 | 28 | for num in nums { 29 | if foundFirstZero { 30 | if num == 0 { 31 | output.append(total) 32 | } else { 33 | output.append(0) 34 | } 35 | } else { 36 | output.append(total/num) 37 | } 38 | } 39 | return output 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/AprilWeek3/AprilSolDay16.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AprilSolDay16.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 4/20/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/valid-parenthesis-string/ 10 | // Refer to LeiHao0: https://leetcode.com/problems/valid-parenthesis-string/discuss/582051/Swift-0ms-100-or-1line-94.44 11 | class AprilSolDay16 { 12 | 13 | func checkValidString(_ s: String) -> Bool { 14 | var stack = [Character]() 15 | for c in s { 16 | if c == "(" || c == "*" { 17 | stack.append(c) 18 | } else { 19 | if let idx = stack.lastIndex(of: "(") { 20 | stack.remove(at: idx) 21 | } else if let idx = stack.lastIndex(of: "*") { 22 | stack.remove(at: idx) 23 | } else { 24 | return false 25 | } 26 | } 27 | } 28 | 29 | // popLast() time complexity = O(1) 30 | while let last = stack.popLast() { 31 | if last == "(" { 32 | return false 33 | } else if let leftIdx = stack.lastIndex(of: "(") { 34 | stack.remove(at: leftIdx) 35 | } 36 | } 37 | return stack.isEmpty 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/AprilWeek3/AprilSolDay17.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AprilSolDay17.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 4/21/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/number-of-islands/ 10 | class AprilSolDay17 { 11 | 12 | func numIslands(_ grid: [[Character]]) -> Int { 13 | var count = 0 14 | var matrix = grid 15 | for x in 0..= 0, matrix[x][y - 1] == "1" { 38 | findAdjacentIslands(x, y - 1, &matrix) 39 | } 40 | 41 | if x - 1 >= 0, matrix[x - 1][y] == "1" { 42 | findAdjacentIslands(x - 1, y, &matrix) 43 | } 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/AprilWeek3/AprilSolDay18.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AprilSolDay18.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 4/21/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/minimum-path-sum/ 10 | class AprilSolDay18 { 11 | 12 | func minPathSum(_ grid: [[Int]]) -> Int { 13 | var matrix = grid 14 | 15 | for i in 0.. 0 && j > 0 { 18 | matrix[i][j] += min(matrix[i-1][j], matrix[i][j-1]) 19 | } else if i > 0 { 20 | matrix[i][j] += matrix[i-1][j] 21 | } else if j > 0 { 22 | matrix[i][j] += matrix[i][j-1] 23 | } 24 | } 25 | } 26 | 27 | return matrix[matrix.count - 1][matrix[0].count - 1] 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/AprilWeek3/AprilSolDay19.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AprilSolDay19.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 4/21/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/search-in-rotated-sorted-array/ 10 | // The solution's runtime complexity must be in the order of O(log n). 11 | class AprilSolDay19 { 12 | 13 | func search(_ nums: [Int], _ target: Int) -> Int { 14 | guard nums.count > 0 else { return -1 } 15 | 16 | var start = 0 17 | var end = nums.count - 1 18 | while start <= end { 19 | let mid = start + (end - start) / 2 20 | let midVal = nums[mid] 21 | 22 | if target == midVal { 23 | return mid 24 | } else if target == nums[start] { 25 | return start 26 | } else if target == nums[end] { 27 | return end 28 | } else if midVal > nums[start] { 29 | // If it falls into this condition, it means the first half of 30 | // the array is not rotated. Therefore, we can decide if the 31 | // target falls into the first half or not. 32 | if target < midVal, target > nums[start] { 33 | end = mid - 1 34 | } else { 35 | start = mid + 1 36 | } 37 | } else { 38 | // If it falls into this condition, it means the second half of 39 | // the array is not rotated. Therefore, we can decide if the 40 | // target falls into the second half or not. 41 | if target > midVal, target < nums[end] { 42 | start = mid + 1 43 | } else { 44 | end = mid - 1 45 | } 46 | } 47 | } 48 | 49 | return -1 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/AprilWeek3/AprilSolDay20.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AprilSolDay20.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 4/21/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/construct-binary-search-tree-from-preorder-traversal/ 10 | class AprilSolDay20 { 11 | 12 | func bstFromPreorder(_ preorder: [Int]) -> TreeNode? { 13 | guard preorder.count > 0 else { return nil } 14 | return bstFromPreorder(preorder, 0, preorder.count - 1) 15 | } 16 | 17 | private func bstFromPreorder(_ preorder: [Int], _ start: Int, _ end: Int) -> TreeNode? { 18 | let root = TreeNode(preorder[start]) 19 | 20 | if start + 1 <= end, preorder.count > 1 { 21 | var rightRootIdx = -1 22 | for idx in start+1...end { 23 | if preorder[idx] > preorder[start] { 24 | rightRootIdx = idx 25 | break 26 | } 27 | } 28 | 29 | if rightRootIdx == start + 1 { 30 | root.right = bstFromPreorder(preorder, rightRootIdx, end) 31 | } else if rightRootIdx == -1 { 32 | root.left = bstFromPreorder(preorder, start + 1, end) 33 | } else { 34 | root.right = bstFromPreorder(preorder, rightRootIdx, end) 35 | root.left = bstFromPreorder(preorder, start + 1, rightRootIdx - 1) 36 | } 37 | } 38 | return root 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/AprilWeek3/AprilSolDay21.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AprilSolDay21.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 4/21/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/explore/featured/card/30-day-leetcoding-challenge/530/week-3/3306/ 10 | class AprilSolDay21 { 11 | 12 | func leftMostColumnWithOne(_ binaryMatrix: BinaryMatrix) -> Int { 13 | let dim = binaryMatrix.dimensions() 14 | 15 | var x = 0 16 | var y = dim[1] - 1 17 | var currentLeftMost = -1 18 | while x < dim[0], y >= 0 { 19 | if y - 1 >= 0 && binaryMatrix.get(x, y - 1) == 1 { 20 | y -= 1 21 | currentLeftMost = y 22 | } else if x + 1 < dim[0] { 23 | x += 1 24 | } else { 25 | return binaryMatrix.get(x, y) == 1 ? y : currentLeftMost 26 | } 27 | } 28 | return -1 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/AprilWeek4/AprilSolDay22.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AprilSolDay22.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 4/27/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/subarray-sum-equals-k/ 10 | class AprilSolDay22 { 11 | 12 | func subarraySum(_ nums: [Int], _ k: Int) -> Int { 13 | var output = 0 14 | var dict = [0:1] // [sum:count] 15 | 16 | var sum = 0 17 | for num in nums { 18 | sum += num 19 | 20 | /** 21 | Let's define prevSum = sum - k 22 | If sum is larger than target k, try to find if sum - k has 23 | occurred in the iteration. If it has, retrieve the times when 24 | sum == prevSum. Since we can exclude those subarrays that have 25 | a sum of prevSum, the count of subarray has target k can be 26 | increased by the count of those subarrays. 27 | */ 28 | if let count = dict[sum - k] { 29 | output += count 30 | } 31 | 32 | dict[sum] = (dict[sum] ?? 0) + 1 33 | } 34 | 35 | return output 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/AprilWeek4/AprilSolDay23.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AprilSolDay23.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 4/27/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/bitwise-and-of-numbers-range/ 10 | // https://docs.swift.org/swift-book/LanguageGuide/AdvancedOperators.html 11 | class AprilSolDay23 { 12 | 13 | func rangeBitwiseAnd(_ m: Int, _ n: Int) -> Int { 14 | if m == 0 { 15 | return 0 16 | } 17 | 18 | var m = m 19 | var n = n 20 | var factor = 0 21 | 22 | while m != n { 23 | m >>= 1 24 | n >>= 1 25 | factor += 1 26 | } 27 | 28 | return m << factor 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/AprilWeek4/AprilSolDay24.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AprilSolDay24.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 4/27/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/lru-cache/ 10 | 11 | class AprilSolDay24 { 12 | 13 | class LRUCache { 14 | 15 | var capacity: Int 16 | var head: ListNode 17 | var tail: ListNode 18 | var dict: [Int:ListNode] 19 | 20 | init(_ capacity: Int) { 21 | self.capacity = capacity 22 | dict = [Int:ListNode]() 23 | 24 | head = ListNode(-1, -1) 25 | tail = ListNode(-1, -1) 26 | head.next = tail 27 | tail.prev = head 28 | } 29 | 30 | func get(_ key: Int) -> Int { 31 | if let node = dict[key] { 32 | remove(node) 33 | insertToHead(node) 34 | return node.val 35 | } 36 | return -1 37 | } 38 | 39 | func insertToHead(_ node: ListNode) { 40 | node.next = head.next 41 | head.next?.prev = node 42 | head.next = node 43 | node.prev = head 44 | } 45 | 46 | func remove(_ node: ListNode) { 47 | node.next?.prev = node.prev 48 | node.prev?.next = node.next 49 | } 50 | 51 | func put(_ key: Int, _ value: Int) { 52 | let node = ListNode(value, key) 53 | 54 | if dict[key] != nil { 55 | remove(dict[key]!) 56 | } else if dict.keys.count == capacity { 57 | if let lastNode = tail.prev { 58 | remove(lastNode) 59 | dict[lastNode.key] = nil 60 | } 61 | } 62 | 63 | dict[key] = node 64 | insertToHead(node) 65 | } 66 | } 67 | 68 | class ListNode { 69 | var val: Int 70 | var key: Int 71 | var next: ListNode? 72 | var prev: ListNode? 73 | 74 | init(_ val: Int, _ key: Int) { 75 | self.val = val 76 | self.key = key 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/AprilWeek4/AprilSolDay25.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AprilSolDay25.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 4/27/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/jump-game/ 10 | class AprilSolDay25 { 11 | 12 | func canJump(_ nums: [Int]) -> Bool { 13 | guard nums.count > 1 else { return true } 14 | 15 | var idx = 0 16 | var maxJump = 0 17 | while idx < nums.count { 18 | if idx > maxJump { 19 | return false 20 | } 21 | maxJump = max(maxJump, nums[idx] + idx) 22 | idx += 1 23 | } 24 | return true 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/AprilWeek4/AprilSolDay26.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AprilSolDay26.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 4/30/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/longest-common-subsequence/ 10 | class AprilSolDay26 { 11 | 12 | func longestCommonSubsequence(_ text1: String, _ text2: String) -> Int { 13 | guard text1.count > 0, text2.count > 0 else { return 0 } 14 | 15 | let arr1 = Array(text1) 16 | let arr2 = Array(text2) 17 | var dp = Array(repeating: Array(repeating: 0, count: arr2.count), count: arr1.count) 18 | for i in 0.. 0, j > 0 { 24 | dp[idx1][idx2] += dp[idx1 + 1][idx2 + 1] 25 | } 26 | dp[idx1][idx2] += 1 27 | } else { 28 | let accum1 = i > 0 ? dp[idx1 + 1][idx2] : 0 29 | let accum2 = j > 0 ? dp[idx1][idx2 + 1] : 0 30 | dp[idx1][idx2] += max(accum1, accum2) 31 | } 32 | } 33 | } 34 | return dp[0][0] 35 | } 36 | } 37 | 38 | // Recursive solution: easy to understand, exceeds the time limit though. 39 | class RescursiveSolution { 40 | 41 | func longestCommonSubsequence(_ text1: String, _ text2: String) -> Int { 42 | return longestCommonSubsequence(Array(text1), Array(text2), 0, 0) 43 | } 44 | 45 | func longestCommonSubsequence(_ arr1: [Character], _ arr2: [Character], _ idx1: Int, _ idx2: Int) -> Int { 46 | if idx1 >= arr1.count || idx2 >= arr2.count { 47 | return 0 48 | } 49 | 50 | if arr1[idx1] == arr2[idx2] { 51 | return 1 + longestCommonSubsequence(arr1, arr2, idx1 + 1, idx2 + 1) 52 | } else { 53 | return max(longestCommonSubsequence(arr1, arr2, idx1, idx2 + 1), longestCommonSubsequence(arr1, arr2, idx1 + 1, idx2)) 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/AprilWeek4/AprilSolDay27.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AprilSolDay27.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 4/30/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/maximal-square/ 10 | class AprilSolDay27 { 11 | 12 | func maximalSquare(_ matrix: [[Character]]) -> Int { 13 | guard matrix.count > 0, matrix[0].count > 0 else { return 0 } 14 | var dp = Array(repeating: Array(repeating: 0, count: matrix[0].count), count: matrix.count) 15 | var maxSideLength = 0 16 | for x in 0.. 0, y > 0 { 20 | dp[x][y] = min(dp[x - 1][y - 1], dp[x - 1][y], dp[x][y - 1] ) + 1 21 | } else { 22 | dp[x][y] = Int(String(matrix[x][y]))! 23 | } 24 | maxSideLength = max(maxSideLength, dp[x][y]) 25 | } 26 | } 27 | } 28 | return maxSideLength*maxSideLength 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/AprilWeek4/AprilSolDay28.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AprilSolDay28.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 4/30/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/explore/featured/card/30-day-leetcoding-challenge/531/week-4/3313/ 10 | class AprilSolDay28 { 11 | 12 | class FirstUnique: FirstUniqueProtocol { 13 | var dict: [Int:DoublyListNode] 14 | var head: DoublyListNode 15 | var tail: DoublyListNode 16 | 17 | required init(_ nums: [Int]) { 18 | dict = [Int:DoublyListNode]() 19 | 20 | head = DoublyListNode(-1) 21 | tail = DoublyListNode(-1) 22 | head.next = tail 23 | tail.prev = head 24 | 25 | for num in nums { 26 | add(num) 27 | } 28 | } 29 | 30 | func appendNode(_ node: DoublyListNode) { 31 | tail.prev?.next = node 32 | node.next = tail 33 | node.prev = tail.prev 34 | tail.prev = node 35 | } 36 | 37 | func removeNode(_ node: DoublyListNode) { 38 | node.next?.prev = node.prev 39 | node.prev?.next = node.next 40 | } 41 | 42 | func showFirstUnique() -> Int { 43 | if let node = head.next { 44 | return node.val 45 | } 46 | return -1 47 | } 48 | 49 | func add(_ value: Int) { 50 | if dict[value] != nil { 51 | removeNode(dict[value]!) 52 | dict[value] = DoublyListNode(-1) 53 | } else { 54 | let newNode = DoublyListNode(value) 55 | appendNode(newNode) 56 | dict[value] = newNode 57 | } 58 | } 59 | } 60 | } 61 | 62 | protocol FirstUniqueProtocol { 63 | // Initializes the object with the numbers in the queue 64 | init(_ nums: [Int]) 65 | // Returns the value of the first unique integer of the queue, and 66 | // returns -1 if there is no such integer. 67 | func showFirstUnique() -> Int 68 | // Insert the value to the queue. 69 | func add(_ val: Int) 70 | } 71 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/AprilWeek5/SolutionDay29.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AprilSolDay29.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 5/1/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/binary-tree-maximum-path-sum/ 10 | /** 11 | Subproblems: 12 | 13 | 1. How to calculate a one-way path that has the largest value? 14 | Let's define a leg as the one-way path that does not pass the 15 | local root, which is the starting nodepassed to the recursion. 16 | 17 | 2. How to find the local max-value path of a node? 18 | It consists of up to two non-overlapping legs since it may or may 19 | not pass the root. That said, legs that share the same root may not 20 | be included simultaneously. 21 | 22 | 3. How to find the max-value path of the entire tree? 23 | It will be obtained by comparing the local max-value paths. 24 | */ 25 | class AprilSolDay29 { 26 | 27 | func maxPathSum(_ root: TreeNode?) -> Int { 28 | guard let root = root else { return 0 } 29 | 30 | var output = Int.min 31 | let _ = getSum(root, &output) 32 | return output 33 | } 34 | 35 | private func getSum(_ root: TreeNode?, _ output: inout Int) -> Int { 36 | guard let root = root else { return 0 } 37 | 38 | var leftSum = 0 39 | var rightSum = 0 40 | if let left = root.left { 41 | leftSum = getSum(left, &output) 42 | } 43 | 44 | if let right = root.right { 45 | rightSum = getSum(right, &output) 46 | } 47 | 48 | let largestLegValue = max(root.val + leftSum, root.val + rightSum, root.val) 49 | 50 | /** 51 | This comparison is trying to find the local maximum value staring from 52 | the local root node. 53 | */ 54 | let localMaxValue = max(root.val + rightSum + leftSum, largestLegValue) 55 | 56 | /** 57 | The comparison here is trying to get the final output, which is the 58 | max-value path of the entire tree. 59 | */ 60 | output = max(output, localMaxValue) 61 | 62 | /** 63 | The return value here is the leg value, aka the one-way path that has the largest 64 | value. Because there might be negative values in the legs, we have to first decide 65 | if we want to include a leg value. If we do, we want to take the leg with larger value. 66 | */ 67 | return largestLegValue 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/AprilWeek5/SolutionDay30.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AprilSolDay30.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 5/1/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | 10 | // Original link is blocked. Refer to other developer's blog. 11 | // https://thefellowprogrammer.blogspot.com/2020/04/check-if-string-is-valid-sequence-from.html 12 | class AprilSolDay30 { 13 | 14 | func isValidSequence(_ root: TreeNode?, _ arr: [Int]) -> Bool { 15 | var current = [Int]() 16 | return isValidSequence(root, ¤t, arr) 17 | } 18 | 19 | private func isValidSequence(_ root: TreeNode?, _ current: inout [Int], _ target: [Int]) -> Bool { 20 | guard let root = root else { 21 | return false 22 | } 23 | 24 | current.append(root.val) 25 | if let left = root.left, let right = root.right { 26 | return isValidSequence(left, ¤t, target) || isValidSequence(right, ¤t, target) 27 | } else if let left = root.left { 28 | return isValidSequence(left, ¤t, target) 29 | } else if let right = root.right { 30 | return isValidSequence(right, ¤t, target) 31 | } else { 32 | return current == target 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/MayWeek1/MaySolDay1.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MaySolDay1.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 5/3/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/first-bad-version/ 10 | class MaySolDay1 { 11 | private var badVersion = 0 12 | 13 | func firstBadVersion(_ n: Int) -> Int { 14 | if n == 1 { 15 | return isBadVersion(n) ? 1 : -1 16 | } 17 | var start = 1 18 | var end = n 19 | while start < end { 20 | let mid = (start + end) / 2 21 | if end == start + 1 { 22 | return isBadVersion(start) ? start : end 23 | } 24 | if isBadVersion(mid) { 25 | end = mid 26 | } else { 27 | start = mid 28 | } 29 | } 30 | return -1 31 | } 32 | 33 | func setBadVersion(_ version: Int) { 34 | self.badVersion = version 35 | } 36 | 37 | private func isBadVersion(_ version: Int) -> Bool { 38 | return version == self.badVersion 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/MayWeek1/MaySolDay2.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MaySolDay2.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 5/3/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/jewels-and-stones/ 10 | class MaySolDay2 { 11 | 12 | func numJewelsInStones(_ J: String, _ S: String) -> Int { 13 | var set = Set() 14 | for ch in J { 15 | set.insert(ch) 16 | } 17 | 18 | var output = 0 19 | for ch in S { 20 | if set.contains(ch) { 21 | output += 1 22 | } 23 | } 24 | 25 | return output 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/MayWeek1/MaySolDay3.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MaySolDay3.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 5/7/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/ransom-note/ 10 | class MaySolDay3 { 11 | 12 | func canConstruct(_ ransomNote: String, _ magazine: String) -> Bool { 13 | var dict = [Character:Int]() 14 | for ch in magazine { 15 | if dict[ch] == nil { 16 | dict[ch] = 1 17 | } else { 18 | dict[ch]! += 1 19 | } 20 | } 21 | 22 | for ch in ransomNote { 23 | if dict[ch] == nil { 24 | return false 25 | } else { 26 | dict[ch]! -= 1 27 | if dict[ch]! == 0 { 28 | dict[ch] = nil 29 | } 30 | } 31 | } 32 | 33 | return true 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/MayWeek1/MaySolDay4.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MaySolDay4.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 5/7/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/number-complement/ 10 | class MaySolDay4 { 11 | 12 | func findComplement(_ num: Int) -> Int { 13 | var i = 1 14 | 15 | while i <= num { 16 | i <<= 1 17 | } 18 | 19 | return (i - 1) ^ num 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/MayWeek1/MaySolDay5.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MaySolDay5.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 5/7/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/first-unique-character-in-a-string/ 10 | class MaySolDay5 { 11 | 12 | func firstUniqChar(_ s: String) -> Int { 13 | var dict = [Character : DoublyListNode]() 14 | let head = DoublyListNode(-1) 15 | let tail = DoublyListNode(-1) 16 | head.next = tail 17 | tail.prev = head 18 | 19 | for (idx, ch) in s.enumerated() { 20 | if dict[ch] == nil { 21 | let node = DoublyListNode(idx) 22 | dict[ch] = node 23 | appendNode(tail, node) 24 | } else if dict[ch]!.val == -1 { 25 | continue 26 | } else { 27 | removeNode(dict[ch]!) 28 | } 29 | } 30 | 31 | return head.next!.val == -1 ? -1 : head.next!.val 32 | } 33 | 34 | private func appendNode(_ tail: DoublyListNode, _ node: DoublyListNode) { 35 | tail.prev?.next = node 36 | node.prev = tail.prev 37 | tail.prev = node 38 | node.next = tail 39 | } 40 | 41 | private func removeNode(_ node: DoublyListNode) { 42 | node.prev?.next = node.next 43 | node.next?.prev = node.prev 44 | node.prev = nil 45 | node.next = nil 46 | node.val = -1 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/MayWeek1/MaySolDay6.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MaySolDay6.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 5/11/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/majority-element/ 10 | class MaySolDay6 { 11 | 12 | func majorityElement(_ nums: [Int]) -> Int { 13 | var dict = [Int:Int]() 14 | 15 | for num in nums { 16 | if dict[num] == nil { 17 | dict[num] = 1 18 | } else { 19 | dict[num]! += 1 20 | } 21 | 22 | if dict[num]! > nums.count/2 { 23 | return num 24 | } 25 | } 26 | 27 | return -1 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/MayWeek1/MaySolDay7.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MaySolDay7.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 5/11/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/cousins-in-binary-tree/ 10 | class MaySolDay7 { 11 | 12 | func isCousins(_ root: TreeNode?, _ x: Int, _ y: Int) -> Bool { 13 | guard let root = root else { return false } 14 | 15 | var setArr = [Set]() 16 | return findCousins(root, 0, x, y, &setArr) 17 | } 18 | 19 | private func findCousins(_ root: TreeNode?, _ level: Int, _ x: Int, _ y: Int, _ setArr: inout [Set]) -> Bool { 20 | guard let root = root else { return false } 21 | 22 | if level >= setArr.count { 23 | let set = Set([root.val]) 24 | setArr.append(set) 25 | } else { 26 | setArr[level].insert(root.val) 27 | } 28 | 29 | if (root.left?.val == x && root.right?.val == y) || 30 | (root.left?.val == y && root.right?.val == x) { 31 | return false 32 | } else if setArr[level].contains(x), setArr[level].contains(y) { 33 | print("b") 34 | return true 35 | } else { 36 | return findCousins(root.left, level + 1, x, y, &setArr) || findCousins(root.right, level + 1, x, y, &setArr) 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/MayWeek2/MaySolDay10.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MaySolDay10.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 5/21/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/find-the-town-judge/ 10 | class MaySolDay10 { 11 | 12 | func findJudge(_ N: Int, _ trust: [[Int]]) -> Int { 13 | if N == 1, trust.count == 0 { 14 | return 1 15 | } 16 | 17 | var dict = [Int:Set]() 18 | var nojudges = Set() 19 | var judge = -1 20 | for arr in trust { 21 | nojudges.insert(arr[0]) 22 | if dict[arr[1]] == nil { 23 | dict[arr[1]] = Set([arr[0]]) 24 | } else { 25 | dict[arr[1]]!.insert(arr[0]) 26 | } 27 | 28 | if dict[arr[1]]!.count == N - 1 { 29 | judge = arr[1] 30 | } 31 | } 32 | 33 | return !nojudges.contains(judge) ? judge : -1 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/MayWeek2/MaySolDay11.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MaySolDay11.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 5/30/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/flood-fill/ 10 | class MaySolDay11 { 11 | 12 | func floodFill(_ image: [[Int]], _ sr: Int, _ sc: Int, _ newColor: Int) -> [[Int]] { 13 | var newImg = image 14 | let oldColor = image[sr][sc] 15 | dfs(sr, sc, &newImg, newColor, oldColor) 16 | return newImg 17 | } 18 | 19 | private func dfs(_ x: Int, _ y: Int, _ image: inout [[Int]], _ newColor: Int, _ oldColor: Int) { 20 | if image[x][y] != oldColor { 21 | return 22 | } 23 | image[x][y] = newColor 24 | 25 | if x + 1 < image.count, image[x + 1][y] != newColor { 26 | dfs(x + 1, y, &image, newColor, oldColor) 27 | } 28 | 29 | if y + 1 < image[x].count, image[x][y + 1] != newColor { 30 | dfs(x, y + 1, &image, newColor, oldColor) 31 | } 32 | 33 | if x - 1 >= 0, image[x - 1][y] != newColor { 34 | dfs(x - 1, y, &image, newColor, oldColor) 35 | } 36 | 37 | if y - 1 >= 0, image[x][y - 1] != newColor { 38 | dfs(x, y - 1, &image, newColor, oldColor) 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/MayWeek2/MaySolDay12.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MaySolDay12.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 5/30/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/single-element-in-a-sorted-array/ 10 | class MaySolDay12 { 11 | 12 | func singleNonDuplicate(_ nums: [Int]) -> Int { 13 | var set = Set() 14 | for num in nums { 15 | if set.contains(num) { 16 | set.remove(num) 17 | } else { 18 | set.insert(num) 19 | } 20 | } 21 | return set.removeFirst() 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/MayWeek2/MaySolDay13.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MaySolDay13.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 5/30/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/remove-k-digits/ 10 | class MaySolDay13 { 11 | 12 | func removeKdigits(_ num: String, _ k: Int) -> String { 13 | guard num.count > 0 && k < num.count else { return "0" } 14 | 15 | let arr = Array(num) 16 | var stackChar = [Character]() 17 | var count = k 18 | var i = 0 19 | while i < arr.count { 20 | // Pop the elements if they are not in the increasing order 21 | while count > 0, let last = stackChar.last, last > arr[i] { 22 | stackChar.removeLast() 23 | count -= 1 24 | } 25 | stackChar.append(arr[i]) 26 | i += 1 27 | } 28 | 29 | while count > 0 { 30 | stackChar.removeLast() 31 | count -= 1 32 | } 33 | 34 | // Find leading 0s 35 | while let first = stackChar.first, first == "0" { 36 | stackChar.removeFirst() 37 | } 38 | 39 | return stackChar.isEmpty ? "0" : String(stackChar) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/MayWeek2/MaySolDay14.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MaySolDay14.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 5/14/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/implement-trie-prefix-tree/ 10 | class MaySolDay14 { 11 | 12 | class Trie: TrieProtocol { 13 | let root: TrieNode 14 | 15 | required init() { 16 | root = TrieNode(Character("0")) 17 | } 18 | 19 | func insert(_ word: String) { 20 | var node = root 21 | for ch in word { 22 | if node.children[ch] == nil { 23 | node.children[ch] = TrieNode(ch) 24 | } 25 | node = node.children[ch]! 26 | } 27 | 28 | node.children[Character("0")] = TrieNode(Character("0")) 29 | } 30 | 31 | func search(_ word: String) -> Bool { 32 | var node = root 33 | for ch in word { 34 | if node.children[ch] != nil { 35 | node = node.children[ch]! 36 | } else { 37 | return false 38 | } 39 | } 40 | return node.children[Character("0")] != nil 41 | } 42 | 43 | func startsWith(_ prefix: String) -> Bool { 44 | var node = root 45 | for ch in prefix { 46 | if node.children[ch] != nil { 47 | node = node.children[ch]! 48 | } else { 49 | return false 50 | } 51 | } 52 | return true 53 | } 54 | } 55 | 56 | class TrieNode { 57 | var char: Character 58 | var children = [Character : TrieNode]() 59 | 60 | init(_ char: Character) { 61 | self.char = char 62 | } 63 | } 64 | } 65 | 66 | protocol TrieProtocol { 67 | // Initialize your data structure here. 68 | init() 69 | // Inserts a word into the trie. 70 | func insert(_ word: String) 71 | // Returns if the word is in the trie. 72 | func search(_ word: String) -> Bool 73 | // Returns if there is any word in the trie that starts with the given prefix 74 | func startsWith(_ prefix: String) -> Bool 75 | } 76 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/MayWeek2/MaySolDay8.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MaySolDay8.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 5/21/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/check-if-it-is-a-straight-line/ 10 | class MaySolDay8 { 11 | 12 | func checkStraightLine(_ coordinates: [[Int]]) -> Bool { 13 | guard coordinates.count > 1 else { return false } 14 | 15 | if coordinates.count == 2 { 16 | return true 17 | } 18 | 19 | let vertical = (coordinates[1][0] - coordinates[0][0]) == 0 20 | let horizontal = (coordinates[1][1] - coordinates[0][1]) == 0 21 | 22 | let slope = (horizontal || vertical) ? 23 | 0 : (coordinates[1][0] - coordinates[0][0])/(coordinates[1][1] - coordinates[0][1]) 24 | for idx in 2.. Bool { 12 | if num == 1 { 13 | return true 14 | } 15 | 16 | for number in 1...num/2 { 17 | let result = number * number 18 | if result >= num { 19 | return result == num 20 | } 21 | } 22 | 23 | return false 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/MayWeek3/MaySolDay15.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MaySolDay15.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 5/30/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/maximum-sum-circular-subarray/ 10 | class MaySolDay15 { 11 | func maxSubarraySumCircular(_ A: [Int]) -> Int { 12 | guard A.count > 0 else { return 0 } 13 | if A.count == 1 { 14 | return A[0] 15 | } 16 | 17 | var output = Int.min 18 | var current = A[0] 19 | // Single interval 20 | for i in 1.. SinglyListNode? { 13 | guard head != nil else { return nil } 14 | 15 | var odd = head 16 | var even = head?.next 17 | let evenHead = even 18 | 19 | while even != nil, even?.next != nil { 20 | odd?.next = even?.next 21 | odd = odd?.next 22 | 23 | even?.next = odd?.next 24 | even = even?.next 25 | } 26 | 27 | odd?.next = evenHead 28 | return head 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/MayWeek3/MaySolDay17.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MaySolDay17.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 5/30/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/find-all-anagrams-in-a-string/ 10 | class MaySolDay17 { 11 | 12 | func findAnagrams(_ s: String, _ p: String) -> [Int] { 13 | guard s.count >= p.count else { return [] } 14 | 15 | var output = [Int]() 16 | let arrP = Array(p), arrS = Array(s) 17 | 18 | var dictS = [Character : Int]() 19 | var dictP = dictS 20 | 21 | var idx = 0 22 | while idx < arrP.count { 23 | dictS[arrS[idx]] = dictS[arrS[idx]] == nil ? 1 : dictS[arrS[idx]]! + 1 24 | dictP[arrP[idx]] = dictP[arrP[idx]] == nil ? 1 : dictP[arrP[idx]]! + 1 25 | idx += 1 26 | } 27 | 28 | if dictS == dictP { 29 | output.append(0) 30 | } 31 | 32 | idx = 1 33 | while idx + arrP.count - 1 < arrS.count { 34 | dictS[arrS[idx - 1]]! -= 1 35 | if dictS[arrS[idx - 1]]! == 0 { 36 | dictS[arrS[idx - 1]] = nil 37 | } 38 | 39 | let temp = idx + arrP.count - 1 40 | dictS[arrS[temp]] = dictS[arrS[temp]] == nil ? 1 : dictS[arrS[temp]]! + 1 41 | 42 | if dictS == dictP { 43 | output.append(idx) 44 | } 45 | 46 | idx += 1 47 | } 48 | 49 | return output 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/MayWeek3/MaySolDay18.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MaySolDay18.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 5/30/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/permutation-in-string/ 10 | class MaySolDay18 { 11 | 12 | func checkInclusion(_ s1: String, _ s2: String) -> Bool { 13 | var dict = [Character:Int]() 14 | for ch in s1 { 15 | dict[ch] = dict[ch] == nil ? 1 : dict[ch]! + 1 16 | } 17 | 18 | let arrS = Array(s2) 19 | var idx = 0 20 | while idx < arrS.count { 21 | let ch = arrS[idx] 22 | if dict[ch] != nil { 23 | var temp = dict 24 | var tempIdx = idx 25 | while tempIdx < arrS.count { 26 | if temp[arrS[tempIdx]] == nil { 27 | break 28 | } else { 29 | temp[arrS[tempIdx]]! -= 1 30 | if temp[arrS[tempIdx]]! == 0 { 31 | temp[arrS[tempIdx]] = nil 32 | } 33 | } 34 | tempIdx += 1 35 | } 36 | 37 | if temp.isEmpty { 38 | return true 39 | } 40 | 41 | } 42 | idx += 1 43 | } 44 | 45 | return false 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/MayWeek3/MaySolDay19.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MaySolDay19.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 5/30/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class MaySolDay19 { 12 | 13 | class StockSpanner { 14 | var stack = [(Int, Int)]() 15 | 16 | init() { 17 | 18 | } 19 | 20 | func next(_ price: Int) -> Int { 21 | var span = 1 22 | while !stack.isEmpty, price >= stack.last!.0 { 23 | span += stack.removeLast().1 24 | } 25 | stack.append((price, span)) 26 | return span 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/MayWeek3/MaySolDay20.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MaySolDay20.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 5/30/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/kth-smallest-element-in-a-bst/ 10 | class MaySolDay20 { 11 | 12 | func kthSmallest(_ root: TreeNode?, _ k: Int) -> Int { 13 | guard let root = root else { return -1 } 14 | var arr = [Int]() 15 | traverse(root, &arr) 16 | arr.sort() 17 | return arr[k - 1] 18 | } 19 | 20 | private func traverse(_ root: TreeNode?, _ arr: inout [Int]) { 21 | guard let root = root else { return } 22 | 23 | arr.append(root.val) 24 | 25 | if let left = root.left { 26 | traverse(left, &arr) 27 | } 28 | 29 | if let right = root.right { 30 | traverse(right, &arr) 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/MayWeek3/MaySolDay21.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MaySolDay21.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 5/30/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/count-square-submatrices-with-all-ones/ 10 | class MaySolDay21 { 11 | func countSquares(_ matrix: [[Int]]) -> Int { 12 | var output = 0 13 | var dp = matrix 14 | for x in 0.. 0, y > 0 { 20 | dp[x][y] = min(dp[x - 1][y], dp[x][y - 1], dp[x - 1][y - 1]) + 1 21 | output += dp[x][y] > 1 ? dp[x][y] - 1 : 0 22 | } 23 | } 24 | } 25 | } 26 | return output 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/MayWeek4/MaySolDay22.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MaySolDay22.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 5/31/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/sort-characters-by-frequency/ 10 | class MaySolDay22 { 11 | 12 | func frequencySort(_ s: String) -> String { 13 | var freqDict = [Character:Int]() 14 | var map = [Int:[Character]]() 15 | var output = [Character]() 16 | for ch in s { 17 | freqDict[ch] = freqDict[ch] == nil ? 1 : freqDict[ch]! + 1 18 | } 19 | 20 | for key in freqDict.keys { 21 | if map[freqDict[key]!] != nil { 22 | map[freqDict[key]!]!.append(key) 23 | } else { 24 | map[freqDict[key]!] = [key] 25 | } 26 | } 27 | 28 | let sortedKeys = map.keys.sorted(by: >) 29 | for key in sortedKeys { 30 | for value in map[key]! { 31 | for _ in 0.. [[Int]] { 13 | guard !A.isEmpty, !B.isEmpty else { 14 | return [] 15 | } 16 | 17 | var output = [[Int]]() 18 | var aIdx = 0 19 | var bIdx = 0 20 | var last = [Int]() 21 | while aIdx < A.count || bIdx < B.count { 22 | if last.isEmpty { 23 | guard aIdx < A.count, bIdx < B.count else { break } 24 | 25 | if aIdx < A.count, A[aIdx][0] < B[bIdx][0] { 26 | last = A[aIdx] 27 | aIdx += 1 28 | } else { 29 | last = B[bIdx] 30 | bIdx += 1 31 | } 32 | } else { 33 | while (aIdx < A.count && A[aIdx][0] <= last[1]) || 34 | (bIdx < B.count && B[bIdx][0] <= last[1]) { 35 | if aIdx < A.count, A[aIdx][0] <= last[1] { 36 | output.append([max(last[0], A[aIdx][0]), min(last[1], A[aIdx][1])]) 37 | last = [min(last[0], A[aIdx][0]), max(last[1], A[aIdx][1])] 38 | aIdx += 1 39 | } 40 | 41 | if bIdx < B.count, B[bIdx][0] <= last[1] { 42 | output.append([max(last[0], B[bIdx][0]), min(last[1], B[bIdx][1])]) 43 | last = [min(last[0], B[bIdx][0]), max(last[1], B[bIdx][1])] 44 | bIdx += 1 45 | } 46 | } 47 | last = [] 48 | } 49 | } 50 | 51 | return output 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/MayWeek4/MaySolDay24.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MaySolDay24.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 5/31/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/construct-binary-search-tree-from-preorder-traversal/ 10 | class MaySolDay24 { 11 | 12 | func bstFromPreorder(_ preorder: [Int]) -> TreeNode? { 13 | guard preorder.count > 0 else { return nil } 14 | return bstFromPreorder(preorder, 0, preorder.count - 1) 15 | } 16 | 17 | private func bstFromPreorder(_ preorder: [Int], _ start: Int, _ end: Int) -> TreeNode? { 18 | let root = TreeNode(preorder[start]) 19 | 20 | if start + 1 <= end, preorder.count > 1 { 21 | var rightRootIdx = -1 22 | for idx in start+1...end { 23 | if preorder[idx] > preorder[start] { 24 | rightRootIdx = idx 25 | break 26 | } 27 | } 28 | 29 | if rightRootIdx == start + 1 { 30 | root.right = bstFromPreorder(preorder, rightRootIdx, end) 31 | } else if rightRootIdx == -1 { 32 | root.left = bstFromPreorder(preorder, start + 1, end) 33 | } else { 34 | root.right = bstFromPreorder(preorder, rightRootIdx, end) 35 | root.left = bstFromPreorder(preorder, start + 1, rightRootIdx - 1) 36 | } 37 | } 38 | return root 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/MayWeek4/MaySolDay25.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MaySolDay25.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 5/31/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/uncrossed-lines/ 10 | class MaySolDay25 { 11 | 12 | func maxUncrossedLines(_ A: [Int], _ B: [Int]) -> Int { 13 | var dp = Array(repeating: Array(repeating: 0, count: B.count+1), count: A.count+1) 14 | for i in 1...A.count { 15 | for j in 1...B.count { 16 | dp[i][j] = (A[i-1] == B[j-1]) ? (1 + dp[i-1][j-1]) : max(dp[i-1][j], dp[i][j-1]) 17 | } 18 | } 19 | return dp[A.count][B.count] 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/MayWeek4/MaySolDay26.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MaySolDay26.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 5/31/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/contiguous-array/ 10 | class MaySolDay26 { 11 | 12 | func findMaxLength(_ nums: [Int]) -> Int { 13 | var dict = [0:-1] 14 | 15 | var maxCount = 0 16 | var count = 0 17 | for idx in 0.. Bool { 13 | graph = Array(repeating: [Int](), count: N+1) 14 | for dislike in dislikes { 15 | let d0 = dislike[0], d1 = dislike[1] 16 | graph[d0].append(d1) 17 | graph[d1].append(d0) 18 | } 19 | for node in 1...N { 20 | if color[node] == nil && !dfs(node, 0) { return false } 21 | } 22 | return true 23 | } 24 | 25 | private var graph = [[Int]]() 26 | private var color = [Int: Int]() 27 | private func dfs(_ node: Int, _ c: Int) -> Bool { 28 | if let v = color[node] { return v == c } 29 | color[node] = c 30 | for i in graph[node] { 31 | if !dfs(i, c ^ 1) { return false } 32 | } 33 | return true 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/MayWeek4/MaySolDay28.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MaySolDay28.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 5/31/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/counting-bits/ 10 | class MaySolDay28 { 11 | 12 | func countBits(_ num: Int) -> [Int] { 13 | var output = [Int]() 14 | for i in 0...num { 15 | output.append(helper(i)) 16 | } 17 | return output 18 | } 19 | 20 | func helper(_ num: Int) -> Int { 21 | var count = 0 22 | var input = num 23 | while input != 0 { 24 | input = input & (input - 1) 25 | count += 1 26 | } 27 | return count 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/MayWeek5/MaySolDay29.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MaySolDay29.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 6/3/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/course-schedule/ 10 | class MaySolDay29 { 11 | func canFinish(_ numCourses: Int, _ prerequisites: [[Int]]) -> Bool { 12 | var preDict = [Int:[Int]]() 13 | for pre in prerequisites { 14 | if preDict[pre[0]] == nil { 15 | preDict[pre[0]] = [pre[1]] 16 | } else { 17 | preDict[pre[0]]!.append(pre[1]) 18 | } 19 | } 20 | 21 | var okCourse = Set() 22 | for course in 1...numCourses { 23 | var taken = Set() 24 | if helper(course, preDict, &okCourse, &taken) { 25 | okCourse.insert(course) 26 | } else { 27 | return false 28 | } 29 | } 30 | 31 | return true 32 | } 33 | 34 | private func helper(_ current: Int, _ preDict: [Int:[Int]], _ okCourse: inout Set, _ taken: inout Set) -> Bool { 35 | if okCourse.contains(current) { 36 | return true 37 | } 38 | if taken.contains(current) { 39 | return false 40 | } 41 | 42 | taken.insert(current) 43 | if preDict[current] != nil { 44 | for pre in preDict[current]! { 45 | if helper(pre, preDict, &okCourse, &taken) { 46 | okCourse.insert(pre) 47 | } else { 48 | return false 49 | } 50 | } 51 | } else { 52 | return true 53 | } 54 | return true 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/MayWeek5/MaySolDay30.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MaySolDay30.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 6/4/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/k-closest-points-to-origin/ 10 | class MaySolDay30 { 11 | func kClosest(_ points: [[Int]], _ K: Int) -> [[Int]] { 12 | let sorted = points.sorted { getDistance($0) < getDistance($1) } 13 | return Array(sorted[0.. Int { 17 | return point[0] * point[0] + point[1] * point[1] 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/MayWeek5/MaySolDay31.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MaySolDay31.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 6/4/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | // LeetCode: https://leetcode.com/problems/edit-distance/ 10 | class MaySolDay31 { 11 | func minDistance(_ word1: String, _ word2: String) -> Int { 12 | let row = word1.count + 1 13 | let column = word2.count + 1 14 | var dp = Array(repeating: Array(repeating: 0, count: column), count: row) 15 | let array1 = Array(word1) 16 | let array2 = Array(word2) 17 | 18 | for i in 0.. Bool { 46 | return lhs.val < rhs.val 47 | } 48 | 49 | public static func == (lhs: TreeNode, rhs: TreeNode) -> Bool { 50 | return lhs.val == rhs.val 51 | } 52 | 53 | } 54 | 55 | public class BinarySearchTree { 56 | private var root: TreeNode? 57 | 58 | // Init BinarySearchTree by its root node 59 | init(root: TreeNode?) { 60 | if !BinarySearchTree.isValidBinarySearchTree(root) { 61 | assertionFailure("This is not a valid binary search tree.") 62 | } 63 | self.root = root 64 | } 65 | 66 | public func isEqualToOtherTree(_ otherRoot: TreeNode?) -> Bool { 67 | return BinarySearchTree.preorderTraversal(self.root) == BinarySearchTree.preorderTraversal(otherRoot) 68 | } 69 | /** 70 | A binary search tree is a binary tree where for every node, any descendant of node.left 71 | has a value < node.val, and any descendant of node.right has a value > node.val. 72 | 73 | - Parameter root: The root of the binary search tree to be examinated. 74 | 75 | - Returns: A boolean indicates whether the binary tree is a binary search tree. 76 | */ 77 | public static func isValidBinarySearchTree(_ root: TreeNode?) -> Bool { 78 | guard let root = root else { 79 | return false 80 | } 81 | 82 | if let left = root.left, let right = root.right { 83 | return left.val < root.val && isValidBinarySearchTree(left) && 84 | right.val > root.val && isValidBinarySearchTree(right) 85 | } else if let left = root.left { 86 | return left.val < root.val && isValidBinarySearchTree(left) 87 | } else if let right = root.right { 88 | return right.val > root.val && isValidBinarySearchTree(right) 89 | } 90 | 91 | return true 92 | } 93 | 94 | public static func preorderTraversal(_ root: TreeNode?) -> [Int] { 95 | var traversal = [Int]() 96 | guard let root = root else { 97 | return traversal 98 | } 99 | 100 | traversal.append(root.val) 101 | if let left = root.left { 102 | traversal.append(contentsOf: preorderTraversal(left)) 103 | } 104 | 105 | if let right = root.right { 106 | traversal.append(contentsOf: preorderTraversal(right)) 107 | } 108 | 109 | return traversal 110 | } 111 | } 112 | 113 | // This is the BinaryMatrix's API. 114 | public class BinaryMatrix { 115 | var matrix = [[Int]]() 116 | 117 | init(matrix: [[Int]]) { 118 | guard matrix.count > 0 else { 119 | assertionFailure("Empty input.") 120 | return 121 | } 122 | 123 | let columnCount = matrix[0].count 124 | for idx in 0.. Int { 134 | guard x < self.matrix.count || y < self.matrix[0].count else { 135 | assertionFailure("Index out of bound.") 136 | return -1 137 | } 138 | return matrix[x][y] 139 | } 140 | 141 | public func dimensions() -> [Int] { 142 | return [self.matrix.count, self.matrix[0].count] 143 | } 144 | } 145 | 146 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/Shared/Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Extensions.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 4/15/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | extension Array where Element == Int { 10 | 11 | public func convertToLinkedList() -> SinglyListNode? { 12 | guard self.count > 0 else { 13 | return nil 14 | } 15 | 16 | let head = SinglyListNode(self[0]) 17 | var idx = 1 18 | var node: SinglyListNode? = head 19 | 20 | while idx < self.count { 21 | node?.next = SinglyListNode(self[idx]) 22 | node = node?.next 23 | idx += 1 24 | } 25 | return head 26 | } 27 | } 28 | 29 | extension Array where Element == Int? { 30 | 31 | public func convertToBinaryTree() -> TreeNode? { 32 | guard self.count > 0 else { 33 | return nil 34 | } 35 | 36 | let root = TreeNode(self[0]!) 37 | constructTreeLevelOrder(0, root, self) 38 | return root 39 | } 40 | 41 | private func constructTreeLevelOrder(_ index: Int, _ root: TreeNode?, _ arr: [Int?]) { 42 | guard let root = root else { return } 43 | 44 | if index < arr.count { 45 | if 2*index+1 < arr.count, let val = arr[2*index+1] { 46 | root.left = TreeNode(val) 47 | constructTreeLevelOrder(2*index+1, root.left, arr) 48 | } 49 | if 2*index+2 < arr.count, let val = arr[2*index+2] { 50 | root.right = TreeNode(val) 51 | constructTreeLevelOrder(2*index+2, root.right, arr) 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /LeetCodeChallenge/LeetCodeChallenge/main.swift: -------------------------------------------------------------------------------- 1 | // 2 | // main.swift 3 | // LeetCodeChallenge 4 | // 5 | // Created by Michael Ho on 4/13/20. 6 | // Copyright © 2020 Michael Ho. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | This place is used as a playground! Feel free to debug here. 13 | 14 | Command + U to run all tests. 15 | */ 16 | print("Hello My LeetCode Challenge!") 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Leetcode 30-Day Challenge April and May Edition 2 | 3 | [![Swift 4.2](https://img.shields.io/badge/Swift-5.0-orange.svg?style=flat)](https://developer.apple.com/swift/) [![License](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/twho/LeetCode-Swift/blob/master/LICENSE) 4 | 5 | ## Summary 6 | - This project aims at solving [LeetCode 30-Day Challenge April Edition](https://leetcode.com/explore/featured/card/30-day-leetcoding-challenge/) and [May LeetCoding Challenge](https://leetcode.com/explore/featured/card/may-leetcoding-challenge/) problems. 7 | - We provide straightforward solutions. All solutions and tests are written in [Swift](https://developer.apple.com/swift/). 8 | - There are **30** programming problems and solutions for April challenge. 9 | - An additional set of **30** code problems and solutions will be uploaded by the end of [May LeetCoding Challenge](https://leetcode.com/explore/featured/card/may-leetcoding-challenge/). 10 | 11 | ## Articles for April Edition 12 | - [iOS Interview Prep Guide: 30-Day Code Challenge in Swift — Week 1/5](https://medium.com/@twho/ios-interview-prep-guide-30-day-code-challenge-in-swift-week-1-5-7198c6a1477a) 13 | - [iOS Interview Prep Guide: 30-Day Code Challenge in Swift — Week 2/5](https://medium.com/@twho/ios-interview-prep-guide-30-day-code-challenge-in-swift-week-2-5-f8d14df99179) 14 | - [iOS Interview Prep Guide: 30-Day Code Challenge in Swift — Week 3/5](https://medium.com/@twho/ios-interview-prep-guide-30-day-code-challenge-in-swift-week-3-5-463f9bb8c4f5) 15 | - [iOS Interview Prep Guide: 30-Day Code Challenge in Swift — Week 4/5](https://medium.com/@twho/ios-interview-prep-guide-30-day-code-challenge-in-swift-week-4-5-647f6050e869) 16 | - [iOS Interview Prep Guide: 30-Day Code Challenge in Swift — Week 5/5](https://medium.com/swlh/ios-interview-prep-guide-30-day-code-challenge-in-swift-week-5-5-d093e2cd4217) 17 | 18 | ## Articles for May Edition 19 | *Updating in progress* 20 | - [Top 15 Swift Code Interview Questions from May Code Challenge — Part 1/3](https://medium.com/swlh/top-15-swift-code-interview-questions-from-may-code-challenge-part-1-3-65c3dc11851b) 21 | 22 | ## Difficulty Legends 23 | | Difficulty | Easy | Medium | Hard | 24 | |:--: | :--: | :--: | :--: | 25 | | Icon | 📗 | 📙 | 📕 | 26 | 27 | ## April Challenge 28 | ### April 1st - April 30th 29 | | Day | Diffculty | Problem | Solution | 30 | |:--:| :--: | :-- | -- | 31 | | 1 |📗|[Single Number](https://leetcode.com/problems/single-number/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek1/AprilSolDay1.swift)| 32 | | 2 |📗| [Happy Number](https://leetcode.com/problems/happy-number/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek1/AprilSolDay2.swift)| 33 | | 3 |📗| [Maximum Subarray](https://leetcode.com/problems/maximum-subarray/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek1/AprilSolDay3.swift)| 34 | | 4 |📗| [Move Zeroes](https://leetcode.com/problems/move-zeroes/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek1/AprilSolDay4.swift)| 35 | | 5 |📗| [Best Time to Buy and Sell Stock II](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek1/AprilSolDay5.swift)| 36 | | 6 |📙| [Group Anagrams](https://leetcode.com/problems/group-anagrams/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek1/AprilSolDay6.swift)| 37 | | 7 |📗| [Counting Elements](https://leetcode.com/problems/counting-elements/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek1/AprilSolDay7.swift)| 38 | | 8 |📗| [Middle of the Linked List](https://leetcode.com/problems/middle-of-the-linked-list/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek2/AprilSolDay8.swift)| 39 | | 9 |📗| [Backspace String Compare](https://leetcode.com/problems/backspace-string-compare/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek2/AprilSolDay9.swift)| 40 | | 10 |📗| [Min Stack](https://leetcode.com/problems/min-stack/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek2/AprilSolDay10.swift)| 41 | | 11 |📗| [Diameter of Binary Tree](https://leetcode.com/problems/diameter-of-binary-tree/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek2/AprilSolDay11.swift)| 42 | | 12 |📗| [Last Stone Weight](https://leetcode.com/problems/last-stone-weight/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek2/AprilSolDay12.swift)| 43 | | 13 |📙| [Contiguous Array](https://leetcode.com/problems/contiguous-array/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek2/AprilSolDay13.swift)| 44 | | 14 |📗| [Perform String Shifts](https://leetcode.com/problems/perform-string-shifts/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek2/AprilSolDay14.swift)| 45 | | 15 |📙| [Product of Array Except Self](https://leetcode.com/problems/product-of-array-except-self/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek3/AprilSolDay15.swift)| 46 | | 16 |📙| [Valid Parenthesis String](https://leetcode.com/problems/valid-parenthesis-string/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek3/AprilSolDay16.swift)| 47 | | 17 |📙| [Number of Islands](https://leetcode.com/problems/number-of-islands/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek3/AprilSolDay17.swift)| 48 | | 18 |📙| [Minimum Path Sum](https://leetcode.com/problems/minimum-path-sum/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek3/AprilSolDay18.swift)| 49 | | 19 |📙| [Search in Rotated Sorted Array](https://leetcode.com/problems/search-in-rotated-sorted-array/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek3/AprilSolDay19.swift)| 50 | | 20 |📙| [Construct Binary Search Tree from Preorder Traversal](https://leetcode.com/problems/construct-binary-search-tree-from-preorder-traversal/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek3/AprilSolDay20.swift)| 51 | | 21 |📙| [Leftmost Column with at Least a One](https://leetcode.com/problems/leftmost-column-with-at-least-a-one/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek3/AprilSolDay21.swift)| 52 | | 22 |📙| [Subarray Sum Equals K](https://leetcode.com/problems/subarray-sum-equals-k/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek4/AprilSolDay22.swift)| 53 | | 23 |📙| [Bitwise AND of Numbers Range](https://leetcode.com/problems/bitwise-and-of-numbers-range/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek4/AprilSolDay23.swift)| 54 | | 24 |📙| [LRU Cache](https://leetcode.com/problems/lru-cache/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek4/AprilSolDay24.swift)| 55 | | 25 |📙| [Jump Game](https://leetcode.com/problems/jump-game/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek4/AprilSolDay25.swift)| 56 | | 26 |📙| [Longest Common Subsequence](https://leetcode.com/problems/longest-common-subsequence/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek4/AprilSolDay26.swift)| 57 | | 27 |📙| [Maximal Square](https://leetcode.com/problems/maximal-square/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek4/AprilSolDay27.swift)| 58 | | 28 |📙| [First Unique Number](https://leetcode.com/problems/first-unique-number/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek4/AprilSolDay28.swift)| 59 | | 29 |📕| [Binary Tree Maximum Path Sum](https://leetcode.com/problems/binary-tree-maximum-path-sum/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek5/AprilSolDay29.swift)| 60 | | 30 |📙| [A String Is a Root-to-Leaf Path in a Binary Tree](https://leetcode.com/problems/check-if-a-string-is-a-valid-sequence-from-root-to-leaves-path-in-a-binary-tree/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/AprilWeek5/AprilSolDay30.swift)| 61 | 62 | ## May Challenge 63 | ### May 1st - May 31st 64 | | Day | Diffculty | Problem | Solution | 65 | |:--:| :--: | :-- | -- | 66 | | 1 |📗|[First Bad Version](https://leetcode.com/problems/first-bad-version/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek1/MaySolDay1.swift)| 67 | | 2 |📗|[Jewels and Stones](https://leetcode.com/problems/jewels-and-stones/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek1/MaySolDay2.swift)| 68 | | 3 |📗|[Ransom Note](https://leetcode.com/problems/ransom-note/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek1/MaySolDay4.swift)| 69 | | 4 |📗|[Number Complement](https://leetcode.com/problems/number-complement/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek1/MaySolDay4.swift)| 70 | | 5 |📗|[First Unique Character in a String](https://leetcode.com/problems/first-unique-character-in-a-string/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek1/MaySolDay5.swift)| 71 | | 6 |📗|[Majority Element](https://leetcode.com/problems/majority-element/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek1/MaySolDay6.swift)| 72 | | 7 |📗|[Cousins in Binary Tree](https://leetcode.com/problems/cousins-in-binary-tree/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek1/MaySolDay7.swift)| 73 | | 8 |📗|[Check If It Is a Straight Line](https://leetcode.com/problems/check-if-it-is-a-straight-line/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek2/MaySolDay8.swift)| 74 | | 9 |📗|[Valid Perfect Square](https://leetcode.com/problems/valid-perfect-square/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek2/MaySolDay9.swift)| 75 | | 10 |📗|[Find the Town Judge](https://leetcode.com/problems/find-the-town-judge/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek2/MaySolDay10.swift)| 76 | | 11 |📗|[Flood Fill](https://leetcode.com/problems/flood-fill/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek2/MaySolDay11.swift)| 77 | | 12 |📙|[Single Element in a Sorted Array](https://leetcode.com/problems/single-element-in-a-sorted-array/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek2/MaySolDay12.swift)| 78 | | 13 |📙|[Remove K Digits](https://leetcode.com/problems/remove-k-digits/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek2/MaySolDay13.swift)| 79 | | 14 |📙|[Implement Trie (Prefix Tree)](https://leetcode.com/problems/implement-trie-prefix-tree/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek2/MaySolDay14.swift)| 80 | | 15 |📙|[Maximum Sum Circular Subarray](https://leetcode.com/problems/maximum-sum-circular-subarray/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek3/MaySolDay15.swift)| 81 | | 16 |📙|[Odd Even Linked List](https://leetcode.com/problems/odd-even-linked-list/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek3/MaySolDay16.swift)| 82 | | 17 |📙|[Find All Anagrams in a String](https://leetcode.com/problems/find-all-anagrams-in-a-string/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek3/MaySolDay17.swift)| 83 | | 18 |📙|[Permutation in String](https://leetcode.com/problems/permutation-in-string/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek3/MaySolDay18.swift)| 84 | | 19 |📙|[Online Stock Span](https://leetcode.com/problems/online-stock-span/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek3/MaySolDay19.swift)| 85 | | 20 |📙|[Kth Smallest Element in a BST](https://leetcode.com/problems/kth-smallest-element-in-a-bst/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek3/MaySolDay20.swift)| 86 | | 21 |📙|[Count Square Submatrices with All Ones](https://leetcode.com/problems/count-square-submatrices-with-all-ones/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek3/MaySolDay21.swift)| 87 | | 22 |📙|[Sort Characters By Frequency](https://leetcode.com/problems/sort-characters-by-frequency/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek4/MaySolDay22.swift)| 88 | | 23 |📙|[Interval List Intersections](https://leetcode.com/problems/interval-list-intersections/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek4/MaySolDay23.swift)| 89 | | 24 |📙|[Construct Binary Search Tree from Preorder Traversal](https://leetcode.com/problems/construct-binary-search-tree-from-preorder-traversal/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek4/MaySolDay24.swift)| 90 | | 25 |📙|[Uncrossed Lines](https://leetcode.com/problems/uncrossed-lines/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek4/MaySolDay25.swift)| 91 | | 26 |📙|[Contiguous Array](https://leetcode.com/problems/contiguous-array/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek4/MaySolDay26.swift)| 92 | | 27 |📙|[Possible Bipartition](https://leetcode.com/problems/possible-bipartition/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek4/MaySolDay27.swift)| 93 | | 28 |📙|[Counting Bits](https://leetcode.com/problems/counting-bits/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek4/MaySolDay28.swift)| 94 | | 29 |📙|[Course Schedule](https://leetcode.com/problems/course-schedule/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek5/MaySolDay29.swift)| 95 | | 30 |📙|[K Closest Points to Origin](https://leetcode.com/problems/k-closest-points-to-origin/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek5/MaySolDay30.swift)| 96 | | 31 |📕|[Edit Distance](https://leetcode.com/problems/edit-distance/) | [Solution](https://github.com/twho/leetcode-30-day-challenge-swift/blob/master/LeetCodeChallenge/LeetCodeChallenge/MayWeek5/MaySolDay31.swift)| 97 | --------------------------------------------------------------------------------