From a556497777461c238d5b1f59d2dd5599767912ec Mon Sep 17 00:00:00 2001 From: yanglbme Date: Mon, 19 May 2025 06:35:27 +0800 Subject: [PATCH] feat: add solutions to lc problem: No.3552 No.3552.Grid Teleportation Traversal --- .../README.md | 257 +++++++++++++++++- .../README_EN.md | 257 +++++++++++++++++- .../Solution.cpp | 41 +++ .../Solution.go | 52 ++++ .../Solution.java | 49 ++++ .../Solution.py | 35 +++ .../Solution.ts | 61 +++++ 7 files changed, 744 insertions(+), 8 deletions(-) create mode 100644 solution/3500-3599/3552.Grid Teleportation Traversal/Solution.cpp create mode 100644 solution/3500-3599/3552.Grid Teleportation Traversal/Solution.go create mode 100644 solution/3500-3599/3552.Grid Teleportation Traversal/Solution.java create mode 100644 solution/3500-3599/3552.Grid Teleportation Traversal/Solution.py create mode 100644 solution/3500-3599/3552.Grid Teleportation Traversal/Solution.ts diff --git a/solution/3500-3599/3552.Grid Teleportation Traversal/README.md b/solution/3500-3599/3552.Grid Teleportation Traversal/README.md index 2deb3af923288..dd6f5ca77ef5c 100644 --- a/solution/3500-3599/3552.Grid Teleportation Traversal/README.md +++ b/solution/3500-3599/3552.Grid Teleportation Traversal/README.md @@ -78,32 +78,281 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3500-3599/3552.Gr -### 方法一 +### 方法一:0-1 BFS + +我们可以使用 0-1 BFS 来解决这个问题。我们从左上角单元格开始,使用双端队列来存储当前单元格的坐标。每次从队列中取出一个单元格,我们会检查它的四个相邻单元格,如果相邻单元格是空单元格且没有被访问过,我们就将它加入队列,并更新它的距离。 + +如果相邻单元格是一个传送门,我们就将它加入队列的前面,并更新它的距离。我们还需要维护一个字典来存储每个传送门的位置,以便在使用传送门时能够快速找到它们。 + +我们还需要一个二维数组来存储每个单元格的距离,初始值为无穷大。我们将起点的距离设置为 0,然后开始 BFS。 + +在 BFS 的过程中,我们会检查每个单元格是否是终点,如果是,就返回它的距离。如果队列为空,说明无法到达终点,返回 -1。 + +时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别是矩阵的行数和列数。 #### Python3 ```python - +class Solution: + def minMoves(self, matrix: List[str]) -> int: + m, n = len(matrix), len(matrix[0]) + g = defaultdict(list) + for i, row in enumerate(matrix): + for j, c in enumerate(row): + if c.isalpha(): + g[c].append((i, j)) + dirs = (-1, 0, 1, 0, -1) + dist = [[inf] * n for _ in range(m)] + dist[0][0] = 0 + q = deque([(0, 0)]) + while q: + i, j = q.popleft() + d = dist[i][j] + if i == m - 1 and j == n - 1: + return d + c = matrix[i][j] + if c in g: + for x, y in g[c]: + if d < dist[x][y]: + dist[x][y] = d + q.appendleft((x, y)) + del g[c] + for a, b in pairwise(dirs): + x, y = i + a, j + b + if ( + 0 <= x < m + and 0 <= y < n + and matrix[x][y] != "#" + and d + 1 < dist[x][y] + ): + dist[x][y] = d + 1 + q.append((x, y)) + return -1 ``` #### Java ```java - +class Solution { + public int minMoves(String[] matrix) { + int m = matrix.length, n = matrix[0].length(); + Map> g = new HashMap<>(); + for (int i = 0; i < m; i++) { + String row = matrix[i]; + for (int j = 0; j < n; j++) { + char c = row.charAt(j); + if (Character.isAlphabetic(c)) { + g.computeIfAbsent(c, k -> new ArrayList<>()).add(new int[] {i, j}); + } + } + } + int[] dirs = {-1, 0, 1, 0, -1}; + int INF = Integer.MAX_VALUE / 2; + int[][] dist = new int[m][n]; + for (int[] arr : dist) Arrays.fill(arr, INF); + dist[0][0] = 0; + Deque q = new ArrayDeque<>(); + q.add(new int[] {0, 0}); + while (!q.isEmpty()) { + int[] cur = q.pollFirst(); + int i = cur[0], j = cur[1]; + int d = dist[i][j]; + if (i == m - 1 && j == n - 1) return d; + char c = matrix[i].charAt(j); + if (g.containsKey(c)) { + for (int[] pos : g.get(c)) { + int x = pos[0], y = pos[1]; + if (d < dist[x][y]) { + dist[x][y] = d; + q.addFirst(new int[] {x, y}); + } + } + g.remove(c); + } + for (int idx = 0; idx < 4; idx++) { + int a = dirs[idx], b = dirs[idx + 1]; + int x = i + a, y = j + b; + if (0 <= x && x < m && 0 <= y && y < n && matrix[x].charAt(y) != '#' + && d + 1 < dist[x][y]) { + dist[x][y] = d + 1; + q.addLast(new int[] {x, y}); + } + } + } + return -1; + } +} ``` #### C++ ```cpp - +class Solution { +public: + int minMoves(vector& matrix) { + int m = matrix.size(), n = matrix[0].size(); + unordered_map>> g; + for (int i = 0; i < m; ++i) + for (int j = 0; j < n; ++j) { + char c = matrix[i][j]; + if (isalpha(c)) g[c].push_back({i, j}); + } + int dirs[5] = {-1, 0, 1, 0, -1}; + int INF = numeric_limits::max() / 2; + vector> dist(m, vector(n, INF)); + dist[0][0] = 0; + deque> q; + q.push_back({0, 0}); + while (!q.empty()) { + auto [i, j] = q.front(); + q.pop_front(); + int d = dist[i][j]; + if (i == m - 1 && j == n - 1) return d; + char c = matrix[i][j]; + if (g.count(c)) { + for (auto [x, y] : g[c]) + if (d < dist[x][y]) { + dist[x][y] = d; + q.push_front({x, y}); + } + g.erase(c); + } + for (int idx = 0; idx < 4; ++idx) { + int x = i + dirs[idx], y = j + dirs[idx + 1]; + if (0 <= x && x < m && 0 <= y && y < n && matrix[x][y] != '#' && d + 1 < dist[x][y]) { + dist[x][y] = d + 1; + q.push_back({x, y}); + } + } + } + return -1; + } +}; ``` #### Go ```go +type pair struct{ x, y int } + +func minMoves(matrix []string) int { + m, n := len(matrix), len(matrix[0]) + g := make(map[rune][]pair) + for i := 0; i < m; i++ { + for j, c := range matrix[i] { + if unicode.IsLetter(c) { + g[c] = append(g[c], pair{i, j}) + } + } + } + dirs := []int{-1, 0, 1, 0, -1} + INF := 1 << 30 + dist := make([][]int, m) + for i := range dist { + dist[i] = make([]int, n) + for j := range dist[i] { + dist[i][j] = INF + } + } + dist[0][0] = 0 + q := list.New() + q.PushBack(pair{0, 0}) + for q.Len() > 0 { + cur := q.Remove(q.Front()).(pair) + i, j := cur.x, cur.y + d := dist[i][j] + if i == m-1 && j == n-1 { + return d + } + c := rune(matrix[i][j]) + if v, ok := g[c]; ok { + for _, p := range v { + x, y := p.x, p.y + if d < dist[x][y] { + dist[x][y] = d + q.PushFront(pair{x, y}) + } + } + delete(g, c) + } + for idx := 0; idx < 4; idx++ { + x, y := i+dirs[idx], j+dirs[idx+1] + if 0 <= x && x < m && 0 <= y && y < n && matrix[x][y] != '#' && d+1 < dist[x][y] { + dist[x][y] = d + 1 + q.PushBack(pair{x, y}) + } + } + } + return -1 +} +``` +#### TypeScript + +```ts +function minMoves(matrix: string[]): number { + const m = matrix.length, + n = matrix[0].length; + const g = new Map(); + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + const c = matrix[i][j]; + if (/^[A-Za-z]$/.test(c)) { + if (!g.has(c)) g.set(c, []); + g.get(c)!.push([i, j]); + } + } + } + + const dirs = [-1, 0, 1, 0, -1]; + const INF = Number.MAX_SAFE_INTEGER; + const dist: number[][] = Array.from({ length: m }, () => Array(n).fill(INF)); + dist[0][0] = 0; + + const cap = m * n * 2 + 5; + const dq = new Array<[number, number]>(cap); + let l = cap >> 1, + r = cap >> 1; + const pushFront = (v: [number, number]) => { + dq[--l] = v; + }; + const pushBack = (v: [number, number]) => { + dq[r++] = v; + }; + const popFront = (): [number, number] => dq[l++]; + const empty = () => l === r; + + pushBack([0, 0]); + + while (!empty()) { + const [i, j] = popFront(); + const d = dist[i][j]; + if (i === m - 1 && j === n - 1) return d; + + const c = matrix[i][j]; + if (g.has(c)) { + for (const [x, y] of g.get(c)!) { + if (d < dist[x][y]) { + dist[x][y] = d; + pushFront([x, y]); + } + } + g.delete(c); + } + + for (let idx = 0; idx < 4; idx++) { + const x = i + dirs[idx], + y = j + dirs[idx + 1]; + if (0 <= x && x < m && 0 <= y && y < n && matrix[x][y] !== '#' && d + 1 < dist[x][y]) { + dist[x][y] = d + 1; + pushBack([x, y]); + } + } + } + return -1; +} ``` diff --git a/solution/3500-3599/3552.Grid Teleportation Traversal/README_EN.md b/solution/3500-3599/3552.Grid Teleportation Traversal/README_EN.md index 069e538048bef..27a10479fa929 100644 --- a/solution/3500-3599/3552.Grid Teleportation Traversal/README_EN.md +++ b/solution/3500-3599/3552.Grid Teleportation Traversal/README_EN.md @@ -76,32 +76,281 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3500-3599/3552.Gr -### Solution 1 +### Solution 1: 0-1 BFS + +We can use 0-1 BFS to solve this problem. We start from the top-left cell and use a double-ended queue to store the coordinates of the current cell. Each time we dequeue a cell, we check its four adjacent cells. If an adjacent cell is an empty cell and has not been visited, we add it to the queue and update its distance. + +If an adjacent cell is a portal, we add it to the front of the queue and update its distance. We also need to maintain a dictionary to store the positions of each portal so that we can quickly find them when using a portal. + +We also need a 2D array to store the distance for each cell, initialized to infinity. We set the distance of the starting point to 0 and then start BFS. + +During the BFS process, we check whether each cell is the destination. If it is, we return its distance. If the queue is empty and the destination has not been reached, we return -1. + +The time complexity is $O(m \times n)$, and the space complexity is $O(m \times n)$, where $m$ and $n$ are the number of rows and columns of the matrix, respectively. #### Python3 ```python - +class Solution: + def minMoves(self, matrix: List[str]) -> int: + m, n = len(matrix), len(matrix[0]) + g = defaultdict(list) + for i, row in enumerate(matrix): + for j, c in enumerate(row): + if c.isalpha(): + g[c].append((i, j)) + dirs = (-1, 0, 1, 0, -1) + dist = [[inf] * n for _ in range(m)] + dist[0][0] = 0 + q = deque([(0, 0)]) + while q: + i, j = q.popleft() + d = dist[i][j] + if i == m - 1 and j == n - 1: + return d + c = matrix[i][j] + if c in g: + for x, y in g[c]: + if d < dist[x][y]: + dist[x][y] = d + q.appendleft((x, y)) + del g[c] + for a, b in pairwise(dirs): + x, y = i + a, j + b + if ( + 0 <= x < m + and 0 <= y < n + and matrix[x][y] != "#" + and d + 1 < dist[x][y] + ): + dist[x][y] = d + 1 + q.append((x, y)) + return -1 ``` #### Java ```java - +class Solution { + public int minMoves(String[] matrix) { + int m = matrix.length, n = matrix[0].length(); + Map> g = new HashMap<>(); + for (int i = 0; i < m; i++) { + String row = matrix[i]; + for (int j = 0; j < n; j++) { + char c = row.charAt(j); + if (Character.isAlphabetic(c)) { + g.computeIfAbsent(c, k -> new ArrayList<>()).add(new int[] {i, j}); + } + } + } + int[] dirs = {-1, 0, 1, 0, -1}; + int INF = Integer.MAX_VALUE / 2; + int[][] dist = new int[m][n]; + for (int[] arr : dist) Arrays.fill(arr, INF); + dist[0][0] = 0; + Deque q = new ArrayDeque<>(); + q.add(new int[] {0, 0}); + while (!q.isEmpty()) { + int[] cur = q.pollFirst(); + int i = cur[0], j = cur[1]; + int d = dist[i][j]; + if (i == m - 1 && j == n - 1) return d; + char c = matrix[i].charAt(j); + if (g.containsKey(c)) { + for (int[] pos : g.get(c)) { + int x = pos[0], y = pos[1]; + if (d < dist[x][y]) { + dist[x][y] = d; + q.addFirst(new int[] {x, y}); + } + } + g.remove(c); + } + for (int idx = 0; idx < 4; idx++) { + int a = dirs[idx], b = dirs[idx + 1]; + int x = i + a, y = j + b; + if (0 <= x && x < m && 0 <= y && y < n && matrix[x].charAt(y) != '#' + && d + 1 < dist[x][y]) { + dist[x][y] = d + 1; + q.addLast(new int[] {x, y}); + } + } + } + return -1; + } +} ``` #### C++ ```cpp - +class Solution { +public: + int minMoves(vector& matrix) { + int m = matrix.size(), n = matrix[0].size(); + unordered_map>> g; + for (int i = 0; i < m; ++i) + for (int j = 0; j < n; ++j) { + char c = matrix[i][j]; + if (isalpha(c)) g[c].push_back({i, j}); + } + int dirs[5] = {-1, 0, 1, 0, -1}; + int INF = numeric_limits::max() / 2; + vector> dist(m, vector(n, INF)); + dist[0][0] = 0; + deque> q; + q.push_back({0, 0}); + while (!q.empty()) { + auto [i, j] = q.front(); + q.pop_front(); + int d = dist[i][j]; + if (i == m - 1 && j == n - 1) return d; + char c = matrix[i][j]; + if (g.count(c)) { + for (auto [x, y] : g[c]) + if (d < dist[x][y]) { + dist[x][y] = d; + q.push_front({x, y}); + } + g.erase(c); + } + for (int idx = 0; idx < 4; ++idx) { + int x = i + dirs[idx], y = j + dirs[idx + 1]; + if (0 <= x && x < m && 0 <= y && y < n && matrix[x][y] != '#' && d + 1 < dist[x][y]) { + dist[x][y] = d + 1; + q.push_back({x, y}); + } + } + } + return -1; + } +}; ``` #### Go ```go +type pair struct{ x, y int } + +func minMoves(matrix []string) int { + m, n := len(matrix), len(matrix[0]) + g := make(map[rune][]pair) + for i := 0; i < m; i++ { + for j, c := range matrix[i] { + if unicode.IsLetter(c) { + g[c] = append(g[c], pair{i, j}) + } + } + } + dirs := []int{-1, 0, 1, 0, -1} + INF := 1 << 30 + dist := make([][]int, m) + for i := range dist { + dist[i] = make([]int, n) + for j := range dist[i] { + dist[i][j] = INF + } + } + dist[0][0] = 0 + q := list.New() + q.PushBack(pair{0, 0}) + for q.Len() > 0 { + cur := q.Remove(q.Front()).(pair) + i, j := cur.x, cur.y + d := dist[i][j] + if i == m-1 && j == n-1 { + return d + } + c := rune(matrix[i][j]) + if v, ok := g[c]; ok { + for _, p := range v { + x, y := p.x, p.y + if d < dist[x][y] { + dist[x][y] = d + q.PushFront(pair{x, y}) + } + } + delete(g, c) + } + for idx := 0; idx < 4; idx++ { + x, y := i+dirs[idx], j+dirs[idx+1] + if 0 <= x && x < m && 0 <= y && y < n && matrix[x][y] != '#' && d+1 < dist[x][y] { + dist[x][y] = d + 1 + q.PushBack(pair{x, y}) + } + } + } + return -1 +} +``` +#### TypeScript + +```ts +function minMoves(matrix: string[]): number { + const m = matrix.length, + n = matrix[0].length; + const g = new Map(); + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + const c = matrix[i][j]; + if (/^[A-Za-z]$/.test(c)) { + if (!g.has(c)) g.set(c, []); + g.get(c)!.push([i, j]); + } + } + } + + const dirs = [-1, 0, 1, 0, -1]; + const INF = Number.MAX_SAFE_INTEGER; + const dist: number[][] = Array.from({ length: m }, () => Array(n).fill(INF)); + dist[0][0] = 0; + + const cap = m * n * 2 + 5; + const dq = new Array<[number, number]>(cap); + let l = cap >> 1, + r = cap >> 1; + const pushFront = (v: [number, number]) => { + dq[--l] = v; + }; + const pushBack = (v: [number, number]) => { + dq[r++] = v; + }; + const popFront = (): [number, number] => dq[l++]; + const empty = () => l === r; + + pushBack([0, 0]); + + while (!empty()) { + const [i, j] = popFront(); + const d = dist[i][j]; + if (i === m - 1 && j === n - 1) return d; + + const c = matrix[i][j]; + if (g.has(c)) { + for (const [x, y] of g.get(c)!) { + if (d < dist[x][y]) { + dist[x][y] = d; + pushFront([x, y]); + } + } + g.delete(c); + } + + for (let idx = 0; idx < 4; idx++) { + const x = i + dirs[idx], + y = j + dirs[idx + 1]; + if (0 <= x && x < m && 0 <= y && y < n && matrix[x][y] !== '#' && d + 1 < dist[x][y]) { + dist[x][y] = d + 1; + pushBack([x, y]); + } + } + } + return -1; +} ``` diff --git a/solution/3500-3599/3552.Grid Teleportation Traversal/Solution.cpp b/solution/3500-3599/3552.Grid Teleportation Traversal/Solution.cpp new file mode 100644 index 0000000000000..0565d6c619949 --- /dev/null +++ b/solution/3500-3599/3552.Grid Teleportation Traversal/Solution.cpp @@ -0,0 +1,41 @@ +class Solution { +public: + int minMoves(vector& matrix) { + int m = matrix.size(), n = matrix[0].size(); + unordered_map>> g; + for (int i = 0; i < m; ++i) + for (int j = 0; j < n; ++j) { + char c = matrix[i][j]; + if (isalpha(c)) g[c].push_back({i, j}); + } + int dirs[5] = {-1, 0, 1, 0, -1}; + int INF = numeric_limits::max() / 2; + vector> dist(m, vector(n, INF)); + dist[0][0] = 0; + deque> q; + q.push_back({0, 0}); + while (!q.empty()) { + auto [i, j] = q.front(); + q.pop_front(); + int d = dist[i][j]; + if (i == m - 1 && j == n - 1) return d; + char c = matrix[i][j]; + if (g.count(c)) { + for (auto [x, y] : g[c]) + if (d < dist[x][y]) { + dist[x][y] = d; + q.push_front({x, y}); + } + g.erase(c); + } + for (int idx = 0; idx < 4; ++idx) { + int x = i + dirs[idx], y = j + dirs[idx + 1]; + if (0 <= x && x < m && 0 <= y && y < n && matrix[x][y] != '#' && d + 1 < dist[x][y]) { + dist[x][y] = d + 1; + q.push_back({x, y}); + } + } + } + return -1; + } +}; diff --git a/solution/3500-3599/3552.Grid Teleportation Traversal/Solution.go b/solution/3500-3599/3552.Grid Teleportation Traversal/Solution.go new file mode 100644 index 0000000000000..b53234e90cd69 --- /dev/null +++ b/solution/3500-3599/3552.Grid Teleportation Traversal/Solution.go @@ -0,0 +1,52 @@ +type pair struct{ x, y int } + +func minMoves(matrix []string) int { + m, n := len(matrix), len(matrix[0]) + g := make(map[rune][]pair) + for i := 0; i < m; i++ { + for j, c := range matrix[i] { + if unicode.IsLetter(c) { + g[c] = append(g[c], pair{i, j}) + } + } + } + dirs := []int{-1, 0, 1, 0, -1} + INF := 1 << 30 + dist := make([][]int, m) + for i := range dist { + dist[i] = make([]int, n) + for j := range dist[i] { + dist[i][j] = INF + } + } + dist[0][0] = 0 + q := list.New() + q.PushBack(pair{0, 0}) + for q.Len() > 0 { + cur := q.Remove(q.Front()).(pair) + i, j := cur.x, cur.y + d := dist[i][j] + if i == m-1 && j == n-1 { + return d + } + c := rune(matrix[i][j]) + if v, ok := g[c]; ok { + for _, p := range v { + x, y := p.x, p.y + if d < dist[x][y] { + dist[x][y] = d + q.PushFront(pair{x, y}) + } + } + delete(g, c) + } + for idx := 0; idx < 4; idx++ { + x, y := i+dirs[idx], j+dirs[idx+1] + if 0 <= x && x < m && 0 <= y && y < n && matrix[x][y] != '#' && d+1 < dist[x][y] { + dist[x][y] = d + 1 + q.PushBack(pair{x, y}) + } + } + } + return -1 +} diff --git a/solution/3500-3599/3552.Grid Teleportation Traversal/Solution.java b/solution/3500-3599/3552.Grid Teleportation Traversal/Solution.java new file mode 100644 index 0000000000000..e8010736752ba --- /dev/null +++ b/solution/3500-3599/3552.Grid Teleportation Traversal/Solution.java @@ -0,0 +1,49 @@ +class Solution { + public int minMoves(String[] matrix) { + int m = matrix.length, n = matrix[0].length(); + Map> g = new HashMap<>(); + for (int i = 0; i < m; i++) { + String row = matrix[i]; + for (int j = 0; j < n; j++) { + char c = row.charAt(j); + if (Character.isAlphabetic(c)) { + g.computeIfAbsent(c, k -> new ArrayList<>()).add(new int[] {i, j}); + } + } + } + int[] dirs = {-1, 0, 1, 0, -1}; + int INF = Integer.MAX_VALUE / 2; + int[][] dist = new int[m][n]; + for (int[] arr : dist) Arrays.fill(arr, INF); + dist[0][0] = 0; + Deque q = new ArrayDeque<>(); + q.add(new int[] {0, 0}); + while (!q.isEmpty()) { + int[] cur = q.pollFirst(); + int i = cur[0], j = cur[1]; + int d = dist[i][j]; + if (i == m - 1 && j == n - 1) return d; + char c = matrix[i].charAt(j); + if (g.containsKey(c)) { + for (int[] pos : g.get(c)) { + int x = pos[0], y = pos[1]; + if (d < dist[x][y]) { + dist[x][y] = d; + q.addFirst(new int[] {x, y}); + } + } + g.remove(c); + } + for (int idx = 0; idx < 4; idx++) { + int a = dirs[idx], b = dirs[idx + 1]; + int x = i + a, y = j + b; + if (0 <= x && x < m && 0 <= y && y < n && matrix[x].charAt(y) != '#' + && d + 1 < dist[x][y]) { + dist[x][y] = d + 1; + q.addLast(new int[] {x, y}); + } + } + } + return -1; + } +} diff --git a/solution/3500-3599/3552.Grid Teleportation Traversal/Solution.py b/solution/3500-3599/3552.Grid Teleportation Traversal/Solution.py new file mode 100644 index 0000000000000..9054875c25d98 --- /dev/null +++ b/solution/3500-3599/3552.Grid Teleportation Traversal/Solution.py @@ -0,0 +1,35 @@ +class Solution: + def minMoves(self, matrix: List[str]) -> int: + m, n = len(matrix), len(matrix[0]) + g = defaultdict(list) + for i, row in enumerate(matrix): + for j, c in enumerate(row): + if c.isalpha(): + g[c].append((i, j)) + dirs = (-1, 0, 1, 0, -1) + dist = [[inf] * n for _ in range(m)] + dist[0][0] = 0 + q = deque([(0, 0)]) + while q: + i, j = q.popleft() + d = dist[i][j] + if i == m - 1 and j == n - 1: + return d + c = matrix[i][j] + if c in g: + for x, y in g[c]: + if d < dist[x][y]: + dist[x][y] = d + q.appendleft((x, y)) + del g[c] + for a, b in pairwise(dirs): + x, y = i + a, j + b + if ( + 0 <= x < m + and 0 <= y < n + and matrix[x][y] != "#" + and d + 1 < dist[x][y] + ): + dist[x][y] = d + 1 + q.append((x, y)) + return -1 diff --git a/solution/3500-3599/3552.Grid Teleportation Traversal/Solution.ts b/solution/3500-3599/3552.Grid Teleportation Traversal/Solution.ts new file mode 100644 index 0000000000000..8df2efaf3d7e8 --- /dev/null +++ b/solution/3500-3599/3552.Grid Teleportation Traversal/Solution.ts @@ -0,0 +1,61 @@ +function minMoves(matrix: string[]): number { + const m = matrix.length, + n = matrix[0].length; + const g = new Map(); + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + const c = matrix[i][j]; + if (/^[A-Za-z]$/.test(c)) { + if (!g.has(c)) g.set(c, []); + g.get(c)!.push([i, j]); + } + } + } + + const dirs = [-1, 0, 1, 0, -1]; + const INF = Number.MAX_SAFE_INTEGER; + const dist: number[][] = Array.from({ length: m }, () => Array(n).fill(INF)); + dist[0][0] = 0; + + const cap = m * n * 2 + 5; + const dq = new Array<[number, number]>(cap); + let l = cap >> 1, + r = cap >> 1; + const pushFront = (v: [number, number]) => { + dq[--l] = v; + }; + const pushBack = (v: [number, number]) => { + dq[r++] = v; + }; + const popFront = (): [number, number] => dq[l++]; + const empty = () => l === r; + + pushBack([0, 0]); + + while (!empty()) { + const [i, j] = popFront(); + const d = dist[i][j]; + if (i === m - 1 && j === n - 1) return d; + + const c = matrix[i][j]; + if (g.has(c)) { + for (const [x, y] of g.get(c)!) { + if (d < dist[x][y]) { + dist[x][y] = d; + pushFront([x, y]); + } + } + g.delete(c); + } + + for (let idx = 0; idx < 4; idx++) { + const x = i + dirs[idx], + y = j + dirs[idx + 1]; + if (0 <= x && x < m && 0 <= y && y < n && matrix[x][y] !== '#' && d + 1 < dist[x][y]) { + dist[x][y] = d + 1; + pushBack([x, y]); + } + } + } + return -1; +}