Generate pairs in range [0, N-1] with sum of bitwise AND of all pairs K
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> |
[[2, 3], [0, 1]]
Time Complexity: O(N)
Auxiliary Space: O(N)
Please Login to comment...