leetcode位运算

本文介绍了位运算的基本概念,包括与(&)、或(|)、异或(^)、取反(~)、左移(<<)、右移(>>、>>>), 并探讨了有符号整数的位表示,特别是补码的重要性。通过例子解释了为什么使用补码进行加减法计算,并展示了位运算在求二进制位数、汉明距离等问题中的应用。" 59108303,5103771,Android 图片选择框架PhotoPicker实战,"['Android开发', '图片选择器', '多张图片选择器框架']
摘要由CSDN通过智能技术生成

1.位运算
&与
|或
^异或
~取反
<<左移
">>"有符号右移
">>>"无符号右移

2.有符号整数和无符号整数
0000 1010 正数
1000 1010 负数
第一位为符号位,正数的符号位为0,负数的符号位为1

byte 8位 short 16位 int 32位 long 64位 -->有符号整数
整数一般使用补码表示

3.原码、反码、补码

原码
10: 00000000 00000000 00000000 00001010
-10: 10000000 00000000 00000000 00001010

反码
符号位不变,其余为取反
10:01111111 11111111 11111111 11110101
-10:11111111 11111111 11111111 11110101

补码
正数的补码等于原码 负数的补码等于反码+1
10:00000000 00000000 00000000 00001010
-10:11111111 11111111 11111111 11110110

4.为什么使用补码
(1)统一数字0的表示
+0: 00000000 00000000 00000000 00000000
-0:
原码 10000000 00000000 00000000 00000000
反码 11111111 11111111 11111111 11111111
补码 00000000 00000000 00000000 00000000

(2)简化整数的加减法计算
-6+5

10000000 0000000 00000000 00000110
00000000 00000000 00000000 00000101
=
10000000 00000000 00000000 00001011
=-11 结果是错的
所以要用补码
11111111 11111111 11111111 11111010(-6的补码)
+
00000000 0000000 0000000 00000101(5的补码)

11111111 11111111 11111111 11111111 (-1的补码)

把结果还原成原码:
先减掉1 11111111 11111111 11111111 11111110
再取反 10000000 00000000 00000000 00000001(-1的原码)

5.有符号整数二进制规律
4位
0000 0
0001 1
0010 2

0111 7
1000(以补码的方式存在) -8
1001 -7
1010 -6
1011 -5
1100 -4
1101 -3
1110 -2
1111 -1
-2**(n-1) ~ 2**(n-1)-1

所以 int的范围是
-231 ~ 231-1

6.按位取反
9的原码 1001
9的补码 01001
取反 10110(补码)
还原成原码(-1,取反码) 11010
得到结果:~9 = -10

7.左移<< 右移>> 无符号右移>>>
4: 00000000 0000000 00000000 00000100
4<<2:0000000 00000000 00000000 00010000
左移低位补0
-4(补码):1111111 11111111 11111111 11111100
-4<<2: 1111111 1111111 11111111 11110000
转成原码(-1,取反码) 10000000 00000000 00000000 00010000 = -16

左移和符号没有关系,不会改变正负号。

15: 0000000 00000000 0000000 00001111
15>>2: 00000000 00000000 00000000 00000011
15>>>2: 00000000 00000000 00000000 00000011

-15: 11111111 1111111 11111111 11110001 (补码)
-15>>2: 11111111 1111111 11111111 11111100(补码)
减1取反后得 10000000 00000000 00000000 00000100
-15>>>2: 00111111 1111111 1111111 1111100
= 1073741820

8.位运算技巧
(1)拿到二进制的低16位: n&0xFFFF
n : 00001010 00010000 11110010 00001010
&
00000000 00000000 11111111 11111111
00000000 00000000 11110010 00001010

(2)对二进制的高16位取反:~(n^0xFFFF) 0xFFFF–>mask掩码
先对低16位取反,再对整个取反(跟1异或等于取反)
n: 00001010 00010000 11110010 00001010
^
00000000 00000000 11111111 11111111
= 00001010 00010000 00001101 11110101
~
11110101 11101111 11110010 00001010

测试第i+1位是否为1:(n&1<<i)!=0
选择掩码1,与数字取&,得到的结果即第1位的结果
如果要测试第二位,则将1<<1
如果要测试第三位,则将1<<2

去掉最后一位1: n&(n-1)
n. : 00001010 00010000 11110010 00001010
&
n-1: 00001010 00010000 11110010 00001001
=00001010 00010000 11110010 00001000

获取最后一位1:
n&-n
n: 00001010 00010000 11110010 00001010
&
-n(补码): 11110101 11101111 00001101 11110110
= 00000000 00000000 00000000 00000010

n&~(n-1)
n^(n&(n-1))

A的位减去B的位 A&~B
A: 00001011 11110010 00000000 11010000
B: 00000001 00101111 11010000 10101000
~B: 11111110 11010000 00101111 01010111
&
=00001010 11010000 00000000 01010000

^的用法技巧
a^0 = a
a^a = 0
a^ (b^ c) = a ^ (c^b) 交换率

191.位1的个数
编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。

利用技巧:判断第i位是否为1

class Solution:
    def hammingWeight(self, n: int) -> int:
        res = 0
        for i in range(1,33):
            if ((n&1<<(i-1)) !=0):
                res += 1
        return res

右移n位,每次右移时,判断第1位是否为1

class Solution:
    def hammingWeight(self, n: int) -> int:
        res = 0
        for i in range(1,33):
            if ((n>>(i-1))&1!=0):
                res += 1
        return res

每次移除掉最后一个1,直到n为0

class Solution:
    def hammingWeight(self, n: int) -> int:
        res = 0
        while n != 0:
            n = n & (n-1)
            res+=1
        return res

461.汉明距离
两个整数之间的 汉明距离 指的是这两个数字对应二进制位不同的位置的数目。

给你两个整数 x 和 y,计算并返回它们之间的汉明距离。

对异或后的结果统计有多少1.

class Solution:
    def hammingDistance(self, x: int, y: int) -> int:
        diff = x^y
        res = 0
        while diff != 0:
            diff = diff&(diff-1)
            res += 1
        return res

在这里插入图片描述
解法1:暴力解法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值