【优选算法篇】:深入浅出位运算--性能优化的利器

✨感谢您阅读本篇文章,文章内容是个人学习笔记的整理,如果哪里有误的话还请您指正噢✨
✨ 个人主页:余辉zmh–CSDN博客
✨ 文章所属专栏:优选算法篇–CSDN博客

在这里插入图片描述

文章目录

  • 一.位运算
    • 一.位运算概述
    • 二.常见的位运算操作符
    • 三.常见的位运算使用场景
  • 二.例题
    • 1.判断字符是否唯一
    • 2.丢失的数字
    • 3.两整数之和
    • 4.只出现一次的数字||
    • 5.只出现一次的数字|||
    • 6.消失的两个数字

一.位运算

一.位运算概述

位运算(Bitwise operation)是直接对整数在内存中的二进制位进行操作的运算。在计算机编程中,位运算非常高效,因为它们直接在二进制层面上操作数据,能够以较少的操作实现复杂的逻辑。下面是几种常用的位运算符号讲解。

二.常见的位运算操作符

  1. 按位与(&)

    • 规则
      • 对两个整数对应的二进制位进行操作,如果对应的二进制位都为1,则结果位为1,否则为0。
    • 示例
      • 假设我们有整数5(二进制为0101)和3(二进制为0011)。
      • 5 & 3的计算过程为:
        • 0101
        • &0011

        • 0001(结果为1)
    • 应用场景
      • 常用于掩码操作。例如,要判断一个整数的某一位是否为1,可以将该整数与一个只有对应位为1的掩码进行按位与操作。
  2. 按位或(|)

    • 规则
      • 对两个整数对应的二进制位进行操作,如果对应的二进制位中有一个为1,则结果位为1。
    • 示例
      • 对于整数5(0101)和3(0011)。
      • 5 | 3的计算过程为:
        • 0101
        • |0011

        • 0111(结果为7)
    • 应用场景
      • 可以用于设置某些位的值。例如,要将一个整数的某几位设置为1,可以将该整数与一个只有对应位为1的数进行按位或操作。
  3. 按位异或(^)

    • 规则
      • 对两个整数对应的二进制位进行操作,如果对应的二进制位不同,则结果位为1,相同则为0。
    • 示例
      • 对于整数5(0101)和3(0011)。
      • 5 ^ 3的计算过程为:
        • 0101
        • ^0011

        • 0110(结果为6)
    • 应用场景
      • 常用于加密算法中的简单加密和解密操作,因为一个数与另一个数进行两次异或操作会得到原数。
  4. 按位取反(~)

    • 规则
      • 对一个整数的二进制位进行取反操作,即0变为1,1变为0。
    • 示例
      • 对于整数5(0101)。
      • ~5的计算过程为:
        • 0101取反后为1010(结果为 - 6,因为在有符号数的表示中,取反后会涉及到补码等概念,在8位二进制表示下,1010表示 - 6)
    • 应用场景
      • 在一些底层的逻辑判断和数据处理中,用于反转数据的某些特性。
  5. 左移(<<)

    • 规则
      • 将一个整数的二进制位向左移动指定的位数,右边空出的位用0填充。
    • 示例
      • 对于整数5(0101),5 << 2表示将5的二进制位向左移动2位。
      • 0101 << 2后变为010100(结果为20,因为左移n位相当于乘以2的n次方,这里5×2² = 20)
    • 应用场景
      • 常用于快速乘以2的幂次方的计算,在优化算法中经常用到。
  6. 右移(>>)

    • 规则

      • 将一个整数的二进制位向右移动指定的位数。如果是无符号数,左边空出的位用0填充;如果是有符号数,根据不同的编程语言和机器,可能是用符号位填充(算术右移)或者用0填充(逻辑右移)。
    • 示例

      • 对于整数12(1100),12 >> 1表示将12的二进制向右移1位。

      • 算术右移(有符号数):

        1100>>1变为1110(结果为-6,因为对于有符号数右移后要保持不变,原数12(假定位8位有符号数二进制表示为1110,符号位为1表示负数,将数值部分右移1位表示负数,将数值部分右移1位后得到1110,在补码表示下为-6)。

      • 逻辑右移:

        1100>>1变为0110(结果为6,逻辑右移是简单的将二进制位右移,左边补0)。

    • 应用场景

      • 常用于快速除以2的幂次方的计算呢,不过对于有符号数的算术右移要注意符号相关的问题。

三.常见的位运算使用场景

在这里插入图片描述

二.例题

1.判断字符是否唯一

题目

在这里插入图片描述

算法原理

利用位图的思想,一个整型有32位,正好可以存放26个字母,一位对应一个字母。

计算每个字母对应的位置,再将该位置标记为1,通过左移即可实现找到对应的位置。

如果该位置已经标记为1时,说明存在重复元素。

这里有一个小的优化,因为每个字母只能出现一次,所以字符串最大长度只能为26,如果字符串长度大于26时,即可直接返回false

代码实现

bool isUnique(string astr){//鸽巢原理优化if(astr.length()>26){return false;}//位图思想int bitmap = 0;for(auto ch : astr){//先求出字符所对应的位置下标int i = ch - 'a';//如果当前字符的位置为一说明字符重复if((bitmap>>i)&1==1){return false;}bitmap |= (1 << i);}return true;
} 

2.丢失的数字

题目

在这里插入图片描述

算法原理

根据异或的特点,相同为0,相异为1,将丢失数字的数组和没有丢失数字的原数组中所有的值全部异或即可找到丢失的数字

代码实现

int missingNumber(vector<int>& nums){//位运算int ans = nums[0];for (int i = 1; i < nums.size();i++){ans ^= nums[i];}for (int i = 0; i < nums.size() + 1;i++){ans ^= i;}return ans;
}

3.两整数之和

题目

在这里插入图片描述

算法原理

在这里插入图片描述

代码实现

//371.两整数之和
int getSum(int a, int b){while(b){int cur=a;a ^= b;b &= cur;b <<= 1;}return a;
}

4.只出现一次的数字||

题目

在这里插入图片描述

算法原理

在这里插入图片描述

代码实现

int singleNumber(vector<int>& nums){int ret = 0;for (int i = 0; i < 32;i++){int sum = 0;//求出数组中每个数的第i位之和for(auto num : nums){if((num>>i)&1==1){sum++;}}//求出只出现一次数字的第i位是1还是0sum %= 3;//修改ret的第i位if(sum==1){ret |= (1 << i);}}return ret;
}

5.只出现一次的数字|||

题目

在这里插入图片描述

算法原理

在这里插入图片描述

代码实现

vector<int> singleNumber(vector<int>& nums) {int tmp=0;for(auto num : nums){tmp^=num;}int mapbit=0;for(int i=0;i<32;i++){if(((tmp>>i)&1)==1){mapbit=i;break;}}int ans1=0,ans2=0;for(auto num : nums){if(((num>>mapbit)&1)==1){ans1^=num;}else{ans2^=num;}}return {ans1,ans2};
}

6.消失的两个数字

题目

在这里插入图片描述

算法原理
这道题其实就是前面两种题型的综合,丢失的数字+只出现一次的数字|||。
具体的算法原理就不再讲解,可以直接看代码实现来理解。

代码实现

vector<int> missingTwo(vector<int>& nums){//1.将当前数组和没有消失的两个数字的原数组全部异或int tmp = 0;for (auto num : nums){tmp ^= num;}for (int i = 1; i <= nums.size() + 2;i++){tmp ^= i;}//2.找到异或后的值哪一位为1int mapbit = 0;for (int i = 0;i<32;i++){if(((tmp>>i)&1)==1){mapbit = i;break;}}//3.根据异或后的值哪一位为1将两个数组中的所有值划分成两个,两个消失的数字分别在其中一个int ans1 = 0, ans2 = 0;for (auto num : nums){if(((num>>mapbit)&1)==1){ans1 ^= num;}else{ans2 ^= num;}}for (int i = 1; i <= nums.size() + 2; i++){if(((i>>mapbit)&1)==1){ans1 ^= i;}else{ans2 ^= i;}}return {ans1, ans2};
}

以上就是关于位运算算法的讲解,如果哪里有错的话,可以在评论区指正,也欢迎大家一起讨论学习,如果对你的学习有帮助的话,点点赞关注支持一下吧!!!
在这里插入图片描述

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

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

相关文章

每日十题八股-2025年1月12日

1.为什么四次挥手之后要等2MSL? 2.服务端出现大量的timewait有哪些原因? 3.TCP和UDP区别是什么&#xff1f; 4.TCP为什么可靠传输 5.怎么用udp实现http&#xff1f; 6.tcp粘包怎么解决&#xff1f; 7.TCP的拥塞控制介绍一下&#xff1f; 8.描述一下打开百度首页后发生的网络过…

微信小程序——创建滑动颜色条

在微信小程序中&#xff0c;你可以使用 slider 组件来创建一个颜色滑动条。以下是一个简单的示例&#xff0c;展示了如何实现一个颜色滑动条&#xff0c;该滑动条会根据滑动位置改变背景颜色。 步骤一&#xff1a;创建小程序项目 首先&#xff0c;使用微信开发者工具创建一个新…

嵌入式Linux之文件IO

一、标准IO库 1.1 打开/关闭文件 fopen 新建 fopen_test.c&#xff0c;写入以下内容&#xff1a; #include <stdio.h> int main() {/* 打开文件函数&#xff1a;FILE *fopen (const char *__restrict __filename,const char *__restrict __modes)参数&#xff1a;c…

HTML5实现好看的端午节网页源码

HTML5实现好看的端午节网页源码 前言一、设计来源1.1 网站首页界面1.2 登录注册界面1.3 端午节由来界面1.4 端午节习俗界面1.5 端午节文化界面1.6 端午节美食界面1.7 端午节故事界面1.8 端午节民谣界面1.9 联系我们界面 二、效果和源码2.1 动态效果2.2 源代码 源码下载结束语 H…

【2024年华为OD机试】(A卷,100分)- 单词倒序(Java JS PythonC/C++)

一、问题描述 题目描述 输入单行英文句子&#xff0c;里面包含英文字母&#xff0c;空格以及,.?三种标点符号&#xff0c;请将句子内每个单词进行倒序&#xff0c;并输出倒序后的语句。 输入描述 输入字符串S&#xff0c;S的长度 1 ≤ N ≤ 100 输出描述 输出倒序后的字…

插入实体自增主键太长,mybatis-plaus自增主键

1、问题 spring-boot整合mybtais执行insert语句时&#xff0c;主键id为长文本数据。 2、分析问题 1)数据库主键是否自增 2&#xff09;数据库主键的种子值设置的多少 3、解决问题 1&#xff09;数据库主键设置的时自增 3&#xff09;种子值是1 所以排查是数据库的问题 4、继…

Java高频面试之SE-11

hello啊&#xff0c;各位观众姥爷们&#xff01;&#xff01;&#xff01;本牛马baby今天又来了&#xff01;哈哈哈哈哈嗝&#x1f436; Java中是引用传递还是值传递&#xff1f; 在 Java 中&#xff0c;方法参数传递是通过 值传递 的方式实现的&#xff0c;但这可能会引起一…

Proser:升级为简易的通讯调试助手软件

我本来打算将Proser定位为一个直观的协议编辑、发送端模拟软件&#xff0c;像下面这样。 但是按耐不住升级的心理&#xff0c;硬生生的把即时收发整合了进去&#xff0c;就像这样&#xff01; 不过&#xff0c;目前针对即时收发还没有发送历史、批量发送等功能&#xff0c;…

php 使用simplexml_load_string转换xml数据格式失败

本文介绍如何使用php函数解析xml数据为数组。 <?php$a <xml><ToUserName><![CDATA[ww8b77afac71336111]]></ToUserName><FromUserName><![CDATA[sys]]></FromUserName><CreateTime>1736328669</CreateTime><Ms…

计算机视觉算法实战——打电话行为检测

✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ ​​​​​​​ ​​​​​​​​​​​​​​​ ​​​​​​ ​ 1. 引言✨✨ 随着智能手机的普及&#xff0c;打电话行为检测成为了计算机视…

SpringBoot日常:集成Kafka

文章目录 1、pom.xml文件2、application.yml3、生产者配置类4、消费者配置类5、消息订阅6、生产者发送消息7、测试发送消息 本章内容主要介绍如何在springboot项目对kafka进行整合&#xff0c;最终能达到的效果就是能够在项目中通过配置相关的kafka配置&#xff0c;就能进行消息…

HTTPS SSL/TLS 工作流程

目录 一、HTTP/HTTPS 简介1、HTTP协议相关内容2、HTTPS协议3、HTTP版本差异&#xff1a; 二、HTTPS 协议工作流程解析1. 客户端请求 SSL 握手2. 服务端接收 SSL 握手连接3. TLS 握手中的密钥协商4. HTTP 数据的加密与解密5. 安全性保障 三、HTTPS 协议的相关知识拓展1. TLS 与 …

Ubuntu中使用miniconda安装R和R包devtools

安装devtools环境包 sudo apt-get install gfortran -y sudo apt-get install build-essential -y sudo apt-get install libxt-dev -y sudo apt-get install libcurl4-openssl-dev -y sudo apt-get install libxml2.6-dev -y sudo apt-get install libssl-dev -y sudo apt-g…

解决SpringBoot无法使用JDK8问题

解决SpringBoot无法使用JDK8问题 现状解决方案 现状 使用idea创建springboot项目无法选择java8。原因是23年11月的spring更新后就明确了不在支持java8版本的项目创建&#xff0c;但是目前为止很多公司开发还在用java8&#xff0c;导致会有问题的产生。 解决方案 使用idea创…

八、系统托盘与配置面板

没有人会把你变得越来越好&#xff0c;时间和经历只是陪衬。 支撑你变得越来越好的&#xff0c;是你自己坚强的意志、修养、品行、以及不断的反思和经验。 人生最好的贵人&#xff0c;就是努力向上的自己。 一、系统托盘 1、资源文件夹 新建资源文件夹&#xff0c;我们需要把…

IntelliJ IDEA中Maven项目的配置、创建与导入全攻略

大家好&#xff0c;我是袁庭新。 IntelliJ IDEA是当前最流行的Java IDE&#xff08;集成开发环境&#xff09;之一&#xff0c;也是业界公认最好用的Java开发工具之一。IntelliJ IDEA支持Maven的全部功能&#xff0c;通过它我们可以很轻松地实现创建Maven项目、导入Maven项目、…

Element-plus、Element-ui之Tree 树形控件回显Bug问题。

需求&#xff1a;提交时&#xff0c;需要把选中状态和半选中状态 的数据id提交。如图所示&#xff1a; 数据回显时&#xff0c;会出现代码如下&#xff1a; <template><el-tree ref"treeRef" :data"tree" show-checkbox node-key"id" …

C语言#define定义宏

目录 一、什么是宏以及宏的声明方式 1.宏常量&#xff1a; 2.宏函数&#xff1a; 二、宏的替换原则 三、宏设计的易犯错误 ERROR1&#xff1a;尾部加分号&#xff08;当然有些特定需要加了分号&#xff0c;这里说明一般情况&#xff09; ERROR2&#xff1a;宏函数定义时&…

第33 章 - ES 实战篇 - MySQL 与 Elasticsearch 的一致性问题

思维导图 0. 前言 MySQL 与 Elasticsearch 一致性问题是老生常谈了。网上有太多关于这方面的文章了&#xff0c;但是千篇一律&#xff0c;看了跟没看没有太大区别。 在生产中&#xff0c;我们往往会通过 DTS 工具将 binlog 导入到 Kafka&#xff0c;再通过 Kafka 消费 binlog&…

Gitlab-Runner配置

原理 Gitlab-Runner是一个非常强大的CI/CD工具。它可以帮助我们自动化执行各种任务&#xff0c;如构建、测试和部署等。Gitlab-Runner和Gitlab通过API通信&#xff0c;接收作业并提交到执行队列&#xff0c;Gitlab-Runner从队列中获取作业&#xff0c;并允许在不同环境下进行作…