3660.跳跃游戏 IX:动态规划+分治(大小值分组)
【LetMeFly】3660.跳跃游戏 IX:动态规划+分治(大小值分组)
力扣题目链接:https://leetcode.cn/problems/jump-game-ix/
给你一个整数数组 nums。
从任意下标 i 出发,你可以根据以下规则跳跃到另一个下标 j:
- 仅当
nums[j] < nums[i]时,才允许跳跃到下标j,其中j > i。 - 仅当
nums[j] > nums[i]时,才允许跳跃到下标j,其中j < i。
对于每个下标 i,找出从 i 出发且可以跳跃 任意 次,能够到达 nums 中的 最大值 是多少。
返回一个数组 ans,其中 ans[i] 是从下标 i 出发可以到达的最大值。
示例 1:
输入: nums = [2,1,3]
输出: [2,2,3]
解释:
- 对于
i = 0:没有跳跃方案可以获得更大的值。 - 对于
i = 1:跳到j = 0,因为nums[j] = 2大于nums[i]。 - 对于
i = 2:由于nums[2] = 3是nums中的最大值,没有跳跃方案可以获得更大的值。
因此,ans = [2, 2, 3]。
示例 2:
输入: nums = [2,3,1]
输出: [3,3,3]
解释:
- 对于
i = 0:向后跳到j = 2,因为nums[j] = 1小于nums[i] = 2,然后从i = 2跳到j = 1,因为nums[j] = 3大于nums[2]。 - 对于
i = 1:由于nums[1] = 3是nums中的最大值,没有跳跃方案可以获得更大的值。 - 对于
i = 2:跳到j = 1,因为nums[j] = 3大于nums[2] = 1。
因此,ans = [3, 3, 3]。
提示:
1 <= nums.length <= 1051 <= nums[i] <= 109
还挺有意思的一道题。
解题方法一:动态规划
$ans[n-1]$等于什么?$ans[n-1]$等于$nums$数组中的最大值。只要前面有比$ans[n-1]$大的,它都能跳过去。
每个数都能跳到最大值吗?不一定。例如$[1,3,2,100,200,300]$,前面的$[1,3,2]$怎么也跳不到后面的$[100,200,300]$,因为$[1,3,2]$的后面没有比1, 3, 2最大值更小的值。
我们算出$0$到$i$的最大值$maximum[i]$,$i+1$到$n-1$的最小值$minimum[i]$,对于下标$i$:
- 如果$maximum[i]\leq minimum[i+1]$,则$i$及其之前没有比$i+1$及其之后更小的数,$i$及其之前的数都跳不到$i+1$及其之后,变成了$[0,i]$范围内的子问题(分治),$ans[i]=maximum[i]$
- 如果$maximum[i]\gt minimum[i+1]$,则$nums[i]$可以先跳到后面比它小的值(的最小值minimum),再跳到$nums[i+1]$,所以$nums[i+1]$能跳到的数$nums[i]$也一定能跳到,$ans[i]=ans[i+1]$(并且$ans[i+1]$一定$\geq nums[i]$)。
$ans[i] = \begin{cases}preMax[i], & preMax[i] \le sufMin[i+1] \ ans[i+1], & preMax[i] > sufMin[i+1]\end{cases}$
得到$maximum$数组和$minimum$数组后,从后往前遍历一遍就能知道答案了。
- 时间复杂度$O(len(nums))$
- 空间复杂度$O(len(nums))$
AC代码
C++
1 | |
解题方法二:空间小优化
不难发现$maximum$数组在从后往前遍历时用过一遍就不再使用了,我们也可以直接把答案放到$maximum$数组中。
- 时间复杂度$O(len(nums))$
- 空间复杂度$O(1)$,力扣返回值不计入算法空间复杂度
AC代码
C++
1 | |
- 执行用时分布0ms击败100.00%
- 消耗内存分布208.63MB击败98.33%
End
同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~
千篇源码题解已开源