You are a hiker preparing for an upcoming hike. You are given heights
, a 2D array of size rows x columns
, where heights[row][col]
represents the height of cell (row, col)
. You are situated in the top-left cell, (0, 0)
, and you hope to travel to the bottom-right cell, (rows-1, columns-1)
(i.e., 0-indexed). You can move up, down, left, or right, and you wish to find a route that requires the minimum effort.
A route's effort is the maximum absolute difference in heights between two consecutive cells of the route.
Return the minimum effort required to travel from the top-left cell to the bottom-right cell.
Example 1:
Input: heights = [[1,2,2],[3,8,2],[5,3,5]] Output: 2 Explanation: The route of [1,3,5,3,5] has a maximum absolute difference of 2 in consecutive cells. This is better than the route of [1,2,2,2,5], where the maximum absolute difference is 3.
Example 2:
Input: heights = [[1,2,3],[3,8,4],[5,3,5]] Output: 1 Explanation: The route of [1,2,3,4,5] has a maximum absolute difference of 1 in consecutive cells, which is better than route [1,3,5,3,5].
Example 3:
Input: heights = [[1,2,1,1,1],[1,2,1,2,1],[1,2,1,2,1],[1,2,1,2,1],[1,1,1,2,1]] Output: 0 Explanation: This route does not require any effort.
Constraints:
rows == heights.length
columns == heights[i].length
1 <= rows, columns <= 100
1 <= heights[i][j] <= 106
最小体力消耗路径。
你准备参加一场远足活动。给你一个二维 rows x columns 的地图 heights ,其中 heights[row][col] 表示格子 (row, col) 的高度。一开始你在最左上角的格子 (0, 0) ,且你希望去最右下角的格子 (rows-1, columns-1) (注意下标从 0 开始编号)。你每次可以往 上,下,左,右 四个方向之一移动,你想要找到耗费 体力 最小的一条路径。
一条路径耗费的 体力值 是路径上相邻格子之间 高度差绝对值 的 最大值 决定的。
请你返回从左上角走到右下角的最小 体力消耗值 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/path-with-minimum-effort
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
这是一道图论/搜索的题,我直接给思路。这道题的解法涉及到Dijikstra算法,因为这道题求的是带权重的图的traverse问题。根据题意,图的每一条边的权重是由每两个相邻的cell.val的差的绝对值产生的,我们要找的是一条路径能从起点走到终点同时在这条路径上的花费是最小的。
至于具体做法,我们会用到BFS。首先我们创建一个和input matrix等长等宽的matrix,记录traverse到每个坐标的花费是多少。我们需要一个最小堆记录[cost, row, col]。当我们遍历到某个坐标的时候,如果已经记录的effort更小则无需更新;如果重新计算的newEffort更小则需要更新effort数组并用这个值代入下一轮的BFS计算。
时间O(m * n * nlogn)
空间O(mn)
Java实现
1 class Solution { 2 public int minimumEffortPath(int[][] heights) { 3 int m = heights.length; 4 int n = heights[0].length; 5 int[][] effort = new int[m][n]; 6 for (int i = 0; i < m; i++) { 7 Arrays.fill(effort[i], Integer.MAX_VALUE); 8 } 9 // dist, row, col 10 PriorityQueue<int[]> queue = new PriorityQueue<>((a, b) -> a[0] - b[0]); 11 queue.offer(new int[] { 0, 0, 0 }); 12 int[][] dirs = new int[][] { { 0, 1 }, { 0, -1 }, { 1, 0 }, { -1, 0 } }; 13 while (!queue.isEmpty()) { 14 int[] min = queue.poll(); 15 int dist = min[0]; 16 int row = min[1]; 17 int col = min[2]; 18 //此时的花费大于已经记录下来的花费了,不用看了 19 if (dist > effort[row][col]) { 20 continue; 21 } 22 // traverse到终点了 23 if (row == m - 1 && col == n - 1) { 24 return dist; 25 } 26 for (int[] dir : dirs) { 27 int newRow = row + dir[0]; 28 int newCol = col + dir[1]; 29 if (newRow >= 0 && newRow < m && newCol >= 0 && newCol < n) { 30 // 新的cost 31 int newDist = Math.max(dist, Math.abs(heights[newRow][newCol] - heights[row][col])); 32 // 如果新的cost小于已经记录的cost,就更新 33 if (newDist < effort[newRow][newCol]) { 34 effort[newRow][newCol] = newDist; 35 queue.offer(new int[] { newDist, newRow, newCol }); 36 } 37 } 38 } 39 } 40 return -1; 41 } 42 }