• [LeetCode 1696] Jump Game VI


    You are given a 0-indexed integer array nums and an integer k.

    You are initially standing at index 0. In one move, you can jump at most k steps forward without going outside the boundaries of the array. That is, you can jump from index i to any index in the range [i + 1, min(n - 1, i + k)] inclusive.

    You want to reach the last index of the array (index n - 1). Your score is the sum of all nums[j] for each index j you visited in the array.

    Return the maximum score you can get.

     

    Example 1:

    Input: nums = [1,-1,-2,4,-7,3], k = 2
    Output: 7
    Explanation: You can choose your jumps forming the subsequence [1,-1,4,3] (underlined above). The sum is 7.
    

    Example 2:

    Input: nums = [10,-5,-2,4,0,3], k = 3
    Output: 17
    Explanation: You can choose your jumps forming the subsequence [10,4,3] (underlined above). The sum is 17.
    

    Example 3:

    Input: nums = [1,-5,-20,4,-1,3,-6,-3], k = 2
    Output: 0
    

     

    Constraints:

    •  1 <= nums.length, k <= 10^5
    • -10^4 <= nums[i] <= 10^4

    Think about solving this problem backward: if we are at the last position, then of all the positions that can reach the last position in 1 jump, we should pick the position that yields the maximum score. This means we need to solve F(last position - 1), F(last position - 2),....... F(last position - K). To solve F(last position - 1), we need to solve F(last position - 2),....... F(last position - K), F(last position - K - 1). It is clear that we have overlapping subproblems, so we also use dynamic programming. 

    Solution 1. O(N * K) DP

    dp[i]: the max score we can get at position i;

    Answer is dp[N - 1]. 

    Solution 2. O(N * logN) DP with max heap

    The bottle neck in solution 1 is that we need to repeatedly find the max dp value among the previous K values. We can speed this up by using a max heap. 

    The max heap's entry stores both dp value and its position. When querying the max dp value, we first pop all the values that are out of the K-sized window. Then we pick a valid max value to update the current dp[i].  The runtime is O(N * logN) since we iterate from 0 to N - 1 and for each position it is added to then popped out of the max heap at most once.

    class Solution {
        public int maxResult(int[] nums, int k) {
            int n = nums.length;
            int[] dp = new int[n];
            PriorityQueue<int[]> q = new PriorityQueue<>(Comparator.comparingInt(e->-e[0]));
            for(int i = 0; i < n; i++) {
                while(q.size() > 0 && q.peek()[1] + k < i) {
                    q.poll();
                }
                dp[i] = nums[i] + (q.size() > 0 ? q.peek()[0] : 0);
                q.add(new int[]{dp[i], i});
            }
            return dp[n - 1];
        }
    }

    Solution 3. O(N) DP with double ended queue

    Can we do better than O(N * logN)? Think about what happens when the current dp[i] is bigger than dp[i - 1]. Since dp[i] appears after dp[i - 1] and is better than dp[i - 1], this means we can ignore dp[i - 1] for the rest of our dp iteration. In general, we can safely discard all previous <= dp values. We still need to keep previous > dp values until they are out of the K-sized window. This calls for a double ended queue. The head has the current max dp value. We remove out of window positions from the head of the dq and remove <= dp values and add newly computed dp value at the end of the dq. 

    class Solution {
        public int maxResult(int[] nums, int k) {
            int n = nums.length;
            int[] dp = new int[n];
            ArrayDeque<Integer> q = new ArrayDeque<>();
            for(int i = 0; i < n; i++) {
                while(q.size() > 0 && q.peekFirst() < i - k) {
                    q.removeFirst();
                }
                dp[i] = nums[i] + (q.size() > 0 ? dp[q.peekFirst()] : 0);
                while(q.size() > 0 && dp[q.peekLast()] <= dp[i]) {
                    q.removeLast();
                }
                q.addLast(i);
            }
            return dp[n - 1];
        }
    }
     
     
  • 相关阅读:
    超前进位加法器
    Xilinx ISE 12.3 LED测试程序
    位图文件(BMP)格式以及Linux下C程序实现
    SPB16.3安装系列指导
    Debian6显卡驱动安装
    深入浅出之正则表达式
    一个在台积电工作3年的工程师写给学弟学妹们的信
    Debian下解决MP3标题乱码
    ubuntu下安装usbblaster(更新)
    乘法器的Verilog HDL实现
  • 原文地址:https://www.cnblogs.com/lz87/p/14406350.html
Copyright © 2020-2023  润新知