题目描述
直接给出题目链接 小U的最大连续移动次数问题 - MarsCode
将题目精炼一下:
一个的矩阵,a[x][y]代表每个坐标(x,y)的高度,小U每次只能走上坡和下坡,也就是不能到高度相同的地方。并且上下坡需要交替执行。求小U在这个矩阵中最多能连续移动多少次?
解题思路
这个题目是标准的dfs题型,唯一的不同的就是约束条件多了两条:
一个是不能到相同高度的地方。
第二个是上下坡必须交替执行。
关键步骤如下:
-
DFS函数的实现:
dfs(int x, int y, ...)是一个递归函数,尝试从点(x, y)出发探索所有可能的路径。- 变量
upOrDown用于指示当前路径是否处于上坡(1)还是下坡(0)状态。 visited数组用于记录当前路径中已经访问过的节点,防止重复访问和形成环。
-
递归遍历:
- 对于每个点
(nx, ny),判断是否在数组范围内。 - 检查是否已经访问过该点,避免重复。
- 检查高度差是否符合上坡或下坡的条件,并判断是否是上下坡交替访问。
- 递归调用
dfs进行深度遍历,并通过Math.max保持最大移动次数。
- 对于每个点
-
回溯:
- 在递归完成后,回溯时将
visited[x][y]重置为未访问状态,以便尝试新的路径。
- 在递归完成后,回溯时将
-
全局遍历:
solution(int m, int n, int[][] a)遍历每个起始点(i, j),分别计算上坡和下坡的最大步数。- 使用
int steps = Math.max(steps1, steps2)对比两种路径的最大步数。 - 更新全局最大值
res。
代码
public class Main {
//要求可移动的最大次数
public static int[][] dir ={{0,1},{1,0},{-1,0},{0,-1}};
public static int dfs(int x,int y,int[][] a,int[][] visited,int upOrDown,int m,int n){
//1代表上坡过来的,0代表下坡过来的
visited[x][y]=1;
int res=0;
for(int i=0;i<4;++i){
int nx = x+dir[i][0];
int ny = y+dir[i][1];
if(nx<0||nx>=m||ny<0||ny>=n){
continue;
}
if(visited[nx][ny]==1){
continue;
}
if(a[nx][ny]==a[x][y]){
continue;
}
if(upOrDown==1&&a[nx][ny]>a[x][y]){
continue;
}
if(upOrDown==0&&a[nx][ny]<a[x][y]){
continue;
}
res=Math.max(res,1+dfs(nx, ny, a, visited, 1-upOrDown, m, n));
}
visited[x][y]=0;
return res;
}
public static int solution(int m, int n, int[][] a) {
// write code here
//每个位置作为起始点走一遍
int res=0;
int[][] visited = new int[m][n];
for(int i=0;i<m;++i){
for(int j=0;j<n;++j){
int steps1 = dfs(i,j,a,visited,0,m,n);
int steps2 = dfs(i,j,a,visited,1,m,n);
int steps=Math.max(steps1,steps2);
res=Math.max(steps,res);
}
}
return res;
}
}
算法复杂度
时间复杂度:O(),外层是的for循环,dfs最坏时间复杂度也是,这个时间复杂度是相当大的,其实可以利用记忆化搜索优化一下,但是我这一块记忆化没有写好,存在问题,就没有在这篇文章进行讨论了。
空间复杂度:O(),创建了visted数组,以及最多存在次递归栈调用。