Skip to content

Commit c45f7b2

Browse files
authored
Merge pull request soapyigu#353 from soapyigu/BFS
Bfs
2 parents 7c5e677 + 346ab14 commit c45f7b2

File tree

4 files changed

+116
-57
lines changed

4 files changed

+116
-57
lines changed

BFS/RaceCar.swift

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/**
2+
* Question Link: https://leetcode.com/problems/race-car/
3+
* Primary idea: BFS to go over A or R at a specific step. Only add R to the queue when necessary.
4+
*
5+
* Time Complexity: O(nlogn), Space Complexity: O(n)
6+
*/
7+
8+
class RaceCar {
9+
func racecar(_ target: Int) -> Int {
10+
let startNode = Node(speed: 1, position: 0)
11+
var queue = [startNode], len = 0, isVisited = Set<Node>()
12+
13+
while !queue.isEmpty {
14+
let size = queue.count
15+
16+
for _ in 0..<size {
17+
let node = queue.removeFirst()
18+
19+
if node.position == target {
20+
return len
21+
}
22+
23+
if isVisited.contains(node) {
24+
continue
25+
}
26+
27+
isVisited.insert(node)
28+
29+
let ANode = Node(speed: node.speed * 2, position: node.position + node.speed)
30+
queue.append(ANode)
31+
32+
if shouldRevert(node, target) {
33+
let RNode = Node(speed: node.speed > 0 ? -1 : 1, position: node.position)
34+
queue.append(RNode)
35+
}
36+
37+
}
38+
39+
len += 1
40+
}
41+
42+
return len
43+
}
44+
45+
private func shouldRevert(_ node: Node, _ target: Int) -> Bool {
46+
return (node.position + node.speed > target && node.speed > 0) || (node.position + node.speed < target && node.speed < 0)
47+
}
48+
49+
struct Node: Hashable {
50+
let speed: Int
51+
let position: Int
52+
}
53+
}

BFS/ShortestPathGetFood.swift

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,29 +13,36 @@ class ShortestPathGetFood {
1313
let start = findStart(grid)
1414

1515
isVisited[start.0][start.1] = true
16-
var queue = [Point(i: start.0, j: start.1, len: 0)]
16+
var queue = [(start.0, start.1)], count = 0
1717

1818
while !queue.isEmpty {
19-
let point = queue.removeFirst()
2019

21-
if grid[point.i][point.j] == "#" {
22-
return point.len
23-
}
20+
let size = queue.count
2421

25-
for dir in [(0, 1), (0, -1), (1, 0), (-1, 0)] {
26-
let (x, y) = (point.i + dir.0, point.j + dir.1)
27-
28-
guard x >= 0 && x < m && y >= 0 && y < n && !isVisited[x][y] else {
29-
continue
22+
for _ in 0..<size {
23+
let point = queue.removeFirst()
24+
25+
if grid[point.0][point.1] == "#" {
26+
return count
3027
}
31-
32-
if grid[x][y] == "X" {
33-
continue
28+
29+
for dir in [(0, 1), (0, -1), (1, 0), (-1, 0)] {
30+
let (x, y) = (point.0 + dir.0, point.1 + dir.1)
31+
32+
guard x >= 0 && x < m && y >= 0 && y < n && !isVisited[x][y] else {
33+
continue
34+
}
35+
36+
if grid[x][y] == "X" {
37+
continue
38+
}
39+
40+
isVisited[x][y] = true
41+
queue.append((x, y))
3442
}
35-
36-
isVisited[x][y] = true
37-
queue.append(Point(i: x, j: y, len: point.len + 1))
3843
}
44+
45+
count += 1
3946
}
4047

4148
return -1
@@ -52,10 +59,4 @@ class ShortestPathGetFood {
5259

5360
return (-1, -1)
5461
}
55-
56-
struct Point {
57-
var i: Int
58-
var j: Int
59-
var len: Int
60-
}
6162
}

BFS/ShortestPathGridObstaclesElimination.swift

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,56 +8,55 @@
88
class ShortestPathGridObstaclesElimination {
99
func shortestPath(_ grid: [[Int]], _ k: Int) -> Int {
1010
let m = grid.count, n = grid[0].count
11-
var remainings = Array(repeating: Array(repeating: -1, count: n), count: m)
11+
var remaining = Array(repeating: Array(repeating: -1, count: n), count: m)
12+
var queue = [Point(i: 0, j: 0, remain: k)], count = 0
1213

13-
remainings[0][0] = k
14-
var queue = [Point(i: 0, j: 0, remain: k)]
15-
var count = 0
16-
17-
if k > m + n - 2 {
18-
return m + n - 2;
14+
if m + n - 2 < k {
15+
return m + n - 2
1916
}
2017

2118
while !queue.isEmpty {
19+
let size = queue.count
2220

23-
let currentPoints = queue
24-
queue.removeAll()
25-
26-
for point in currentPoints {
27-
if point.i == m - 1 && point.j == n - 1 {
21+
for _ in 0..<size {
22+
let point = queue.removeFirst()
23+
24+
if point.i == m - 1, point.j == n - 1 {
2825
return count
2926
}
30-
31-
for dir in [(0, 1), (0, -1), (1, 0), (-1, 0)] {
32-
let (x, y) = (point.i + dir.0, point.j + dir.1)
3327

28+
for dir in [[0, 1], [0, -1], [1, 0], [-1, 0]] {
29+
let (x, y) = (point.i + dir[0], point.j + dir[1])
30+
3431
guard x >= 0 && x < m && y >= 0 && y < n else {
3532
continue
3633
}
37-
38-
if grid[x][y] == 1 && point.remain <= 0 {
34+
35+
if grid[x][y] == 1 && point.remain == 0 {
3936
continue
4037
}
4138

42-
let remain = grid[x][y] == 1 ? point.remain - 1 : point.remain
43-
// only choose the path if remainings are greater
44-
if remainings[x][y] >= remain {
39+
let nextRemaining = grid[x][y] == 1 ? point.remain - 1 : point.remain
40+
41+
if remaining[x][y] >= nextRemaining {
4542
continue
46-
}
43+
}
4744

48-
remainings[x][y] = remain
49-
queue.append(Point(i: x, j: y, remain: remain))
45+
remaining[x][y] = nextRemaining
46+
queue.append(Point(i: x, j: y, remain: nextRemaining))
47+
5048
}
5149
}
50+
5251
count += 1
5352
}
5453

5554
return -1
5655
}
5756

5857
struct Point {
59-
var i: Int
60-
var j: Int
61-
var remain: Int
58+
let i: Int
59+
let j: Int
60+
let remain: Int
6261
}
6362
}

BFS/WordLadder.swift

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,26 @@
1010

1111
class WordLadder {
1212
func ladderLength(_ beginWord: String, _ endWord: String, _ wordList: [String]) -> Int {
13-
var wordSet = Set(wordList), wordStepQueue = [(beginWord, 1)]
13+
var wordSet = Set(wordList), wordQueue = [beginWord], count = 1
1414

15-
while !wordStepQueue.isEmpty {
16-
let (currentWord, currentStep) = wordStepQueue.removeFirst()
15+
while !wordQueue.isEmpty {
1716

18-
if currentWord == endWord {
19-
return currentStep
20-
}
17+
let size = wordQueue.count
2118

22-
for word in neighbors(for: currentWord, in: wordSet) {
19+
for _ in 0..<size {
20+
let currentWord = wordQueue.removeFirst()
21+
22+
if currentWord == endWord {
23+
return count
24+
}
2325

24-
wordStepQueue.append((word, currentStep + 1))
25-
wordSet.remove(word)
26+
for word in neighbors(for: currentWord, in: wordSet) {
27+
wordQueue.append(word)
28+
wordSet.remove(word)
29+
}
2630
}
31+
32+
count += 1
2733
}
2834

2935
return 0

0 commit comments

Comments
 (0)