Skip to content

Commit 4db7a75

Browse files
author
Michael Ho
committed
Add new solutions
1 parent e334569 commit 4db7a75

File tree

23 files changed

+571
-34
lines changed

23 files changed

+571
-34
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// LeetCode: https://leetcode.com/problems/min-stack/
2+
3+
import XCTest
4+
5+
struct StackElement {
6+
var val: Int
7+
var minVal: Int
8+
9+
init(_ val: Int, _ minVal: Int) {
10+
self.val = val
11+
self.minVal = minVal
12+
}
13+
}
14+
15+
class MinStack {
16+
var arr: [StackElement]
17+
18+
/** initialize your data structure here. */
19+
init() {
20+
arr = [StackElement]()
21+
}
22+
23+
func push(_ x: Int) {
24+
let min = getMin()
25+
var element = StackElement(x, min)
26+
if x < min {
27+
element = StackElement(x, x)
28+
}
29+
arr.append(element)
30+
}
31+
32+
func pop() {
33+
if arr.isEmpty {
34+
return
35+
}
36+
arr.removeLast()
37+
}
38+
39+
func top() -> Int {
40+
return arr.last!.val
41+
}
42+
43+
func getMin() -> Int {
44+
if let val = arr.last?.minVal {
45+
return val
46+
}
47+
return Int.max
48+
}
49+
}

Problems/201-300/Hard/0224-BasicCalculator.playground/Contents.swift

+23-34
Original file line numberDiff line numberDiff line change
@@ -4,46 +4,35 @@ import XCTest
44

55
class Solution {
66
func calculate(_ s: String) -> Int {
7-
var output: [Int] = []
8-
let strArr = Array(s + "+")
9-
var open: [[Int]] = []
7+
var brackets = 0
8+
var op = "+"
109
var num = 0
11-
var sign: Character = "+"
12-
13-
for ch in strArr {
14-
if ch >= "0" && ch <= "9" {
15-
num = num*10 + Int(String(ch))!
16-
} else if ch == "+" || ch == "-" {
17-
if open.count > 0 {
18-
open[0].append(sign == "+" ? num : -num)
10+
var ops = [1]
11+
var output = [Int]()
12+
for ch in s+"+" {
13+
if ch == "(" {
14+
brackets += 1
15+
if brackets < ops.count {
16+
ops[brackets] = op == "+" ? 1*ops[brackets-1] : -1*ops[brackets-1]
1917
} else {
20-
output.append(sign == "+" ? num : -num)
18+
ops.append(op == "+" ? 1*ops[brackets-1] : -1*ops[brackets-1])
2119
}
22-
num = 0
23-
sign = ch
24-
} else if ch == "(" {
25-
var newSign = sign == "+" ? 1 : -1
26-
if open.count > 0 {
27-
newSign *= open[0][0]
28-
}
29-
var arr: [Int] = [newSign]
30-
open.insert(arr, at: 0)
31-
sign = "+"
20+
op = "+"
3221
} else if ch == ")" {
33-
if num != 0 {
34-
open[0].append(sign == "+" ? num : -num)
35-
num = 0
36-
}
37-
let sign = open[0].removeFirst()
38-
output.append(sign * open[0].reduce(0, {x,y in
39-
x+y
40-
}))
41-
open.removeFirst()
22+
let val = num*ops[brackets]
23+
output.append(op == "+" ? val : -val)
24+
brackets -= 1
25+
num = 0
26+
} else if ch >= "0", ch <= "9" {
27+
num = num*10 + Int(String(ch))!
28+
} else if ch == "+" || ch == "-" {
29+
let val = num*ops[brackets]
30+
output.append(op == "+" ? val : -val)
31+
num = 0
32+
op = String(ch)
4233
}
4334
}
44-
return output.reduce(0, {x,y in
45-
x+y
46-
})
35+
return output.reduce(0, +)
4736
}
4837
}
4938

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<playground version='5.0' target-platform='macos'>
3+
<timeline fileName='timeline.xctimeline'/>
4+
</playground>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// LeetCode: https://leetcode.com/problems/redundant-connection/
2+
3+
import XCTest
4+
5+
class Solution {
6+
// There are implicitly three wrong situations:
7+
// #1. HAS 2-parent, NO cycle;
8+
// #2. NO 2-parent, HAS cycle;
9+
// #3. HAS 2-parent, HAS cycle;
10+
11+
func findRedundantConnection(_ edges: [[Int]]) -> [Int] {
12+
var map = [Int: [Int]]()
13+
for edge in edges {
14+
var visisted = Set<Int>()
15+
if dfs(edge[0], edge[1], map, &visisted) {
16+
return edge
17+
}
18+
if map[edge[0]] != nil {
19+
map[edge[0]]!.append(edge[1])
20+
} else {
21+
map[edge[0]] = [edge[1]]
22+
}
23+
if map[edge[1]] != nil {
24+
map[edge[1]]!.append(edge[0])
25+
} else {
26+
map[edge[1]] = [edge[0]]
27+
}
28+
}
29+
return []
30+
}
31+
32+
private func dfs(_ start: Int, _ dest: Int, _ map: [Int: [Int]], _ visited: inout Set<Int>) -> Bool {
33+
if start == dest {
34+
return true
35+
}
36+
visited.insert(start)
37+
if let edges = map[start] {
38+
for next in edges {
39+
if !visited.contains(next) {
40+
if dfs(next, dest, map, &visited) {
41+
return true
42+
}
43+
}
44+
45+
}
46+
}
47+
return false
48+
}
49+
}
50+
51+
class Tests: XCTestCase {
52+
let s = Solution()
53+
54+
func testSample1() {
55+
let input = [[1,2], [1,3], [2,3]]
56+
let expected = [2, 3]
57+
XCTAssertEqual(expected, s.findRedundantConnection(input))
58+
}
59+
60+
func testSample2() {
61+
let input = [[1,2], [2,3], [3,4], [1,4], [1,5]]
62+
let expected = [1, 4]
63+
XCTAssertEqual(expected, s.findRedundantConnection(input))
64+
}
65+
}
66+
67+
Tests.defaultTestSuite.run()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<playground version='5.0' target-platform='macos'>
3+
<timeline fileName='timeline.xctimeline'/>
4+
</playground>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// LeetCode: https://leetcode.com/problems/redundant-connection-ii/
2+
3+
import XCTest
4+
5+
// There are implicitly three wrong situations:
6+
// #1. HAS 2-parent, NO cycle;
7+
// #2. NO 2-parent, HAS cycle;
8+
// #3. HAS 2-parent, HAS cycle;
9+
class Solution {
10+
var parents = [Int: Int]()
11+
var candidate1 = [-1, -1]
12+
var candidate2 = [-1, -1]
13+
14+
func findRedundantDirectedConnection(_ edges: [[Int]]) -> [Int] {
15+
var edges = edges
16+
// #1. HAS 2-parent
17+
for i in 0..<edges.count {
18+
let parent = edges[i][0]
19+
let child = edges[i][1]
20+
if let existedParent = parents[child] {
21+
candidate1 = [existedParent, child]
22+
candidate2 = edges[i]
23+
edges[i][1] = -1
24+
} else {
25+
parents[child] = parent
26+
}
27+
}
28+
parents = [Int: Int]()
29+
var foundEdge: [Int]?
30+
for edge in edges {
31+
guard edge[1] != -1 else { continue }
32+
if let foundEdge = union(edge[0], edge[1]) {
33+
return foundEdge
34+
}
35+
}
36+
// If we reach this point, that means we previously invalidated the corrent "wrong" edge and there is no cycle,
37+
// which is situation #1, just return candidate2.
38+
return candidate2
39+
}
40+
41+
private func union(_ x: Int, _ y: Int) -> [Int]? {
42+
let xParent = find(x)
43+
let yParent = find(y)
44+
guard xParent != yParent else {
45+
if candidate1[0] == -1 {
46+
return [x, y]
47+
} else {
48+
return candidate1
49+
}
50+
}
51+
parents[yParent] = xParent
52+
return nil
53+
}
54+
55+
private func find(_ x: Int) -> Int {
56+
if parents[x] == nil { return x }
57+
return find(parents[x]!)
58+
}
59+
}
60+
61+
class Tests: XCTestCase {
62+
let s = Solution()
63+
64+
func testSample1() {
65+
66+
}
67+
}
68+
69+
Tests.defaultTestSuite.run()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<playground version='5.0' target-platform='macos'>
3+
<timeline fileName='timeline.xctimeline'/>
4+
</playground>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
// LeetCode: https://leetcode.com/problems/my-calendar-i/
2+
3+
import XCTest
4+
5+
class MyCalendar {
6+
var records: [[Int]]
7+
8+
init() {
9+
records = [[Int]]()
10+
}
11+
12+
func book(_ start: Int, _ end: Int) -> Bool {
13+
if records.count == 0 {
14+
records.append([start, end])
15+
return true
16+
}
17+
18+
if records.count == 1 {
19+
if records[0][1] <= start {
20+
records.insert([start, end], at: 1)
21+
return true
22+
} else if records[0][0] >= end {
23+
records.insert([start, end], at: 0)
24+
return true
25+
}
26+
return false
27+
}
28+
29+
var left = 0
30+
var right = records.count
31+
while left < right {
32+
let mid = left + (right - left)/2
33+
if records[mid][0] == start || records[mid][1] == end {
34+
return false
35+
} else if records[mid][0] > start {
36+
right = mid
37+
} else {
38+
left = mid + 1
39+
}
40+
}
41+
// If the inserted time if larger than all.
42+
if left == records.count, start >= records[records.count-1][1] {
43+
records.append([start, end])
44+
return true
45+
}
46+
// Invalid index
47+
if left - 1 >= 0, records[left-1][1] > start {
48+
return false
49+
}
50+
// Invalid index
51+
if records[left][0] < end {
52+
return false
53+
}
54+
records.insert([start, end], at: left)
55+
return true
56+
}
57+
}
58+
59+
class Tests: XCTestCase {
60+
let calendar = MyCalendar()
61+
62+
func testSample1() {
63+
let input = [
64+
[10, 20],
65+
[15, 25],
66+
[20, 30]
67+
]
68+
let expected = [true, false, true]
69+
for (idx, i) in input.enumerated() {
70+
XCTAssertEqual(expected[idx], calendar.book(i[0], i[1]))
71+
}
72+
}
73+
74+
func testSample2() {
75+
let input = [
76+
[12,20],[21,29],[11,20],
77+
[12,17],[84,90],[60,68],
78+
[88,94],[23,32],[88,94],
79+
[15,20],[77,83],[34,42],
80+
[44,53],[35,40],[24,31],
81+
[48,55],[0,6],[6,13],
82+
[58,63],[15,23]
83+
]
84+
let expected = [
85+
true,true,false,
86+
false,true,true,
87+
false,false,false,
88+
false,true,true,
89+
true,false,false,
90+
false,true,false,
91+
false,false
92+
]
93+
for (idx, i) in input.enumerated() {
94+
XCTAssertEqual(expected[idx], calendar.book(i[0], i[1]))
95+
}
96+
}
97+
98+
func testSample3() {
99+
let input = [
100+
[47,50],[33,41],[39,45],
101+
[33,42],[25,32],[26,35],
102+
[19,25],[3,8],[8,13],
103+
[18,27]
104+
]
105+
let expected = [
106+
true,true,false,
107+
false,true,false,
108+
true,true,true,
109+
false
110+
]
111+
for (idx, i) in input.enumerated() {
112+
XCTAssertEqual(expected[idx], calendar.book(i[0], i[1]))
113+
}
114+
}
115+
}
116+
117+
Tests.defaultTestSuite.run()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<playground version='5.0' target-platform='macos'>
3+
<timeline fileName='timeline.xctimeline'/>
4+
</playground>

0 commit comments

Comments
 (0)