leetcode5366. 检查网格中是否存在有效路径
给你一个 m x n 的网格 grid。网格里的每个单元都代表一条街道。grid[i][j] 的街道可以是:
1 表示连接左单元格和右单元格的街道。
2 表示连接上单元格和下单元格的街道。
3 表示连接左单元格和下单元格的街道。
4 表示连接右单元格和下单元格的街道。
5 表示连接左单元格和上单元格的街道。
6 表示连接右单元格和上单元格的街道。
你最开始从左上角的单元格 (0,0) 开始出发,网格中的「有效路径」是指从左上方的单元格 (0,0) 开始、一直到右下方的 (m-1,n-1) 结束的路径。该路径必须只沿着街道走。
注意:你 不能 变更街道。
如果网格中存在有效的路径,则返回 true,否则返回 false 。
我的思路
dfs查找,分6种情况,当前的是哪一种路,然后下一步要走哪一种路,如果不能走就不去搜索。第一次做这种题,代码还是很不好看的。一堆ifelse可以用switch优化。
class Solution {
public boolean hasValidPath(int[][] grid) {
visited=new int[grid.length][grid[0].length];
visited[0][0]=1;
dfs(grid,0,0);
// for(int i=0;i<visited.length;i++){
// for(int j=0;j<visited[i].length;j++){
// System.out.print(visited[i][j]+" ");
// }
// System.out.println();
// }
return flag;
}
public boolean flag=false;
public int[][]visited;
public void dfs(int[][]grid,int x,int y){
//System.out.println("x "+x+"y "+y);
if(x==grid.length-1&&y==grid[0].length-1){
flag=true;
return;
}
int[][]direction={{-1,0},{0,1},{1,0},{0,-1}};
int now=grid[x][y];
//
for(int i=0;i<4;i++){
int nextX=x+direction[i][0];
int nextY=y+direction[i][1];
//System.out.println(nextX+" "+nextY);
if(nextX<0||nextX>grid.length-1||nextY<0||nextY>grid[0].length-1)
continue;
int nextP=grid[nextX][nextY];
if(now==1){
if((i==0||i==2))
continue;
else{
if(i==1){
if(nextP==2||nextP==4||nextP==6)continue;
}else if(i==3){
if(nextP==2||nextP==3||nextP==5)continue;
}
}
}
if(now==2){
if((i==1||i==3))
continue;
else{
if(i==0){
if(nextP==1||nextP==5||nextP==6)continue;
}else if(i==2){
if(nextP==1||nextP==3||nextP==4)continue;
}
}
}
if(now==3){
if((i==0||i==1))
continue;
else{
if(i==2){
if(nextP==1||nextP==4)continue;
}else if(i==3){
if(nextP==2||nextP==5)continue;
}
}
}
if(now==4){
if((i==0||i==3))
continue;
else{
if(i==1){
if(nextP==2||nextP==6)continue;
}else if(i==2){
if(nextP==1||nextP==3)continue;
}
}
}
if(now==5){
if((i==2||i==1))
continue;
else{
if(i==0){
if(nextP==1||nextP==6)continue;
}else if(i==3){
if(nextP==2||nextP==3)continue;
}
}
}
if(now==6){
if((i==2||i==3))
continue;
else{
if(i==0){
if(nextP==1||nextP==5)continue;
}else if(i==1){
if(nextP==2||nextP==4)continue;
}
}
}
if(visited[nextX][nextY]==1)
continue;
visited[nextX][nextY]=1;
dfs(grid,nextX,nextY);
}
}
}
优化方法
评论区看到的检查网格中是否存在有效路径。
class Solution {
public:
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};//定义四个方向,上下左右
//建立形状和方向的映射
int a[7][2] = {{0,0},{2,3},{0,1},{1,2},{1,3},{0,2},{0,3}};
int n,m;
bool visited[500][500];
//判读顶点是否规范
bool check(int x,int y){
if(x < 0 || x >= m || y<0 || y >= n){
return false;
}
return true;
}
void dfs(int x,int y,vector<vector<int>>& grid){
if(check(x,y)==false) return;
visited[x][y] = true;//标记访问
// cout<<"x="<<x<<'\t'<<"y="<<y<<endl;
int tmpdir = grid[x][y];//取出该点的街道类型
for(int i=0;i<2;i++){
int t = a[tmpdir][i];
int tx = dir[t][0] + x;
int ty = dir[t][1] + y;
//(tx,ty)是下一跳可到达的点。需要再去判读,该点是否和
if(check(tx,ty)){
// cout<<"tx="<<tx<<"\t"<<"ty="<<ty<<endl;
int tmp = grid[tx][ty];//得到下一步的街道类型
for(int k=0;k<2;k++){
int p = a[tmp][k];//得到该街道的两个方向
if(dir[t][0] + dir[p][0]==0 && dir[t][1]+dir[p][1]==0){//判读是否可以走通
if(!visited[tx][ty]){
dfs(tx,ty,grid);
}
}
}
}
}
}
bool hasValidPath(vector<vector<int>>& grid) {
m = grid.size();//行数
n = grid[0].size();//列数
dfs(0,0,grid);
if(visited[m-1][n-1] == true){
return true;//可到达
}
return false;
}
};
多用了一个数组表示当前的路的状态,再根据dir[t][0] + dir[p][0]==0 && dir[t][1]+dir[p][1]==0判断能不能再继续走。
这周的第三道题最后五分钟才写出来,还好也是三道题,基本目标达成了。
leetcode 63/100