通过位运算取出一个数字的二进制表示的每一位(从末位开始取),比如说:
11=(1011),所以依次取出末位1,然后是1,0,1
public class bit_cal
{
public static void main(String[] args)
{
int x=11;
while(x!=0)
{
int temp=x&1;
System.out.println(temp);//输出此时二进制表示的最后一位是0还是1
x=x>>1;//x右移
}
}
}
//最后打印输出结果为:1101
//11=1011,所以输出确实应该是1101
例题1:191. 位1的个数 - 力扣(LeetCode)
下面这种方法是最简单的方法,把这个数二进制形式下的最后一位依次取出来
这里的有符号右移和无符号右移的问题参考这个链接>>有符号右移和>>>无符号右移_Pr Young的博客-CSDN博客
public class Solution
{
// you need to treat n as an unsigned value
public int hammingWeight(int n)
{
int result=0;
while(n!=0)
{
if((n&1)!=0)//判断最后一位是否为0,不为0,那就统计结果加1
{
result++;
}
n=n>>>1;//注意这里用无符号右移,而不是有符号右移
}
return result;
}
}
还有下面的方法也是可以的:
将输进来的数依次和下面32个数进行与操作,结果不为0说明输进来的数这一位是1,结果为0说明输进来的数这一位是0,用一个数count来统计位为1的位数
左移32次法:
public class Solution
{
// you need to treat n as an unsigned value
public int hammingWeight(int n)
{
int count=0;
int m=1;//32个数中的第一个数,0000.....0001
for(int i=1;i<=32;i++)
{
if((n&m)!=0) count++;
m=m<<1;//m左移1位
}
return count;
}
}
当然你也可以不断的将输入的n进行右移一位,和0000.....0001来进行与操作,右移32次法:
public class Solution
{
// you need to treat n as an unsigned value
public int hammingWeight(int n)
{
int count=0;
int m=1;
for(int i=1;i<=32;i++)
{
if((n&m)!=0) count++;
n=n>>1;//n右移1位
}
return count;
}
}
解法3:利用性质:n&(n-1),运算结果是把n的二进制表示中的最低位的1变成0:
利用这个性质,不断的将当前n和n-1进行&操作,直到n变成0,进行了多少次与操作,就说明有多少位的1
public class Solution
{
// you need to treat n as an unsigned value
public int hammingWeight(int n)
{
int count=0;
while(n!=0)
{
n=n&(n-1);
count++;
}
return count;
}
}
力扣338 比特位计数 (就是统计0~n中每个数有多少位1)
class Solution
{
public int[] countBits(int n)
{
int[] result=new int[n+1];
for(int i=0;i<=n;i++)
{
result[i]=dfs(i);
}
return result;
}
public int dfs(int k)
{
int result=0;
while(k!=0)
{
if((k&1)!=0)//判断最后一位是否为0,不为0,那就统计结果加1
{
result++;
}
k=k>>>1;
}
return result;
}
}
1231. 2 的幂 - 力扣(LeetCode)
231. 2 的幂 - 力扣(LeetCode)
判断一个数是否是2的n次方,比如16是,5不是
暴力法:
class Solution
{
public boolean isPowerOfTwo(int n)
{
for(int i=0;Math.pow(2,i)<=n;i++)
{
if(Math.pow(2,i)==n) return true;
}
return false;
}
}
如果一个数m是2的n次方,那么它的二进制表示就是100000,最高位为1,其他位都是0
而m-1的二进制表示就是011111,最高位为0,其他位为1
所以m&m-1=0
class Solution
{
public boolean isPowerOfTwo(int n)
{
//提交时发现有两个测试用例0和-2147483648
//这两个预期都是false,但是我们答案得到的是true
if(n<=0) return false;
return (n&(n-1))==0;
}
}
342. 4的幂 - 力扣(LeetCode)
核心:首先这个数得是2的n次方,其次这个数除以3余数必须为1,那么这个数就是4的幂
class Solution
{
public boolean isPowerOfFour(int n)
{
return ((n&(n-1))==0)&&(n%3==1);
}
}
面试题 16.01. 交换数字 - 力扣(LeetCode)
不使用中间变量交换两个数字
class Solution
{
public int[] swapNumbers(int[] numbers)
{
numbers[0] = numbers[0] ^ numbers[1];
numbers[1] = numbers[0] ^ numbers[1];
numbers[0] = numbers[0] ^ numbers[1];
return numbers;
}
}
136. 只出现一次的数字 - 力扣(LeetCode)
数组中只出现一次的数(其他数都出现两次)
利用性质:(1)任何数和自己做异或(异为1,同为0),结果都为0
(2)0和任何数做异或,结果为本身
class Solution
{
public int singleNonDuplicate(int[] nums)
{
int result=0;
for(int num:nums)
{
result=result^num;
}
return result;
}
}
461. 汉明距离 - 力扣(LeetCode)
也就是说先将两个数进行异或运算,然后就是上卖那道题目了:求位1的个数
class Solution
{
public int hammingDistance(int x, int y)
{
//先求出x^y,即x和y做异或运算就可以求出这两个数之间有多少位不一样了
//然后看结果中有几位1就知道汉明距离是多少了
//那怎么看一个数的二进制表示里面有几个1呢?x=x&(x-1)看几次x才能变为0
int temp=x^y;
int result=0;
while(temp!=0)
{
result++;
temp=temp&(temp-1);
}
return result;
}
}
力扣剑指offer65 不用加号 通过位运算实现两数相加
力扣371两整数之和也是一样的题目
(1)异或就是不进位相加
(2) 那进位信息怎么求呢?求与,然后再向左移动一位
所以:不进位相加(异或)+进位信息(与操作然后向左移一位)
class Solution
{
public int add(int a,int b)
{
int temp1=0;//记录异或的结果
int temp2=0;//记录与然后左移一位的结果
while (b != 0)//与的结果为0就跳出循环
{
temp1 = a ^ b;
temp2 = (a & b) << 1;
a = temp1;
b = temp2;
}
//最后返回的是异或的结果
return a;
}
}
不用加号 通过位运算实现两数相减
减法a-b,就是a加上b的相反数
一个数的相反数怎么求,这个数取反加1就是这个数的相反数
class Solution
{
public int add(int a,int b)
{
b=~b+1;
int temp1=0;//记录异或的结果
int temp2=0;//记录与然后左移一位的结果
while (b != 0)//与的结果为0就跳出循环
{
temp1 = a ^ b;
temp2 = (a & b) << 1;
a = temp1;
b = temp2;
}
//最后返回的是异或的结果
return a;
}
}
不用乘号,通过位运算实现两数两乘
class Solution
{
public int multi(int a,int b)
{
int result=0;
while(b!=0)
{
if(b&1)!=0
{
}
}
}