位运算

定义

  • 程序中数据都是以二进制形式存储的,位运算就是直接对二进制位进行操作,处理速度非常快。

符号

符号描述运算规则
&两个位都为1时,结果才为1,其他情况结果为0
|两个位都为0时,结果才为0,其他情况结果为1
^异或两个位相同时,结果为0,不同时,结果为1
~取反0变1,1变0
<<左移各二进制位左移若干位,高位丢弃,低位补0
>>右移各二进制位全部右移若干位,对于无符号数,高位补0;对于有符号数,
各编译器处理方法不一样,有的补符号位(算数右移),有的补0(逻辑右移)
  • 逻辑右移就是不考虑符号位,右移一位,左边补零即可。 算术右移需要考虑符号位,右移一位,若符号位为1,就在左边补1;否则就补0。`
  • 有符号数的最高位是符号位,0表示正数,1表示负数,在计算机中,负数以原码的补码形式表达
  • 正数的原码,反码,补码都相同。
  • 负数的原码是对应正数的原码将符号位从0改为1,负数的反码为对该数的原码除符号位外各位取反,负数的补码为负数的反码再加1。
  • 例子:2的8位原码为 00000010,-2的8位原码为 10000010,-2的反码为 11111101,-2的补码为 11111110。
  • 20 原码 00010100 -20 10010100 -20 10001011 10001100

异或特点

  • x ^ 0 = x
  • x ^ 1s = ~x // 1s = ~0
  • x ^ (~x) = 1s
  • x ^ x = 0
  • a ^ b = c => a ^ c = b,b ^ c = a
  • a ^ b ^ c = a ^ (b ^ c)= (a ^ b) ^ c

常用

  • x & 1 == 1 或 x & 1 == 0 判断奇偶性
  • X = X & (X - 1) = > 清零最低位 (因为如果X最后一位是1,则X-1最后一位是0,相与,最后一位得0,如果X的最低位1后面一堆0,比如是 1000 则X-1之后 变为 0111,相与得到 0000)
  • X & -X = > 得到最低位的1

更复杂操作

  • 将x最右边n位清0:x & (~0 << n)
  • 获取x的第n位值(0或者1):(x >> n ) & 1
  • 获取x的第n位的幂值: x & (1 << (n-1))
  • 仅将第n位置为1:x | (1 << n)
  • 仅将第n位置为0:x | ~((1 << n))
  • 将x最高位至第n位(含)清零: x & ((1 << n) - 1)
  • 将第n位至第0位(含)清零: x & (~((1 << n) - 1))

题目

leetcode 231. 2的幂

func isPowerOfTwo(n int) bool {
    // 2的x次幂特点:二进制有且只有一个1。
    // 去掉最低位的1,即是去掉所有1,即是等于0。再约束其本身不为0。
    return n & (n -1) == 0  && n!=0
}

leetcode 338. 比特位计数

解法1
  • 每个数单独计算1的位数
func countBits(num int) []int {
    var ret []int
    var x,c int
    for i := 0; i <=num ; i ++{
        x = i 
        c = 0
        for x != 0 {
            x = x & (x-1)
            c ++ 
        }
        ret = append(ret,c)
    }
    return ret
}
解法2
  • 动态规划推导状态转移方程
func countBits(num int) []int {
    ret:= make([]int,num+1)
    for i := 1; i <=num ; i ++{
        ret[i] = ret[i&(i-1)]+1
    }
    return ret
}

leetcode 52. N皇后 II

func totalNQueens(n int) int {
	var count int
	var d func(int,int,int,int)
	d = func(row, col, pie, na int) {
		if row == n {
			count++
			return
		}
		bits := (^(col | pie | na)) & ((1 << uint(n)) - 1)
		for bits > 0 {
			p := bits & -bits
			d(row+1, col|p, (pie|p)<<1, (na|p)>>1)
			bits &= bits - 1
		}
	}
	d(0, 0, 0, 0)
	return count
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值