跳转至

3221. 最大数组跳跃得分 II 🔒

题目描述

给定一个数组 nums,你必须从索引 0 开始跳跃,直到到达数组的最后一个元素,使得获取 最大 分数。

每一次 跳跃 中,你可以从下标 i 跳到一个 j > i 的下标,并且可以得到 (j - i) * nums[j] 的分数。

返回你能够取得的最大分数。

 

示例 1:

输入:nums = [1,5,8]

输出:16

解释:

有两种可能的方法可以到达最后一个元素:

  • 0 -> 1 -> 2 得分为 (1 - 0) * 5 + (2 - 1) * 8 = 13
  • 0 -> 2 得分为 (2 - 0) * 8 = 16

示例 2:

输入:nums = [4,5,2,8,9,1,3]

输出:42

解释:

我们可以按 0 -> 4 -> 6 进行跳跃,得分为 (4 - 0) * 9 + (6 - 4) * 3 = 42

 

提示:

  • 2 <= nums.length <= 105
  • 1 <= nums[i] <= 105

解法

方法一:单调栈

我们观察发现,对于当前位置 $i$,我们应该跳到下一个值最大的位置 $j$,这样才能获得最大的分数。

因此,我们遍历数组 $\textit{nums}$,维护一个从栈底到栈顶单调递减的栈 $\textit{stk}$。对于当前遍历到的位置 $i$,如果栈顶元素对应的值小于等于 $\textit{nums}[i]$,我们就不断地弹出栈顶元素,直到栈为空或者栈顶元素对应的值大于 $\textit{nums}[i]$,然后将 $i$ 入栈。

然后,我们初始化答案 $\textit{ans}$ 和当前位置 $i = 0$,遍历栈中的元素,每次取出栈顶元素 $j$,更新答案 $\textit{ans} += \textit{nums}[j] \times (j - i)$,然后更新 $i = j$。

最后返回答案 $\textit{ans}$。

时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是数组的长度。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class Solution:
    def maxScore(self, nums: List[int]) -> int:
        stk = []
        for i, x in enumerate(nums):
            while stk and nums[stk[-1]] <= x:
                stk.pop()
            stk.append(i)
        ans = i = 0
        for j in stk:
            ans += nums[j] * (j - i)
            i = j
        return ans
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class Solution {
    public long maxScore(int[] nums) {
        Deque<Integer> stk = new ArrayDeque<>();
        for (int i = 0; i < nums.length; ++i) {
            while (!stk.isEmpty() && nums[stk.peek()] <= nums[i]) {
                stk.pop();
            }
            stk.push(i);
        }
        long ans = 0, i = 0;
        while (!stk.isEmpty()) {
            int j = stk.pollLast();
            ans += (j - i) * nums[j];
            i = j;
        }
        return ans;
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class Solution {
public:
    long long maxScore(vector<int>& nums) {
        vector<int> stk;
        for (int i = 0; i < nums.size(); ++i) {
            while (stk.size() && nums[stk.back()] <= nums[i]) {
                stk.pop_back();
            }
            stk.push_back(i);
        }
        long long ans = 0, i = 0;
        for (int j : stk) {
            ans += (j - i) * nums[j];
            i = j;
        }
        return ans;
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
func maxScore(nums []int) (ans int64) {
    stk := []int{}
    for i, x := range nums {
        for len(stk) > 0 && nums[stk[len(stk)-1]] <= x {
            stk = stk[:len(stk)-1]
        }
        stk = append(stk, i)
    }
    i := 0
    for _, j := range stk {
        ans += int64((j - i) * nums[j])
        i = j
    }
    return
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
function maxScore(nums: number[]): number {
    const stk: number[] = [];
    for (let i = 0; i < nums.length; ++i) {
        while (stk.length && nums[stk.at(-1)!] <= nums[i]) {
            stk.pop();
        }
        stk.push(i);
    }
    let ans = 0;
    let i = 0;
    for (const j of stk) {
        ans += (j - i) * nums[j];
        i = j;
    }
    return ans;
}

评论