# Rearrange an array to maximize sum of Bitwise AND of same-indexed elements with another array

Given two arrays A[] and B[] of sizes N, the task is to find the maximum sum of Bitwise AND of same-indexed elements in the arrays A[] and B[] that can be obtained by rearranging the array B[] in any order.

Examples:

Input: A[] = {1, 2, 3, 4}, B[] = {3, 4, 1, 2}
Output: 10
Explanation: One possible way is to obtain the maximum value is to rearrange the array B[] to {1, 2, 3, 4}.
Therefore, sum of Bitwise AND of same-indexed elements of the arrays A[] and B[] = { 1&1 + 2&2 + 3&3 + 4&4 = 10), which is the maximum possible.

Input: A[] = {3, 5, 7, 11}, B[] = {2, 6, 10, 12}
Output: 22

Naive Approach: The simplest approach to solve the problem is to generate all possible permutations of array B[] and for each permutation, calculate the sum of Bitwise AND of same-indexed elements in arrays A[] and B[] and update the maximum possible sum accordingly. Finally, print the maximum sum possible.

Time Complexity: O(N! * N)
Auxiliary Space: O(1)

Efficient Approach: The above approach can also be optimized based on the following observations:

• For each array element of A[] the idea is to chose a not selected array element of B[] using bitmasking which will give maximum bitwise AND sum upto the current index.
• The idea is to use Dynamic Programming with bitmasking as it has overlapping subproblems and optimal substructure.
• Suppose, dp(i, mask) represents the maximum bitwise AND sum of array A[] and i, with the selected elements of array B[] represented by bits-position of mask.
• Then the transition from one state to another state can be defined as:
• For all j in the range [0, N]:

Follow the steps below to solve the problem:

• Define a vector of vectors, says dp of dimension N*2N  with value -1 to store all dp-states.
• Define a recursive Dp function say maximizeAndUtil(i, mask) to find the maximum sum of the bitwise AND of the elements at the same respective positions in both arrays A[] and B[]:
• In the base case, if i is equal to N then return 0.
• Iterate over the range [0, N-1] using variable j and in each iteration, If jth bit in the mask is not set then update dp[i][mask] as dp[i][mask] = max(dp[i][mask], maximizeUtil(i+1, mask| 2j).
• Call the recursive function maximizeAnd(0, 0) and print the value returned by it as the answer.

Below is the implementation of the above approach:

## C++

 `// C++ program for the above approach``#include ``using` `namespace` `std;` `// Function to implement recursive DP``int` `maximizeAnd(``int` `i, ``int` `mask,``                ``int``* A, ``int``* B, ``int` `N,``                ``vector >& dp)``{``    ``// If i is equal to N``    ``if` `(i == N)``        ``return` `0;` `    ``// If dp[i][mask] is not``    ``// equal to -1``    ``if` `(dp[i][mask] != -1)``        ``return` `dp[i][mask];` `    ``// Iterate over the array B[]``    ``for` `(``int` `j = 0; j < N; ++j) {` `        ``// If current element``        ``// is not yet selected``        ``if` `(!(mask & (1 << j))) {` `            ``// Update dp[i][mask]``            ``dp[i][mask] = max(``                ``dp[i][mask],``                ``(A[i] & B[j])``                    ``+ maximizeAnd(i + 1, mask | (1 << j), A,``                                  ``B, N, dp));``        ``}``    ``}``    ``// Return dp[i][mask]``    ``return` `dp[i][mask];``}` `// Function to obtain maximum sum``// of Bitwise AND of same-indexed``// elements from the arrays A[] and B[]``int` `maximizeAndUtil(``int``* A, ``int``* B, ``int` `N)``{``    ``// Stores all dp-states``    ``vector > dp(``        ``N, vector<``int``>(1 << N + 1, -1));` `    ``// Returns the maximum value``    ``// returned by the function maximizeAnd()``    ``return` `maximizeAnd(0, 0, A, B, N, dp);``}` `// Driver Code``int` `main()``{``    ``int` `A[] = { 3, 5, 7, 11 };``    ``int` `B[] = { 2, 6, 10, 12 };``    ``int` `N = ``sizeof` `A / ``sizeof` `A[0];` `    ``cout << maximizeAndUtil(A, B, N);``}`

## Java

 `// Java program for the above approach``import` `java.io.*;``import` `java.lang.*;``import` `java.util.*;` `public` `class` `GFG {` `    ``// Function to implement recursive DP``    ``static` `int` `maximizeAnd(``int` `i, ``int` `mask, ``int` `A[],``                           ``int` `B[], ``int` `N, ``int``[][] dp)``    ``{``        ``// If i is equal to N``        ``if` `(i == N)``            ``return` `0``;` `        ``// If dp[i][mask] is not``        ``// equal to -1``        ``if` `(dp[i][mask] != -``1``)``            ``return` `dp[i][mask];` `        ``// Iterate over the array B[]``        ``for` `(``int` `j = ``0``; j < N; ++j) {` `            ``// If current element``            ``// is not yet selected``            ``if` `((mask & (``1` `<< j)) == ``0``) {` `                ``// Update dp[i][mask]``                ``dp[i][mask] = Math.max(``                    ``dp[i][mask],``                    ``(A[i] & B[j])``                        ``+ maximizeAnd(i + ``1``,``                                      ``mask | (``1` `<< j), A, B,``                                      ``N, dp));``            ``}``        ``}``        ``// Return dp[i][mask]``        ``return` `dp[i][mask];``    ``}` `    ``// Function to obtain maximum sum``    ``// of Bitwise AND of same-indexed``    ``// elements from the arrays A[] and B[]``    ``static` `int` `maximizeAndUtil(``int` `A[], ``int` `B[], ``int` `N)``    ``{``      ` `        ``// Stores all dp-states``        ``int` `dp[][] = ``new` `int``[N][(``1` `<< N) + ``1``];``        ``for` `(``int` `dd[] : dp)``            ``Arrays.fill(dd, -``1``);` `        ``// Returns the maximum value``        ``// returned by the function maximizeAnd()``        ``return` `maximizeAnd(``0``, ``0``, A, B, N, dp);``    ``}` `    ``// Driver Code``    ``public` `static` `void` `main(String[] args)``    ``{``        ``int` `A[] = { ``3``, ``5``, ``7``, ``11` `};``        ``int` `B[] = { ``2``, ``6``, ``10``, ``12` `};``        ``int` `N = A.length;` `        ``System.out.print(maximizeAndUtil(A, B, N));``    ``}``}` `// This code is contributed by Kingash.`

## Python3

 `# Python3 program for the above approach` `# Function to implement recursive DP``def` `maximizeAnd(i, mask, A, B, N, dp):``    ` `    ``# If i is equal to N``    ``if` `(i ``=``=` `N):``        ``return` `0` `    ``# If dp[i][mask] is not``    ``# equal to -1``    ``if` `(dp[i][mask] !``=` `-``1``):``        ``return` `dp[i][mask]` `    ``# Iterate over the array B[]``    ``for` `j ``in` `range``(N):``        ` `        ``# If current element``        ``# is not yet selected``        ``if` `((mask & (``1` `<< j)) ``=``=` `0``):``            ` `            ``# Update dp[i][mask]``            ``dp[i][mask] ``=` `max``(``                ``dp[i][mask],(A[i] & B[j]) ``+``                ``maximizeAnd(i ``+` `1``, mask | (``1` `<< j),``                            ``A, B, N, dp))``                ` `    ``# Return dp[i][mask]``    ``return` `dp[i][mask]` `# Function to obtain maximum sum``# of Bitwise AND of same-indexed``# elements from the arrays A[] and B[]``def` `maximizeAndUtil(A, B, N):``    ` `    ``# Stores all dp-states``    ``temp ``=` `[``-``1` `for` `i ``in` `range``(``1` `<< N ``+` `1``)]``    ``dp ``=` `[temp ``for` `i ``in` `range``(N)]` `    ``# Returns the maximum value``    ``# returned by the function maximizeAnd()``    ``return` `maximizeAnd(``0``, ``0``, A, B, N, dp)` `# Driver Code``if` `__name__ ``=``=` `'__main__'``:``    ` `    ``A ``=` `[ ``3``, ``5``, ``7``, ``11` `]``    ``B ``=` `[ ``2``, ``6``, ``10``, ``12` `]``    ``N ``=` `len``(A)` `    ``print``(maximizeAndUtil(A, B, N))``    ` `# This code is contributed by ipg2016107`

## C#

 `// C# program for the above approach``using` `System;` `class` `GFG {` `    ``// Function to implement recursive DP``    ``static` `int` `maximizeAnd(``int` `i, ``int` `mask, ``int``[] A,``                           ``int``[] B, ``int` `N, ``int``[,] dp)``    ``{``        ``// If i is equal to N``        ``if` `(i == N)``            ``return` `0;` `        ``// If dp[i][mask] is not``        ``// equal to -1``        ``if` `(dp[i, mask] != -1)``            ``return` `dp[i, mask];` `        ``// Iterate over the array B[]``        ``for` `(``int` `j = 0; j < N; ++j) {` `            ``// If current element``            ``// is not yet selected``            ``if` `((mask & (1 << j)) == 0) {` `                ``// Update dp[i][mask]``                ``dp[i, mask] = Math.Max(``                    ``dp[i, mask],``                    ``(A[i] & B[j])``                        ``+ maximizeAnd(i + 1,``                                      ``mask | (1 << j), A, B,``                                      ``N, dp));``            ``}``        ``}``        ``// Return dp[i][mask]``        ``return` `dp[i, mask];``    ``}` `    ``// Function to obtain maximum sum``    ``// of Bitwise AND of same-indexed``    ``// elements from the arrays A[] and B[]``    ``static` `int` `maximizeAndUtil(``int``[] A, ``int``[] B, ``int` `N)``    ``{``      ` `        ``// Stores all dp-states``        ``int``[,] dp = ``new` `int``[N, (1 << N) + 1];``        ``for``(``int` `i = 0; i

## Javascript

 ``

Output
```22

```

Time Complexity: O (N2 * 2N)
Auxiliary Space: O(N * 2N

DP Tabulation Approach(Iterative approach): The approach to solving this problem is the same but the DP tabulation(bottom-up) method is better than the Dp + memoization(top-down) because the memoization method needs extra stack space of recursion calls. Below are the steps:

• Create a 2D matrix, say DP[][] to store the solution of the subproblems and initialize it with 0.
• Initialize the DP with base cases.
• Now Iterate over subproblems to get the value of the current problem from the previous computation of subproblems stored in the DP[][] as the transition from one state to another state can be defined as:
• For all j in the range [0, N], If the jth bit of mask is not set then, dp(i, mask) = max(dp(i, mask|(1<<j))).
• Return the final solution stored in dp[0][(1 << N) – 1].

Implementation:

## C++

 `#include ``using` `namespace` `std;` `// Function to obtain maximum sum``// of Bitwise AND of same-indexed``// elements from the arrays A[] and B[]``int` `maximizeAndUtil(``int``* A, ``int``* B, ``int` `N)``{``    ``// dp[i][mask] stores the maximum sum of Bitwise AND``    ``// of first i elements of A and jth element of B,``    ``// where each element of B can be used at most once and``    ``// the set of already used elements is represented by``    ``// the binary mask 'mask'.``    ``vector > dp(N + 1, vector<``int``>(1 << N, 0));` `    ``// dp[N][mask] is initialized to 0 for all masks``    ``// as Bitwise AND of empty sets is 0.``    ``for` `(``int` `mask = 0; mask < (1 << N); mask++) {``        ``dp[N][mask] = 0;``    ``}` `    ``// i ranges from N-1 to 0``    ``for` `(``int` `i = N - 1; i >= 0; i--) {` `        ``// j ranges from 0 to N-1``        ``for` `(``int` `j = 0; j < N; j++) {` `            ``// If the j-th element of B is``            ``// not already used``            ``if` `((1 << j) & ((1 << N) - 1)) {` `                ``// Iterate over all possible``                ``// sets of elements of B``                ``// that can be used along``                ``// with the j-th element``                ``for` `(``int` `mask = 0; mask < (1 << N);``                     ``mask++) {``                    ``if` `((1 << j) & mask) {``                        ``dp[i][mask] = max(``                            ``dp[i][mask],``                            ``(A[i] & B[j])``                                ``+ dp[i + 1]``                                    ``[mask ^ (1 << j)]);``                    ``}``                ``}``            ``}``        ``}``    ``}` `    ``// The maximum sum is stored``    ``// in dp[0][(1 << N) - 1]``    ``return` `dp[0][(1 << N) - 1];``}` `// Driver Code``int` `main()``{``    ``int` `A[] = { 3, 5, 7, 11 };``    ``int` `B[] = { 2, 6, 10, 12 };``    ``int` `N = ``sizeof` `A / ``sizeof` `A[0];` `    ``cout << maximizeAndUtil(A, B, N);``}`

## Java

 `import` `java.util.*;` `// Added by ~Nikunj Sonigara``public` `class` `Main {``    ``public` `static` `int` `maximizeAndUtil(``int``[] A, ``int``[] B, ``int` `N) {``        ``int``[][] dp = ``new` `int``[N + ``1``][``1` `<< N];` `        ``for` `(``int` `mask = ``0``; mask < (``1` `<< N); mask++) {``            ``dp[N][mask] = ``0``;``        ``}` `        ``for` `(``int` `i = N - ``1``; i >= ``0``; i--) {``            ``for` `(``int` `j = ``0``; j < N; j++) {``                ``if` `((``1` `<< j & (``1` `<< N) - ``1``) != ``0``) {``                    ``for` `(``int` `mask = ``0``; mask < (``1` `<< N); mask++) {``                        ``if` `((``1` `<< j & mask) != ``0``) {``                            ``dp[i][mask] = Math.max(dp[i][mask], (A[i] & B[j]) + dp[i + ``1``][mask ^ (``1` `<< j)]);``                        ``}``                    ``}``                ``}``            ``}``        ``}` `        ``return` `dp[``0``][(``1` `<< N) - ``1``];``    ``}` `    ``public` `static` `void` `main(String[] args) {``        ``int``[] A = {``3``, ``5``, ``7``, ``11``};``        ``int``[] B = {``2``, ``6``, ``10``, ``12``};``        ``int` `N = A.length;` `        ``System.out.println(maximizeAndUtil(A, B, N));``    ``}``}`

## Python3

 `# Added by ~Nikunj Sonigara` `def` `maximizeAndUtil(A, B, N):``    ``dp ``=` `[[``0``] ``*` `(``1` `<< N) ``for` `_ ``in` `range``(N ``+` `1``)]` `    ``for` `mask ``in` `range``(``1` `<< N):``        ``dp[N][mask] ``=` `0` `    ``for` `i ``in` `range``(N ``-` `1``, ``-``1``, ``-``1``):``        ``for` `j ``in` `range``(N):``            ``if` `(``1` `<< j) & ((``1` `<< N) ``-` `1``):``                ``for` `mask ``in` `range``(``1` `<< N):``                    ``if` `(``1` `<< j) & mask:``                        ``dp[i][mask] ``=` `max``(dp[i][mask], (A[i] & B[j]) ``+` `dp[i ``+` `1``][mask ^ (``1` `<< j)])` `    ``return` `dp[``0``][(``1` `<< N) ``-` `1``]` `if` `__name__ ``=``=` `"__main__"``:``    ``A ``=` `[``3``, ``5``, ``7``, ``11``]``    ``B ``=` `[``2``, ``6``, ``10``, ``12``]``    ``N ``=` `len``(A)` `    ``print``(maximizeAndUtil(A, B, N))`

## C#

 `using` `System;` `public` `class` `MaximizeAndUtilMain``{``    ``public` `static` `int` `MaximizeAndUtil(``int``[] A, ``int``[] B, ``int` `N)``    ``{``        ``// Initialize a 2D array to store the dynamic programming results.``        ``int``[,] dp = ``new` `int``[N + 1, 1 << N];` `        ``// Initialize the last row of the dynamic programming table to 0.``        ``for` `(``int` `mask = 0; mask < (1 << N); mask++)``        ``{``            ``dp[N, mask] = 0;``        ``}` `        ``// Start filling the dynamic programming table from the second-to-last row, going backwards.``        ``for` `(``int` `i = N - 1; i >= 0; i--)``        ``{``            ``// Iterate through all elements in array B.``            ``for` `(``int` `j = 0; j < N; j++)``            ``{``                ``// Check if the j-th element in array B is included in the current mask.``                ``if` `((1 << j & ((1 << N) - 1)) != 0)``                ``{``                    ``// Iterate through all possible masks.``                    ``for` `(``int` `mask = 0; mask < (1 << N); mask++)``                    ``{``                        ``// Check if the j-th element is included in the current mask.``                        ``if` `((1 << j & mask) != 0)``                        ``{``                            ``// Calculate the maximum of the current dp value and the bitwise AND of A[i] and B[j]``                            ``// plus the value from the next row and the mask with j-th bit turned off.``                            ``dp[i, mask] = Math.Max(dp[i, mask], (A[i] & B[j]) + dp[i + 1, mask ^ (1 << j)]);``                        ``}``                    ``}``                ``}``            ``}``        ``}` `        ``// The result is stored in the top-left cell of the dynamic programming table.``        ``return` `dp[0, (1 << N) - 1];``    ``}` `    ``public` `static` `void` `Main()``    ``{``        ``int``[] A = { 3, 5, 7, 11 };``        ``int``[] B = { 2, 6, 10, 12 };``        ``int` `N = A.Length;` `        ``// Call the MaximizeAndUtil function and print the result.``        ``Console.WriteLine(MaximizeAndUtil(A, B, N));``    ``}``}`

## Javascript

 `function` `maximizeAndUtil(A, B, N) {``  ``// dp[i][mask] stores the maximum sum of Bitwise AND``  ``// of first i elements of A and jth element of B,``  ``// where each element of B can be used at most once and``  ``// the set of already used elements is represented by``  ``// the binary mask 'mask'.``  ``const dp = ``new` `Array(N + 1).fill(0).map(() => ``new` `Array(1 << N).fill(0));` `  ``// dp[N][mask] is initialized to 0 for all masks``  ``// as Bitwise AND of empty sets is 0.``  ``for` `(let mask = 0; mask < (1 << N); mask++) {``    ``dp[N][mask] = 0;``  ``}` `  ``// i ranges from N-1 to 0``  ``for` `(let i = N - 1; i >= 0; i--) {``    ``// j ranges from 0 to N-1``    ``for` `(let j = 0; j < N; j++) {``      ``// If the j-th element of B is``      ``// not already used``      ``if` `((1 << j) & ((1 << N) - 1)) {``        ``// Iterate over all possible``        ``// sets of elements of B``        ``// that can be used along``        ``// with the j-th element``        ``for` `(let mask = 0; mask < (1 << N); mask++) {``          ``if` `((1 << j) & mask) {``            ``dp[i][mask] = Math.max(``              ``dp[i][mask],``              ``(A[i] & B[j]) + dp[i + 1][mask ^ (1 << j)]``            ``);``          ``}``        ``}``      ``}``    ``}``  ``}` `  ``// The maximum sum is stored``  ``// in dp[0][(1 << N) - 1]``  ``return` `dp[0][(1 << N) - 1];``}` `// Driver code``const A = [3, 5, 7, 11];``const B = [2, 6, 10, 12];``const N = A.length;` `console.log(maximizeAndUtil(A, B, N));`

Output
```22

```

Time Complexity: O (N2 * 2N)
Auxiliary Space: O(N * 2N

Previous
Next