Maximize occurrences of values between L and R on sequential addition of Array elements with modulo H
Given an array arr[] having N positive integers and a positive integers H, the task is to count the maximum occurrences of a value from the range [L, R] on adding arr[i] or arr[i] – 1 to X (initially 0). The integer X must be always be less than H. If it is greater than H, replace X by X % H
Examples:
Input: arr = {16, 17, 14, 20, 20, 11, 22}, H = 24, L = 21, R = 23
Output: 3
Explanation:
Initially X = 0.
Then add arr[0] – 1 to X, now the X is 15. This X is not good.
Then add arr[1] – 1 to X, now the X is 15 + 16 = 31. 31 % H = 7. This X is also not good.
Then add arr[2] to X, now the X is 7 + 14 = 21. This X is good.
Then add arr[3] – 1 to X, now the X is (21 + 19) % H = 16. This X is not good.
Then add arr[4] to X, now the X is (16 + 20) % H = 12. This X is not good.
Then add arr[5] to X, now the X is 12 + 11 = 23. This X is good.
Then add arr[6] to X, now the X is 23 + 22 = 21. This X is also good.
So, the maximum number of good X in the example is 3.
Input: arr = {1, 2, 3}, H = 5, L = 1, R = 2
Output: 2
Approach: This problem can be solved with dynamic programming. Maintain a table dp[N+1][H] which represents the maximum occurrences of an element in the range [L, R] on adding upto i elements. For every ith index, calculate the maximum possible frequency obtainable by adding arr[i] and arr[i] – 1. Once, computed for all indices, find the maximum from the last row of the dp[][] matrix.
Below is the implementation of above approach:
C++
#include <bits/stdc++.h>
using namespace std;
void goodInteger( int arr[], int n,
int h, int l, int r)
{
vector<vector< int > > dp(
n + 1,
vector< int >(h, -1));
dp[0][0] = 0;
for ( int i = 0; i < n; i++) {
for ( int j = 0; j < h; j++) {
if (dp[i][j] != -1) {
int h1 = (j + arr[i]) % h;
int h2 = (j + arr[i] - 1) % h;
dp[i + 1][h1]
= max(dp[i + 1][h1],
dp[i][j]
+ (h1 >= l
&& h1 <= r));
dp[i + 1][h2]
= max(dp[i + 1][h2],
dp[i][j]
+ (h2 >= l
&& h2 <= r));
}
}
}
int ans = 0;
for ( int i = 0; i < h; i++) {
if (dp[n][i] != -1)
ans = max(ans, dp[n][i]);
}
cout << ans << "\n" ;
}
int main()
{
int A[] = { 16, 17, 14, 20, 20, 11, 22 };
int H = 24;
int L = 21;
int R = 23;
int size = sizeof (A) / sizeof (A[0]);
goodInteger(A, size, H, L, R);
return 0;
}
|
Java
class GFG{
static void goodInteger( int arr[], int n,
int h, int l, int r)
{
int [][]dp = new int [n + 1 ][h];
for ( int i = 0 ; i < n; i++)
for ( int j = 0 ; j < h; j++)
dp[i][j] = - 1 ;
dp[ 0 ][ 0 ] = 0 ;
for ( int i = 0 ; i < n; i++)
{
for ( int j = 0 ; j < h; j++)
{
if (dp[i][j] != - 1 )
{
int h1 = (j + arr[i]) % h;
int h2 = (j + arr[i] - 1 ) % h;
dp[i + 1 ][h1] = Math.max(dp[i + 1 ][h1],
dp[i][j] +
((h1 >= l &&
h1 <= r) ?
1 : 0 ));
dp[i + 1 ][h2] = Math.max(dp[i + 1 ][h2],
dp[i][j] +
((h2 >= l &&
h2 <= r) ?
1 : 0 ));
}
}
}
int ans = 0 ;
for ( int i = 0 ; i < h; i++)
{
if (dp[n][i] != - 1 )
ans = Math.max(ans, dp[n][i]);
}
System.out.print(ans + "\n" );
}
public static void main(String[] args)
{
int A[] = { 16 , 17 , 14 , 20 , 20 , 11 , 22 };
int H = 24 ;
int L = 21 ;
int R = 23 ;
int size = A.length;
goodInteger(A, size, H, L, R);
}
}
|
Python3
def goodInteger(arr, n, h, l, r):
dp = [[ - 1 for i in range (h)]
for j in range (n + 1 )]
dp[ 0 ][ 0 ] = 0
for i in range (n):
for j in range (h):
if (dp[i][j] ! = - 1 ):
h1 = (j + arr[i]) % h
h2 = (j + arr[i] - 1 ) % h
dp[i + 1 ][h1] = max (dp[i + 1 ][h1],
dp[i][j] +
(h1 > = l and h1 < = r))
dp[i + 1 ][h2] = max (dp[i + 1 ][h2],
dp[i][j] +
(h2 > = l and h2 < = r))
ans = 0
for i in range (h):
if (dp[n][i] ! = - 1 ):
ans = max (ans, dp[n][i])
print (ans)
if __name__ = = '__main__' :
A = [ 16 , 17 , 14 , 20 , 20 , 11 , 22 ]
H = 24
L = 21
R = 23
size = len (A)
goodInteger(A, size, H, L, R)
|
C#
using System;
class GFG{
static void goodint( int []arr, int n,
int h, int l, int r)
{
int [,]dp = new int [n + 1, h];
for ( int i = 0; i < n; i++)
for ( int j = 0; j < h; j++)
dp[i, j] = -1;
dp[0, 0] = 0;
for ( int i = 0; i < n; i++)
{
for ( int j = 0; j < h; j++)
{
if (dp[i, j] != -1)
{
int h1 = (j + arr[i]) % h;
int h2 = (j + arr[i] - 1) % h;
dp[i + 1, h1] = Math.Max(dp[i + 1, h1],
dp[i, j] +
((h1 >= l &&
h1 <= r) ?
1 : 0));
dp[i + 1, h2] = Math.Max(dp[i + 1, h2],
dp[i, j] +
((h2 >= l &&
h2 <= r) ?
1 : 0));
}
}
}
int ans = 0;
for ( int i = 0; i < h; i++)
{
if (dp[n, i] != -1)
ans = Math.Max(ans, dp[n, i]);
}
Console.Write(ans + "\n" );
}
public static void Main(String[] args)
{
int []A = { 16, 17, 14, 20, 20, 11, 22 };
int H = 24;
int L = 21;
int R = 23;
int size = A.Length;
goodint(A, size, H, L, R);
}
}
|
Javascript
<script>
function goodInteger(arr, n, h, l, r)
{
let dp = new Array(n + 1);
for ( var i = 0; i < dp.length; i++)
{
dp[i] = new Array(2);
}
for (let i = 0; i < n+1; i++)
for (let j = 0; j < h; j++)
dp[i][j] = -1;
dp[0][0] = 0;
for (let i = 0; i < n; i++)
{
for (let j = 0; j < h; j++)
{
if (dp[i][j] != -1)
{
let h1 = (j + arr[i]) % h;
let h2 = (j + arr[i] - 1) % h;
dp[i + 1][h1] = Math.max(dp[i + 1][h1],
dp[i][j] +
((h1 >= l &&
h1 <= r) ?
1 : 0));
dp[i + 1][h2] = Math.max(dp[i + 1][h2],
dp[i][j] +
((h2 >= l &&
h2 <= r) ?
1 : 0));
}
}
}
let ans = 0;
for (let i = 0; i < h; i++)
{
if (dp[n][i] != -1)
ans = Math.max(ans, dp[n][i]);
}
document.write(ans + "\n" );
}
let A = [ 16, 17, 14, 20, 20, 11, 22 ];
let H = 24;
let L = 21;
let R = 23;
let size = A.length;
goodInteger(A, size, H, L, R);
</script>
|
Time Complexity: O(N * H)
Auxiliary Space: O(N*H)
Efficient approach: Space optimization
In previous approach, the current value dp[i][j] is only depend upon the current and previous row values of DP. So to optimize the space complexity we use a single 1D array to store the computations.
Implementation steps:
- Create a 1D vector dp of size h and initialize it with -1.
- Set a base case by initializing the values of dp, dp[0] = 0.
- Now iterate over subproblems by the help of nested loop and get the current value from previous computations.
- Now Create a temporary 1d vector new_dp used to store the current values from previous computations.
- After every iteration assign the value of new_dp to dp for further iteration.
- Initialize a variable ans to store the final answer and update it by iterating through the Dp.
- At last print the final answer stored in ans .
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
void goodInteger( int arr[], int n, int h, int l, int r)
{
vector< int > dp(h, -1);
dp[0] = 0;
for ( int i = 0; i < n; i++) {
vector< int > new_dp(h, -1);
for ( int j = 0; j < h; j++) {
if (dp[j] != -1) {
int h1 = (j + arr[i]) % h;
int h2 = (j + arr[i] - 1) % h;
new_dp[h1] = max(new_dp[h1], dp[j] + (h1 >= l && h1 <= r));
new_dp[h2] = max(new_dp[h2], dp[j] + (h2 >= l && h2 <= r));
}
}
dp = new_dp;
}
int ans = 0;
for ( int i = 0; i < h; i++) {
ans = max(ans, dp[i]);
}
cout << ans << "\n" ;
}
int main()
{
int A[] = { 16, 17, 14, 20, 20, 11, 22 };
int H = 24;
int L = 21;
int R = 23;
int size = sizeof (A) / sizeof (A[0]);
goodInteger(A, size, H, L, R);
return 0;
}
|
Java
import java.util.*;
public class Main {
static void goodInteger( int [] arr, int n, int h, int l,
int r)
{
List<Integer> dp
= new ArrayList<>(Collections.nCopies(h, - 1 ));
dp.set( 0 , 0 );
for ( int i = 0 ; i < n; i++) {
List<Integer> new_dp = new ArrayList<>(
Collections.nCopies(h, - 1 ));
for ( int j = 0 ; j < h; j++) {
if (dp.get(j) != - 1 ) {
int h1 = (j + arr[i]) % h;
int h2 = (j + arr[i] - 1 ) % h;
new_dp.set(
h1,
Math.max(new_dp.get(h1),
dp.get(j)
+ (h1 >= l && h1 <= r
? 1
: 0 )));
new_dp.set(
h2,
Math.max(new_dp.get(h2),
dp.get(j)
+ (h2 >= l && h2 <= r
? 1
: 0 )));
}
}
dp = new_dp;
}
int ans = 0 ;
for ( int i = 0 ; i < h; i++) {
ans = Math.max(ans, dp.get(i));
}
System.out.println(ans);
}
public static void main(String[] args)
{
int [] A = { 16 , 17 , 14 , 20 , 20 , 11 , 22 };
int H = 24 ;
int L = 21 ;
int R = 23 ;
int size = A.length;
goodInteger(A, size, H, L, R);
}
}
|
Python3
def goodInteger(arr, n, h, l, r):
dp = [ - 1 ] * h
dp[ 0 ] = 0
for i in range (n):
new_dp = [ - 1 ] * h
for j in range (h):
if dp[j] ! = - 1 :
h1 = (j + arr[i]) % h
h2 = (j + arr[i] - 1 ) % h
new_dp[h1] = max (new_dp[h1], dp[j] + (h1 > = l and h1 < = r))
new_dp[h2] = max (new_dp[h2], dp[j] + (h2 > = l and h2 < = r))
dp = new_dp
ans = 0
for i in range (h):
ans = max (ans, dp[i])
print (ans)
if __name__ = = "__main__" :
A = [ 16 , 17 , 14 , 20 , 20 , 11 , 22 ]
H = 24
L = 21
R = 23
size = len (A)
goodInteger(A, size, H, L, R)
|
C#
using System;
using System.Collections.Generic;
using System.Linq;
public class GFG
{
static void goodInteger( int [] arr, int n, int h, int l,
int r)
{
List< int > dp
= new List< int >(Enumerable.Repeat(-1, h));
dp[0] = 0;
for ( int i = 0; i < n; i++) {
List< int > new_dp = new List< int >(
Enumerable.Repeat(-1, h));
for ( int j = 0; j < h; j++) {
if (dp[j] != -1) {
int h1 = (j + arr[i]) % h;
int h2 = (j + arr[i] - 1) % h;
new_dp[h1] = Math.Max(new_dp[h1],
dp[j]
+ (h1 >= l && h1 <= r
? 1
: 0));
new_dp[h2] = Math.Max(new_dp[h2],
dp[j]
+ (h2 >= l && h2 <= r
? 1
: 0));
}
}
dp = new_dp;
}
int ans = 0;
for ( int i = 0; i < h; i++) {
ans = Math.Max(ans, dp[i]);
}
Console.WriteLine(ans);
}
public static void Main( string [] args)
{
int [] A = { 16, 17, 14, 20, 20, 11, 22 };
int H = 24;
int L = 21;
int R = 23;
int size = A.Length;
goodInteger(A, size, H, L, R);
}
}
|
Javascript
function goodInteger(arr, n, h, l, r) {
const dp = new Array(h).fill(-1);
dp[0] = 0;
for (let i = 0; i < n; i++) {
const new_dp = new Array(h).fill(-1);
for (let j = 0; j < h; j++) {
if (dp[j] !== -1) {
const h1 = (j + arr[i]) % h;
const h2 = (j + arr[i] - 1) % h;
new_dp[h1] = Math.max(new_dp[h1], dp[j] + (h1 >= l && h1 <= r ? 1 : 0));
new_dp[h2] = Math.max(new_dp[h2], dp[j] + (h2 >= l && h2 <= r ? 1 : 0));
}
}
dp.splice(0, dp.length, ...new_dp);
}
let ans = 0;
for (let i = 0; i < h; i++) {
ans = Math.max(ans, dp[i]);
}
document.write(ans);
}
const A = [16, 17, 14, 20, 20, 11, 22];
const H = 24;
const L = 21;
const R = 23;
const size = A.length;
goodInteger(A, size, H, L, R);
|
Time Complexity: O(N * H)
Auxiliary Space: O(H)
Last Updated :
24 Aug, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...