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%