Skip to content
Related Articles

Related Articles

Generate pairs in range [0, N-1] with sum of bitwise AND of all pairs K

Improve Article
Save Article
  • Last Updated : 21 Sep, 2022
Improve Article
Save Article

Given an integer N (which is always a power of 2) denoting the length of an array which contains integers in range [0, N-1] exactly once, the task is to pair up these elements in a way such that the sum of AND of the pair is equal to K. i.e ∑ (ai & bi) = K.

Note: Each element can be part of only one pair.

Examples:

Input: N = 4, K = 2
Output: [[0, 1], [2, 3]]
Explanation: Here N = 4 means array contains arr[] = {0, 1, 2, 3}, 
Pairs = [0, 1] and [2, 3]
(0 & 1) + (2 & 3) = 0 + 2 = 2.

Input: N = 8, K = 4
Output: [[4, 7], [1, 6], [2, 5], [0, 3]]

 

Approach: The solution to the problem is based on the following observation:

There can be four cases as shown below:

  • Case 1 (If K = 0):
    • Because N is power of 2, the pairs of form {0+i, N-1-i} will always have bitwise AND as 0 [where i = 0 to (N-1)/2].
    • Here AND of every pair is going to be 0 which implies the sum of every AND pair is going to be 0.
    • After that for K = 0 form these pairs in the following form: [[0, N-1], [1, N-2] . . .].
  • Case 2 (If K > 0 and K < N-1):
    • Bitwise AND of K with N-1 is always K.
    • From the above pairs,  exchanging only elements of two pairs and make pairs [K, N-1] and [0, the one which was a pair of K]. So the AND will be K.
  • Case 3 (If K = N-1 and N = 4): 
    • In this case pairing is not possible print -1.
  • Case 4 (If K = N-1 and N > 4):
    • The maximum AND of any pair can be N-2 which can be formed by N-1 and N-2. So other two pairs can be formed to have bitwise AND =1 i.e. (N-3 with 1) and (0 with 2) because N-3 and 1 are always odd. The other pairs can be kept as it was in case-1. So total bitwise AND sum will be N-1.

Follow the steps mentioned below:

  • Check the values of K and N.
  • Form the pairs as per the case mentioned above according to the values of N and K.

Below is the implementation of the above approach:

C++




// C++ code to implement the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to print N-1 Pairs
void pairOfAND(int N, int K)
{
   
    // Initializing ans which contains
    // AND pairs having sum equal to K
    vector<vector<int> > ans;
 
    // Case 1 and Case 2
    if (K >= 0 || K < N - 1) {
 
        // Hash Map contains pairs
        map<int, int> pair;
        for (int i = 0, j = N - 1; i < N / 2; i++, j--) {
            pair.insert({ i, j });
            pair.insert({ j, i });
        }
 
        // Case 1
        if (K == 0) {
            for (int i = 0; i < N / 2; i++) {
                vector<int> al;
                al.push_back(i);
                al.push_back(pair[i]);
                ans.push_back(al);
            }
        }
 
        // Case 2
        else if (K < N / 2) {
            vector<int> al;
            al.push_back(K);
            al.push_back(N - 1);
            ans.push_back(al);
            for (int i = 1; i < N / 2; i++) {
                al = {};
                al.push_back((i == K) ? 0 : i);
                al.push_back(pair[i]);
                ans.push_back(al);
            }
        }
        else {
            vector<int> al;
            al.push_back(K);
            al.push_back(N - 1);
            ans.push_back(al);
            for (int i = N / 2; i < N - 1; i++) {
                al = {};
                al.push_back((i == K) ? 0 : i);
                al.push_back(pair[i]);
                ans.push_back(al);
            }
        }
    }
 
    // Case 4
    else {
        if (N != 4) {
            vector<int> al;
            al.push_back(N - 1);
            al.push_back(N - 2);
            ans.push_back(al);
            al = {};
            al.push_back(N - 3);
            al.push_back(1);
            ans.push_back(al);
            al = {};
            al.push_back(0);
            al.push_back(2);
            ans.push_back(al);
            for (int i = 3; i < N / 2; i++) {
                al = {};
                int comp = i ^ (N - 1);
                al.push_back(i);
                al.push_back(comp);
                ans.push_back(al);
            }
        }
    }
 
    // Case 3
    if (ans.size() == 0)
        cout << (-1);
    else
        for (auto arr : ans) {
            for (auto dt : arr)
                cout << dt << " ";
            cout << "\n";
        }
}
 
// Driver Code
int main()
{
    int N = 4;
    int K = 2;
    pairOfAND(N, K);
 
    return 0;
}
 
    // This code is contributed by rakeshsahnis


Java




// Java code to implement the above approach
 
import java.util.*;
 
class GFG {
 
    // Function to print N-1 Pairs
    public static void pairOfAND(int N,
                                 int K)
    {
        // Initializing ans which contains
        // AND pairs having sum equal to K
        List<List<Integer> > ans
            = new ArrayList<>();
 
        // Case 1 and Case 2
        if (K >= 0 || K < N - 1) {
 
            // Hash Map contains pairs
            Map<Integer, Integer> pair
                = new HashMap<>();
            for (int i = 0, j = N - 1;
                 i < N / 2;
                 i++, j--) {
                pair.put(i, j);
                pair.put(j, i);
            }
 
            // Case 1
            if (K == 0) {
                for (int i = 0; i < N / 2;
                     i++) {
                    List<Integer> al
                        = new ArrayList<>();
                    al.add(i);
                    al.add(pair.get(i));
                    ans.add(al);
                }
            }
 
            // Case 2
            else if (K < N / 2) {
                List<Integer> al
                    = new ArrayList<>();
                al.add(K);
                al.add(N - 1);
                ans.add(al);
                for (int i = 1; i < N / 2;
                     i++) {
                    al = new ArrayList<>();
                    al.add((i == K) ? 0 : i);
                    al.add(pair.get(i));
                    ans.add(al);
                }
            }
            else {
                List<Integer> al
                    = new ArrayList<>();
                al.add(K);
                al.add(N - 1);
                ans.add(al);
                for (int i = N / 2; i < N - 1;
                     i++) {
                    al = new ArrayList<>();
                    al.add((i == K) ? 0 : i);
                    al.add(pair.get(i));
                    ans.add(al);
                }
            }
        }
 
        // Case 4
        else {
            if (N != 4) {
                List<Integer> al
                    = new ArrayList<>();
                al.add(N - 1);
                al.add(N - 2);
                ans.add(al);
                al = new ArrayList<>();
                al.add(N - 3);
                al.add(1);
                ans.add(al);
                al = new ArrayList<>();
                al.add(0);
                al.add(2);
                ans.add(al);
                for (int i = 3; i < N / 2;
                     i++) {
                    al = new ArrayList<>();
                    int comp = i ^ (N - 1);
                    al.add(i);
                    al.add(comp);
                    ans.add(al);
                }
            }
        }
 
        // Case 3
        if (ans.isEmpty())
            System.out.println(-1);
        else
            System.out.println(ans);
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        int N = 4;
        int K = 2;
        pairOfAND(N, K);
    }
}


Python3




# Python3 code to implement the above approach
# Function to print N-1 Pairs
def pairOfAND(N, K):
   
    # Initializing ans which contains
    # AND pairs having sum equal to K
    ans = []
 
    # Case 1 and Case 2
    if (K >= 0 or K < N - 1):
 
        # Hash Map contains pairs
        pair = {}
        j = N-1
        for i in range(0, int(N/2)):
            pair[i] = j
            pair[j] = i
            j = j-1
 
        # Case 1
        if (K == 0):
            for i in range(0, int(N/2)):
                al = []
                al.append(i)
                al.append(pair.get(i))
                ans.append(al)
 
        # Case 2
        elif (K < N / 2):
            al = []
            al.append(K)
            al.append(N - 1)
            ans.append(al)
            for i in range(1, int(N/2)):
                al = []
                to_be_appended = i
                if(i is K):
                        to_be_appended = 0
                al.append(to_be_appended)
                al.append(pair.get(i))
                ans.append(al)
        else:
            al = []
            al.append(K)
            al.append(N - 1)
            ans.append(al)
            for i in range(int(N/2), N-1):
                al = []
                to_be_appended = i
                if(i == K):
                  to_be_appended = 0
 
                al.append(to_be_appended)
                al.append(pair.get(i))
                ans.append(al)
 
    # Case 4
    else:
        if (N != 4):
            al = []
            al.append(N - 1)
            al.append(N - 2)
            ans.append(al)
            al = []
            al.append(N - 3)
            al.append(1)
            ans.append(al)
            al = []
            al.append(0)
            al.append(2)
            ans.append(al)
            for i in range(3, int(N/2)):
                al = []
                comp = i ^ (N - 1)
                al.append(i)
                al.append(comp)
                ans.append(al)
 
    # Case 3
    if (len(ans) is 0):
        return -1
    else:
        return ans
 
# Driver Code
N = 4
K = 2
print(pairOfAND(N, K))
 
# This code is contributed by akashish__


C#




// C# code to implement the above approach
using System;
using System.Collections.Generic;
 
public class GFG {
 
  // Function to print N-1 Pairs
  public static void pairOfAND(int N, int K)
  {
 
    // Initializing ans which contains
    // AND pairs having sum equal to K
    // vector<vector<int> > ans;
    List<List<int> > ans = new List<List<int> >();
 
    // Case 1 and Case 2
    if (K >= 0 || K < N - 1) {
 
      // Hash Map contains pairs
      // map<int, int> pair;
      Dictionary<int, int> pair
        = new Dictionary<int, int>();
      for (int i = 0, j = N - 1; i < N / 2;
           i++, j--) {
        pair.Add(i, j);
        pair.Add(j, i);
      }
 
      // Case 1
      if (K == 0) {
        for (int i = 0; i < N / 2; i++) {
          List<int> al = new List<int>();
          al.Add(i);
          al.Add(pair[i]);
          ans.Add(al);
        }
      }
 
      // Case 2
      else if (K < N / 2) {
        List<int> al = new List<int>();
        al.Add(K);
        al.Add(N - 1);
        ans.Add(al);
        for (int i = 1; i < N / 2; i++) {
          al = new List<int>();
          al.Add((i == K) ? 0 : i);
          al.Add(pair[i]);
          ans.Add(al);
        }
      }
      else {
        List<int> al = new List<int>();
        al.Add(K);
        al.Add(N - 1);
        ans.Add(al);
        for (int i = N / 2; i < N - 1; i++) {
          al = new List<int>();
          int to_be_pushed = i;
          if (i == K)
            to_be_pushed = 0;
          al.Add(to_be_pushed);
          al.Add(pair[i]);
          ans.Add(al);
        }
      }
    }
 
    // Case 4
    else {
      if (N != 4) {
        List<int> al = new List<int>();
        al.Add(N - 1);
        al.Add(N - 2);
        ans.Add(al);
        al = new List<int>();
        al.Add(N - 3);
        al.Add(1);
        ans.Add(al);
        al = new List<int>();
        al.Add(0);
        al.Add(2);
        ans.Add(al);
        for (int i = 3; i < N / 2; i++) {
          al = new List<int>();
          int comp = i ^ (N - 1);
          al.Add(i);
          al.Add(comp);
          ans.Add(al);
        }
      }
    }
 
    // Case 3
    if (ans.Count == 0)
      Console.Write("-1");
    else {
      for (int i = 0; i < ans.Count; i++) {
        for (int j = 0; j < ans[i].Count; j++) {
          Console.Write(ans[i][j] + " ");
        }
        Console.WriteLine("");
      }
    }
  }
 
  static public void Main()
  {
    // Code
    int N = 4;
    int K = 2;
    pairOfAND(N, K);
  }
}
 
// This code is contributed by akashish__


Javascript




<script>
// Javascript code to implement the above approach
// Function to print N-1 Pairs
function pairOfAND(N, K)
{
 
    // Initializing ans which contains
    // AND pairs having sum equal to K
    // vector<vector<let> > ans;
    let ans = [];
 
    // Case 1 and Case 2
    if (K >= 0 || K < N - 1) {
 
        // Hash Map contains pairs
        let pair = new Map();
        for (let i = 0, j = N - 1; i < N / 2; i++, j--) {
            pair.set(i, j);
            pair.set(j, i);
        }
 
        // Case 1
        if (K == 0) {
            for (let i = 0; i < N / 2; i++) {
                // vector<let> al;
                let al = [];
                al.push(i);
                al.push(pair.get(i));
                ans.push(al);
            }
        }
 
        // Case 2
        else if (K < N / 2) {
            al = [];
            al.push(K);
            al.push(N - 1);
            ans.push(al);
            for (let i = 1; i < N / 2; i++) {
                al = [];
                al.push((i == K) ? 0 : i);
                al.push(pair[i]);
                ans.push(al);
            }
        }
        else {
            al = [];
            al.push(K);
            al.push(N - 1);
            ans.push(al);
            for (let i = N / 2; i < N - 1; i++) {
                al = [];
                let to_be_pushed =i;
                if(i==K) to_be_pushed =0;
                 
                al.push(to_be_pushed);
                al.push(pair.get(i));
                ans.push(al);
            }
        }
    }
 
    // Case 4
    else {
        if (N != 4) {
            al = [];
            al.push(N - 1);
            al.push(N - 2);
            ans.push(al);
            al = [];
            al.push(N - 3);
            al.push(1);
            ans.push(al);
            al = [];
            al.push(0);
            al.push(2);
            ans.push(al);
            for (let i = 3; i < N / 2; i++) {
                al = [];
                let comp = i ^ (N - 1);
                al.push(i);
                al.push(comp);
                ans.push(al);
            }
        }
    }
 
    // Case 3
    if (ans.length == 0)
            console.log(-1);
        else
            console.log(ans);
}
 
// Driver Code
    let N = 4;
    let K = 2;
    pairOfAND(N, K);
 
    // This code is contributed by akashish__
</script>


Output

[[2, 3], [0, 1]]

Time Complexity: O(N)
Auxiliary Space: O(N)


My Personal Notes arrow_drop_up
Related Articles

Start Your Coding Journey Now!