算法学习--位运算

位运算

1.常见的几种位运算符

  • &:与运算
  • |:或运算
  • ^:异或运算
  • ~:非/取反
  • >>:右移,高位用符号位填充
    对int型数据1>>35 == 1>>3,int是32位,超过32位后会进行截取,同理,long就是64位
  • >>>:右移,高位用0填充
  • <<:左移

2.运算符的几种常见方法

  1. 判断奇偶
    x & 1 = 1 -> x为奇数
    x & 1 = 0 -> x为偶数
  2. 获取二进制x的第n位是0还是1
    如果(x & (1 << n)) == 0,则该位为0,否则位1
  3. 1左移表示乘以2,1右移表示除以2
    2^n = 1 << n
    1/(2^n) = 1 >> n
  4. 使用异或运算可以消除重复
    A ^ A = 0
    A ^ 0 = A
    A ^ B ^ A = B
  5. 消除二进制的最后一个1
    x & (x-1)
  6. 交换2个数(不使用额外空间)
    a = a ^ b
    b = a ^ b
    a = a ^ b
  7. n个相同n进制的数不进位相加,结果为0
    二进制下 111 + 111 = 0
    三进制下 121 + 121 = 0
  8. 求两个数的中间值(a < b)
    mid = a + ((b-a) >> 1)

3.例题

  1. 找出一个数组中唯一的重复数
/*
假设有11个数,其中1-10各一个,其中有一个数有2个,找出这个数;
根据性质1^2^2^3^1^2^3 = 2
*/
public static void main(String[] args) {
	int[] arr = {1,2,3,3,4,5,6,7,8,9,10};
	int num = 0;
	for(int i = 0; i < arr.length; i++){
		num = num ^ arr[i];
	}
	for(int i = 1; i < arr.length; i++){
		num = num ^ i;
	}
	System.out.println(num);
}
  1. 数二进制中1的个数
//根据x&(x-1)可以消除最后一个1,消除到x=0的次数
public static void main(String[] args) {
        int num = 999;
        //System.out.println(Integer.toString(num, 2));
        int count = 0;
        while (num != 0){
            num = num & (num-1);
            count++;
        }
        System.out.println(count);
    }
  1. 判断一个数是不是2的次方
//由于2^n的二进制中只有1个1,所以x&(x-1)=0
public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    int num = scanner.nextInt();
    if((num & (num-1)) == 0){
        System.out.println("是");
    }else{
        System.out.println("否");
    }
}
  1. 二进制数中0和1互换
/*
1.一个数与0101...0101(0xaaaaaaaa)做与运算,保留奇数位,偶数位全为0;将得到的数左移
2.一个数与1010...1010(0x55555555)做与运算,保留偶数位,奇数位全为0;将得到的数右移
3.将左右移后的数异或即得到结果
*/
public static void main(String[] args) {
    int num = 9;
    //一个1010用16进制是a,int是32位的1010...,即8个a
    int even = num & 0xaaaaaaaa;
    //0101对应16进制即5,8个5
    int odd = num & 0x55555555;
    System.out.println((even>>1)^(odd<<1));
}
  1. 0-1之间浮点实数的二进制表示
//将一个double数转成二进制表示,如果小数点后32位无法表示,则返回ERROR
public static void main(String[] args){
    double a = 0.625;
    StringBuilder stringBuilder = new StringBuilder("0.");
    while (a > 0){
        //将数字*2
        double r = a * 2;
        if(r >= 1){//*2后的数字大于1,则该位为1,将*2的数-1
            stringBuilder.append("1");
            a = r -1;
        }else{//*2后的数小于1,则该位为0,该数等于*2的数
            stringBuilder.append("0");
            a = r;
        }
        if(stringBuilder.length() > 34){
            System.out.println("ERROR");
            return;
        }
    }
    System.out.println(stringBuilder.toString());
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值