Bit Manipulation
Posted jiachengzhang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Bit Manipulation相关的知识,希望对你有一定的参考价值。
//hamming distance: the number of different bits
private static int hammingDistance(int num1,int num2){
//The first way is using bitCount
int res = Integer.bitCount(num1^num2);
//The second may is
int diff = 0;
while(num1!=0||num2!=0){
if(num1%2!=num2%2)
diff++;
num1>>=1;
num2>>=1;
}
// System.out.println(res==diff);
return diff;
}
//total hamming distance among nums
private static int totalHammingDistance(int[] nums){//O(n)
int total = 0;
for (int i = 0;i<32;i++){
int count = 0;
for (int j = 0;j<nums.length;j++){
count+=(nums[j]>>i)&1;
}
total+=count*(nums.length-count);
//count is the number of numbers whose i th bit is 1
//nums.length-count is the number of numbers whose i th bit is 0
//we need the permutation
}
return total;
}
//hammingWeight is the number of 1‘s in an integer
private static int hammingWeight(int n){
//O(1)
//check bit by bit
int res = 0;
int mask = 1;
for (int i = 0;i<32;i++){
if((n&mask)!=0) //!= > & in priority
res++;
mask<<=1;
}
/*
* 111&110=110
* 110&101=100
* 100&011=000*/
int count = 0;
while(n!=0){
count++;
n&=n-1;
}
//System.out.println(res==count);
return count;
}
//hammingWeight is a series of consecutive numbers
public int[] countBits(int num) {
//method 1
//the basic spirit of the hamming weight problem is i&(i-1)
//which will get convert the rightmost bit which is 1 into 0
//by checking whether the result is 0 we can count the number of 1;
int[] res = new int[num+1];
res[0] = 0;
for(int i = 1;i<=num;i++){
res[i] = 1+ res[i&(i-1)];
}
//method 2
//the spirit is the number is the previous power of 2 + some number
//e.g. 10 = 8+2 = 1000 + 0010, the previous power of 2 which is 8
//always contains one 1. And other 1‘s come from the rest number which is
//in this case, 0010
int base = 1;
int nextBase = base*2;
int ans[] = new int[num+1];
for(int i = 1;i<=num;i++){
ans[i] = 1+ ans[i-base];
if (i==nextBase-1){
base = nextBase;
nextBase*=2;
}
}
return res;
}
//if we want to find the only different element, using ^
//only one number in the array is not repeated, others repeat twice
private static int singleNumber(int nums[]){
int res = nums[0];
for (int i = 1;i<nums.length;i++){
res^=nums[i];
}
return res;
}
//one number repeated once others repeated 3 times
private static int singleNumber2(int nums[]){
int ans = 0;
for(int i = 0; i < 32; i++) {
int sum = 0;
//the sum of times of 1 in each bit
//if sum reaches 3, clear it
//if kth bit of the unique number is 1, sum will be 1
//sum<<i will find the position
for(int j = 0; j < nums.length; j++) {
if(((nums[j] >> i) & 1) == 1) {
sum++;
sum %= 3;
}
}
if(sum != 0) {
ans |= sum << i;
}
}
return ans;
//2,2,2,3
//a=0,2,0,0
//b=2,0,0,3
/* int a = 0, b = 0;
for (int i = 0; i < nums.length; i++) {
b = (b ^ nums[i]) & ~a;
a = (a ^ nums[i]) & ~b;
}
return b;*/
}
//only two not repeated other repeat twice
private static int[] singleNumber3(int nums[]){
int diff = 0;
int[] res = new int[2];
for(int i = 0;i<nums.length;i++){
diff^= nums[i];
}
// 3 is 011, 5 is 101 another e.g. 3 is 011, 4 is 100 , 3^4 is 111=>111&001=001
//3^5 = 110
//-diff is 010 diff&-diff is 010
diff&= -diff; //there must exist at least one bit = 1 in num , to find the rightmost bit which is 1, assume the pos is k
//-diff = diff 取反加1
for(int i = 0;i<nums.length;i++){
if((diff & nums[i]) == 0){ // nums whose kth bit is 1, existing in pairs except one of target nums
res[0]^= nums[i];
}else{
res[1]^=nums[i]; // nums whose kth bit is not 1, existing in pairs except one of target nums
}
}
return res;
}
//assume t contains all chars in s but is added only one different char
private static char findTheDifference(String s,String t){
//method 1; by ^
char c = 0;
for (char c1:s.toCharArray())
c^=c1;
for (char c2:t.toCharArray())
c^=c2;
System.out.println(c);
//method 2; by sum
int sum1 = 0,sum2 =0 ;
for (char c1:s.toCharArray())
sum1+=c1;
for (char c2:t.toCharArray())
sum2+=c2;
System.out.println((char)(sum2-sum1));
//method 3; by checker
int checker = 0;
for (char c1:s.toCharArray())
checker|=1<<c1;
for (char c2:t.toCharArray())
if ((checker&(1<<c2))==0)
System.out.println(c2);
return c;
}
//add two integer
private static int add(int a,int b){
if(b==0)
return a;
int sum = a^b; //get sum without carry
int carry = (a&b)<<1; //get carry. since it will add to the upper bit, we need a left shift
return add(sum,carry);
}
//find the majority number: times>n/2
private static int majorityNumber(int[] nums){
//Boyer-Moore voting Algorithm; time O(n) space O(1)
//https://blog.csdn.net/kimixuchen/article/details/52787307
int count = 1;
int candidate = nums[0];
for (int num:nums){
if (count==0){
count=1;
candidate = num;
}
else if(num==candidate)
count++;
else
count--;
}
return candidate;
//other ways: hashmap O(n)+O(n)
// sort and get the middle one: O(nlogn)+O(1)
}
//find the majority number: times>n/3
public static List<Integer> majorityElement(int[] nums){
int count1 = 0,count2 = 0;
int candidate1 = 0,candidate2 = 1;//they must be different
//because nums can contains all the same elements
for(int num:nums){
if(num==candidate1)
count1++;
else if(num==candidate2)
count2++;
else if(count1==0){
candidate1=num;
count1=1;
}
else if(count2==0){
candidate2=num;
count2=1;
}
else{
count1--;
count2--;
}
}
count1=0;
count2=0;
for(int num:nums){ //to check if candidates are majorities
//since there may be no majority number
if(num==candidate1)
count1++;
if(num==candidate2)
count2++;
}
List<Integer> res= new ArrayList<>();
if(count1>nums.length/3)
res.add(candidate1);
if(count2>nums.length/3)
res.add(candidate2);
return res;
}
//.Reverse bits of a given 32 bits unsigned integer.
private static int reverseBits(int n){
//res makes a left shift every time to empty its rightmost bit for the next bit of n
//then we get each bit of n from right to left
//once we give res a bit of n, this bit will move to left with res
//so the rightmost bit of n will move to the leftmost bit of res in the end.
int res = 0;
for (int i = 0;i<32;i++){
res = res<<1 | n&1;
n>>=1;
}
return res;
}
//two adjacent bits will always have different values.
private static boolean hasAlternatingBits(int n) {
n^=n>>1;
return (n&(n+1))==0?true:false;
//n&(n+1) can check whether n is 111..
}
以上是关于Bit Manipulation的主要内容,如果未能解决你的问题,请参考以下文章