leetcode
leetcode 1801 ~ 1850
网格图中机器人回家的最小代价

网格图中机器人回家的最小代价

难度:

标签:

题目描述

给你一个 m x n 的网格图,其中 (0, 0) 是最左上角的格子,(m - 1, n - 1) 是最右下角的格子。给你一个整数数组 startPos ,startPos = [startrow, startcol] 表示 初始 有一个 机器人 在格子 (startrow, startcol) 处。同时给你一个整数数组 homePos ,homePos = [homerow, homecol] 表示机器人的  在格子 (homerow, homecol) 处。

机器人需要回家。每一步它可以往四个方向移动:,同时机器人不能移出边界。每一步移动都有一定代价。再给你两个下标从 0 开始的额整数数组:长度为 m 的数组 rowCosts  和长度为 n 的数组 colCosts 。

  • 如果机器人往  或者往  移动到第 r  的格子,那么代价为 rowCosts[r] 。
  • 如果机器人往  或者往  移动到第 c  的格子,那么代价为 colCosts[c] 。

请你返回机器人回家需要的 最小总代价 。

 

示例 1:

输入:startPos = [1, 0], homePos = [2, 3], rowCosts = [5, 4, 3], colCosts = [8, 2, 6, 7]
输出:18
解释:一个最优路径为:
从 (1, 0) 开始
-> 往下走到 (2, 0) 。代价为 rowCosts[2] = 3 。
-> 往右走到 (2, 1) 。代价为 colCosts[1] = 2 。
-> 往右走到 (2, 2) 。代价为 colCosts[2] = 6 。
-> 往右走到 (2, 3) 。代价为 colCosts[3] = 7 。
总代价为 3 + 2 + 6 + 7 = 18

示例 2:

输入:startPos = [0, 0], homePos = [0, 0], rowCosts = [5], colCosts = [26]
输出:0
解释:机器人已经在家了,所以不需要移动。总代价为 0 。

 

提示:

  • m == rowCosts.length
  • n == colCosts.length
  • 1 <= m, n <= 105
  • 0 <= rowCosts[r], colCosts[c] <= 104
  • startPos.length == 2
  • homePos.length == 2
  • 0 <= startrow, homerow < m
  • 0 <= startcol, homecol < n

代码结果

运行时间: 49 ms, 内存: 28.0 MB


/*
 * 思路:
 * 1. 使用Java Stream计算行和列移动的代价。
 * 2. 使用IntStream遍历并计算每一步的代价。
 */

import java.util.stream.IntStream;

public class MinCostToHomeStream {
    public int minCost(int[] startPos, int[] homePos, int[] rowCosts, int[] colCosts) {
        int startRow = startPos[0];
        int startCol = startPos[1];
        int homeRow = homePos[0];
        int homeCol = homePos[1];

        // 计算行移动代价
        int rowCost = startRow < homeRow ?
            IntStream.rangeClosed(startRow + 1, homeRow).map(i -> rowCosts[i]).sum() :
            IntStream.rangeClosed(homeRow, startRow - 1).map(i -> rowCosts[startRow - (i - homeRow) - 1]).sum();

        // 计算列移动代价
        int colCost = startCol < homeCol ?
            IntStream.rangeClosed(startCol + 1, homeCol).map(i -> colCosts[i]).sum() :
            IntStream.rangeClosed(homeCol, startCol - 1).map(i -> colCosts[startCol - (i - homeCol) - 1]).sum();

        return rowCost + colCost;
    }
}

解释

方法:

此题解通过直接计算从起始位置到目标位置的行和列移动代价来解决问题。首先,将起始位置 (startPos) 和目标位置 (homePos) 分别分解为行和列的坐标。接着,根据行和列坐标的相对位置(是否需要向上或向下、向左或向右移动),计算行和列的代价。如果目标行在起始行的下方,累加从起始行到目标行之间的所有行代价;如果在上方,则累加从目标行到起始行的行代价。列的处理方法相同。最后,将行和列的代价相加得到总代价。

时间复杂度:

O(m + n)

空间复杂度:

O(1)

代码细节讲解

🦆
为什么题解在计算从起始位置到目标位置的行代价时,使用了`rowCosts[i + 1 : x + 1]`而不是`rowCosts[i:x]`?
题解中使用`rowCosts[i + 1 : x + 1]`而不是`rowCosts[i:x]`是因为行代价`rowCosts[i]`代表的是从第`i`行移动到第`i+1`行的代价。因此,如果机器人从行`i`移动到行`x`,则需要从`i+1`行开始计算移动代价,直到`x`行,故取`i+1`到`x+1`的切片来确保包括从`i`到`x`的所有移动代价。
🦆
在计算列代价时,为何选择累加`colCosts[j + 1 : y + 1]`的方式?这是否意味着初始单元格的列代价不被考虑?
列代价的计算类似于行代价。`colCosts[j]`代表从第`j`列移动到第`j+1`列的代价。当使用`colCosts[j + 1 : y + 1]`累加时,意味着从第`j`列出发的移动代价不包括在内,因为这代表的是从`j+1`列开始到`y`列的移动。如果机器人从列`j`向列`y`移动,其实是从`j`列的下一列开始计算代价,所以初始单元格的列代价并不需要被考虑。
🦆
如果起始位置和目标位置在同一行或同一列,此方法是否仍然有效?比如`startPos`和`homePos`完全相同的情况。
如果起始位置和目标位置在同一行或同一列,比如完全相同的情况,此方法仍然有效。在这种情况下,行或列的切片操作将返回一个空列表,例如`rowCosts[x:x]`或`colCosts[y:y]`,其结果是`sum`函数将返回0。因此,总代价将为0,这符合预期,因为机器人无需移动。
🦆
题解假设了直接向目标方向移动,是否有必要检查中间路径上是否存在更低代价的替代路径?
在本题解中,假设的是机器人移动的行和列代价是固定的,并且只与移动的行列位置有关,不依赖于其他路径选择。因此,题解采取了直接计算从起始位置到目标位置的最短路径代价的简单方法。如果行和列的代价变化不仅取决于移动的行列,而且与具体的路径选择有关,则需要考虑更复杂的路径规划算法,如动态规划或Dijkstra算法来找到最低代价的路径。

相关问题