Skip to content

Commit beb6161

Browse files
authored
Problems/graph (#24)
* Update array note * Update graph note * Update 59. Spiral Matrix II problem solution * Add 797. All Paths From Source to Target solution * Add 797. All Paths From Source to Target recursive solution * Add 797. All Paths From Source to Target bfs solution * Add 733. Flood Fill solution * Add 733. Flood Fill dfs solution * Update 387. First Unique Character in a String solution * Update graph problems and 242. Valid Anagram solution * Add 200. Number of Islands solution * Add 130. Surrounded Regions solution * Add 695. Max Area of Island solution * Add 200. Number of Islands BFS solution * Add 542. 01 Matrix solution * Add 994. Rotting Oranges solution * Add 310. Minimum Height Trees attempt * Add 417. Pacific Atlantic Water Flow solution * Add 785. Is Graph Bipartite? solution * Add 1254. Number of Closed Islands solution * Add 841. Keys and Rooms solution * Add linked list sentinel node template * Update linked list problems note * Add 127. Word Ladder solution * Update 141. Linked List Cycle solution * Add 207. Course Schedule solution * Add 210. Course Schedule II solution * Add 743. Network Delay Time solutions * Add 399. Evaluate Division solution * Update 743. Network Delay Time dijkstra] algorithm solution * Add 1091. Shortest Path in Binary Matrix solution * Add 787. Cheapest Flights Within K Stops attempt * Update 92. Reverse Linked List II solution * Update 234. Palindrome Linked List solution * Add update graph problem solving tips
1 parent f0fcc34 commit beb6161

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1956
-170
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
## [1091. Shortest Path in Binary Matrix](https://leetcode.com/problems/shortest-path-in-binary-matrix/)
2+
3+
```kotlin
4+
fun shortestPathBinaryMatrix(grid: Array<IntArray>): Int {
5+
val infinite = Int.MAX_VALUE / 2
6+
val n = grid.size
7+
if (grid[0][0] == 1 || grid[n -1][n - 1] == 1) return -1
8+
9+
val distances = Array(n) { _ -> IntArray(n) { _ -> infinite }}
10+
val queue = ArrayDeque<Pair<Int, Int>>()
11+
val visited = hashSetOf<Pair<Int, Int>>()
12+
queue.add(0 to 0)
13+
visited.add(0 to 0)
14+
distances[0][0] = 1
15+
while (!queue.isEmpty()) {
16+
val node = queue.removeFirst()
17+
val x = node.first
18+
val y = node.second
19+
20+
val directions = arrayOf(
21+
intArrayOf(-1, -1),
22+
intArrayOf(-1, 0),
23+
intArrayOf(-1, 1),
24+
intArrayOf(0, -1),
25+
intArrayOf(0, 1),
26+
intArrayOf(1, -1),
27+
intArrayOf(1, 0),
28+
intArrayOf(1, 1)
29+
)
30+
directions.forEach { d ->
31+
val newX = x + d[0]
32+
val newY = y + d[1]
33+
val distance = distances[x][y] + 1
34+
if (newX in 0 until grid.size && newY in 0 until grid.size && grid[newX][newY] == 0) {
35+
if (distances[newX][newY] > distance) {
36+
distances[newX][newY] = distance
37+
}
38+
39+
if (!visited.contains(newX to newY)) {
40+
queue.addLast(newX to newY)
41+
visited.add(newX to newY)
42+
}
43+
}
44+
}
45+
}
46+
val result = distances[n - 1][n - 1]
47+
return if (result == infinite) -1 else result
48+
}
49+
```
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
## [1254. Number of Closed Islands](https://leetcode.com/problems/number-of-closed-islands/)
2+
3+
* We traversal from the 4 edges to search **non-closed** islands and mark the region as invalid during traversal.
4+
* Then we traversal the graph again to find `0`, that would be closed islands.
5+
6+
```kotlin
7+
class Solution {
8+
private val invalid = 2
9+
private val nonClosedLands = hashSetOf<Pair<Int, Int>>()
10+
private val directions = arrayOf(
11+
-1 to 0, 1 to 0, 0 to -1, 0 to 1)
12+
13+
fun closedIsland(grid: Array<IntArray>): Int {
14+
val m = grid.size
15+
val n = grid[0].size
16+
17+
for (row in 0 until m) {
18+
dfs(grid, row, 0)
19+
dfs(grid, row, n - 1)
20+
}
21+
22+
for (col in 0 until n) {
23+
dfs(grid, 0, col)
24+
dfs(grid, m - 1, col)
25+
}
26+
27+
var count = 0
28+
for (row in 0 until m) {
29+
for (col in 0 until n) {
30+
if (grid[row][col] == 0) {
31+
dfs(grid, row, col)
32+
count++
33+
}
34+
}
35+
}
36+
return count
37+
}
38+
39+
private fun dfs(grid: Array<IntArray>, x: Int, y: Int) {
40+
if (x in 0 until grid.size &&
41+
y in 0 until grid[0].size &&
42+
grid[x][y] == 0) {
43+
grid[x][y] = invalid
44+
45+
directions.forEach {
46+
dfs(grid, x + it.first, y + it.second)
47+
}
48+
}
49+
}
50+
}
51+
```

leetcode/127.word-ladder.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
## [127. Word Ladder](https://leetcode.com/problems/word-ladder/)
2+
3+
* Build the graph: the pair words that differ by one character will be the edge.
4+
5+
```js
6+
hot:[dot,lot,]
7+
dot:[hot,dog,lot,]
8+
dog:[dot,log,cog,]
9+
lot:[hot,dot,log,]
10+
log:[dog,lot,cog,]
11+
cog:[dog,log,]
12+
```
13+
14+
* Run BFS on the graph that calculates the shortest path.
15+
16+
```kotlin
17+
fun ladderLength(beginWord: String, endWord: String, wordList: List<String>): Int {
18+
if (beginWord == endWord) return 0
19+
val queue = ArrayDeque<String>()
20+
val visited = hashSetOf<String>()
21+
val graph = mutableMapOf<String, MutableSet<String>>()
22+
graph[beginWord] = mutableSetOf<String>()
23+
for (word in wordList) {
24+
if (diff(beginWord, word) == 1) graph[beginWord]?.add(word)
25+
}
26+
for (word1 in wordList) {
27+
graph[word1] = mutableSetOf()
28+
for (word2 in wordList) {
29+
if (diff(word1, word2) == 1) graph[word1]?.add(word2)
30+
}
31+
}
32+
33+
queue.addLast(beginWord)
34+
visited.add(beginWord)
35+
36+
var distance = 1
37+
while (!queue.isEmpty()) {
38+
val size = queue.size
39+
for (i in 0 until size) {
40+
val currentWord = queue.removeFirst()
41+
graph[currentWord]?.forEach { word ->
42+
if (!visited.contains(word)) {
43+
if (word == endWord) {
44+
return distance + 1
45+
}
46+
visited.add(word)
47+
queue.addLast(word)
48+
}
49+
}
50+
}
51+
distance++
52+
}
53+
return 0
54+
}
55+
56+
private fun diff(w1: String, w2: String): Int {
57+
var diff = 0
58+
for (i in 0 until w1.length) {
59+
if (w1[i] != w2[i]) diff++
60+
}
61+
return diff
62+
}
63+
```

leetcode/130.surrounded-regions.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
## [130. Surrounded Regions](https://leetcode.com/problems/surrounded-regions/)
2+
3+
4+
```kotlin
5+
class Solution {
6+
7+
private val regions = hashSetOf<Pair<Int, Int>>()
8+
private val visited = hashSetOf<Pair<Int, Int>>()
9+
10+
fun solve(board: Array<CharArray>): Unit {
11+
for (m in 0 until board.size) {
12+
for (n in 0 until board[m].size) {
13+
if (board[m][n] == 'O' && !visited.contains(m to n)) {
14+
val currentRegions = hashSetOf<Pair<Int, Int>>()
15+
if (dfs(board, m, n, currentRegions)) {
16+
regions.addAll(currentRegions)
17+
}
18+
}
19+
}
20+
}
21+
22+
regions.forEach {
23+
board[it.first][it.second] = 'X'
24+
}
25+
}
26+
27+
private fun dfs(board: Array<CharArray>, x: Int, y: Int, regions: HashSet<Pair<Int, Int>>): Boolean {
28+
if (x < 0 || y < 0 || x > board.size - 1 || y > board[0].size - 1) return false
29+
if (board[x][y] == 'X' || visited.contains(x to y)) return true
30+
31+
visited.add(x to y)
32+
regions.add(x to y)
33+
34+
val up = dfs(board, x - 1, y, regions)
35+
val down = dfs(board, x + 1, y, regions)
36+
val left = dfs(board, x, y - 1, regions)
37+
val right = dfs(board, x, y + 1, regions)
38+
return up && down && left && right
39+
}
40+
}
41+
```
42+
43+
### Failed Cases
44+
```js
45+
O X X
46+
O O X
47+
O X X
48+
```

leetcode/141.linked-list-cycle.md

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,34 @@ We can use two pointers approach to solve this with `O(1)` space:
2424
fun hasCycle(head: ListNode?): Boolean {
2525
var slow: ListNode? = head
2626
var fast: ListNode? = head
27-
while (fast != null && fast?.next != null) {
27+
while (fast != null && fast.next != null) {
2828
show = show?.next
2929
fast = fast?.next?.next
30+
if (fast == slow) return true
31+
}
32+
return false
33+
}
34+
```
3035

31-
if (show == fast) {
32-
return true
33-
}
36+
For two pointers approach, there are some equivalent implementations:
37+
38+
> **Important**!! But we will choose above impelementation since it will affect the idea and result of [142. Linked List Cycle II](https://leetcode.com/problems/linked-list-cycle-ii/).
39+
40+
```kotlin
41+
/// Slow 1, fast 2
42+
// **Slow 2, fast 4
43+
// Slow 2, fast 4
44+
// **Slow 3, fast 3
45+
// Slow 3, fast 3
46+
//true
47+
fun hasCycle2(head: ListNode?): Boolean {
48+
var slow: ListNode? = head
49+
var fast: ListNode? = head?.next
50+
while (slow != null) {
51+
if (slow == fast) return true
52+
slow = slow.next
53+
fast = fast?.next?.next
3454
}
3555
return false
3656
}
37-
```
57+
```

leetcode/142.linked-list-cycle-ii.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ fun detectCycle(head: ListNode?): ListNode? {
1818
We can use two pointers approach to solve this with `O(1)` space. (like [the solution](../leetcode/141.linked-list-cycle.md) with some extra steps)
1919

2020
> Explanation: https://leetcode.cn/problems/linked-list-cycle-ii/solution/142-huan-xing-lian-biao-ii-jian-hua-gong-shi-jia-2/
21+
>
22+
> There are some equivalent two pointers implementation, but we have make sure that `slow` and `fast` pointers **start from the same node**!!.
2123
2224
```kotlin
2325
fun detectCycle(head: ListNode?): ListNode? {

leetcode/200.number-of-islands.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
## [200. Number of Islands](https://leetcode.com/problems/number-of-islands/)
2+
3+
### DFS
4+
```kotlin
5+
class Solution {
6+
7+
private val visited = hashSetOf<Pair<Int, Int>>()
8+
private var numberOfIslands = 0
9+
10+
fun numIslands(grid: Array<CharArray>): Int {
11+
12+
for (m in 0 until grid.size) {
13+
for (n in 0 until gridcharArrayOf(m).size) {
14+
if (!visited.contains(m to n) && gridcharArrayOf(m)charArrayOf(n) == '1') {
15+
dfs(grid, m, n)
16+
numberOfIslands++
17+
}
18+
}
19+
}
20+
return numberOfIslands
21+
}
22+
23+
private fun dfs(grid: Array<CharArray>, x: Int, y: Int) {
24+
if (x < 0 || y < 0 || x >= grid.size || y >= gridcharArrayOf(0).size || gridcharArrayOf(x)charArrayOf(y) == '0' || visited.contains(x to y)) return
25+
26+
visited.add(x to y)
27+
dfs(grid, x - 1, y)
28+
dfs(grid, x + 1, y)
29+
dfs(grid, x, y - 1)
30+
dfs(grid, x, y + 1)
31+
}
32+
}
33+
```
34+
35+
### BFS
36+
```kotlin
37+
class Solution {
38+
private val visited = hashSetOf<Pair<Int, Int>>()
39+
fun numIslands(grid: Array<CharArray>): Int {
40+
var numOfIslands = 0
41+
42+
for (m in 0 until grid.size) {
43+
for (n in 0 until grid[m].size) {
44+
if (grid[m][n] == '1' && !visited.contains(m to n)) {
45+
val queue = ArrayDeque<Pair<Int, Int>>()
46+
queue.addLast(m to n)
47+
while (!queue.isEmpty()) {
48+
val node = queue.removeFirst()
49+
val x = node.first
50+
val y = node.second
51+
52+
if (!validPosition(grid, x, y)) continue
53+
visited.add(x to y)
54+
queue.addLast(x - 1 to y)
55+
queue.addLast(x + 1 to y)
56+
queue.addLast(x to y - 1)
57+
queue.addLast(x to y + 1)
58+
}
59+
numOfIslands++
60+
}
61+
}
62+
}
63+
return numOfIslands
64+
}
65+
66+
private fun validPosition(grid: Array<CharArray>, x: Int, y: Int) =
67+
x in 0..grid.size - 1 && y in 0..grid[x].size - 1 && grid[x][y] == '1' && !visited.contains(x to y)
68+
}
69+
```

leetcode/203.remove-linked-list-elements.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
When deleting a node, we can implement in the following way:
1212

1313
```kotlin
14-
var previous: ListNode? = sentinel
14+
var previous: ListNode? = null
1515
var current: ListNode? = head
1616
while (current != null) {
1717
if (current == nodeToDelete) {
@@ -31,6 +31,7 @@ We introduce *sentinel node* to help us when deleting the head node so that we c
3131
fun removeElements(head: ListNode?, `val`: Int): ListNode? {
3232
val sentinel = ListNode(-1)
3333
sentinel.next = head
34+
// Here is different part.
3435
var previous: ListNode? = sentinel
3536
var current: ListNode? = head
3637
while (current != null) {

leetcode/206.reverse-linked-list.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
## [206. Reverse Linked List](https://leetcode.com/problems/reverse-linked-list/)
22

33
```kotlin
4-
data class ListNode(
5-
val value: Int,
6-
var next: ListNode? = null
7-
)
8-
94
fun reverseList(head: ListNode?): ListNode? {
105
var previous: ListNode? = null
116
var current: ListNode? = head
@@ -21,3 +16,4 @@ fun reverseList(head: ListNode?): ListNode? {
2116
return previous
2217
}
2318
```
19+

0 commit comments

Comments
 (0)