1. 程式人生 > 其它 >LeetCode 1696 跳躍遊戲 VI

LeetCode 1696 跳躍遊戲 VI

技術標籤:單調佇列動態規劃LeetCode

LeetCode 1696 跳躍遊戲 VI

題目連結

給你一個下標從 0 0 0 開始的整數陣列 n u m s nums nums 和一個整數 k k k

一開始你在下標 0 0 0 處。每一步,你最多可以往前跳 k k k 步,但你不能跳出陣列的邊界。也就是說,你可以從下標 i i i 跳到 [ i + 1 , m i n ( n − 1 , i + k ) ] [i + 1, min(n - 1, i + k)] [i+1min(n1,i+k)] 包含 兩個端點的任意位置。

你的目標是到達陣列最後一個位置(下標為 n − 1 n - 1

n1 ),你的 得分 為經過的所有數字之和。

請你返回你能得到的 最大得分 。

示例 1:

輸入:nums = [1,-1,-2,4,-7,3], k = 2
輸出:7
解釋:你可以選擇子序列 [1,-1,4,3] (上面加粗的數字),和為 7 。

示例 2:

輸入:nums = [10,-5,-2,4,0,3], k = 3
輸出:17
解釋:你可以選擇子序列 [10,4,3] (上面加粗數字),和為 17 。

示例 3:

輸入:nums = [1,-5,-20,4,-1,3,-6,-3], k = 2
輸出:0

這題很容易想到 DP,但是 DP 的複雜度是 O ( n k ) O(nk)

O(nk) 的,顯然會超時,所以我們要用一種資料結構快速找到 [ i − k , i − 1 ] [i-k,i-1] [ik,i1] 的最大值,顯然容易想到單調佇列,用一個單調佇列維護區間,隊首即為最大值,再結合 DP 即可,AC程式碼如下:

class Solution {
public:
    int maxResult(vector<int>& nums, int k) {
        deque<int>q;
        vector<int>dp(nums.size(),0);
        dp[0]=nums[0];
        q.
push_back(0); for(int i=1;i<nums.size();i++){ while(i-q.front()>k) q.pop_front(); dp[i]=dp[q.front()]+nums[i]; while(q.size()&&dp[i]>dp[q.back()]) q.pop_back(); q.push_back(i); } return dp[nums.size()-1]; } };