思路
题目要求在给定的数组中,从第一个位置出发,每一步可以向前跳跃最多 k 步,求能够获得的最大得分。这是一个典型的动态规划问题,需要找到状态转移方程来表示每个位置的最大得分。
解题方法
我们可以使用动态规划来解决这个问题。定义一个长度为 n 的数组 dp,其中 dp[i] 表示在到达位置 i 时的最大得分。状态转移方程可以表示为:
dp[i]=max i−k≤j<i dp[j]+nums[i]
即,在位置 i 处的最大得分是在当前窗口内(i-k 到 i-1)找到的最大得分,加上当前位置的值。
我们可以使用一个优先级队列(最大堆)或者队列来维护当前窗口内的最大得分,以优化查找最大得分的过程。
复杂度
时间复杂度: O(nlogk)O(n \log k)O(nlogk)
空间复杂度: O(n)O(n)O(n)
Code
class Solution {
public:
int maxResult(std::vector<int>& nums, int k) {
int n = nums.size();
std::vector<int> dp(n, 0); // dp数组,用于存储到达每个位置的最大得分
dp[0] = nums[0]; // 初始位置的最大得分就是该位置的值
for (int i = 1; i < n; ++i) {
int maxScore = dp[i - 1]; // 初始化为前一个位置的最大得分
for (int j = std::max(0, i - k); j < i; ++j) { // 在当前窗口内找到最大得分
maxScore = std::max(maxScore, dp[j]);
}
dp[i] = maxScore + nums[i]; // 更新当前位置的最大得分
}
return dp[n - 1]; // 返回最终到达数组末尾的最大得分
}
};
class Solution {
public:
int maxResult(std::vector<int>& nums, int k) {
int n = nums.size();
std::vector<int> dp(n, 0); // dp数组,用于存储到达每个位置的最大得分
dp[0] = nums[0]; // 初始位置的最大得分就是该位置的值
// 使用优先级队列,按照最大得分排序
std::priority_queue<std::pair<int, int>> maxHeap;
maxHeap.push({dp[0], 0});
for (int i = 1; i < n; ++i) {
// 移除超出当前窗口范围的元素
while (maxHeap.top().second < i - k) {
maxHeap.pop();
}
dp[i] = maxHeap.top().first + nums[i]; // 更新当前位置的最大得分
maxHeap.push({dp[i], i}); // 将当前位置的信息加入优先级队列
}
return dp[n - 1]; // 返回最终到达数组末尾的最大得分
}
};
class Solution {
public:
int maxResult(std::vector<int>& nums, int k) {
int n = nums.size();
std::vector<int> dp(n, 0); // dp数组,用于存储到达每个位置的最大得分
std::deque<int> dq; // 双端队列,用于维护当前窗口内的最大值的索引
dp[0] = nums[0]; // 初始位置的最大得分就是该位置的值
dq.push_back(0); // 将初始位置索引加入队列
for (int i = 1; i < n; ++i) {
// 移除超出当前窗口范围的元素
while (!dq.empty() && dq.front() < i - k) {
dq.pop_front();
}
// 更新dp[i],使用当前窗口内的最大值
dp[i] = nums[i] + dp[dq.front()];
// 移除小于等于dp[i]的元素(保持队列单调递减)
while (!dq.empty() && dp[i] >= dp[dq.back()]) {
dq.pop_back();
}
// 将当前索引加入队列
dq.push_back(i);
}
return dp[n - 1]; // 返回最终到达数组末尾的最大得分
}
};