Leetcode: 1425

Description

Given an integer array nums and an integer k, return the maximum sum of a non-empty subsequence of that array such that for every two consecutive integers in the subsequence, nums[i] and nums[j], where i < j, the condition j - i <= k is satisfied.

A subsequence of an array is obtained by deleting some number of elements (can be zero) from the array, leaving the remaining elements in their original order.

Example

Input: nums = [10,2,-10,5,20], k = 2
Output: 37
Explanation: The subsequence is [10, 2, 5, 20].

分析

这道题目可以用 dp 来做, 转移方程为 dp[i] = nums[i] + max(dp[i-1], dp[i-2]....., 0) 。 使用这个转移方程会非常慢
改用 queue 来存储 (-dp[i], i) 的信息,使用最小堆来获取最大的 dp[i],实现如下
import heapq
class Solution(object):
    def _fast(self, nums):
        m = nums[0]
        N = len(nums)
        totalM = m
        for i in range(1, N):
            m = max(nums[i]+m, nums[i])
            totalM = max(totalM, m)
        return totalM
    
    def constrainedSubsetSum(self, nums, k):
        if k == 1:
            return self._fast(nums)
        Q, M, N = [], float('-inf'), len(nums)
        
        for i in range(N):
            n_v = nums[i]
            while Q:
                v, idx = Q[0]
                if i - idx > k:
                    heapq.heappop(Q)
                    continue
                n_v += -v
                break
            M = max(M, n_v)
            if n_v > 0:
                if n_v == M:        
                    Q = [(-n_v, i)] # 这是优化的关键,使用这个作为优化,性能可以 beat 100% 。否则性能只能 beat 25 % 
                else:
                    heapq.heappush(Q, (-n_v, i))
        return M


也尝试使用 monostack 来计算,即逆序遍历 arr。每个 point 计算最大能 jump 的点。把求取最大和子序列的行为看成是 frog jump
这样的逻辑有瑕疵,25 个testcase 只能过 23 个。

nums  [10,2,-10,5,20], k = 2,计算的 jump 数组为 [1, 3, 3,4, -1] 

总结

优化后,速度 beat 100%
原文地址:https://www.cnblogs.com/tmortred/p/15163520.html