Count ways to choose elements from given Arrays
Last Updated :
14 Apr, 2023
Given arrays A[] and B[] of size N, the task is to count ways to form an array of size N such that the new array formed has ith element either A[i] or B[i] and adjacent elements are different.
Examples:
Input: A[] = {1, 4, 3}, B[] = {2, 2, 4}
Output: 4
Explanation: Possible arrays are {1, 4, 3}, {1, 2, 3}, {1, 2, 4} and {2, 4, 3}.
Below is the Recursion Tree. Green is a valid move whereas red is an invalid move.
Example-1
Input: A[] = {1, 2, 3, 4}, B[] = {5, 6, 7, 8}
Output: 16
Naive approach: The basic way to solve the problem is as follows:
The basic way to solve this problem is to generate all possible combinations by using a recursive approach.
Time Complexity: O(2N)
Auxiliary Space: O(1)
Efficient Approach/Memoization: The above approach can be optimized based on the following idea:
Dynamic programming can be used to solve this problem:
- dp[i][j] represents number of possible arrays of size i with last element chosen from array j (0 for A[] and 1 for B[]).
It can be observed that the recursive function is called exponential times. That means that some states are called repeatedly.
So the idea is to store the value of each state. This can be done by storing the value of a state and whenever the function is called, returning the stored value without computing again.
Follow the steps below to solve the problem:
- Declare a dp array, dp[100001][2] initialized with -1 using memset() function.
- Create a 2d array Arr[][], whose first column will contain array A[] and the second column will have array B[].
- Create a recursive function that takes four parameters i and j such that i represents position and j represents the last element chosen from either A[] or B[], Arr[] stores array A[] and B[], and size of array N.
- Calling recursive function recur(0, 0, Arr, N) with i = 0 indicates we will fill the first position of the required array.
- Check if i == N, return 1.
- Check if dp[i][j] != -1, return dp[i][j].
- Initialize variable ans = 0 to count the number of valid solutions.
- Call recursive function for both choosing an element from A[] (in this case Arr[][0]) or B[] (in this case Arr[][1]) and add the answer returned to cnt .
- Return ans calculated for the current state.
- Save the answer in dp[i][j] before returning.
Below is the implementation of the above approach:
C++
// C++ code to implement the approach
#include <bits/stdc++.h>
using namespace std;
// mod to avoid integer overflow
const int mod = 1e9 + 7;
// dp table
int dp[100001][2];
// recursive Function to count ways to
// form array of size N such that adjcent
// elements chosen are different
int recur(int i, int j, vector<vector<int> >& Arr, int N)
{
// If already computed state just
// return dp[i][j]
if (dp[i][j] != -1)
return dp[i][j];
// If array of size N is possible
if (i == N)
return 1;
// Answer initialized with value zero
int ans = 0;
// if choosing element from A[]
if (i == 0 or Arr[i - 1][j] != Arr[i][0])
ans = (ans + recur(i + 1, 0, Arr, N)) % mod;
// if choosing element from B[]
if (i == 0 or Arr[i - 1][j] != Arr[i][1])
ans = (ans + recur(i + 1, 1, Arr, N)) % mod;
// Return the final answer
return dp[i][j] = ans;
}
// Function to count ways to form
// array of size N such that adjcent
// elements chosen are different
void findWays(int A[], int B[], int N)
{
// initializing dp table with - 1
memset(dp, -1, sizeof(dp));
// making one array for A[] & B[]
vector<vector<int> > Arr(N, vector<int>(2));
// filling Arr
for (int i = 0; i < N; i++) {
Arr[i][0] = A[i];
Arr[i][1] = B[i];
}
// calling recursive function
cout << recur(0, 0, Arr, N) << endl;
}
// Driver Code
int main()
{
// Input 1
int A[] = { 1, 4, 3 }, B[] = { 2, 2, 4 };
int N = sizeof(A) / sizeof(A[0]);
// Function Call
findWays(A, B, N);
// Input 2
int A1[] = { 1, 2, 3, 4 }, B1[] = { 5, 6, 7, 8 };
int N1 = sizeof(A1) / sizeof(A1[0]);
// Function Call
findWays(A1, B1, N1);
return 0;
}
Java
// Java code to implement the approach
import java.io.*;
import java.util.*;
class GFG {
// mod to avoid integer overflow
static final int mod = (int)1e9 + 7;
// dp table
static int[][] dp = new int[100001][2];
// recursive Function to count ways to form array of
// size N such that adjacent elements chosen are
// different
static int recur(int i, int j, int[][] Arr, int N)
{
// If already computed state just return dp[i][j]
if (dp[i][j] != -1)
return dp[i][j];
// If array of size N is possible
if (i == N)
return 1;
// Answer initialized with value zero
int ans = 0;
// if choosing element from A[]
if (i == 0 || Arr[i - 1][j] != Arr[i][0])
ans = (ans + recur(i + 1, 0, Arr, N)) % mod;
// if choosing element from B[]
if (i == 0 || Arr[i - 1][j] != Arr[i][1])
ans = (ans + recur(i + 1, 1, Arr, N)) % mod;
// Return the final answer
return dp[i][j] = ans;
}
// Function to count ways to form array of size N such
// that adjacent elements chosen are different
static void findWays(int[] A, int[] B, int N)
{
// initializing dp table with -1
for (int i = 0; i <= N; i++) {
Arrays.fill(dp[i], -1);
}
// making one array for A[] & B[]
int[][] Arr = new int[N][2];
// filling Arr
for (int i = 0; i < N; i++) {
Arr[i][0] = A[i];
Arr[i][1] = B[i];
}
// calling recursive function
System.out.println(recur(0, 0, Arr, N));
}
public static void main(String[] args)
{
// Input 1
int[] A = { 1, 4, 3 };
int[] B = { 2, 2, 4 };
int N = A.length;
// Function Call
findWays(A, B, N);
// Input 2
int[] A1 = { 1, 2, 3, 4 };
int[] B1 = { 5, 6, 7, 8 };
int N1 = A1.length;
// Function Call
findWays(A1, B1, N1);
}
}
// This code is contributed by lokesh.
Python
# python code to implement the approach
MOD = int(1e9) + 7
# dp table
dp = [[-1 for j in range(2)] for i in range(100001)]
# recursive Function to count ways to
# form array of size N such that adjacent
# elements chosen are different
def recur(i, j, arr, N):
global dp
# If already computed state just
# return dp[i][j]
if dp[i][j] != -1:
return dp[i][j]
# If array of size N is possible
if i == N:
return 1
# Answer initialized with value zero
ans = 0
# if choosing element from A[]
if i == 0 or arr[i - 1][j] != arr[i][0]:
ans = (ans + recur(i + 1, 0, arr, N)) % MOD
# if choosing element from B[]
if i == 0 or arr[i - 1][j] != arr[i][1]:
ans = (ans + recur(i + 1, 1, arr, N)) % MOD
# Return the final answer
dp[i][j] = ans
return ans
# Function to count ways to form
# array of size N such that adjacent
# elements chosen are different
def findWays(A, B, N):
global dp
# making one array for A[] & B[]
arr = [[0 for j in range(2)] for i in range(N)]
# filling arr
for i in range(N):
arr[i][0] = A[i]
arr[i][1] = B[i]
# initializing dp table with -1
for i in range(100001):
dp[i][0] = dp[i][1] = -1
# calling recursive function
print(recur(0, 0, arr, N))
# Driver Code
if __name__ == '__main__':
# Input 1
A = [1, 4, 3]
B = [2, 2, 4]
N = len(A)
# Function Call
findWays(A, B, N)
# Input 2
A1 = [1, 2, 3, 4]
B1 = [5, 6, 7, 8]
N1 = len(A1)
# Function Call
findWays(A1, B1, N1)
# This code is contributed by lokesh.
C#
// C# code for the approach
using System;
public class GFG {
// mod to avoid integer overflow
const int mod = 1000000007;
// dp table
static int[, ] dp = new int[100001, 2];
// recursive Function to count ways to
// form array of size N such that adjcent
// elements chosen are different
static int recur(int i, int j, int[][] Arr, int N)
{
// If already computed state just
// return dp[i][j]
if (dp[i, j] != -1)
return dp[i, j];
// If array of size N is possible
if (i == N)
return 1;
// Answer initialized with value zero
int ans = 0;
// if choosing element from A[]
if (i == 0 || Arr[i - 1][j] != Arr[i][0])
ans = (ans + recur(i + 1, 0, Arr, N)) % mod;
// if choosing element from B[]
if (i == 0 || Arr[i - 1][j] != Arr[i][1])
ans = (ans + recur(i + 1, 1, Arr, N)) % mod;
// Return the final answer
return dp[i, j] = ans;
}
// Function to count ways to form
// array of size N such that adjcent
// elements chosen are different
static void findWays(int[] A, int[] B, int N)
{
// initializing dp table with - 1
for (int i = 0; i < 100001; i++)
for (int j = 0; j < 2; j++)
dp[i, j] = -1;
// making one array for A[] & B[]
int[][] Arr = new int[N][];
// filling Arr
for (int i = 0; i < N; i++) {
Arr[i] = new int[2];
Arr[i][0] = A[i];
Arr[i][1] = B[i];
}
// calling recursive function
Console.WriteLine(recur(0, 0, Arr, N));
}
// Driver Code
public static void Main()
{
// Input 1
int[] A = { 1, 4, 3 }, B = { 2, 2, 4 };
int N = A.Length;
// Function Call
findWays(A, B, N);
// Input 2
int[] A1 = { 1, 2, 3, 4 }, B1 = { 5, 6, 7, 8 };
int N1 = A1.Length;
// Function Call
findWays(A1, B1, N1);
}
}
JavaScript
// mod to avoid integer overflow
const mod = 1e9 + 7;
// dp table
const dp = new Array(100001).fill(null).map(() => new Array(2).fill(-1));
// recursive Function to count ways to
// form array of size N such that adjacent
// elements chosen are different
function recur(i, j, Arr, N) {
// If already computed state just
// return dp[i][j]
if (dp[i][j] !== -1) {
return dp[i][j];
}
// If array of size N is possible
if (i === N) {
return 1;
}
// Answer initialized with value zero
let ans = 0;
// if choosing element from A[]
if (i === 0 || Arr[i - 1][j] !== Arr[i][0]) {
ans = (ans + recur(i + 1, 0, Arr, N)) % mod;
}
// if choosing element from B[]
if (i === 0 || Arr[i - 1][j] !== Arr[i][1]) {
ans = (ans + recur(i + 1, 1, Arr, N)) % mod;
}
// Return the final answer
return dp[i][j] = ans;
}
// Function to count ways to form
// array of size N such that adjacent
// elements chosen are different
function findWays(A, B, N) {
for(let i=0; i<100001; i++){
for(let j=0; j<2; j++)
dp[i][j]=-1;
}
// making one array for A[] & B[]
const Arr = new Array(N).fill(null).map((_, i) => [A[i], B[i]]);
// calling recursive function
console.log(recur(0, 0, Arr, N));
}
// Driver Code
(function main() {
// Input 1
const A = [1, 4, 3], B = [2, 2, 4];
const N = A.length;
// Function Call
findWays(A, B, N);
// Input 2
const A1 = [1, 2, 3, 4], B1 = [5, 6, 7, 8];
const N1 = A1.length;
// Function Call
findWays(A1, B1, N1);
})();
Time Complexity: O(N)
Auxiliary Space: O(N)
Related Articles:
Similar Reads
Count unequal element pairs from the given Array Given an array arr[] of N elements. The task is to count the total number of indices (i, j) such that arr[i] != arr[j] and i < j.Examples: Input: arr[] = {1, 1, 2} Output: 2 (1, 2) and (1, 2) are the only valid pairs.Input: arr[] = {1, 2, 3} Output: 3Input: arr[] = {1, 1, 1} Output: 0 Recommended
10 min read
Count of elements in X axis for given Q ranges Given a 2D array arr[][] where each array element denotes a point in the X axis and the number of elements on that point. A query array queries[] of size Q is given where each element is of type {l, r}. The task is to find the count of elements in the given range for each query. Examples: Input: arr
10 min read
Count pairs from given array with Bitwise OR equal to K Given an array arr[] consisting of N positive integers and an integer K, the task is to count all pairs possible from the given array with Bitwise OR equal to K. Examples: Input: arr[] = {2, 38, 44, 29, 62}, K = 46Output: 2Explanation: Only the following two pairs are present in the array whose Bitw
5 min read
Count ways to select K array elements lying in a given range Given three positive integers, L, R, K and an array arr[] consisting of N positive integers, the task is to count the number of ways to select at least K array elements from the given array having values in the range [L, R]. Examples: Input: arr[] = {12, 4, 6, 13, 5, 10}, K = 3, L = 4, R = 10 Output
9 min read
Counting frequencies of array elements Given an array arr[] of non-negative integers which may contain duplicate elements. Return the frequency of each distinct element present in the array.Examples: Input : arr[] = [10, 20, 10, 5, 20]Output : [[10, 2], [20, 2], [ 5, 1]]Explanation: Here, 10 occurs 2 times, 20 occurs 2 times, and 5 occur
10 min read