LC-6305.二进制矩阵中翻转最多一次使路径不连通

题目描述

leetcode 中等题

给你一个下标从 0 开始的 m x n 二进制 矩阵 grid 。你可以从一个格子 (row, col) 移动到格子 (row + 1, col) 或者 (row, col + 1) ,前提是前往的格子值为 1 。如果从 (0, 0) 到 (m - 1, n - 1) 没有任何路径,我们称该矩阵是 不连通 的。

你可以翻转 最多一个 格子的值(也可以不翻转)。你 不能翻转 格子 (0, 0) 和 (m - 1, n - 1) 。

如果可以使矩阵不连通,请你返回 true ,否则返回 false 。

注意 ,翻转一个格子的值,可以使它的值从 0 变 1 ,或从 1 变 0 。

示例1:

1
2
3
输入:grid = [[1,1,1],[1,0,0],[1,1,1]]
输出:true
解释:按照上图所示我们翻转蓝色格子里的值,翻转后从 (0, 0) 到 (2, 2) 没有路径。

提示1:

1
2
3
4
5
m == grid.length
n == grid[i].length
1 <= m, n <= 1000
1 <= m * n <= 10^5
grid[0][0] == grid[m - 1][n - 1] == 1

遍历轮廓

下轮廓:优先向下走,否则再向右走

右轮廓:优先向右走,否则再向下走

一个结论是:如果两个轮廓有交集(除了起点终点),那么翻转交集中的任意一个格子,都可以使矩阵不连通。

实际代码中,可以在遍历某个轮廓时,直接将该轮廓的所有点翻转,那么假设第二次出发还能到达终点,则无法使矩阵不连通。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
class Solution {
int m;
int n;

public boolean isPossibleToCutPath(int[][] grid) {
m = grid.length;
n = grid[0].length;
if(!clean(grid, 0, 0)){
return true;
}
Queue<int[]> queue = new ArrayDeque<>();
queue.offer(new int[]{0, 0});
int cnt = 0;
while(!queue.isEmpty()){
int[] index = queue.poll();
if(index[0] == m - 1 && index[1] == n - 1){
return false;
}
if(index[0] + 1 < m && grid[index[0] + 1][index[1]] == 1){
grid[index[0] + 1][index[1]] = 0;
queue.offer(new int[]{index[0] + 1, index[1]});
}
if(index[1] + 1 < n && grid[index[0]][index[1] + 1] == 1){
grid[index[0]][index[1] + 1] = 0;
queue.offer(new int[]{index[0], index[1] + 1});
}
}
return true;
}

private boolean clean(int[][] grid, int x, int y){
if(y == m - 1 && x == n - 1){
return true;
}
grid[y][x] = 0;
if(x + 1 < n && grid[y][x + 1] == 1){
return clean(grid, x + 1, y);
}
if(y + 1 < m && grid[y + 1][x] == 1){
return clean(grid, x, y + 1);
}
return false;
}
}

注意到可以通过一个通用的 $dfs$ 来满足两次遍历的需求,还可以用 $逻辑与$ 来实现优先某个方向的逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
int[][] grid;
int m;
int n;

public boolean isPossibleToCutPath(int[][] grid) {
this.grid = grid;
m = grid.length;
n = grid[0].length;
return !dfs(0, 0) || !dfs(0, 0);
}

private boolean dfs(int x, int y){
if(y == m - 1 && x == n - 1){
return true;
}
grid[y][x] = 0;
return (x + 1 < n && grid[y][x + 1] == 1 && dfs(x + 1, y)) ||
(y + 1 < m && grid[y + 1][x] == 1 && dfs(x, y + 1));
}
}

LC-6305.二进制矩阵中翻转最多一次使路径不连通
https://wecgwm.github.io/2023/02/06/LC-6305-二进制矩阵中翻转最多一次使路径不连通/
作者
yichen
发布于
2023年2月6日
许可协议