Maximum Balanced Subsequence Sum
HARDDescription
You are given a 0-indexed integer array nums.
A subsequence of nums having length k and consisting of indices i0 < i1 < ... < ik-1 is balanced if the following holds:
nums[ij] - nums[ij-1] >= ij - ij-1, for everyjin the range[1, k - 1].
A subsequence of nums having length 1 is considered balanced.
Return an integer denoting the maximum possible sum of elements in a balanced subsequence of nums.
A subsequence of an array is a new non-empty array that is formed from the original array by deleting some (possibly none) of the elements without disturbing the relative positions of the remaining elements.
Example 1:
Input: nums = [3,3,5,6] Output: 14 Explanation: In this example, the subsequence [3,5,6] consisting of indices 0, 2, and 3 can be selected. nums[2] - nums[0] >= 2 - 0. nums[3] - nums[2] >= 3 - 2. Hence, it is a balanced subsequence, and its sum is the maximum among the balanced subsequences of nums. The subsequence consisting of indices 1, 2, and 3 is also valid. It can be shown that it is not possible to get a balanced subsequence with a sum greater than 14.
Example 2:
Input: nums = [5,-1,-3,8] Output: 13 Explanation: In this example, the subsequence [5,8] consisting of indices 0 and 3 can be selected. nums[3] - nums[0] >= 3 - 0. Hence, it is a balanced subsequence, and its sum is the maximum among the balanced subsequences of nums. It can be shown that it is not possible to get a balanced subsequence with a sum greater than 13.
Example 3:
Input: nums = [-2,-1] Output: -1 Explanation: In this example, the subsequence [-1] can be selected. It is a balanced subsequence, and its sum is the maximum among the balanced subsequences of nums.
Constraints:
1 <= nums.length <= 105-109 <= nums[i] <= 109
Approaches
Checkout 2 different approaches to solve Maximum Balanced Subsequence Sum. Click on different approaches to view the approach and algorithm in detail.
Brute-force Dynamic Programming
This approach uses dynamic programming to solve the problem. First, we transform the problem's condition. The condition nums[i_j] - nums[i_{j-1}] >= i_j - i_{j-1} can be rewritten as nums[i_j] - i_j >= nums[i_{j-1}] - i_{j-1}. Let's define a new array b where b[i] = nums[i] - i. The problem now is to find a subsequence with non-decreasing b values that has the maximum sum of corresponding nums values.
We define dp[i] as the maximum sum of a balanced subsequence ending at index i. To compute dp[i], we look at all previous indices j < i. If b[j] <= b[i], it means we can extend a balanced subsequence ending at j with the element at i. We choose the j that gives the maximum dp[j] to maximize the new sum.
Algorithm
- Create a
dparray of sizen, wherenis the length ofnums. - Initialize a variable
max_sumto the smallest possible long value. - Loop
ifrom0ton-1:- Initialize
maxPrevSum = 0. - Loop
jfrom0toi-1:- If
(long)nums[j] - j <= (long)nums[i] - i, updatemaxPrevSum = Math.max(maxPrevSum, dp[j]).
- If
- Set
dp[i] = nums[i] + maxPrevSum. - Update
max_sum = Math.max(max_sum, dp[i]).
- Initialize
- Return
max_sum.
The recurrence relation is dp[i] = nums[i] + max({0} U {dp[j] | 0 <= j < i and b[j] <= b[i]}), where b[k] = nums[k] - k.
We iterate through each element of the array from left to right. For each element nums[i], we calculate the maximum possible sum of a balanced subsequence ending at this index. This is done by finding the maximum sum of a valid preceding subsequence and adding nums[i] to it. A preceding subsequence ending at index j is valid if j < i and nums[j] - j <= nums[i] - i. If no such valid preceding subsequence exists or if all of them have a sum less than or equal to zero, we can start a new subsequence with just nums[i], which means we add 0 to nums[i].
The algorithm is as follows:
- Create an array
dpof the same size asnums, wheredp[i]will store the maximum sum of a balanced subsequence ending at indexi. - Iterate through the
numsarray with indexifrom 0 ton-1. - For each
i, initialize a variablemaxPrevSumto 0. - Start an inner loop with index
jfrom 0 toi-1. - Inside the inner loop, check if the balanced condition is met:
(long)nums[j] - j <= (long)nums[i] - i. - If the condition is met, update
maxPrevSum = Math.max(maxPrevSum, dp[j]). - After the inner loop, calculate
dp[i] = nums[i] + maxPrevSum. - The final answer is the maximum value found in the
dparray.
import java.util.Arrays;
class Solution {
public long maxBalancedSubsequenceSum(int[] nums) {
int n = nums.length;
long[] dp = new long[n];
long maxSum = Long.MIN_VALUE;
for (int i = 0; i < n; i++) {
long maxPrevSum = 0;
for (int j = 0; j < i; j++) {
if ((long)nums[j] - j <= (long)nums[i] - i) {
maxPrevSum = Math.max(maxPrevSum, dp[j]);
}
}
dp[i] = (long)nums[i] + maxPrevSum;
maxSum = Math.max(maxSum, dp[i]);
}
return maxSum;
}
}
Complexity Analysis
Pros and Cons
- Simple to understand and implement.
- Correctly solves the problem based on the DP formulation.
- Inefficient due to the nested loops.
- Time complexity of O(n^2) is too slow for the given constraints (
n <= 10^5), leading to a "Time Limit Exceeded" error on large inputs.
Code Solutions
Checking out 3 solutions in different languages for Maximum Balanced Subsequence Sum. Click on different languages to view the code.
class BinaryIndexedTree { private int n ; private long [] c ; private final long inf = 1L << 60 ; public BinaryIndexedTree ( int n ) { this . n = n ; c = new long [ n + 1 ]; Arrays . fill ( c , - inf ); } public void update ( int x , long v ) { while ( x <= n ) { c [ x ] = Math . max ( c [ x ], v ); x += x & - x ; } } public long query ( int x ) { long mx = - inf ; while ( x > 0 ) { mx = Math . max ( mx , c [ x ]); x -= x & - x ; } return mx ; } } class Solution { public long maxBalancedSubsequenceSum ( int [] nums ) { int n = nums . length ; int [] arr = new int [ n ]; for ( int i = 0 ; i < n ; ++ i ) { arr [ i ] = nums [ i ] - i ; } Arrays . sort ( arr ); int m = 0 ; for ( int i = 0 ; i < n ; ++ i ) { if ( i == 0 || arr [ i ] != arr [ i - 1 ]) { arr [ m ++] = arr [ i ]; } } BinaryIndexedTree tree = new BinaryIndexedTree ( m ); for ( int i = 0 ; i < n ; ++ i ) { int j = search ( arr , nums [ i ] - i , m ) + 1 ; long v = Math . max ( tree . query ( j ), 0 ) + nums [ i ]; tree . update ( j , v ); } return tree . query ( m ); } private int search ( int [] nums , int x , int r ) { int l = 0 ; while ( l < r ) { int mid = ( l + r ) >> 1 ; if ( nums [ mid ] >= x ) { r = mid ; } else { l = mid + 1 ; } } return l ; } }Video Solution
Watch the video walkthrough for Maximum Balanced Subsequence Sum
Similar Questions
5 related questions you might find useful
Algorithms:
Patterns:
Data Structures:
Subscribe to Scale Engineer newsletter
Learn about System Design, Software Engineering, and interview experiences every week.
No spam, unsubscribe at any time.