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.
For example:
Input: nums = [10,2,-10,5,20], k = 2 Output: 37 Explanation: The subsequence is [10, 2, 5, 20].
Input: nums = [-1,-2,-3], k = 1 Output: -1 Explanation: The subsequence must be non-empty, so we choose the largest number.
Input: nums = [10,-2,-10,-5,20], k = 2 Output: 23 Explanation: The subsequence is [10, -2, -5, 20].
## Maximum Sum of Non-empty Subsequence with Distance Constraint
### Problem Description
Given an integer array `nums` and an integer `k`, the goal is to find the maximum sum of a **non-empty** subsequence such that for every two consecutive integers `nums[i]` and `nums[j]` (where `i < j`), the condition `j - i <= k` is satisfied. A subsequence is obtained by deleting some elements from the array, keeping the remaining elements in their original order.
### Naive Approach (Brute Force)
A brute-force approach would involve generating all possible subsequences and checking if each subsequence satisfies the given condition `j - i <= k`. For each valid subsequence, we calculate its sum and keep track of the maximum sum found so far. This approach is highly inefficient due to the exponential number of possible subsequences.
```python
def max_subsequence_sum_brute_force(nums, k):
n = len(nums)
max_sum = float('-inf')
for i in range(1 << n):
subsequence = []
indices = []
for j in range(n):
if (i >> j) & 1:
subsequence.append(nums[j])
indices.append(j)
if not subsequence:
continue
is_valid = True
for l in range(1, len(indices)):
if indices[l] - indices[l-1] > k:
is_valid = False
break
if is_valid:
max_sum = max(max_sum, sum(subsequence))
return max_sum
Complexity Analysis of Brute Force Approach:
nums
. This is because we generate 2n subsequences and, for each subsequence, we iterate through its elements (up to n elements).nums
. This is because, in the worst case, we store a subsequence containing all the elements of nums
.We can use dynamic programming to solve this problem efficiently. Let dp[i]
be the maximum sum of a valid subsequence ending at index i
. The recurrence relation is as follows:
dp[i] = nums[i] + max(0, dp[j])
for all j
such that i - k <= j < i
To find the maximum dp[j]
efficiently, we can use a max heap (priority queue) to store the dp
values along with their indices. The heap allows us to quickly retrieve the maximum dp[j]
within the k
window and remove outdated dp
values.
import heapq
def max_subsequence_sum(nums, k):
n = len(nums)
dp = [float('-inf')] * n
heap = [] # (dp[i], i)
max_sum = float('-inf')
for i in range(n):
# Remove outdated dp values from the heap
while heap and heap[0][1] < i - k:
heapq.heappop(heap)
# Calculate dp[i]
if heap:
dp[i] = nums[i] + max(0, -heap[0][0]) # Heap stores negative values
else:
dp[i] = nums[i]
max_sum = max(max_sum, dp[i])
# Add dp[i] to the heap (negated for max heap)
heapq.heappush(heap, (-dp[i], i))
# Edge case: all numbers are negative
if max_sum == float('-inf'):
return max(nums)
return max_sum
Explanation:
dp
array with negative infinity and a max heap heap
to store (dp[i], i)
pairs.nums
array from i = 0
to n - 1
.k
window (i.e., i - k > j
).dp[i]
as nums[i] + max(0, dp[j])
where dp[j]
is the maximum dp
value within the k
window. We use 0
to avoid including negative sums.max_sum
with the maximum value encountered so far.dp[i]
to the heap. Note that we store -dp[i]
in the heap to simulate a max heap with heapq
.max_sum
.k >= 1
. The constraint j - i <= k
ensures that only consecutive elements or elements that are nearby can be part of subsequence. k = 0
would not make sense in this context.nums
. The main loop iterates n
times. Inside the loop, the heapq.heappop
and heapq.heappush
operations take O(log n) time. Therefore, the overall time complexity is dominated by the heap operations, resulting in O(n log n).nums
. The dp
array stores n
values, and the heap can store at most n
elements in the worst case. Therefore, the space complexity is O(n).