📌  相关文章
📜  最多跳跃长度为 K 的数组可能获得的最大分数(1)

📅  最后修改于: 2023-12-03 15:10:34.685000             🧑  作者: Mango

最多跳跃长度为 K 的数组可能获得的最大分数

问题描述

给定一个长度为 N 的整数数组 nums 和一个整数 K,你需要从数组起始位置开始跳跃。每次跳跃时,你可以选择跳跃至多 K 个位置,得到当前位置的分数。目标是获得最大的总分数,问最多能获得多少分数。

示例
Input: nums = [1, -1, -2, 4, -7, 3], K = 2
Output: 7
Explanation: 从位置 0 开始,可以跳跃至位置 2 并得到 -2 的分数,然后跳跃至位置 4 并得到 -7 的分数,最后跳跃至位置 5 并得到 3 的分数,总分数为 -2 -7 + 3 = -6 + 3 = -3。
而如果在位置 3 处停止跳跃,可以得到更多的分数 -2 + 4 = 2,因此第二个方案得分为 2。因此最大的分数为 7。
解题思路

这道题可以使用动态规划来解决。

我们定义 dp[i] 表示从数组起始位置开始跳跃到第 i 个位置时,可以获得的最大分数。那么最终的结果就是 dp[N-1]。

对于位置 i,我们可以从 i-K 到 i-1 之间的任意一个位置 j 跳跃到 i,dp[i] 就是在所有 dp[j] + nums[i] 中取最大值。因此,我们可以得到如下的状态转移方程:

dp[i] = max(dp[j] + nums[i])  (i-K <= j < i)

由此可见,当前状态的取值只与上一个状态有关。因此,我们可以使用一个大小为 K 的滑动窗口来记录上一个状态的取值。

状态转移方程中求最大值的时间复杂度为 O(K),而我们需要计算 N 个状态,因此总时间复杂度为 O(NK)。

需要注意的一点是,如果 K >= N,那么我们可以直接跳跃到终点,因此最大分数为 sum(nums)。此时状态转移方程中的 j 的范围应为 [0, i),否则会导致数组越界。

代码实现

以下是 Python 代码实现:\newline

def max_score(nums, K):
    N = len(nums)
    if K >= N:
        return sum(nums)
    dp = [0] * N
    q = collections.deque()
    q.append(0)
    for i in range(1, N):
        while q and q[0] + K < i:
            q.popleft()
        dp[i] = dp[q[0]] + nums[i]
        while q and dp[i] >= dp[q[-1]]:
            q.pop()
        q.append(i)
    return dp[N-1]