Count of valid arrays of size P with elements in range [1, N] having duplicates at least M distance apart
Go to CDN’s CopyGiven three integers N, M and P, the task is to find the total number of valid arrays that can be created of size P having each element in range [1, N], such that the duplicates appear at least M distance apart.
Example:
Input: N = 2, M = 0, P = 3
Output: 6
Explanation: All valid arrays are: {1, 2, 1}, {1, 1, 2}, {2, 1, 1}, {2, 2, 1}, {2, 1, 2}, {1, 2, 2}.
Input: N = 2, M = 1, P = 4
Output: 2
Explanation: All valid arrays are: {1, 2, 1, 2}, {2, 1, 2, 1}
Approach: The problem can be solved with the help of Dynamic Programming,
- There are two choices possible at each index are : either we append already used element at least M distance apart, or we append a new element and decrement the count of unused characters.
- To handle this, use recursive dynamic programming.
- To speed up the recursive calls, use memoization so that already calculated states are not calculated again.
- Let’s define: dp[i][j][k] as the number of arrays till i-th position in which j unique elements are present and k be number of elements which are not used.
- At each step there are two options:
1. Choose previously occurred elements, j and k wouldn’t change as number of used and unused elements doesn’t change : dp[i+1][j][k]
2. Choose element that has never been used, for this case, the number of used character will increment by 1 and the number of unused characters will decrement by 1 : dp[i+1][j+1][k-1]
dp[i][j][k] will be the summation of above two steps, represented as :
dp[i][j][k] = dp[i+1][j][k] + dp[i+1][j+1][k-1]
- The final answer will be dp[0][0][N].
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int calculate( int position, int used, int unused, int P,
int M, vector<vector<vector< int > > >& dp)
{
if (position == P) {
return unused == 0 ? 1 : 0;
}
if (dp[position][used][unused] != -1)
return dp[position][used][unused];
int result = 0;
if (unused > 0) {
result += calculate(position + 1, used + 1,
unused - 1, P, M, dp)
* unused;
}
if (used > M) {
result += calculate(position + 1,
used, unused, P,
M, dp)
* (used - M);
}
return dp[position][used][unused] = result;
}
int solve( int N, int P, int M)
{
vector<vector<vector< int > > > dp(
101,
vector<vector< int > >(101,
vector< int >(101, -1)));
return calculate(0, 0, N, P, M, dp);
}
int main()
{
int N = 2, M = 0, P = 3;
cout << solve(N, P, M);
}
|
Java
import java.io.*;
class GFG
{
static int calculate( int position, int used, int unused, int P,
int M, int dp[][][])
{
if (position == P)
{
return unused == 0 ? 1 : 0 ;
}
if (dp[position][used][unused] != - 1 )
return dp[position][used][unused];
int result = 0 ;
if (unused > 0 ) {
result += calculate(position + 1 , used + 1 ,
unused - 1 , P, M, dp)
* unused;
}
if (used > M)
{
result += calculate(position + 1 ,
used, unused, P,
M, dp)
* (used - M);
}
return dp[position][used][unused] = result;
}
static int solve( int N, int P, int M)
{
int [][][] dp = new int [ 101 ][ 101 ][ 101 ];
for ( int i = 0 ; i < 101 ; i++)
{
for ( int j = 0 ; j < 101 ; j++)
for ( int k = 0 ; k < 101 ; k++)
dp[i][j][k] = - 1 ;
}
return calculate( 0 , 0 , N, P, M, dp);
}
public static void main(String[] args)
{
int N = 2 , M = 0 , P = 3 ;
System.out.println(solve(N, P, M));
}
}
|
Python3
def calculate(position, used, unused, P, M, dp):
if (position = = P):
if unused = = 0 :
return 1
else :
return 0
if (dp[position][used][unused] ! = - 1 ):
return dp[position][used][unused]
result = 0
if (unused > 0 ):
result + = calculate(position + 1 , used + 1 ,unused - 1 , P, M, dp) * unused
if (used > M):
result + = calculate(position + 1 ,used, unused, P,M, dp) * (used - M)
dp[position][used][unused] = result
return dp[position][used][unused]
def solve(N, P, M):
dp = [[[ - 1 for i in range ( 101 )] for i in range ( 101 )] for j in range ( 101 )]
return calculate( 0 , 0 , N, P, M, dp)
if __name__ = = '__main__' :
N = 2
M = 0
P = 3
print (solve(N, P, M))
|
C#
using System;
public class GFG
{
static int calculate( int position, int used, int unused, int P,
int M, int [,,]dp)
{
if (position == P)
{
return unused == 0 ? 1 : 0;
}
if (dp[position,used,unused] != -1)
return dp[position,used,unused];
int result = 0;
if (unused > 0)
{
result += calculate(position + 1, used + 1,
unused - 1, P, M, dp)
* unused;
}
if (used > M)
{
result += calculate(position + 1,
used, unused, P,
M, dp)
* (used - M);
}
return dp[position,used,unused] = result;
}
static int solve( int N, int P, int M)
{
int [,,] dp = new int [101,101,101];
for ( int i = 0; i < 101; i++)
{
for ( int j = 0; j < 101; j++)
for ( int k = 0; k < 101; k++)
dp[i, j, k] = -1;
}
return calculate(0, 0, N, P, M, dp);
}
public static void Main(String[] args)
{
int N = 2, M = 0, P = 3;
Console.WriteLine(solve(N, P, M));
}
}
|
Javascript
<script>
function calculate(position, used, unused, P,
M, dp)
{
if (position == P)
{
return unused == 0 ? 1 : 0;
}
if (dp[position][used][unused] != -1)
return dp[position][used][unused];
let result = 0;
if (unused > 0)
{
result += calculate(position + 1, used + 1,
unused - 1, P, M, dp)
* unused;
}
if (used > M)
{
result += calculate(position + 1,
used, unused, P,
M, dp)
* (used - M);
}
return dp[position][used][unused] = result;
}
function solve(N, P, M)
{
var dp = new Array(101);
for (let i = 0; i < dp.length; i++) {
dp[i] = new Array(101).fill(-1);
}
for (let i = 0; i < dp.length; i++) {
for (let j = 0; j < dp[0].length; j++) {
dp[i][j] = new Array(101).fill(-1);
}
}
return calculate(0, 0, N, P, M, dp);
}
let N = 2, M = 0, P = 3;
document.write(solve(N, P, M));
</script>
|
Time Complexity: O(N*M*P) (Because of three dependent variables)
Auxiliary Space: O(N*M*P) (Size of the DP matrix)
Last Updated :
17 Aug, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...