mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-08 16:54:50 +08:00
@ -236,9 +236,222 @@ for (int j = 0; j < m; j++) {
|
||||
|
||||
空间复杂度为:O(n * m) 这个就不难理解了。开了几个 n * m 的数组。
|
||||
|
||||
|
||||
## 其他语言版本
|
||||
|
||||
### Java
|
||||
|
||||
深度优先遍历:
|
||||
|
||||
```Java
|
||||
class Solution {
|
||||
// 四个位置
|
||||
private static final int[][] position = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
|
||||
|
||||
/**
|
||||
* @param heights 题目给定的二维数组
|
||||
* @param row 当前位置的行号
|
||||
* @param col 当前位置的列号
|
||||
* @param sign 记录是哪一条河,两条河中可以一个为 0,一个为 1
|
||||
* @param visited 记录这个位置可以到哪条河
|
||||
*/
|
||||
public void dfs(int[][] heights, int row, int col, int sign, boolean[][][] visited) {
|
||||
for (int[] current: position) {
|
||||
int curRow = row + current[0], curCol = col + current[1];
|
||||
// 越界
|
||||
if (curRow < 0 || curRow >= heights.length || curCol < 0 || curCol >= heights[0].length)
|
||||
continue;
|
||||
// 高度不合适或者已经被访问过了
|
||||
if (heights[curRow][curCol] < heights[row][col] || visited[curRow][curCol][sign]) continue;
|
||||
visited[curRow][curCol][sign] = true;
|
||||
dfs(heights, curRow, curCol, sign, visited);
|
||||
}
|
||||
}
|
||||
|
||||
public List<List<Integer>> pacificAtlantic(int[][] heights) {
|
||||
int rowSize = heights.length, colSize = heights[0].length;
|
||||
List<List<Integer>> ans = new ArrayList<>();
|
||||
// 记录 [row, col] 位置是否可以到某条河,可以为 true,反之为 false;
|
||||
// 假设太平洋的标记为 1,大西洋为 0
|
||||
boolean[][][] visited = new boolean[rowSize][colSize][2];
|
||||
for (int row = 0; row < rowSize; row++) {
|
||||
visited[row][colSize - 1][0] = true;
|
||||
visited[row][0][1] = true;
|
||||
dfs(heights, row, colSize - 1, 0, visited);
|
||||
dfs(heights, row, 0, 1, visited);
|
||||
}
|
||||
for (int col = 0; col < colSize; col++) {
|
||||
visited[rowSize - 1][col][0] = true;
|
||||
visited[0][col][1] = true;
|
||||
dfs(heights, rowSize - 1, col, 0, visited);
|
||||
dfs(heights, 0, col, 1, visited);
|
||||
}
|
||||
for (int row = 0; row < rowSize; row++) {
|
||||
for (int col = 0; col < colSize; col++) {
|
||||
// 如果该位置即可以到太平洋又可以到大西洋,就放入答案数组
|
||||
if (visited[row][col][0] && visited[row][col][1])
|
||||
ans.add(List.of(row, col));
|
||||
}
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
广度优先遍历:
|
||||
|
||||
```Java
|
||||
class Solution {
|
||||
// 四个位置
|
||||
private static final int[][] position = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
|
||||
|
||||
/**
|
||||
* @param heights 题目给定的二维数组
|
||||
* @param queue 记录可以到达边界的节点
|
||||
* @param visited 记录这个位置可以到哪条河
|
||||
*/
|
||||
public void bfs(int[][] heights, Queue<int[]> queue, boolean[][][] visited) {
|
||||
while (!queue.isEmpty()) {
|
||||
int[] curPos = queue.poll();
|
||||
for (int[] current: position) {
|
||||
int row = curPos[0] + current[0], col = curPos[1] + current[1], sign = curPos[2];
|
||||
// 越界
|
||||
if (row < 0 || row >= heights.length || col < 0 || col >= heights[0].length) continue;
|
||||
// 高度不合适或者已经被访问过了
|
||||
if (heights[row][col] < heights[curPos[0]][curPos[1]] || visited[row][col][sign]) continue;
|
||||
visited[row][col][sign] = true;
|
||||
queue.add(new int[]{row, col, sign});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<List<Integer>> pacificAtlantic(int[][] heights) {
|
||||
int rowSize = heights.length, colSize = heights[0].length;
|
||||
List<List<Integer>> ans = new ArrayList<>();
|
||||
boolean[][][] visited = new boolean[rowSize][colSize][2];
|
||||
// 队列,保存的数据为 [行号, 列号, 标记]
|
||||
// 假设太平洋的标记为 1,大西洋为 0
|
||||
Queue<int[]> queue = new ArrayDeque<>();
|
||||
for (int row = 0; row < rowSize; row++) {
|
||||
visited[row][colSize - 1][0] = true;
|
||||
visited[row][0][1] = true;
|
||||
queue.add(new int[]{row, colSize - 1, 0});
|
||||
queue.add(new int[]{row, 0, 1});
|
||||
}
|
||||
for (int col = 0; col < colSize; col++) {
|
||||
visited[rowSize - 1][col][0] = true;
|
||||
visited[0][col][1] = true;
|
||||
queue.add(new int[]{rowSize - 1, col, 0});
|
||||
queue.add(new int[]{0, col, 1});
|
||||
}
|
||||
bfs(heights, queue, visited);
|
||||
for (int row = 0; row < rowSize; row++) {
|
||||
for (int col = 0; col < colSize; col++) {
|
||||
// 如果该位置即可以到太平洋又可以到大西洋,就放入答案数组
|
||||
if (visited[row][col][0] && visited[row][col][1])
|
||||
ans.add(List.of(row, col));
|
||||
}
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Python
|
||||
|
||||
深度优先遍历
|
||||
|
||||
```Python3
|
||||
class Solution:
|
||||
def __init__(self):
|
||||
self.position = [[-1, 0], [0, 1], [1, 0], [0, -1]] # 四个方向
|
||||
|
||||
# heights:题目给定的二维数组, row:当前位置的行号, col:当前位置的列号
|
||||
# sign:记录是哪一条河,两条河中可以一个为 0,一个为 1
|
||||
# visited:记录这个位置可以到哪条河
|
||||
def dfs(self, heights: List[List[int]], row: int, col: int, sign: int, visited: List[List[List[int]]]):
|
||||
for current in self.position:
|
||||
curRow, curCol = row + current[0], col + current[1]
|
||||
# 索引下标越界
|
||||
if curRow < 0 or curRow >= len(heights) or curCol < 0 or curCol >= len(heights[0]): continue
|
||||
# 不满足条件或者已经被访问过
|
||||
if heights[curRow][curCol] < heights[row][col] or visited[curRow][curCol][sign]: continue
|
||||
visited[curRow][curCol][sign] = True
|
||||
self.dfs(heights, curRow, curCol, sign, visited)
|
||||
|
||||
def pacificAtlantic(self, heights: List[List[int]]) -> List[List[int]]:
|
||||
rowSize, colSize = len(heights), len(heights[0])
|
||||
# visited 记录 [row, col] 位置是否可以到某条河,可以为 true,反之为 false;
|
||||
# 假设太平洋的标记为 1,大西洋为 0
|
||||
# ans 用来保存满足条件的答案
|
||||
ans, visited = [], [[[False for _ in range(2)] for _ in range(colSize)] for _ in range(rowSize)]
|
||||
for row in range(rowSize):
|
||||
visited[row][0][1] = True
|
||||
visited[row][colSize - 1][0] = True
|
||||
self.dfs(heights, row, 0, 1, visited)
|
||||
self.dfs(heights, row, colSize - 1, 0, visited)
|
||||
for col in range(0, colSize):
|
||||
visited[0][col][1] = True
|
||||
visited[rowSize - 1][col][0] = True
|
||||
self.dfs(heights, 0, col, 1, visited)
|
||||
self.dfs(heights, rowSize - 1, col, 0, visited)
|
||||
for row in range(rowSize):
|
||||
for col in range(colSize):
|
||||
# 如果该位置即可以到太平洋又可以到大西洋,就放入答案数组
|
||||
if visited[row][col][0] and visited[row][col][1]:
|
||||
ans.append([row, col])
|
||||
return ans
|
||||
```
|
||||
|
||||
广度优先遍历
|
||||
|
||||
```Python3
|
||||
class Solution:
|
||||
def __init__(self):
|
||||
self.position = [[-1, 0], [0, 1], [1, 0], [0, -1]]
|
||||
|
||||
# heights:题目给定的二维数组,visited:记录这个位置可以到哪条河
|
||||
def bfs(self, heights: List[List[int]], queue: deque, visited: List[List[List[int]]]):
|
||||
while queue:
|
||||
curPos = queue.popleft()
|
||||
for current in self.position:
|
||||
row, col, sign = curPos[0] + current[0], curPos[1] + current[1], curPos[2]
|
||||
# 越界
|
||||
if row < 0 or row >= len(heights) or col < 0 or col >= len(heights[0]): continue
|
||||
# 不满足条件或已经访问过
|
||||
if heights[row][col] < heights[curPos[0]][curPos[1]] or visited[row][col][sign]: continue
|
||||
visited[row][col][sign] = True
|
||||
queue.append([row, col, sign])
|
||||
|
||||
def pacificAtlantic(self, heights: List[List[int]]) -> List[List[int]]:
|
||||
rowSize, colSize = len(heights), len(heights[0])
|
||||
# visited 记录 [row, col] 位置是否可以到某条河,可以为 true,反之为 false;
|
||||
# 假设太平洋的标记为 1,大西洋为 0
|
||||
# ans 用来保存满足条件的答案
|
||||
ans, visited = [], [[[False for _ in range(2)] for _ in range(colSize)] for _ in range(rowSize)]
|
||||
# 队列,保存的数据为 [行号, 列号, 标记]
|
||||
# 假设太平洋的标记为 1,大西洋为 0
|
||||
queue = deque()
|
||||
for row in range(rowSize):
|
||||
visited[row][0][1] = True
|
||||
visited[row][colSize - 1][0] = True
|
||||
queue.append([row, 0, 1])
|
||||
queue.append([row, colSize - 1, 0])
|
||||
for col in range(0, colSize):
|
||||
visited[0][col][1] = True
|
||||
visited[rowSize - 1][col][0] = True
|
||||
queue.append([0, col, 1])
|
||||
queue.append([rowSize - 1, col, 0])
|
||||
self.bfs(heights, queue, visited) # 广度优先遍历
|
||||
for row in range(rowSize):
|
||||
for col in range(colSize):
|
||||
# 如果该位置即可以到太平洋又可以到大西洋,就放入答案数组
|
||||
if visited[row][col][0] and visited[row][col][1]:
|
||||
ans.append([row, col])
|
||||
return ans
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
<p align="center">
|
||||
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
||||
|
@ -144,6 +144,232 @@ public:
|
||||
}
|
||||
};
|
||||
```
|
||||
## 其他语言版本
|
||||
|
||||
### Java
|
||||
|
||||
深度优先遍历版本:
|
||||
|
||||
```java
|
||||
class Solution {
|
||||
// 四个方向
|
||||
private static final int[][] position = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
|
||||
|
||||
// 深度优先遍历,把可以通向边缘部分的 1 全部标记成 true
|
||||
public void dfs(int[][] grid, int row, int col, boolean[][] visited) {
|
||||
for (int[] current: position) {
|
||||
int newRow = row + current[0], newCol = col + current[1];
|
||||
// 下标越界直接跳过
|
||||
if (newRow < 0 || newRow >= grid.length || newCol < 0 || newCol >= grid[0].length) continue;
|
||||
// 当前位置不是 1 或者已经被访问了就直接跳过
|
||||
if (grid[newRow][newCol] != 1 || visited[newRow][newCol]) continue;
|
||||
visited[newRow][newCol] = true;
|
||||
dfs(grid, newRow, newCol, visited);
|
||||
}
|
||||
}
|
||||
|
||||
public int numEnclaves(int[][] grid) {
|
||||
int rowSize = grid.length, colSize = grid[0].length, ans = 0; // ans 记录答案
|
||||
// 标记数组记录每个值为 1 的位置是否可以到达边界,可以为 true,反之为 false
|
||||
boolean[][] visited = new boolean[rowSize][colSize];
|
||||
// 左侧边界和右侧边界查找 1 进行标记并进行深度优先遍历
|
||||
for (int row = 0; row < rowSize; row++) {
|
||||
if (grid[row][0] == 1 && !visited[row][0]) {
|
||||
visited[row][0] = true;
|
||||
dfs(grid, row, 0, visited);
|
||||
}
|
||||
if (grid[row][colSize - 1] == 1 && !visited[row][colSize - 1]) {
|
||||
visited[row][colSize - 1] = true;
|
||||
dfs(grid, row, colSize - 1, visited);
|
||||
}
|
||||
}
|
||||
// 上边界和下边界遍历,但是四个角不用遍历,因为上面已经遍历到了
|
||||
for (int col = 1; col < colSize - 1; col++) {
|
||||
if (grid[0][col] == 1 && !visited[0][col]) {
|
||||
visited[0][col] = true;
|
||||
dfs(grid, 0, col, visited);
|
||||
}
|
||||
if (grid[rowSize - 1][col] == 1 && !visited[rowSize - 1][col]) {
|
||||
visited[rowSize - 1][col] = true;
|
||||
dfs(grid, rowSize - 1, col, visited);
|
||||
}
|
||||
}
|
||||
// 查找没有标记过的 1,记录到 ans 中
|
||||
for (int row = 0; row < rowSize; row++) {
|
||||
for (int col = 0; col < colSize; col++) {
|
||||
if (grid[row][col] == 1 && !visited[row][col]) ++ans;
|
||||
}
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
广度优先遍历版本:
|
||||
|
||||
```java
|
||||
class Solution {
|
||||
// 四个方向
|
||||
private static final int[][] position = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
|
||||
|
||||
// 广度优先遍历,把可以通向边缘部分的 1 全部标记成 true
|
||||
public void bfs(int[][] grid, Queue<int[]> queue, boolean[][] visited) {
|
||||
while (!queue.isEmpty()) {
|
||||
int[] curPos = queue.poll();
|
||||
for (int[] current: position) {
|
||||
int row = curPos[0] + current[0], col = curPos[1] + current[1];
|
||||
// 下标越界直接跳过
|
||||
if (row < 0 || row >= grid.length || col < 0 || col >= grid[0].length)
|
||||
continue;
|
||||
// 当前位置不是 1 或者已经被访问了就直接跳过
|
||||
if (visited[row][col] || grid[row][col] == 0) continue;
|
||||
visited[row][col] = true;
|
||||
queue.add(new int[]{row, col});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int numEnclaves(int[][] grid) {
|
||||
int rowSize = grid.length, colSize = grid[0].length, ans = 0; // ans 记录答案
|
||||
// 标记数组记录每个值为 1 的位置是否可以到达边界,可以为 true,反之为 false
|
||||
boolean[][] visited = new boolean[rowSize][colSize];
|
||||
Queue<int[]> queue = new ArrayDeque<>();
|
||||
// 搜索左侧边界和右侧边界查找 1 存入队列
|
||||
for (int row = 0; row < rowSize; row++) {
|
||||
if (grid[row][0] == 1) {
|
||||
visited[row][0] = true;
|
||||
queue.add(new int[]{row, 0});
|
||||
}
|
||||
if (grid[row][colSize - 1] == 1) {
|
||||
visited[row][colSize - 1] = true;
|
||||
queue.add(new int[]{row, colSize - 1});
|
||||
}
|
||||
}
|
||||
// 搜索上边界和下边界遍历,但是四个角不用遍历,因为上面已经遍历到了
|
||||
for (int col = 1; col < colSize - 1; col++) {
|
||||
if (grid[0][col] == 1) {
|
||||
visited[0][col] = true;
|
||||
queue.add(new int[]{0, col});
|
||||
}
|
||||
if (grid[rowSize - 1][col] == 1 && !visited[rowSize - 1][col]) {
|
||||
visited[rowSize - 1][col] = true;
|
||||
queue.add(new int[]{rowSize - 1, col});
|
||||
}
|
||||
}
|
||||
bfs(grid, queue, visited); // 广度优先遍历
|
||||
// 查找没有标记过的 1,记录到 ans 中
|
||||
for (int row = 0; row < rowSize; row++) {
|
||||
for (int col = 0; col < colSize; col++) {
|
||||
if (grid[row][col] == 1 && !visited[row][col]) ++ans;
|
||||
}
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Python
|
||||
|
||||
深度优先遍历
|
||||
|
||||
```Python3
|
||||
class Solution:
|
||||
def __init__(self):
|
||||
self.position = [[-1, 0], [0, 1], [1, 0], [0, -1]] # 四个方向
|
||||
|
||||
# 深度优先遍历,把可以通向边缘部分的 1 全部标记成 true
|
||||
def dfs(self, grid: List[List[int]], row: int, col: int, visited: List[List[bool]]) -> None:
|
||||
for current in self.position:
|
||||
newRow, newCol = row + current[0], col + current[1]
|
||||
# 索引下标越界
|
||||
if newRow < 0 or newRow >= len(grid) or newCol < 0 or newCol >= len(grid[0]):
|
||||
continue
|
||||
# 当前位置值不是 1 或者已经被访问过了
|
||||
if grid[newRow][newCol] == 0 or visited[newRow][newCol]: continue
|
||||
visited[newRow][newCol] = True
|
||||
self.dfs(grid, newRow, newCol, visited)
|
||||
|
||||
def numEnclaves(self, grid: List[List[int]]) -> int:
|
||||
rowSize, colSize, ans = len(grid), len(grid[0]), 0
|
||||
# 标记数组记录每个值为 1 的位置是否可以到达边界,可以为 True,反之为 False
|
||||
visited = [[False for _ in range(colSize)] for _ in range(rowSize)]
|
||||
# 搜索左边界和右边界,对值为 1 的位置进行深度优先遍历
|
||||
for row in range(rowSize):
|
||||
if grid[row][0] == 1:
|
||||
visited[row][0] = True
|
||||
self.dfs(grid, row, 0, visited)
|
||||
if grid[row][colSize - 1] == 1:
|
||||
visited[row][colSize - 1] = True
|
||||
self.dfs(grid, row, colSize - 1, visited)
|
||||
# 搜索上边界和下边界,对值为 1 的位置进行深度优先遍历,但是四个角不需要,因为上面遍历过了
|
||||
for col in range(1, colSize - 1):
|
||||
if grid[0][col] == 1:
|
||||
visited[0][col] = True
|
||||
self.dfs(grid, 0, col, visited)
|
||||
if grid[rowSize - 1][col] == 1:
|
||||
visited[rowSize - 1][col] = True
|
||||
self.dfs(grid, rowSize - 1, col, visited)
|
||||
# 找出矩阵中值为 1 但是没有被标记过的位置,记录答案
|
||||
for row in range(rowSize):
|
||||
for col in range(colSize):
|
||||
if grid[row][col] == 1 and not visited[row][col]:
|
||||
ans += 1
|
||||
return ans
|
||||
```
|
||||
|
||||
广度优先遍历
|
||||
|
||||
```Python3
|
||||
class Solution:
|
||||
def __init__(self):
|
||||
self.position = [[-1, 0], [0, 1], [1, 0], [0, -1]] # 四个方向
|
||||
|
||||
# 广度优先遍历,把可以通向边缘部分的 1 全部标记成 true
|
||||
def bfs(self, grid: List[List[int]], queue: deque, visited: List[List[bool]]) -> None:
|
||||
while queue:
|
||||
curPos = queue.popleft()
|
||||
for current in self.position:
|
||||
row, col = curPos[0] + current[0], curPos[1] + current[1]
|
||||
# 索引下标越界
|
||||
if row < 0 or row >= len(grid) or col < 0 or col >= len(grid[0]): continue
|
||||
# 当前位置值不是 1 或者已经被访问过了
|
||||
if grid[row][col] == 0 or visited[row][col]: continue
|
||||
visited[row][col] = True
|
||||
queue.append([row, col])
|
||||
|
||||
|
||||
def numEnclaves(self, grid: List[List[int]]) -> int:
|
||||
rowSize, colSize, ans = len(grid), len(grid[0]), 0
|
||||
# 标记数组记录每个值为 1 的位置是否可以到达边界,可以为 True,反之为 False
|
||||
visited = [[False for _ in range(colSize)] for _ in range(rowSize)]
|
||||
queue = deque() # 队列
|
||||
# 搜索左侧边界和右侧边界查找 1 存入队列
|
||||
for row in range(rowSize):
|
||||
if grid[row][0] == 1:
|
||||
visited[row][0] = True
|
||||
queue.append([row, 0])
|
||||
if grid[row][colSize - 1] == 1:
|
||||
visited[row][colSize - 1] = True
|
||||
queue.append([row, colSize - 1])
|
||||
# 搜索上边界和下边界查找 1 存入队列,但是四个角不用遍历,因为上面已经遍历到了
|
||||
for col in range(1, colSize - 1):
|
||||
if grid[0][col] == 1:
|
||||
visited[0][col] = True
|
||||
queue.append([0, col])
|
||||
if grid[rowSize - 1][col] == 1:
|
||||
visited[rowSize - 1][col] = True
|
||||
queue.append([rowSize - 1, col])
|
||||
self.bfs(grid, queue, visited) # 广度优先遍历
|
||||
# 找出矩阵中值为 1 但是没有被标记过的位置,记录答案
|
||||
for row in range(rowSize):
|
||||
for col in range(colSize):
|
||||
if grid[row][col] == 1 and not visited[row][col]:
|
||||
ans += 1
|
||||
return ans
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 类似题目
|
||||
|
||||
* 1254. 统计封闭岛屿的数目
|
||||
@ -153,3 +379,4 @@ public:
|
||||
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
||||
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
||||
</a>
|
||||
|
||||
|
Reference in New Issue
Block a user