Bit Manipulation
Bit Manipulation
Note ->
● Remember whenever you do n >> 2 , it does not automatically changes the value of n , to actually change the value
of n you need to do n = n >> 2
● Position of brackets always place brackets like → ( arr[i] & (1<<k) ) // inner and then outer
If u place like ( arr[i] ) & (1<<k) , or arr[i] & (1<<k) , this will give wrong results
● For arrays we do indexing from left to right , but note that in case of binary number , if we have to do indexing we do it
from right to left, because 5 for ex in binary is 101 , but in computer it is not stored as 101 but 0000…....101, so we
can not actually find a starting point from left , that’s why we do indexing from right to left
★ Theory
Bit_Magic_Theory.pdf
1) Single number
// a^a^a^a....(even times) = 0
// a^a^a^a....(odd times) = a
i) Single number II
Approach 1 -> use map and maintain freq of all elements , and at last return those elements which have freq as one , T.C ->
O(nlogn) S.C -> O(n)
Approach 2 -> sort the array , after sorting the element which has both of its adjacent neighbors different will be your ans ,
for ex array after sorting look like , arr[ ] = { 1 , 1 ,1 , 3, 3, 3, 4 , 5 ,5 5} , so clearly 4 has both of its neighbor different , handle
corner cases when your ans element is at extreme edges of arr,
T.C -> O(nlogn) S.C -> O(1)
Approach 3 -> We know that each integer is represented as a 32 bit binary number internally, the idea is to count the
number of 1’s, in each of these 32 indexes, and if at any any of these indexes the overall count of 1’s is of of the form 3n +1 ,
then this means ,the unique element which we are searching for has its bit set at that specific index .
The i pointer moves from left to right , covering each of the 32 bit indexes, and for each of the ith index column , the j pointer
moves from top to bottom to find the count of 1’s in that ith index column
—---------------------------------------------------------------
Count of 1’s in each of 32 indexes : 0 ….0 0 0 0 0 3 6 4
Since at index 0 the overall count of 1’s is 4 which is of form 3n + 1, we can say that the unique element
that we are searching for has its bit set at index 0,
While at rest all of the indexes , the overall count of 1’s is in the form of 3n , so we can safely say that the unique element
that we are searching for has its bit clear at all other indexes,
for(int i = 0 ; i < 32 ; i++) // i pointer to traverse the 32 indexes , it moves from right
to left
{
int count = 0; // for each new column , initialize count with 0 again
if( (count %3) == 1){ans = ans |(1<< i);} // if after traversing that whole column the
count of 1's is of form 3n+1 ,the we set the ith index bit in our ans variable as 1
}
return ans; // return the ans
}
Better -> Create a map<int,int> mp , and push all elements in it , while maintaining freq and at last print those elements which
have freq = 1 , T.C = O(nlogn)
Best -> Using Bit - Manipulation, we can get best time complexity , T.C = O(n)
Clearly we can see if we xor all numbers in 5’s group we get 5 , because all other members in 5’s group appear two
times and 5 appear only one time and similarly if we xor all numbers in 7’s group we get 7
long long int n = x_o_r; // when we are doing x_o_r - 1 , it is causing integer overflow ,
for a very large -ve no , so we store it in long long data type
int index = log2(n & (~(n-1))); // finding index at which rightmost bit is set
vector<int> v{ans1,ans2};
return v;
}
We simply find ans for different values of N , and then after observing we can see a pattern is found,
Now , we need to remove 1 ^ 2 term from this expression 1 ^ 2 ^ 3 ^ 4 ^ 5 ^ 6 , to get our ans
And we know the best way to cancel elements in XOR, is to take XOR of that no with itself
So we do
= 3^4^5^6
So , find XOR till R , and XOR till L-1 , and then take their XOR’S
3 2 1 0 --> indexes
now 10 = 1 0 1 0 in binary ,
since k = 2 , we keep 1 at index 2 and rest bit as zero , and hence we get 100 as our mask and
now,we know that
so somehow , we need to move 1 at 2nd bit position to create a mask with which
we can do then & operation
for general if we do (1 << k) --> then this moves 1 to kth index and after that we can
do & operation so ,
*/
3 2 1 0 --> indexes
now 10 = 1 0 1 0 in binary ,
we know that if n & 1 == 0 , then this means at 0th index, we have bit 0
and if n & 1 != 0 , then this means at 0th index, we have bit 1
so ,if somehow we could bring its 2nd index bit at 0th index , then after that using & operator
with 1 we could check that whether 2nd bit is set or not
// let ‘s say k = 3 , then to set 3rd bit our mask would be 1000 , so generalizing for any k
for setting the kth bit , our mask would be 1 << k, after that once we have generated our mask
We simply need to take OR operation with input n
// suppose to clear 2nd bit , your mask would be 0 1 1 , but how to generate 0 1 1 , for this
first generate 1 0 0 using ( 1 << 2) and then simply negate it so ~( 1 0 0 ) = 0 1 1
Generalizing this for any k , to generate mask , we first do (1 << k) and then negate it to get our
mask , so our mask is ~(1 << k)
Once the mask is generated we need to simply take & with the given input n
If we do n & (n-1) it will do the job, not much intuition behind it take example to verify for n = 13 and for n = 12
i) Power of 2 or not
We will observe that any 2’s power binary representation has only 1 set bit and that is also present at MSB
So if we clear the rightmost set bit of any 2’s power binary form , we are sure that we will get all zeros
bool isPowerOfTwo(int x)
{
if(x == 0) return false; // corner case deal it separately u can’t find x-1 for x = 0
Ques said to return the position of the only set bit, if it has more than 1 set bit , or 0 set bit then return -1;
int findPosition(int n)
{
if( n == 0 ) return -1; // when no set bit , it's all zero in binary i.e 0 in decimal so
return -1
/* for it to have only one set - bit , we can ensure that by clearing its rightmost-set bit ,
since it has only 1 set bit ,so after clearing its rightmost set bit we should get all zeros in
binary i.e 0 in decimal , in other words we could also say that for it to have only 1 set bit, it
should be power of 2 and , so we have used the condition to check power of 2
*/
return log2( (n & (~(n-1))) ) + 1; // position of the rightmost set bit , is the
position of the only set bit
}
else return -1; // more than one set bit case , so return -1
}
T.C → O( 𝑙𝑜𝑔2n ) , to understand time complexity , don’t think in terms of binary number simply think that we are running a
loop until n reaches zero , and at each iteration we are doing n = n / 2, hence the time complexity is O( 𝑙𝑜𝑔2n )
int count = 0;
While ( n != 0)
{
if( n & 1 == 1) count;
n = n >> 1;
}
return count;
Approach 2-> the idea is to use the clear rightmost set bit ques concept , we keep clearing the rightmost set bit , until we
reach zero , and the no of times we need to clear the rightmost set bit = count of no of set bits
T.C -> O(no of set bits present) , this is better than first approach
while( n != 0)
{
n = n & (n - 1);
count++;
}
return count;
/* bits needed to be flipped to convert A to B , this ques can be re - stated to find count of the
no of bits that differ in A and B , because for ex: A = 0 1 1 1 0
B = 1 0 1 0 0
once we get the count of no of bits that differ, at those position only we have to toggle the bit
*/
/*
we use the property of xor , that xor of two same bits is 0 , and xor of two different bits is 1
so we could say that count of set bits in A ^ B , is nothing but the count of number of bits that
differ in A and B
*/
Approach 1 ->Again use the same concept of iterating the whole binary number , and as soon as you find 1 break out, as you
keep shifting bits towards right , keep increment your index variable
T.C → O( 𝑙𝑜𝑔2n ) think that we are running a loop until n reaches zero , and at each iteration we are doing n = n / 2, hence the
time complexity is O( 𝑙𝑜𝑔2n )
int getFirstSetBit(int n)
{
int index = 0;
int ans = 0;
while(n != 0)
{
if((n & 1) == 1){ans = index;break;}
else
{
n = n >> 1;
index++;
}
}
return ans;
}
Approach 2 -> a simple formula , not much intuition , put values to verify the result
T.C → O( 𝑙𝑜𝑔2n ) same as that of first approach, but one line solution
int getFirstSetBit(int n)
{
return log2( n & (~(n-1)) );
}
The question is to find XOR of the XOR’s of all subsets. i.e if the set is { 1 , 3, 2 }. All subsets are : [{1}, {2}, {3}, {1, 3}, {1, 2},
{3, 2}, {1, 2, 3}]. Find the XOR of each of the subset and then find the XOR of every subset result
The ans is always going to be zero , because each element will eventually come even number of times when we find XOR of
each of the subset and then find the XOR of every subset result,
Only in one case when n == 1 i.e size of array is one , in that case ans will be that one element only
int findXOR(int arr[], int n)
{
if (n == 1)
return arr[0];
else
return 0;
}
One way to go about is using back-tracking , the other way could be by using bit- manipulation
0 1 2 —> indexes
For ex - let’s say our arr[ ] is { 1 , 2 , 3 } , if i want to include 0th index value and 1st index value in my subset then i will set
the set the 0th and 1st index bit as 1 and for excluding the 2nd index value in my subset, i will set 2nd index bit as 0 , so the
value that we get is is 0 1 1 , and not 1 1 0
NOTE : -> There is a difference in indexing of array and binary numbers, when i say 0th index for array it means left
most - value , whereas 0th index for binary is right most bit
2 1 0 → indexes
So our mask is 0 1 1
❖ So , just remember that which-ever index value of array you want to include in subset , make that
corresponding index bit as 1,
So given an arr[ ] = { 1 , 2 , 3 } and If i say mask is 1 0 1 , then this mask corresponds to which subset ?
Ans -> find all those indexes whose bits value are set,
2 1 0 → indexes
So our mask is 1 0 1
We can see index 0 , and index 2 has their bits = 1, so our subset = {arr[0] ,arr[2] } = { 1 , 3 }
0 0 0 —-> 0 in decimal
0 0 1 —-> 1 in decimal
0 1 0 —-> 2 in decimal
0 1 1 —-> 3 in decimal
1 0 0 —-> 4 in decimal
1 0 1 —-> 5 in decimal
1 1 0 —-> 6 in decimal
1 1 1 —-> 7 in decimal
Hence we can conclude that mask varies from 0 to 7 , or to be more generalized we can say that
mask varies from 0 to 2^n - 1 , where n is the size of array
// each mask value corresponds to one subset , and the subset which that mask represent is
founded using inner while loop , while the outer loop cover all the mask values from 0 to 2^n -1
vector<vector<int>> ans;
for (int mask = 0; mask < pow(2, n) ; mask++) // let ‘s say at any moment mask is 5 , then this
corresponds to mask as 1 0 1
{
vector<int> temp;
int index = 0; // to keep track of those indexes whose bit value is 1 in mask ,here mask = 1 0 1
int x = mask; // storing mask in another variable , so that mask doesn't gets changed
ans.push_back(temp);
}
Also,the number of times this whole subtraction process needs to be done = 5 = quotient
In short the algo for division using bit manipulation is ,let’s say u want to find 23 / 3
𝑖
We try to find the highest possible value of i that satisfy this equation - > divisor * 2 < dividend , once we get that i
value ,we do 2 things
𝑖
1. We subtract ( divisor * 2 ) from our current dividend , to get new dividend ,
𝑖
so dividend = dividend - ( divisor * 2 )
𝑖 𝑖
2. And we also add this 2 to our ans variable so , ans = ans + 2
And we keep doing this whole process until our dividend is greater than divisor
For dry run of this algo , see the leetcode discuss section link
Complete Thinking Process | Intuitive Explanation | All rules followed | C++ code - LeetCode Discuss
Once you will come out of this inner while loop , the current i value will be such that this
equation -> divisor * 2^i <= dividend,will not be satisfied , but we need to find the highest
possible value of i , that satisfy this equation ,So we just take 1 value less than the current i
value ,
So do i - - ;
Now since we have got the required i value ,we need to do those two task that were mentioned above
}
return ans;
𝑖
But if you notice we have used operation of multiplying by 2 , but we can use left shift command to get the same result , this
was the whole reason why we were dealing with power of 2’s this whole time
dividend = dividend - (divisor * 2^i) ; is equivalent to -> dividend = dividend - (divisor << i) ;
1. there can be chances that our quotient goes overflow , and this will happen only in cases when
you dividend = INT_MAX or INT_MIN and divisor = 1 or -1
so after seeing the range of dividend mentioned in ques, according deal these cases as instructed
in the ques
2. for safety purposes store your ans , dividend and divisor in long long int ,and also figure out
the sign of your ans , whether overall ans will be +ve or -ve
*/
int divide(int a, int b)
{
if( a == INT_MIN && b == -1){return INT_MAX;} // dealing with overflow corner cases
if( a == INT_MIN && b == 1){return INT_MIN;}
if( a == INT_MAX && b == 1){return INT_MAX;}
if( a == INT_MAX && b == -1){return -INT_MAX;}
int sign = 1;
if( (a < 0 && b > 0) || ( a > 0 && b < 0)){sign = -1;} // if any of a or b is -ve , overall ans
will be -ve
if( sign == 1) return ans;
else return -ans;
In recursion , our aim is to break our i/p into smaller i/p until we reach the base case,
Here also with the help of this recursive relation square(n) = 4*square(n/2) ,(for n = even) we are breaking
our i/p into smaller i/p.So ,now instead of finding square of n ,our problem reduces to
finding square of n/2 we keep going like this until we hit the base case when n == 0
int square(int n)
{
if ( (n & 1) == 1 ) // If n is odd
return ((square(x) << 2) + (x << 2) + 1);
else // If n is even
return (square(x) << 2);
}