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

• Last Updated : 16 Jun, 2021

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 same respective positions in both arrays A[] and B[]:
• 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 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;` `    ``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

My Personal Notes arrow_drop_up