Find the Count of Monotonic Pairs I
HARDDescription
You are given an array of positive integers nums of length n.
We call a pair of non-negative integer arrays (arr1, arr2) monotonic if:
- The lengths of both arrays are
n. arr1is monotonically non-decreasing, in other words,arr1[0] <= arr1[1] <= ... <= arr1[n - 1].arr2is monotonically non-increasing, in other words,arr2[0] >= arr2[1] >= ... >= arr2[n - 1].arr1[i] + arr2[i] == nums[i]for all0 <= i <= n - 1.
Return the count of monotonic pairs.
Since the answer may be very large, return it modulo 109 + 7.
Example 1:
Input: nums = [2,3,2]
Output: 4
Explanation:
The good pairs are:
([0, 1, 1], [2, 2, 1])([0, 1, 2], [2, 2, 0])([0, 2, 2], [2, 1, 0])([1, 2, 2], [1, 1, 0])
Example 2:
Input: nums = [5,5,5,5]
Output: 126
Constraints:
1 <= n == nums.length <= 20001 <= nums[i] <= 50
Approaches
Checkout 3 different approaches to solve Find the Count of Monotonic Pairs I. Click on different approaches to view the approach and algorithm in detail.
Dynamic Programming with Prefix Sums
This approach optimizes the naive DP solution by observing that the inner loop is calculating a sum over a range. Such summations can be computed efficiently using prefix sums. By pre-calculating the prefix sums for each row of the DP table, we can determine the value of any dp[i][j] in constant time, which significantly improves the overall time complexity.
Algorithm
- The DP state
dp[i][j]is the same as the naive approach. - The transition
dp[i][j] = sum(dp[i-1][k])is over a contiguous range ofk. - The upper bound for
kislimit = min(nums[i-1], j - max(0, nums[i] - nums[i-1])). - We can precompute prefix sums for each row
i-1of the DP table into an arrayps[i-1]. dp[i][j]can then be found in O(1) time usingps[i-1][limit].- This removes the innermost loop from the naive DP approach.
The key insight is that the transition dp[i][j] = sum(dp[i-1][k]) is performed for k in the range [0, limit], where limit = min(nums[i-1], j - max(0, nums[i] - nums[i-1])). This is a prefix sum.
We can maintain a parallel 2D array, ps, where ps[i][x] stores the sum of dp[i][k] for k from 0 to x. After computing the i-1-th row of the dp table, we can compute the i-1-th row of the ps table in O(M) time. Then, when computing the i-th row of dp, each dp[i][j] can be found in O(1) by looking up the precomputed value in ps[i-1], effectively eliminating one loop from the previous approach.
Algorithm Steps:
- Create a DP table
dp[n][M+1]and a prefix sum tableps[n][M+1]. - Base Case (i=0): Fill
dp[0]andps[0]as before. - Transitions (i > 0): For
ifrom1ton-1:- For each
jfrom0tonums[i]:- Calculate the upper bound for
k:limit = min(nums[i-1], j - max(0, nums[i] - nums[i-1])). - If
limit >= 0, setdp[i][j] = ps[i-1][limit].
- Calculate the upper bound for
- Compute the prefix sums for the new
dp[i]row and store them inps[i].
- For each
- Final Result: The answer is
ps[n-1][nums[n-1]].
class Solution {
public int countMonotonicPairs(int[] nums) {
int n = nums.length;
int maxVal = 0;
for (int num : nums) {
maxVal = Math.max(maxVal, num);
}
long[][] dp = new long[n][maxVal + 1];
long[][] ps = new long[n][maxVal + 1];
int MOD = 1_000_000_007;
// Base case: i = 0
for (int j = 0; j <= nums[0]; j++) {
dp[0][j] = 1;
}
ps[0][0] = dp[0][0];
for (int j = 1; j <= maxVal; j++) {
ps[0][j] = (ps[0][j - 1] + dp[0][j]) % MOD;
}
// Fill DP table for i > 0
for (int i = 1; i < n; i++) {
long diff = (long)nums[i] - nums[i-1];
for (int j = 0; j <= nums[i]; j++) {
long k_upper_bound = j - Math.max(0, diff);
long limit = Math.min(nums[i-1], k_upper_bound);
if (limit >= 0) {
dp[i][j] = ps[i-1][(int)limit];
}
}
ps[i][0] = dp[i][0];
for (int j = 1; j <= maxVal; j++) {
ps[i][j] = (ps[i][j - 1] + dp[i][j]) % MOD;
}
}
return (int) ps[n - 1][nums[n - 1]];
}
}
Complexity Analysis
Pros and Cons
- Much faster than the naive DP approach, with a time complexity of O(n * M).
- Handles the given constraints very efficiently.
- Requires additional space for the prefix sum table, although the asymptotic space complexity remains the same.
Code Solutions
Checking out 3 solutions in different languages for Find the Count of Monotonic Pairs I. Click on different languages to view the code.
class Solution { public int countOfPairs ( int [] nums ) { final int mod = ( int ) 1 e9 + 7 ; int n = nums . length ; int m = Arrays . stream ( nums ). max (). getAsInt (); int [][] f = new int [ n ][ m + 1 ]; for ( int j = 0 ; j <= nums [ 0 ]; ++ j ) { f [ 0 ][ j ] = 1 ; } int [] g = new int [ m + 1 ]; for ( int i = 1 ; i < n ; ++ i ) { g [ 0 ] = f [ i - 1 ][ 0 ]; for ( int j = 1 ; j <= m ; ++ j ) { g [ j ] = ( g [ j - 1 ] + f [ i - 1 ][ j ]) % mod ; } for ( int j = 0 ; j <= nums [ i ]; ++ j ) { int k = Math . min ( j , j + nums [ i - 1 ] - nums [ i ]); if ( k >= 0 ) { f [ i ][ j ] = g [ k ]; } } } int ans = 0 ; for ( int j = 0 ; j <= nums [ n - 1 ]; ++ j ) { ans = ( ans + f [ n - 1 ][ j ]) % mod ; } return ans ; } }Video Solution
Watch the video walkthrough for Find the Count of Monotonic Pairs I
Similar Questions
5 related questions you might find useful
Patterns:
Data Structures:
Companies:
Subscribe to Scale Engineer newsletter
Learn about System Design, Software Engineering, and interview experiences every week.
No spam, unsubscribe at any time.