跳跃游戏 V
难度:
标签:
题目描述
给你一个整数数组 arr
和一个整数 d
。每一步你可以从下标 i
跳到:
i + x
,其中i + x < arr.length
且0 < x <= d
。i - x
,其中i - x >= 0
且0 < x <= d
。
除此以外,你从下标 i
跳到下标 j
需要满足:arr[i] > arr[j]
且 arr[i] > arr[k]
,其中下标 k
是所有 i
到 j
之间的数字(更正式的,min(i, j) < k < max(i, j)
)。
你可以选择数组的任意下标开始跳跃。请你返回你 最多 可以访问多少个下标。
请注意,任何时刻你都不能跳到数组的外面。
示例 1:
输入:arr = [6,4,14,6,8,13,9,7,10,6,12], d = 2 输出:4 解释:你可以从下标 10 出发,然后如上图依次经过 10 --> 8 --> 6 --> 7 。 注意,如果你从下标 6 开始,你只能跳到下标 7 处。你不能跳到下标 5 处因为 13 > 9 。你也不能跳到下标 4 处,因为下标 5 在下标 4 和 6 之间且 13 > 9 。 类似的,你不能从下标 3 处跳到下标 2 或者下标 1 处。
示例 2:
输入:arr = [3,3,3,3,3], d = 3 输出:1 解释:你可以从任意下标处开始且你永远无法跳到任何其他坐标。
示例 3:
输入:arr = [7,6,5,4,3,2,1], d = 1 输出:7 解释:从下标 0 处开始,你可以按照数值从大到小,访问所有的下标。
示例 4:
输入:arr = [7,1,7,1,7,1], d = 2 输出:2
示例 5:
输入:arr = [66], d = 1 输出:1
提示:
1 <= arr.length <= 1000
1 <= arr[i] <= 10^5
1 <= d <= arr.length
代码结果
运行时间: 55 ms, 内存: 16.1 MB
/*
* Problem: Given an integer array arr and an integer d, you can jump from index i to:
* i + x where i + x < arr.length and 0 < x <= d
* i - x where i - x >= 0 and 0 < x <= d
* You can only jump to index j if arr[i] > arr[j] and arr[i] > arr[k] for all k between i and j.
* Return the maximum number of indices you can visit.
* This solution uses Java Stream to sort indices and find the maximum jumps.
*/
import java.util.stream.IntStream;
public class Solution {
public int maxJumps(int[] arr, int d) {
int n = arr.length;
int[] dp = new int[n];
return IntStream.range(0, n)
.map(i -> dfs(arr, dp, i, d))
.max()
.orElse(1);
}
private int dfs(int[] arr, int[] dp, int i, int d) {
if (dp[i] != 0) return dp[i];
int max = 1;
for (int j = 1; j <= d; j++) {
if (i + j < arr.length && arr[i] > arr[i + j]) {
max = Math.max(max, 1 + dfs(arr, dp, i + j, d));
} else break;
}
for (int j = 1; j <= d; j++) {
if (i - j >= 0 && arr[i] > arr[i - j]) {
max = Math.max(max, 1 + dfs(arr, dp, i - j, d));
} else break;
}
return dp[i] = max;
}
}
解释
方法:
题解采用了单调栈的方法来解决问题。首先,我们创建一个长度为n+1的dp数组,初始值为1,表示每个下标最少可以访问1个位置。然后,遍历数组,并维护一个单调递增的栈。遍历时,如果当前元素大于栈顶元素,则开始处理栈中的元素。对于每个被弹出的栈中元素,我们更新它的右侧最远可跳位置,并尝试更新它左侧元素的dp值。处理完所有元素后,栈顶元素的dp值就是我们需要的结果。这种方法的关键在于,通过维护一个单调栈,我们能够有效地处理每个元素左右可跳的最大范围,从而动态地更新dp数组。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
在单调栈的使用中,如何确保处理的是`arr[i] > arr[k]`这个条件,其中`k`是在`i`和`j`之间的任意一个下标?
▷🦆
单调栈中添加了哨兵元素`float('inf')`,这样做的目的是什么?
▷🦆
如何处理在`arr[i]`和`arr[j]`之间存在多个相同元素的情况,它们对单调栈的影响是什么?
▷🦆
在更新dp数组时,如何避免重复计算或者错过必要的更新,尤其是在`i - j <= d`和`j - stack[-1] <= d`的条件下?
▷