[LeetCode] 2297. Jump Game VIII

You are given a 0-indexed integer array nums of length n. You are initially standing at index 0. You can jump from index i to index j where i < j if:

  • nums[i] <= nums[j] and nums[k] < nums[i] for all indexes k in the range i < k < j, or
  • nums[i] > nums[j] and nums[k] >= nums[i] for all indexes k in the range i < k < j.

You are also given an integer array costs of length n where costs[i] denotes the cost of jumping to index i.

Return the minimum cost to jump to the index n - 1.

Example 1:

Input: nums = [3,2,4,4,1], costs = [3,7,6,4,2]
Output: 8
Explanation: You start at index 0.
- Jump to index 2 with a cost of costs[2] = 6.
- Jump to index 4 with a cost of costs[4] = 2.
The total cost is 8. It can be proven that 8 is the minimum cost needed.
Two other possible paths are from index 0 -> 1 -> 4 and index 0 -> 2 -> 3 -> 4.
These have a total cost of 9 and 12, respectively.

Example 2:

Input: nums = [0,1,2], costs = [1,1,1]
Output: 2
Explanation: Start at index 0.
- Jump to index 1 with a cost of costs[1] = 1.
- Jump to index 2 with a cost of costs[2] = 1.
The total cost is 2. Note that you cannot jump directly from index 0 to index 2 because nums[0] <= nums[1].

Constraints:

  • n == nums.length == costs.length
  • 1 <= n <= 105
  • 0 <= nums[i], costs[i] <= 105

跳跃游戏 VIII。

给定一个长度为 n 的下标从 0 开始的整数数组 nums。初始位置为下标 0。当 i < j 时,你可以从下标 i 跳转到下标 j:

对于在 i < k < j 范围内的所有下标 k 有 nums[i] <= nums[j] 和 nums[k] < nums[i] , 或者
对于在 i < k < j 范围内的所有下标 k 有 nums[i] > nums[j] 和 nums[k] >= nums[i] 。
你还得到了一个长度为 n 的整数数组 costs,其中 costs[i] 表示跳转到下标 i 的代价。

返回跳转到下标 n - 1 的最小代价。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/jump-game-viii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路是单调栈 + 动态规划。注意题目规定的从下表 i 跳到下标 j 的条件有两个,

  1. 对于在 i < k < j 范围内的所有下标 k 有 nums[i] <= nums[j] 和 nums[k] < nums[i]
  2. 对于在 i < k < j 范围内的所有下标 k 有 nums[i] > nums[j] 和 nums[k] >= nums[i]

我们用中文翻译一下这两个条件,

  • 条件一,j 一定在 i 的右侧,且是 i 的右侧遇到的第一个 >= nums[i] 的元素,因为中间的 nums[k] 统统小于 nums[i]
  • 条件二,j 一定在 i 的右侧,且是 i 的右侧遇到的第一个 < nums[i] 的元素,因为中间的 nums[k] 统统大于等于 nums[i]

我们发现其实这两个条件是在逻辑上是互补的,所以无论 nums[j] 与 nums[i] 谁大谁小,都会被处理到。所以这里我们用两个 stack 分别处理条件一和条件二,这样我们就能确保从 0 开始可以跳到数组内的任意一个位置,无非是 cost 不同而已。

时间O(n)

空间O(n)

Java实现

 1 class Solution {
 2     public long minCost(int[] nums, int[] costs) {
 3         Deque<Integer> stack1 = new ArrayDeque<>();
 4         Deque<Integer> stack2 = new ArrayDeque<>();
 5         int n = nums.length;
 6         long[] dp = new long[n];
 7         Arrays.fill(dp, Long.MAX_VALUE);
 8         dp[0] = 0;
 9         for (int j = 0; j < n; j++) {
10             while (!stack1.isEmpty() && nums[stack1.peek()] <= nums[j]) {
11                 int i = stack1.pop();
12                 dp[j] = Math.min(dp[j], dp[i] + costs[j]);
13             }
14             stack1.push(j);
15 
16             while (!stack2.isEmpty() && nums[stack2.peek()] > nums[j]) {
17                 int i = stack2.pop();
18                 dp[j] = Math.min(dp[j], dp[i] + costs[j]);
19             }
20             stack2.push(j);
21         }
22         return dp[n - 1];
23     }
24 }

 

LeetCode 题目总结

posted @ 2023-07-21 03:00  CNoodle  阅读(212)  评论(0编辑  收藏  举报