首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

C++面试基础系列-bit_operation

  • 25-02-19 04:41
  • 3579
  • 7887
blog.csdn.net

系列文章目录

总目录链接


文章目录

  • 系列文章目录
    • 总目录链接
  • C++面试基础系列-bit_operation
    • 1.bit_operation定义
    • 2.bit_operation位运算符号类型
    • 3.位运算的常用操作总结
    • 4.位运算与宏定义
    • 5.二进制枚举子集
      • 5.1.二进制枚举子集简介
      • 5.2 二进制枚举子集代码
    • 关于作者


C++面试基础系列-bit_operation


1.bit_operation定义

位操作也叫位运算,计算机底层基于二进制计算,所以位运算的运算效率更高,速度更快。

  • 对于正数来说,其反码和原码一致。对负数来说,反码就是对除去最高符号位之外的所有二进制位取反。

  • 对于正数来说,其补码与反码一致。对负数来说,补码就是对反码做通常意义上的加一操作(含进位)。

  • 整数在计算机中是以补码的形式储存的,这就是为什么我们要介绍原码、反码和补码。

  • 补码的好处:

    • 其一是明确了整数「0」的表示(否则可以有 0000 0000 和 1000 0000 两种方式表示),
    • 其二是对整数的加法只需要统一的一套电路来处理即可。
 20 = 0001 0100(原码Source code) = 0001 0100(反码Inverse code) = 0001 0100(补码complement)
-20 = 1001 0100(原码Source code) = 1110 1011(反码Inverse code) = 1110 1100(补码complement)
  • 1
  • 2

2.bit_operation位运算符号类型

符号描述运算规则
&与两个位都为1时,结果才为1
|或两个位都为0时,结果才为0
^异或两个位相同为0,相异为1
~取反0变1,1变0
<<左移各二进位全部左移若干位,高位丢弃,低位补0
>>右移各二进位全部右移若干位,高位补0或符号位补齐

3.位运算的常用操作总结

功 能位运算示例
方法一:提取最右边的1出来x & (~x + 1)100101000 -> 000001000
方法二:提取最右边的1出来x & (-x)100101000 -> 000001000
从右边开始,把最后一个 1 1 1 改写成 0 0 0x & (x - 1)100101000 -> 100100000
去掉右边起第一个 1 1 1 的左边x & (x ^ (x - 1)) 或 x & (-x)100101000 -> 1000
去掉最后一位x >> 1101101 -> 10110
取右数第 k k k 位x >> (k - 1) & 11101101 -> 1, k = 4
取末尾 3 3 3 位x & 71101101 -> 101
取末尾 k k k 位x & 151101101 -> 1101, k = 4
只保留右边连续的 1 1 1(x ^ (x + 1)) >> 1100101111 -> 1111
右数第 k k k 位取反x ^ (1 << (k - 1))101001 -> 101101, k = 3
在最后加一个 0 0 0x << 1101101 -> 1011010
在最后加一个 1 1 1(x << 1) + 1101101 -> 1011011
把右数第 k k k 位变成 0 0 0x & ~(1 << (k - 1))101101 -> 101001, k = 3
把右数第 k k k 位变成 1 1 1x | (1 << (k - 1))101001 -> 101101, k = 3
把右边起第一个 0 0 0 变成 1 1 1x | (x + 1)100101111 -> 100111111
把右边连续的 0 0 0 变成 1 1 1x | (x - 1)11011000 -> 11011111
把右边连续的 1 1 1 变成 0 0 0x & (x + 1)100101111 -> 100100000
把最后一位变成 0 0 0x | 1 - 1101101 -> 101100
把最后一位变成 1 1 1x | 1101100 -> 101101
把末尾 k k k 位变成 1 1 1x | (1 << k - 1)101001 -> 101111, k = 4
最后一位取反x ^ 1101101 -> 101100
末尾 k k k 位取反x ^ (1 << k - 1)101001 -> 100110, k = 4

4.位运算与宏定义


#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitReverse(value, bit) ((value) ^= (1UL << (bit)))
#define bitWrite(value, bit, bitvalue) ((bitvalue) ? bitSet(value, bit) : bitClear(value, bit))

#define lowByte(w) ((w) & 0xff)
#define highByte(w) ((w) >> 8)

#define bitRigthmostGet(value) ((value) & (-value))
#define bitRigthmostClear(value) ((value) & (value-1))

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

5.二进制枚举子集

除了上面的这些常见操作,我们经常常使用二进制数第 1 ∼ n 1 \sim n 1∼n 位上 0 0 0 或 1 1 1 的状态来表示一个由 1 ∼ n 1 \sim n 1∼n 组成的集合。也就是说通过二进制来枚举子集。

5.1.二进制枚举子集简介

先来介绍一下「子集」的概念。

  • 子集:如果集合 A A A 的任意一个元素都是集合 S S S 的元素,则称集合 A A A 是集合 S S S 的子集。可以记为 A ∈ S A \in S A∈S。

有时候我们会遇到这样的问题:给定一个集合 S S S,枚举其所有可能的子集。

枚举子集的方法有很多,这里介绍一种简单有效的枚举方法:「二进制枚举子集算法」。

对于一个元素个数为 n n n 的集合 S S S 来说,每一个位置上的元素都有选取和未选取两种状态。我们可以用数字 1 1 1 来表示选取该元素,用数字 0 0 0 来表示不选取该元素。

那么我们就可以用一个长度为 n n n 的二进制数来表示集合 S S S 或者表示 S S S 的子集。其中二进制的每一个二进位都对应了集合中某一个元素的选取状态。对于集合中第 i i i 个元素来说,二进制对应位置上的 1 1 1 代表该元素被选取, 0 0 0 代表该元素未被选取。

举个例子,比如长度为 5 5 5 的集合 S = { 5 , 4 , 3 , 2 , 1 } S = \lbrace 5, 4, 3, 2, 1 \rbrace S={5,4,3,2,1},我们可以用一个长度为 5 5 5 的二进制数来表示该集合。

比如二进制数 1111 1 ( 2 ) 11111_{(2)} 11111(2)​ 就表示选取集合的第 1 1 1 位、第 2 2 2 位、第 3 3 3 位、第 4 4 4 位、第 5 5 5 位元素,也就是集合 { 5 , 4 , 3 , 2 , 1 } \lbrace 5, 4, 3, 2, 1 \rbrace {5,4,3,2,1},即集合 S S S 本身。如下表所示:

集合 S 中元素位置54321
二进位对应值11111
对应选取状态选取选取选取选取选取

再比如二进制数 1010 1 ( 2 ) 10101_{(2)} 10101(2)​ 就表示选取集合的第 1 1 1 位、第 3 3 3 位、第 5 5 5 位元素,也就是集合 { 5 , 3 , 1 } \lbrace 5, 3, 1 \rbrace {5,3,1}。如下表所示:

集合 S 中元素位置54321
二进位对应值10101
对应选取状态选取未选取选取未选取选取

再比如二进制数 0100 1 ( 2 ) 01001_{(2)} 01001(2)​ 就表示选取集合的第 1 1 1 位、第 4 4 4 位元素,也就是集合 { 4 , 1 } \lbrace 4, 1 \rbrace {4,1}。如下标所示:

集合 S 中元素位置54321
二进位对应值01001
对应选取状态未选取选取未选取未选取选取

通过上面的例子我们可以得到启发:对于长度为 5 5 5 的集合 S S S 来说,我们只需要从 00000 ∼ 11111 00000 \sim 11111 00000∼11111 枚举一次(对应十进制为 0 ∼ 2 5 − 1 0 \sim 2^5 - 1 0∼25−1)即可得到长度为 5 5 5 的集合 S S S 的所有子集。

我们将上面的例子拓展到长度为 n n n 的集合 S S S。可以总结为:

  • 对于长度为 n n n 的集合 S S S 来说,只需要枚举 0 ∼ 2 n − 1 0 \sim 2^n - 1 0∼2n−1(共 2 n 2^n 2n 种情况),即可得到集合 S S S 的所有子集。

5.2 二进制枚举子集代码

class Solution:
    def subsets(self, S):                   # 返回集合 S 的所有子集
        n = len(S)                          # n 为集合 S 的元素个数
        sub_sets = []                       # sub_sets 用于保存所有子集
        for i in range(1 << n):             # 枚举 0 ~ 2^n - 1
            sub_set = []                    # sub_set 用于保存当前子集
            for j in range(n):              # 枚举第 i 位元素
                if i >> j & 1:              # 如果第 i 为元素对应二进位删改为 1,则表示选取该元素
                    sub_set.append(S[j])    # 将选取的元素加入到子集 sub_set 中
            sub_sets.append(sub_set)        # 将子集 sub_set 加入到所有子集数组 sub_sets 中
        return sub_sets                     # 返回所有子集
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

(https://liam.page/2015/10/02/how-to-get-the-last-1-bit-of-an-integer/

https://github.com/itcharge/LeetCode-Py


关于作者

  • 微信公众号:WeSiGJ
  • GitHub:https://github.com/wesigj/cplusplusboys
  • CSDN:https://blog.csdn.net/wesigj
  • 微博:
  • -版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
WeSiGJ
微信公众号
共同分享,共同交流, 共同学习!
注:本文转载自blog.csdn.net的WeSiGJ的文章"https://blog.csdn.net/wesigj/article/details/141294512"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2491) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top