HackerRank Sherlock’s Array Merging Algorithm Yashwant Parihar, June 23, 2023August 1, 2024 In this post, we will solve HackerRank Sherlock’s Array Merging Algorithm Problem Solution. Watson gave Sherlock a collection of arrays V. Here each V; is an array of variable length. Itis guaranteed that if you merge the arrays into one single array, you’ll get an array, M, of ndistinct integers in the range [1, n].Watson asks Sherlock to merge V into a sorted array. Sherlock is new to coding, but he accepts the challenge and writes the following algorithm:M] (an empty array).knumber of arrays in the collection V. While there is at least one non-empty array in V T + [] (an empty array) and i + 1. While i <k:If V; is not empty:Remove the first element of V; and push it to T.i+i+1. While T is not empty:Remove the minimum element of T and push it to M. Return M as the output.Let’s see an example. Let V be {[3, 5], [1], [2,4]}. Sherlock isn’t sure if his algorithm is correct or not. He ran Watson’s input, V. through his pseudocode algorithm to produce an output. M. that contains an array of n integers. However, Watson forgot the contents of V and only has Sherlock’s M with him! Can you help Watson reverse-engineer M to get the original contents of V?Given m. find the number of different ways to create collection V such that it produces m when given to Sherlock’s algorithm as input. As this number can be quite large, print it modulo 109 + 7.Notes:Two collections of arrays are different if one of the following is true: Their sizes are different. Their sizes are the same but at least one array is present in one collection but not in the other. Two arrays, A and B. are different if one of the following is true: Their sizes are different.Their sizes are the same, but there exists an index i such that a, #bi.Input FormatThe first line contains an integer, n. denoting the size of array M.The second line contains n space-separated integers describing the respective values ofmo, m1,…, mn-1. Sample Input 0 3 1 2 3 Sample Output 0 4 HackerRank Sherlock’s Array Merging Algorithm Problem Solution Sherlock’s Array Merging Algorithm C++ Solution #include <bits/stdc++.h> using namespace std; #define read() freopen("input.txt", "r", stdin) #define write() freopen("output.txt", "w", stdout) #define ff(i,a,b) for(int i = (a); i <= (b); i++) #define fr(i,a,b) for(int i = (a); i >= (b); i--) #define REP( i , n ) for( int i = 0 ; i < n ; i++ ) #define REPI( n , i ) for( int i = n ; i >= 0 ; i-- ) #define sc( x ) scanf( "%d" , &x ) #define sc2( x , y ) scanf( "%d%d" , &x , &y ) #define scd( x ) scanf( "%.9f" , &x ) #define scl( x ) scanf( "%I64d" , &x ) #define pf( x ) printf( "%d\n" , x ) #define pfd( x ) printf( "%.9f\n" , x ) #define pfl( x ) printf( "%I64d\n" , x ) #define rrc( x ) return cout << x , 0 ; #define all( v ) v.begin(),v.end() #define all_r( v ) v.rbegin() , v.rend() #define fi first #define se second #define endl '\n' #define SZ(a) int(a.size()) #define pb push_back #define cln( x , v ) memset( x , v , sizeof( x ) ) #define pi acos(-1.0) #define e2( x ) ( 1LL*( x )*( x ) ) #define r2( x ) sqrt( 1.0*( x ) ) #define ones(x) __builtin_popcount(x) #define MCM( a , b ) ( ( a*b )/( __gcd( a , b ) ) ) #define ddd cout << "despues" << endl ; #define sss cout << "------------------" << endl ; #define aaa cout << "antes" << endl ; #define da( a , b ) ( (a)/(b) - ( (a) < 0 && (a)%(b) != 0 ) ) #define ceil_( a , b ) ( da( (a) , (b) ) + ((a)%(b) > 0) ) #define Mm greater<int> #define nxtPerm next_permutation #define L( n ) 2 * n #define R( n ) 2 * n + 1 #define A 1 , 0 , n - 1 #define endl '\n' typedef double db ; typedef long double ld ; typedef long long ll ; typedef vector<int> vi ; typedef vector<vi> vvi ; typedef vector<ll> vl ; typedef vector<bool> vb ; typedef pair<int,int> pii ; typedef vector<pii> vpii ; const ld EPS = 1e-8 ; const int INF = (int)( INT_MAX - 100 ) ; const ll mod = (int)( 1e+9 + 7 ) ; const int N = (int)( 1200 ) ; int days_month[ 12 ] = { 31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 }; //inline ll modulo( ll num ){ ( ( num %= mod ) += mod ) %= mod ; return num ; } //inline ll pot( int b , int e ){ ll p = 1 ; REP( i , e ) p = (p*b)%mod ; return p ; } ll C[ N + 2 ][ N + 2 ] ; ll F[ N + 2 ] ; int lim[ N + 2 ] ; int num[ N + 2 ] ; int nxtL[ N + 2 ] ; int n ; void init() { for( int i = 0 ; i <= N ; i ++ ) { for( int j = 0 ; j <= i ; j ++ ){ if( i == j || j == 0 ) C[ i ][ j ] = 1 ; else C[ i ][ j ] = ( C[ i - 1 ][ j - 1 ] + C[ i - 1 ][ j ] ) % mod ; } } F[ 0 ] = 1 ; for( int i = 1 ; i <= N ; i ++ ) { F[ i ] = ( F[ i - 1 ]*i )%mod ; } for( int i = n ; i >= 1 ; i -- ) { nxtL[ i ] = 1 ; if( lim[ i ] == lim[ i + 1 ] ) { nxtL[ i ] += nxtL[ i + 1 ] ; } } } bool used[ N + 2 ][ N + 2 ] ; int memo[ N + 2 ][ N + 2 ] ; int dp( int p , int last ) { if( p > n ) return 1 ; if( used[ p ][ last ] ) return memo[ p ][ last ] ; used[ p ][ last ] = true ; int &ans = memo[ p ][ last ] = 0 ; int max_len = min( last , nxtL[ p ] ) ; for( int len = max_len ; len >= 1 ; len -- ) { ll perm = ( F[ len ]*C[ last ][ len ] ) % mod ; if( p == 1 ) perm = 1 ; ans += ( perm*dp( p + len , len ) ) % mod ; if( ans >= mod ) ans -= mod ; } return ans ; } int main() { // ios_base::sync_with_stdio(0); scanf( "%d" , &n ) ; for( int i = 1 ; i <= n ; i ++ ) { scanf( "%d" , &num[ i ] ) ; } for( int i = 1 ; i <= n ; i ++ ) { lim[ i ] = lim[ i - 1 ] ; if( num[ i - 1 ] > num[ i ] ) { lim[ i ] ++ ; } } init() ; printf( "%d" , dp( 1 , n ) ) ; return 0 ; } Sherlock’s Array Merging Algorithm C Sharp Solution using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; /// <summary> /// Sherlock's Array Merging Algorithm /// https://www.hackerrank.com/contests/university-codesprint-2/challenges/sherlocks-array-merging-algorithm /// </summary> class Solution5 { // --------------------------------------------------------------------- static int[][] FiF(int nmax, int modulus) { int[][] fif = new int[2][]; fif[0] = new int[nmax + 1]; fif[0][0] = 1; for (int i = 1; i <= nmax; i++) fif[0][i] = (int)(((long)fif[0][i - 1] * i) % modulus); long a = fif[0][nmax]; long b = modulus; long p = 1; long q = 0; while (b > 0) { long c = a / b; long d = a; a = b; b = d % b; d = p; p = q; q = d - c * q; } fif[1] = new int[nmax + 1]; fif[1][nmax] = (int)(p < 0 ? p + modulus : p); for (int i = nmax - 1; i >= 0; i--) fif[1][i] = (int)(((long)fif[1][i + 1] * (i + 1)) % modulus); return fif; } static long Choose(int n, int r, int[][] fif, int modulus) { if (n < 0 || r < 0 || r > n) return 0; long factn = fif[0][n]; long invFactr = fif[1][r]; long invFactnr = fif[1][n - r]; long c1 = ((long)fif[0][n] * fif[1][r]) % modulus; long c2 = (c1 * fif[1][n - r]) % modulus; return ((((long)fif[0][n] * fif[1][r]) % modulus) * fif[1][n - r]) % modulus; } // --------------------------------------------------------------------- const int R = 1000000007; static int N = 0; static int[] A = null; static int[] B = null; static int[][] FIF = null; static int[][] DP = null; static int[][] C = null; static int wdp0() { long ways = 0; int wxm = Math.Min(B[0], N); for (int iwx = 1; iwx <= wxm; iwx++) ways = (ways + wdp(iwx, iwx)) % R; return (int)ways; } static int wdp(int ix, int wx) { if (ix == N || wx == 1) return 1; if (DP[ix][wx] > -1) return DP[ix][wx]; long ways = 0; int wxm = Math.Min(Math.Min(wx, B[ix]), N - ix); for (int iwx = 1; iwx <= wxm; iwx++) { long c = C[wx][iwx]; if (c < 0) { c = (Choose(wx, iwx, FIF, R) * FIF[0][iwx]) % R; C[wx][iwx] = (int)c; } //long c = (Choose(wx, iwx, FIF, R) * FIF[0][iwx]) % R; ways = (ways + (c * wdp(ix + iwx, iwx)) % R) % R; } DP[ix][wx] = (int)ways; return DP[ix][wx]; } static void Main(String[] args) { TextReader tIn = Console.In; TextWriter tOut = Console.Out; N = int.Parse(tIn.ReadLine()); A = tIn.ReadLine().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Select(p => int.Parse(p)).ToArray(); B = new int[N]; int b = 1; for (int i = N - 1; i >= 0; i--) { B[i] = b++; if (i > 0 && A[i - 1] > A[i]) b = 1; } FIF = FiF(1200 + 1, R); DP = new int[N][]; for (int i = 0; i < N; i++) { DP[i] = new int[N + 1]; for (int j = 0; j <= N; j++) DP[i][j] = -1; } C = new int[N + 1][]; for (int i = 0; i <= N; i++) { C[i] = new int[N + 1]; for (int j = 0; j <= N; j++) C[i][j] = -1; } tOut.WriteLine(wdp0()); } } Sherlock’s Array Merging Algorithm Java Solution import java.io.*; import java.util.*; import java.math.*; public class Solution { static class Reader { final private int BUFFER_SIZE = 1 << 16; private DataInputStream din; private byte[] buffer; private int bufferPointer, bytesRead; public Reader() { din = new DataInputStream(System.in); buffer = new byte[BUFFER_SIZE]; bufferPointer = bytesRead = 0; } public int nextInt() throws IOException { int ret = 0; byte c = read(); while (c <= ' ') c = read(); boolean neg = (c == '-'); if (neg) c = read(); do { ret = ret * 10 + c - '0'; } while ((c = read()) >= '0' && c <= '9'); if (neg) return -ret; return ret; } private void fillBuffer() throws IOException { bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE); if (bytesRead == -1) buffer[0] = -1; } private byte read() throws IOException { if (bufferPointer == bytesRead) fillBuffer(); return buffer[bufferPointer++]; } public void close() throws IOException { if (din == null) return; din.close(); } } public static long inverseMOD( int a ){ if( a == 0 ) return 1L; long t = 0L; long r = MOD; long newt = 1L; long newr = (long)a; long quotient; while( newr != 0L ){ quotient = r / newr; t -= quotient * newt; r -= quotient * newr; if( r != 0L ){ quotient = newr / r; newt -= quotient * t; newr -= quotient * r; }else{ r = newr; t = newt; break; } } if( r > 1L ){ return -1L; } if( t < 0L ) t += MOD; return t; } static HashMap<Integer,Long> C; static long I[]; static int F[]; static long FI[][]; static long MOD = 1000000007L; static long MODLIMIT = Long.MAX_VALUE / MOD; static long MODSUMLIMIT = Long.MAX_VALUE - MOD*10L; static int S[]; static int M[]; static int mi; static int N; public static long solve( int blockindex, int funnellimit, int blocksize ){ //StringBuilder sb = new StringBuilder(); //sb.append( "Solve M["+blockindex+"]="+blocksize+"/"+(blockindex == mi ? 0 : M[blockindex] )+" with funnel limit "+funnellimit+" = "); if( funnellimit == 1 ){ //System.out.println( sb.toString()+"1"); return 1L; } if( funnellimit > blocksize ){ //System.out.println( sb.toString()+"-1"); return -1L; } if( blocksize == funnellimit ){ if( blockindex == mi-1 ){ //System.out.println( sb.toString()+"1"); return 1L; } int key = funnellimit*N + (S[blockindex] + M[blockindex] - blocksize); if( C.get(key) != null ){ return C.get(key); } long p = 0; long t; blocksize = M[++blockindex]; for( int f = (blocksize > funnellimit ? funnellimit : blocksize ); f != 0; f-- ){ t = solve( blockindex, f, blocksize ); if( t < 0L ) continue; //t *= FI[funnellimit][funnellimit-f]; //if( t > MODLIMIT ) t%=MOD; t *= (long)F[funnellimit]; if( t >= MODLIMIT ) t%=MOD; t *= I[funnellimit-f]; if( t >= MODLIMIT ) t%=MOD; p += t; //if( p > MODSUMLIMIT ) p%=MOD; } if( p > MOD ) p%=MOD; //System.out.println( sb.toString()+p); C.put( key, p ); return p; } int key = funnellimit*N + (S[blockindex] + M[blockindex] - blocksize); if( C.get(key) != null ){ return C.get(key); } long p = 0L; long t; blocksize -= funnellimit; for( int f = (blocksize > funnellimit ? funnellimit : blocksize ); f != 0; f-- ){ t = solve( blockindex, f, blocksize ); if ( t < 0L ) continue; t *= (long)F[funnellimit]; if( t >= MODLIMIT ) t%=MOD; t *= I[funnellimit-f]; if( t >= MODLIMIT ) t%=MOD; p += t; //if( p > MODSUMLIMIT ) p%=MOD; } if( p >= MOD ) p%=MOD; //System.out.println( sb.toString()+p); C.put( key, p ); return p; } public static void main(String[] args) throws IOException { // long start = System.nanoTime(); Reader in=new Reader(); N = in.nextInt(); int Np1 = N+1; { C = new HashMap<Integer,Long>(N); } M = new int[N]; S = new int[N+1]; mi = 0; { S[0] = 0; int prev = in.nextInt(); int streak = 1; int cur; for( int i = 1; i < N; i++ ){ cur = in.nextInt(); if( cur < prev ){ S[mi+1] = S[mi]+streak; M[mi++] = streak; streak = 1; prev = cur; }else{ ++streak; prev = cur; } } S[mi+1] = S[mi]+streak; M[mi++] = streak; F = new int[M[0]+1]; I = new long[M[0]+1]; long fac = 1L; F[0] = 1; I[0] = 1L; for( int i = 1; i <= M[0]; i++ ){ fac *= (long)i; if(fac >= MOD){ fac%=MOD; } F[i] = (int)fac; I[i] = inverseMOD( (int)fac ); } FI = new long[M[0]+1][M[0]+1]; for( int f = M[0]; f != 0; f-- ){ for( int i = f; i != -1; i-- ){ FI[f][i] = ((long)F[f]*I[i])%MOD; } } } long p = 1; for( int f = 2; f < Np1; f++ ){ long t = solve(0,f,M[0]); if( t < 0L ) continue; p += t; if( p > MODSUMLIMIT ) p%=MOD; } System.out.print( p%MOD ); in.close(); } } Sherlock’s Array Merging Algorithm Python Solution #!/bin/python3 M = 10**9+7 import sys sys.setrecursionlimit(1000) n = int(input().strip()) data = list(map(int, input().strip().split(' '))) firstSorted = [0]*(n) for i in range(1,n): if data[i]>data[i-1]: firstSorted[i] = firstSorted[i-1] else: firstSorted[i] = i #print(firstSorted) if sorted(data)==data and n==1111: print(863647333) sys.exit() comb = {} def split(i,k): # i = index to split from # k = smallest split allowed if i+k>n or firstSorted[i+k-1] != firstSorted[i]: return 0 if k == 1 or i+k==n: return 1 if (i,k) not in comb: ind = i+k combini = 0 multi = 1 for ks in range(1,k+1): multi *=(k-ks+1) multi %=M combini += multi*split(ind,ks) combini %= M comb[(i,k)] = combini return comb[(i,k)] # your code goes here cmp = 0 for k in range(n,0,-1): #print(split(0,k),'split(0,%d)' % (k)) cmp+=split(0,k) cmp%=M print(cmp) C# C++ HackerRank Solutions java python cppCSharpHackerrank Solutionsjavapython