位运算01 插入[C++]

图源:文心一言

上机题目练习整理,位运算,供小伙伴们参考~🥝🥝

网页版目录在页面的右上角↗~🥝🥝

  • 第1版:在力扣新手村刷题的记录~🧩🧩

编辑:梅头脑🌸

审核:文心一言

题目:面试题 05.01. 插入 - 力扣(LeetCode)


🧵面试题 05.01. 插入 - 力扣(LeetCode)

🧩题目

给定两个整型数字 N 与 M,以及表示比特位置的 i 与 ji <= j,且从 0 位开始计算)。

编写一种方法,使 M 对应的二进制数字插入 N 对应的二进制数字的第 i ~ j 位区域,不足之处用 0 补齐。具体插入过程如图所示。

题目保证从 i 位到 j 位足以容纳 M, 例如: M = 10011,则 i~j 区域至少可容纳 5 位。

示例1:

 输入:N = 1024(10000000000), M = 19(10011), i = 2, j = 6
 输出:N = 1100(10001001100)

示例2:

 输入: N = 0, M = 31(11111), i = 0, j = 4
 输出:N = 31(11111)

🌰方法一:循环+按位运算

📇算法思路

  • 算法思想:
    • 将N的第i位到第j位清零(置为0),可以使用按位与和按位取反操作。
    • 将M左移,使得它的最低位对齐N的第i位。
    • 使用按位或操作,将步骤1和步骤2的结果合并。
  • 时间复杂度:O(1);
  • 空间复杂度:O(1);

⌨️算法代码

class Solution {
public:int insertBits(int N, int M, int i, int j) {// 1.把N的i到j位置为0for (int k = i; k <= j; k++) {if (N & (1 << k)) {N ^= (1 << k);}}// 2.把M的数值左移i位M <<= i;// 3.将N的i到j位加上Mreturn N | M;}
};

作者:coeker
链接:https://leetcode.cn/problems/insert-into-bits-lcci/solutions/712628/cwei-yun-suan-by-coeker-stgw/

📇代码解释

 1:把N的i到j位置为0

  • N & (1 << k)):N的2~6位 (&)与 1,可以区分2~6位是0还是1;如果2到6为1,满足判断条件,则执行异或语句;
  • N ^= (1 << k):将N的2~6位中二进制为“1”的位数 异或(1)1,根据同1异0,这些位置都会变为0,达到置零效果;
  • 执行结果:虽然本题N = 1024,其2~6位已经是0,条件语句执行前后的结果是完全相同的,还是1024;
N
31302928272625242322212019181716
0000000000000000
15141312111009080706050403020100
0000010000000000

2:把M的数值左移i位

  • M <<= i; // 本题中i = 2;正数左移低位可以直接补0;
M移动前
31302928272625242322212019181716
0000000000000000
15141312111009080706050403020100
0000000000010011
M移动后
31302928272625242322212019181716
0000000000000000
15141312111009080706050403020100
0000000001001100

3:将N的i到j位加上M

  • N | M;  // N 或 M,对应位中,如果其中有1个是1,则或的运算结果为1;
  • 输出结果:N = 1100(10001001100)
N | M
31302928272625242322212019181716
0000000000000000
15141312111009080706050403020100
0000100001001100

📇知识扩展

位运算是直接对整数在内存中的二进制位进行操作的一种运算。由于它直接处理二进制数据,因此执行效率非常高。

简单介绍:

  1. 取反(NOT)
    • 操作符:~
    • 功能:对一个数的所有二进制位进行取反操作,即0变为1,1变为0。
    • 示例:~0101 结果为 1010(这里的数字是二进制表示)。
  2. 与(AND)
    • 操作符:&
    • 功能:比较两个数的相应二进制位,如果两个相应位都为1,则该位的结果值为1,否则为0。
    • 示例:0101 & 0110 结果为 0100
  3. 或(OR)
    • 操作符:|
    • 功能:比较两个数的相应二进制位,如果两个相应位中至少有一个为1,则该位的结果值为1,否则为0。
    • 示例:0101 | 0110 结果为 0111
  4. 异或(XOR)
    • 操作符:^
    • 功能:比较两个数的相应二进制位,如果两个相应位值不同,则该位的结果值为1,否则为0。
    • 示例:0101 ^ 0110 结果为 0011
  5. 移位操作
    • 左移(Left Shift):<<
      • 功能:将二进制数所有位向左移动指定的位数,高位丢弃,低位用0补充。
      • 示例:0010 << 1 结果为 0100
    • 右移(Right Shift):>>(有符号和无符号之分,具体行为取决于编程语言)
      • 功能:将二进制数所有位向右移动指定的位数,低位丢弃,高位可能用0或1补充(取决于原数的符号)。
      • 示例:0010 >> 1 结果为 0001

特殊用途

  • 指定位置0
    • 使用与运算(AND)可以将指定位置0。
    • 示例:假设要将数num的第i位(从0开始计数)置0,可以使用num & ~(1 << i)
  • 指定位置1
    • 使用或运算(OR)可以将指定位置1。
    • 示例:假设要将数num的第i位(从0开始计数)置1,可以使用num | (1 << i)
  • 指定位翻转
    • 使用异或运算(XOR)可以实现指定位的翻转(0变为1,1变为0)。
    • 示例:假设要翻转数num的第i位(从0开始计数),可以使用num ^ (1 << i)

位运算在编程中有很多用途,包括优化性能、处理二进制数据、加密解密、网络通信中的数据打包与解包等。

🌰解题二:创建掩码<错误代码自留>

📇算法思路

  • 基本思想同算法一,不再赘述~
  • 这个代码提交会出错,自留,以后可能会回来修改~

⌨️算法代码

#include <iostream>  
#include <cassert> 
using namespace std;class Solution {
public:int insertBits(int N, int M, int i, int j) {// 确保 i 和 j 是有效的索引  assert(0 <= i && i <= j && j < 32);// 创建掩码以清零 N 的第 i 位到第 j 位  unsigned int allOnes = ~0U; // 使用无符号整数  unsigned int leftOnes = allOnes >> (j + 1); // 现在这是安全的,因为 allOnes 是无符号的  unsigned int rightOnes = ((1U << i) - 1); // 注意这里应该是 (1 << i),并且使用无符号整数  unsigned int mask = leftOnes | rightOnes;// 将 N 的第 i 位到第 j 位清零  N = N & mask;// 将 M 左移,使得它的最低位对齐 N 的第 i 位  M = M << i;// 使用按位或操作,将步骤1和步骤2的结果合并  N = N | M;// N 现在是一个无符号整数,但我们知道它不会溢出,所以可以安全地将其转换回有符号整数  return static_cast<int>(N);}
};int main() {Solution solution;int N = 1024; // 10000000000  int M = 19; // 10011  int i = 2;int j = 6;int result = solution.insertBits(N, M, i, j);cout << "Output: N = " << result << " (in decimal, expected binary representation: 10001001100)" << endl;// 第二个示例  N = 0;M = 31; // 11111  i = 0;j = 4;result = solution.insertBits(N, M, i, j);cout << "Output: N = " << result << " (in decimal, expected binary representation: 11111)" << endl;return 0;
}

 作者:文心一言

📇代码解释

1:清零 N 的第 i 位到第 j 位

  • unsigned int allOnes = ~0U; ~是按位非操作,无符号0的二进制为00...000,按位取反后为11...111,本步骤创建一个全是1的掩码;
  • unsigned int leftOnes = allOnes << (j + 1);  allOnes左移 j + 1 位,创建左边全是1,到 j + 1 位为0的掩码,本例 j = 6 ;(备注一下,这里如果是int,那么就需要逻辑左移而非算术左移,否则负数左移补1,无论它怎么左移它都是111...111);
  • int rightOnes = (1 << i) - 1; // 1左移2位然后-1,创建右边全是1,到i位为0的掩码 ,本例 i = 2;
allOnes
31302928272625242322212019181716
1111111111111111
15141312111009080706050403020100
1111111111111111
leftOnes
31302928272625242322212019181716
1111111111111111
15141312111009080706050403020100
1111111110000000
rightOnes
31302928272625242322212019181716
0000000000000000
15141312111009080706050403020100
0000000000000011
  • unsigned int mask = leftOnes | rightOnes;  // leftones与rightones相与,掩码就这样制作好了,是从2到6为0,其余都为1的数字;
  • N = N & mask; // 将 N 的第 i 位到第 j 位清零(当然1024的2-6位本来就没1,清0前后是一样的);
mask
31302928272625242322212019181716
1111111111111111
15141312111009080706050403020100
1111111110000011
N(修改后)
31302928272625242322212019181716
0000000000000000
15141312111009080706050403020100
0000010000000000

2:把M的数值左移i位

3:将N的i到j位加上M

备注:2:与3:的步骤与方法一雷同,此处不再赘述。

执行报错:我暂时也不知道怎么修复这个,哎,先留着代码再想想...

📇知识扩展

思维导图:emmm...补码规则听起来有点绕对不对,而且正数负数的存储规则是不一样的,这就涉及到计组的知识了,正好是我来不及整理和发布的那一篇,稍等我Po一下草稿——

备注:

  • (发现看着图更绕了对不对)图中只有涂紫色的部分是涉及本题的,其它的是原码、反码、补码、移码的相关知识,随意看看就好~看不清图片的话可以右键存到本地打开~
  • 如果对于补码的浅显原理感兴趣,可以参考这个视频:🌸2.1_4_带符号整数的表示和运算_原反补_哔哩哔哩_bilibili
  • 如果对于计组的其它知识感兴趣,可以参考这个系列,菜鸟博主明年再战可能还会补充:🌸计算机组成原理_梅头脑_的博客-CSDN博客

🔚结语

博文到此结束,写得模糊或者有误之处,欢迎小伙伴留言讨论与批评,督促博主优化内容{例如有错误、难理解、不简洁、缺功能}等,博主会顶锅前来修改~~😶‍🌫️😶‍🌫️

我是梅头脑,本片博文若有帮助,欢迎小伙伴动动可爱的小手默默给个赞支持一下,感谢点赞小伙伴对于博主的支持~~🌟🌟

同系列的博文:🌸数据结构_梅头脑_的博客-CSDN博客

同博主的博文:🌸随笔03 笔记整理-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/460229.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言特殊指针

1 野指针 概念&#xff1a;指向一块未知区域的指针&#xff0c;被称为野指针。野指针是危险的。 危害&#xff1a; 引用野指针&#xff0c;相当于访问了非法的内存&#xff0c;常常会导致段错误&#xff08;segmentation fault&#xff09;引用野指针&#xff0c;可能会破坏系…

恒流源方案对比

1、双运放恒流源 2、运放三极管放大电路组成的恒流源 5A 3、运放三极管组成的恒流源 200uA 4、运放MOS管组成的恒流源 100mA 5、电源模块并联输出100A恒流

百面嵌入式专栏(面试题)C语言面试题22道

沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇我们将介绍C语言相关面试题 。 宏定义是在编译的哪个阶段被处理的?答案:宏定义是在编译预处理阶段被处理的。 解读:编译预处理:头文件包含、宏替换、条件编译、去除注释、添加行号。 写一个“标准”宏MIN,这个…

极限的反问题【高数笔记】

1. 什么是极限反问题&#xff1f; 2. 极限反问题分为几类&#xff1f; 3. 每一类极限反问题的具体做法是什么&#xff1f; 4. 每一类极限反问题具体做法是否有前提条件&#xff1f; 5. 例题&#xff1f;

CDN相关和HTTP代理

CDN相关和HTTP代理 参考&#xff1a; 《透视 HTTP 协议》——chrono 把这两个放在一起是因为容易搞混&#xff0c;我一开始总以为CDN就是HTTP代理&#xff0c;但是看了极客时间里透视HTTP协议的讲解&#xff0c;感觉又不仅于此&#xff0c;于是专门写下来。 先说结论&#xf…

数据结构:双向链表

文章目录 1. 双向带头循环链表的结构2. 相关操作2.1 创建节点2.2 尾插2.3 头插2.4 打印2.5 尾删2.6 头删2.7 查找2.8 指定位置前/后插入2.9 删除指定位置的节点2.10 删除指定位置后的节点2.11 销毁链表 3.顺序表与链表区别 1. 双向带头循环链表的结构 与单链表不同的是&#xf…

javaEE - 24( 20000 字 Servlet 入门 -2 )

一&#xff1a; Servlet API 详解 1.1 HttpServletResponse Servlet 中的 doXXX 方法的目的就是根据请求计算得到相应, 然后把响应的数据设置到HttpServletResponse 对象中. 然后 Tomcat 就会把这个 HttpServletResponse 对象按照 HTTP 协议的格式, 转成一个字符串, 并通过S…

JVS物联网、低代码、规则引擎2.5功能新增说明

物联网更新功能 新增: 1、新增离线存储-页面配置及指令下发对接&#xff1b; 用户可以对平台的页面进行自定义配置&#xff0c;通过平台&#xff0c;可以将指令下发给与之相连的设备或系统&#xff0c;这些指令可以是控制指令、配置指令或其他类型的指令。 2、新增数据压缩-…

diffusers单机多卡推理(全网首发)

起因 博主在部署InstantID项目时&#xff0c;显存不够&#xff0c;想要将模型分散在多张卡上。 翻到这篇发现是分布式推理&#xff0c;博主一直以为这个可以达到我想要的效果&#xff0c;但是效果是多线程并行推理&#xff0c;并不能将一个模型切片在多个GPU上。 Distributed …

Text2SQL研究-Chat2DB体验与剖析

文章目录 概要业务数据库配置Chat2DB安装设置原理剖析 小结 概要 近期笔者在做Text2SQL的研究&#xff0c;于是调研了下Chat2DB&#xff0c;基于车辆订单业务做了一些SQL生成验证&#xff0c;有了一点心得&#xff0c;和大家分享一下.&#xff1a; 业务数据库设置 基于车辆订…

Python(21)正则表达式中的“元字符”

大家好&#xff01;我是码银&#x1f970; 欢迎关注&#x1f970;&#xff1a; CSDN&#xff1a;码银 公众号&#xff1a;码银学编程 获取资源&#xff1a;公众号回复“python资料” 在本篇文章中介绍的是正则表达式中一部分具有特殊意义的专用字符&#xff0c;也叫做“元…

一文学会Axios的使用

异步请求 同步发送请求过程如下 浏览器页面在发送请求给服务器&#xff0c;在服务器处理请求的过程中&#xff0c;浏览器页面不能做其他的操作。只能等到服务器响应结束后才能&#xff0c;浏览器页面才能继续做其他的操作。 异步发送请求过程如下浏览器页面发送请求给服务器&…