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++ 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 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 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# 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__ |
<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)