Skip to content
Related Articles

Related Articles

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

View Discussion
Improve Article
Save Article
  • 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]:
      • If the jth bit of mask is not set then, dp(i, mask) = max(dp(i, mask|(1<<j))).

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.
    • If dp[i][mask] is not equal to -1 i.e already visited then return dp[i][mask].
    • 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).
    • Finally, return dp[i][mask].
  • 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 <bits/stdc++.h>
using namespace std;
 
// Function to implement recursive DP
int maximizeAnd(int i, int mask,
                int* A, int* B, int N,
                vector<vector<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))) {
 
            // 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<vector<int> > 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<N; i++)
        {
            for(int j =0 ; j<(1 << N) + 1; j++)
            {
                dp[i, j] = -1;
            }
        }
 
        // Returns the maximum value
        // returned by the function maximizeAnd()
        return maximizeAnd(0, 0, A, B, N, dp);
    }
 
    // Driver Code
    static void Main()
    {
        int[] A = { 3, 5, 7, 11 };
        int[] B = { 2, 6, 10, 12 };
        int N = A.Length;
 
        Console.Write(maximizeAndUtil(A, B, N));
    }
}
 
// This code is contributed by sanjoy_62.

Javascript




<script>
 
// Javascript program for the above approach
 
// Function to implement recursive DP
function 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(var j = 0; j < N; ++j)
    {
         
        // If current element
        // is not yet selected
        if (!(mask & (1 << j)))
        {
             
            // 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[]
function maximizeAndUtil(A, B, N)
{
     
    // Stores all dp-states
    var dp = Array.from(
        Array(N), () => Array(1 << N + 1).fill(-1));
 
    // Returns the maximum value
    // returned by the function maximizeAnd()
    return maximizeAnd(0, 0, A, B, N, dp);
}
 
// Driver Code
var A = [ 3, 5, 7, 11 ];
var B = [ 2, 6, 10, 12 ];
var N = A.length
 
document.write(maximizeAndUtil(A, B, N));
 
// This code is contributed by rrrtnx
 
</script>

Output: 

22

 

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

 


My Personal Notes arrow_drop_up
Recommended Articles
Page :

Start Your Coding Journey Now!