From a01c5ccb0094170ccc267ec117c9b5366d23e057 Mon Sep 17 00:00:00 2001 From: yennanliu Date: Fri, 6 Oct 2023 17:38:26 +0800 Subject: [PATCH] add 286 java, update 286 py, cheatsheet, progress --- README.md | 2 +- data/progress.txt | 2 +- data/to_review.txt | 18 +- doc/cheatsheet/bfs.md | 98 +++++++++ .../java/LeetCodeJava/BFS/WallsAndGates.java | 205 ++++++++++++++++++ .../Breadth-First-Search/walls-and-gates.py | 98 +++++---- 6 files changed, 373 insertions(+), 50 deletions(-) create mode 100644 leetcode_java/src/main/java/LeetCodeJava/BFS/WallsAndGates.java diff --git a/README.md b/README.md index 8ed68ff8a..e5292a043 100644 --- a/README.md +++ b/README.md @@ -870,7 +870,7 @@ 207| [Course Schedule](https://leetcode.com/problems/course-schedule/)| [Python](./leetcode_python/Breadth-First-Search/course-schedule.py), [Java](./leetcode_java/src/main/java/LeetCodeJava/BFS/CourseSchedule.java) | _O(\|V\| + \|E\|)_ | _O(\|E\|)_ | Medium |Curated Top 75, Topological Sort, backtrack, `good trick`,`dfs`, `bfs` , `amazon`,`fb`| AGAIN**************** (12) (MUST) 210| [Course Schedule II](https://leetcode.com/problems/course-schedule-ii/)| [Python](./leetcode_python/Breadth-First-Search/course-schedule-ii.py) | _O(\|V\| + \|E\|)_ | _O(\|E\|)_ | Medium |Topological Sort,check `# 207 Course Schedule ` first, `dfs`, `bfs` ,`amazon` ,`fb` | AGAIN********* (9) (again) 261| [Graph Valid Tree](https://leetcode.com/problems/graph-valid-tree/)| [Python](./leetcode_python/Breadth-First-Search/graph-valid-tree.py) | _O(\|V\| + \|E\|)_ | _O(\|V\| + \|E\|)_ | Medium | Curated Top 75, AGAIN, bfs, dfs, grpah, 🔒, `graph`,`quick union`,`union find` ,`google`,`amazon`,`fb`| AGAIN************* (8) -286| [Walls and Gates](https://leetcode.com/problems/walls-and-gates/)| [Python](./leetcode_python/Breadth-First-Search/walls-and-gates.py) | _O(m * n)_ | _O(g)_ | Medium | 🔒, `dfs`, `bfs` , `good basic`, `google`,`amazon`,`FB`| AGAIN******** (7) +286| [Walls and Gates](https://leetcode.com/problems/walls-and-gates/)| [Python](./leetcode_python/Breadth-First-Search/walls-and-gates.py), [Java](./leetcode_java/src/main/java/LeetCodeJava/BFS/WallsAndGates.java)| _O(m * n)_ | _O(g)_ | Medium | 🔒, `dfs`, `bfs` , `good basic`, `google`,`amazon`,`FB`| AGAIN******** (7) 310| [Minimum Height Trees](https://leetcode.com/problems/minimum-height-trees/)| [Python](./leetcode_python/Breadth-First-Search/minimum-height-trees.py) | _O(n)_ | _O(n)_ | Medium |`complex`| AGAIN (3) (not start) 433| [Minimum Genetic Mutation](https://leetcode.com/problems/minimum-genetic-mutation/)| [Python](./leetcode_python/Breadth-First-Search/minimum-genetic-mutation.py) | _O(n * b)_ | _O(b)_ | Medium |check `# 127 Word Ladder`, `good basic`| AGAIN*** (3) 444| [Sequence Reconstruction](https://leetcode.com/problems/sequence-reconstruction/)| [Python](./leetcode_python/Breadth-First-Search/sequence-reconstruction.py) | _O(n * s)_ | _O(n)_ | Medium | 🔒 Topological Sort , `google`, `airbnb`| AGAIN** (3) (not start) diff --git a/data/progress.txt b/data/progress.txt index a1f239fbf..96c0a6f2c 100644 --- a/data/progress.txt +++ b/data/progress.txt @@ -1,4 +1,4 @@ -20231006: quick_sort +20231006: quick_sort,286 20231003: 994 20231002: 130 20231001: 417 diff --git a/data/to_review.txt b/data/to_review.txt index 91afa5530..9fef80281 100644 --- a/data/to_review.txt +++ b/data/to_review.txt @@ -1,25 +1,25 @@ -2023-11-30 -> ['quick_sort'] +2023-11-30 -> ['quick_sort,286'] 2023-11-27 -> ['994'] 2023-11-25 -> ['417'] 2023-11-24 -> ['133,695'] -2023-11-09 -> ['quick_sort'] +2023-11-09 -> ['quick_sort,286'] 2023-11-06 -> ['994'] 2023-11-04 -> ['417'] 2023-11-03 -> ['133,695'] 2023-10-28 -> ['654,106,105'] -2023-10-27 -> ['quick_sort'] +2023-10-27 -> ['quick_sort,286'] 2023-10-24 -> ['994', '200'] 2023-10-22 -> ['417'] 2023-10-21 -> ['133,695', '131,17'] -2023-10-19 -> ['quick_sort'] +2023-10-19 -> ['quick_sort,286'] 2023-10-16 -> ['994', '79'] 2023-10-15 -> ['40'] -2023-10-14 -> ['quick_sort', '417', '90'] +2023-10-14 -> ['quick_sort,286', '417', '90'] 2023-10-13 -> ['133,695', '46'] -2023-10-11 -> ['quick_sort', '994'] -2023-10-09 -> ['quick_sort', '417'] -2023-10-08 -> ['quick_sort', '994', '133,695'] -2023-10-07 -> ['quick_sort', '654,106,105', '78,39'] +2023-10-11 -> ['quick_sort,286', '994'] +2023-10-09 -> ['quick_sort,286', '417'] +2023-10-08 -> ['quick_sort,286', '994', '133,695'] +2023-10-07 -> ['quick_sort,286', '654,106,105', '78,39'] 2023-10-06 -> ['994', '417', '355'] 2023-10-05 -> ['994', '133,695', '621'] 2023-10-04 -> ['994', '417'] diff --git a/doc/cheatsheet/bfs.md b/doc/cheatsheet/bfs.md index bd225f5e1..27fe218cd 100644 --- a/doc/cheatsheet/bfs.md +++ b/doc/cheatsheet/bfs.md @@ -411,6 +411,7 @@ class Solution: ``` ### 2-7) Walls and gates ```python +# python # 286 Walls and Gates # note : there is also a dfs solution @@ -436,6 +437,103 @@ class Solution: q.append((new_x, new_y)) ``` +```java +// java +// Lc 286 + public void wallsAndGates(int[][] rooms) { + + class Pair { + U key; + V value; + W value2; + + Pair(U key, V value, W value2) { + this.key = key; + this.value = value; + this.value2 = value2; + } + + U getKey() { + return this.key; + } + + V getValue() { + return this.value; + } + + W getValue2() { + return this.value2; + } + + } + + // edge case + if (rooms.length == 1 && rooms[0].length == 1) { + return; + } + + int space_cnt = 0; + int gete_cnt = 0; + int[][] dirs = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; + + int len = rooms.length; + int width = rooms[0].length; + + // init queue + Queue q = new LinkedList(); + + // get cnt + for (int i = 0; i < width; i++) { + for (int j = 0; j < len; j++) { + if (rooms[j][i] == 0) { + gete_cnt += 1; + // NOTE !!! we should do BFS with "gete" instead of space point + q.add(new Pair(i, j, -1)); + } else if (rooms[j][i] == 2147483647) { + space_cnt += 1; + //q.add(new Pair(i, j, -1)); // append space point to queue, for BFS + } else { + //obstacle_cnt += 1; + } + } + } + + // if there is no gate or no space -> quit directly + if (gete_cnt == 0 || space_cnt == 0) { + return; + } + + // bfs + while (!q.isEmpty()) { + + Pair p = q.poll(); + int x = (int) p.getKey(); + int y = (int) p.getValue(); + int dist = (int) p.getValue2(); + + for (int[] dir : dirs) { + + int dx = dir[0]; + int dy = dir[1]; + int new_x = x + dx; + int new_y = y + dy; + + String idx = new_x + "-" + new_x; + + if (0 <= new_x && new_x < width && 0 <= new_x && new_y < len) { + // NOTE !!! we do NOTHING if point is out of border or point is "NOT a space" + if (new_x < 0 || new_x > width || new_y < 0 || new_y > len || rooms[new_y][new_x] != 2147483647) { + continue; + } + rooms[new_y][new_x] = rooms[y][x] + 1; + q.add(new Pair(new_x, new_y, dist + 1)); + } + + } + } + } +``` + ### 2-8) The Maze ```python # 490 The Maze diff --git a/leetcode_java/src/main/java/LeetCodeJava/BFS/WallsAndGates.java b/leetcode_java/src/main/java/LeetCodeJava/BFS/WallsAndGates.java new file mode 100644 index 000000000..bdb70f3fa --- /dev/null +++ b/leetcode_java/src/main/java/LeetCodeJava/BFS/WallsAndGates.java @@ -0,0 +1,205 @@ +package LeetCodeJava.BFS; + +// https://leetcode.com/problems/walls-and-gates/description/ + +import java.util.*; + +public class WallsAndGates { + + // V0 + // IDEA : BFS + public void wallsAndGates(int[][] rooms) { + + class Pair { + U key; + V value; + W value2; + + Pair(U key, V value, W value2) { + this.key = key; + this.value = value; + this.value2 = value2; + } + + U getKey() { + return this.key; + } + + V getValue() { + return this.value; + } + + W getValue2() { + return this.value2; + } + + } + + // edge case + if (rooms.length == 1 && rooms[0].length == 1) { + return; + } + + int space_cnt = 0; + int gete_cnt = 0; + int[][] dirs = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; + + int len = rooms.length; + int width = rooms[0].length; + + // init queue + Queue q = new LinkedList(); + + // get cnt + for (int i = 0; i < width; i++) { + for (int j = 0; j < len; j++) { + if (rooms[j][i] == 0) { + gete_cnt += 1; + // NOTE !!! we should do BFS with "gete" instead of space point + q.add(new Pair(i, j, -1)); + } else if (rooms[j][i] == 2147483647) { + space_cnt += 1; + //q.add(new Pair(i, j, -1)); // append space point to queue, for BFS + } else { + //obstacle_cnt += 1; + } + } + } + + // if there is no gate or no space -> quit directly + if (gete_cnt == 0 || space_cnt == 0) { + return; + } + + // bfs + while (!q.isEmpty()) { + + Pair p = q.poll(); + int x = (int) p.getKey(); + int y = (int) p.getValue(); + int dist = (int) p.getValue2(); + + for (int[] dir : dirs) { + + int dx = dir[0]; + int dy = dir[1]; + int new_x = x + dx; + int new_y = y + dy; + + String idx = new_x + "-" + new_x; + + if (0 <= new_x && new_x < width && 0 <= new_x && new_y < len) { + + // NOTE !!! don't use logic in commented code +// if (rooms[new_y][new_x] == 0 && !seen.contains(idx)) { +// rooms[new_y][new_x] = dist; +// seen.add(idx); +// } else { +// dist += 1; +// q.add(new Pair(new_x, new_y, dist)); +// } + + // NOTE !!! we do NOTHING if point is out of border or point is "NOT a space" + if (new_x < 0 || new_x > width || new_y < 0 || new_y > len || rooms[new_y][new_x] != 2147483647) { + continue; + } + rooms[new_y][new_x] = rooms[y][x] + 1; + q.add(new Pair(new_x, new_y, dist + 1)); + } + + } + } + } + + // V1 + // IDEA BFS + // https://leetcode.com/problems/walls-and-gates/editorial/ + private static final int EMPTY = Integer.MAX_VALUE; + private static final int GATE = 0; + private static final List DIRECTIONS = Arrays.asList( + new int[]{1, 0}, + new int[]{-1, 0}, + new int[]{0, 1}, + new int[]{0, -1} + ); + + public void wallsAndGates_1(int[][] rooms) { + int m = rooms.length; + if (m == 0) return; + int n = rooms[0].length; + Queue q = new LinkedList<>(); + for (int row = 0; row < m; row++) { + for (int col = 0; col < n; col++) { + if (rooms[row][col] == GATE) { + q.add(new int[]{row, col}); + } + } + } + while (!q.isEmpty()) { + int[] point = q.poll(); + int row = point[0]; + int col = point[1]; + for (int[] direction : DIRECTIONS) { + int r = row + direction[0]; + int c = col + direction[1]; + if (r < 0 || c < 0 || r >= m || c >= n || rooms[r][c] != EMPTY) { + continue; + } + rooms[r][c] = rooms[row][col] + 1; + q.add(new int[]{r, c}); + } + } + } + + // V2 + // IDEA BRUTE FORCE (TLE) + // https://leetcode.com/problems/walls-and-gates/editorial/ +// private static final int EMPTY = Integer.MAX_VALUE; +// private static final int GATE = 0; +// private static final int WALL = -1; +// private static final List DIRECTIONS = Arrays.asList( +// new int[] { 1, 0}, +// new int[] {-1, 0}, +// new int[] { 0, 1}, +// new int[] { 0, -1} +// ); +// +// public void wallsAndGates_2(int[][] rooms) { +// if (rooms.length == 0) return; +// for (int row = 0; row < rooms.length; row++) { +// for (int col = 0; col < rooms[0].length; col++) { +// if (rooms[row][col] == EMPTY) { +// rooms[row][col] = distanceToNearestGate(rooms, row, col); +// } +// } +// } +// } +// +// private int distanceToNearestGate(int[][] rooms, int startRow, int startCol) { +// int m = rooms.length; +// int n = rooms[0].length; +// int[][] distance = new int[m][n]; +// Queue q = new LinkedList<>(); +// q.add(new int[] { startRow, startCol }); +// while (!q.isEmpty()) { +// int[] point = q.poll(); +// int row = point[0]; +// int col = point[1]; +// for (int[] direction : DIRECTIONS) { +// int r = row + direction[0]; +// int c = col + direction[1]; +// if (r < 0 || c < 0 || r >= m || c >= n || rooms[r][c] == WALL +// || distance[r][c] != 0) { +// continue; +// } +// distance[r][c] = distance[row][col] + 1; +// if (rooms[r][c] == GATE) { +// return distance[r][c]; +// } +// q.add(new int[] { r, c }); +// } +// } +// return Integer.MAX_VALUE; +// } + +} diff --git a/leetcode_python/Breadth-First-Search/walls-and-gates.py b/leetcode_python/Breadth-First-Search/walls-and-gates.py index 92a04bab4..6e1ddeda0 100644 --- a/leetcode_python/Breadth-First-Search/walls-and-gates.py +++ b/leetcode_python/Breadth-First-Search/walls-and-gates.py @@ -1,31 +1,73 @@ """ -You are given a m x n 2D grid initialized with these three possible values. +286. Walls and Gates +Medium --1 - A wall or an obstacle. -0 - A gate. -INF - Infinity means an empty room. We use the value 231 - 1 = 2147483647 to represent INF as you may assume that the distance to a gate is less than 2147483647. +company +DoorDash +company +Amazon +company +Facebook + +You are given an m x n grid rooms initialized with these three possible values. + +-1 A wall or an obstacle. +0 A gate. +INF Infinity means an empty room. We use the value 231 - 1 = 2147483647 to represent INF as you may assume that the distance to a gate is less than 2147483647. Fill each empty room with the distance to its nearest gate. If it is impossible to reach a gate, it should be filled with INF. -Example: + + +Example 1: + -Given the 2D grid: +Input: rooms = [[2147483647,-1,0,2147483647],[2147483647,2147483647,2147483647,-1],[2147483647,-1,2147483647,-1],[0,-1,2147483647,2147483647]] +Output: [[3,-1,0,1],[2,2,1,-1],[1,-1,2,-1],[0,-1,3,4]] +Example 2: -INF -1 0 INF -INF INF INF -1 -INF -1 INF -1 -0 -1 INF INF -After running your function, the 2D grid should be: +Input: rooms = [[-1]] +Output: [[-1]] + -3 -1 0 1 -2 2 1 -1 -1 -1 2 -1 -0 -1 3 4 +Constraints: + +m == rooms.length +n == rooms[i].length +1 <= m, n <= 250 +rooms[i][j] is -1, 0, or 231 - 1. """ +# V0 +# IDEA : BFS +class Solution: + def wallsAndGates(self, rooms): + # base case: + if not rooms: + return + row, col = len(rooms), len(rooms[0]) + ### NOTE BELOW TRICK : find the index of a gate + q = [(i, j) for i in range(row) for j in range(col) if rooms[i][j] == 0] + for x, y in q: + """ + NOTE !!! we do BFS with gate points + + -> since BFS make sure shortest distance, and shortest distance between gete and space is what we need + -> get the distance from a gate + """ + distance = rooms[x][y]+1 + directions = [(-1,0), (1,0), (0,-1), (0,1)] + for dx, dy in directions: + # find the INF around the gate + new_x, new_y = x+dx, y+dy + if 0 <= new_x < row and 0 <= new_y < col and rooms[new_x][new_y] == 2147483647: + # update the value + rooms[new_x][new_y] = distance + q.append((new_x, new_y)) + # V0 -# IDEA : DFS +# IDEA : DFS -> TLE (time out error) class Solution: def wallsAndGates(self, rooms: List[List[int]]) -> None: """ @@ -48,31 +90,9 @@ def dfs(self, rooms, x, y, dist): for dx, dy in [(-1,0),(1,0),(0,-1),(0,1)]: self.dfs(rooms, x+dx, y+dy, dist+1) -# V0' -# IDEA : BFS -class Solution: - def wallsAndGates(self, rooms): - # base case: - if not rooms: - return - row, col = len(rooms), len(rooms[0]) - ### NOTE BELOW TRICK : find the index of a gate - q = [(i, j) for i in range(row) for j in range(col) if rooms[i][j] == 0] - for x, y in q: - # get the distance from a gate - distance = rooms[x][y]+1 - directions = [(-1,0), (1,0), (0,-1), (0,1)] - for dx, dy in directions: - # find the INF around the gate - new_x, new_y = x+dx, y+dy - if 0 <= new_x < row and 0 <= new_y < col and rooms[new_x][new_y] == 2147483647: - # update the value - rooms[new_x][new_y] = distance - q.append((new_x, new_y)) - # V1 # https://blog.csdn.net/danspace1/article/details/86615657 -# IDEA : DFS +# IDEA : DFS -> TLE (time out error) # IDEA : # 1) GO THROUGH 2D GRID, GOT THE ZEROS (rooms[i][j] == 0) # 2) DOING DFS OPERATION ON THE ZEROS