1631. 最小体力消耗路径

https://leetcode-cn.com/problems/path-with-minimum-effort/

题目描述

你准备参加一场远足活动。给你一个二维 rows x columns 的地图 heights ,其中 heights[row][col] 表示格子 (row, col) 的高度。一开始你在最左上角的格子 (0, 0) ,且你希望去最右下角的格子 (rows-1, columns-1) (注意下标从 0 开始编号)。你每次可以往 上,下,左,右 四个方向之一移动,你想要找到耗费 体力 最小的一条路径。

一条路径耗费的 体力值 是路径上相邻格子之间 高度差绝对值 的 最大值 决定的。

请你返回从左上角走到右下角的最小 体力消耗值 。

 

示例 1:

前置知识

公司

  • 暂无

思路

如果采用暴力解法, 需要找出所有的路径,然后返回最小代价的即可,时间复杂度是指数级别。回头看一下数据范围是 10e6,因此这种解法是不行的。

由于题目的解空间是 [0, 10**6 - 1]。

对解空间这个概念不熟悉的,可以看我之前的一篇题解686. 重复叠加字符串匹配

本质上,我们需要进行发问:

  • 0 可以么?

  • 1 可以么?

  • 2 可以么?

  • 。。。

直到找到第一个不可以的,我们返回前一个即可。

关于可不可以,我们可以使用 DFS 来做,由于只需要找到一条满足条件的,或者找到一个不满足的提前退出,因此最坏的情况是一直符合,并走到终点,这种情况下时间复杂度是 $(m \times n)$,因此总的时间复杂度是 $O(m \times n \times 10**6)$。

实际上,上面的不断发问的过程不就是一个连续的递增序列么? 我们的目标不就是在一个连续递增序列找指定值么?于是二分法就不难想到。

而且这道题本质就是二分查找中的查找最右侧满足条件的值,关于这个问题,我已经在 【91 天学算法】二分查找 中进行了详细描述,并给出了代码模板,直接套就可以了。

值得注意的是,我们只需要找到一个满足条件的路径即可,因此可以利用短路剪枝。

而不是写出下面的代码(下面的代码会超时):

代码

代码支持:Python3

复杂度分析

m 为 矩阵的高度, n 为矩阵的长度。

  • 时间复杂度:$O(4 \times m \times n \times log_2 10^6)$,其中 $log_2 10^6$ 为二分的次数, $4 \times m \times n$ 为每次 dfs 的时间。

  • 空间复杂度:$O(m \times n)$,不管是递归的栈开销还是 visited 的开销都是 $O(m \times n)$。

相关问题

最后更新于

这有帮助吗?