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

✨感谢您阅读本篇文章,文章内容是个人学习笔记的整理,如果哪里有误的话还请您指正噢✨
✨ 个人主页:余辉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还是0
        sum %= 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.找到异或后的值哪一位为1
    int 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};
}

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

创业AI Agents系统深度解析

Agents 近日&#xff0c;AI领域的知名公司Anthropic发布了一份题为《构建高效的智能代理》的报告。该报告基于Anthropic过去一年与多个团队合作构建大语言模型&#xff08;LLM&#xff09;智能代理系统的经验&#xff0c;为开发者及对该领域感兴趣的人士提供了宝贵的洞见。本文…

【Spring Boot】Spring 事务探秘:核心机制与应用场景解析

前言 &#x1f31f;&#x1f31f;本期讲解关于spring 事务介绍~~~ &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 &#x1f525; 你的点赞就是小编不断更新的最大动力 &#x1f386;那么废话不多说直…

centos7.6 安装nginx 1.21.3与配置ssl

1 安装依赖 yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel2 下载Nginx wget http://nginx.org/download/nginx-1.21.3.tar.gz3 安装目录 mkdir -p /data/apps/nginx4 安装 4.1 创建用户 创建用户nginx使用的nginx用户。 #添加www组 # groupa…

夯实前端基础之HTML篇

知识点概览 HTML部分 1. DOM和BOM有什么区别&#xff1f; DOM&#xff08;Document Object Model&#xff09; 当网页被加载时&#xff0c;浏览器会创建页面的对象文档模型&#xff0c;HTML DOM 模型被结构化为对象树 用途&#xff1a; 主要用于网页内容的动态修改和交互&…

Elasticsearch:向量数据库基础设施类别的兴衰

过去几年&#xff0c;我一直在观察嵌入技术如何从大型科技公司的 “秘密武器” 转变为日常开发人员工具。接下来发生的事情 —— 向量数据库淘金热、RAG 炒作周期以及最终的修正 —— 教会了我们关于新技术如何在更广泛的生态系统中找到一席之地的宝贵经验。 更多有关向量搜索…

【华为云开发者学堂】基于华为云 CodeArts CCE 开发微服务电商平台

实验目的 通过完成本实验&#xff0c;在 CodeArts 平台完成基于微服务的应用开发&#xff0c;构建和部署。 ● 理解微服务应用架构和微服务模块组件 ● 掌握 CCE 平台创建基于公共镜像的应用的操作 ● 掌握 CodeArts 平台编译构建微服务应用的操作 ● 掌握 CodeArts 平台部署微…

计科高可用服务器架构实训(防火墙、双机热备,VRRP、MSTP、DHCP、OSPF)

一、项目介绍 需求分析&#xff1a; &#xff08;1&#xff09;总部和分部要求网络拓扑简单&#xff0c;方便维护&#xff0c;网络有扩展和冗余性&#xff1b; &#xff08;2&#xff09;总部分财务部&#xff0c;人事部&#xff0c;工程部&#xff0c;技术部&#xff0c;提供…

【C++入门】详解合集

目录 &#x1f495;1.C中main函数内部———变量的访问顺序 &#x1f495;2.命名空间域 namespace &#x1f495;3.命名空间域&#xff08;代码示例&#xff09;&#xff08;不要跳&#xff09; &#x1f495;4.多个命名空间域的内部重名 &#x1f495;5.命名空间域的展开 …

预编译SQL

预编译SQL 预编译SQL是指在数据库应用程序中&#xff0c;SQL语句在执行之前已经通过某种机制&#xff08;如预编译器&#xff09;进行了解析、优化和准备&#xff0c;使得实际执行时可以直接使用优化后的执行计划&#xff0c;而不需要每次都重新解析和编译。这么说可能有一些抽…

qemu搭建虚拟的aarch64环境开发ebpf

一、背景 需求在嵌入式环境下进行交叉编译&#xff0c;学习ebpf相关技术&#xff0c;所以想搭建一个不依赖硬件环境的学习环境。 本文使用的环境版本&#xff1a; 宿主机&#xff1a; Ubuntu24.02 libbpf-bootstrap源码&#xff1a; https://github.com/libbpf/libbpf-boots…

深度学习从入门到实战——卷积神经网络原理解析及其应用

卷积神经网络CNN 卷积神经网络前言卷积神经网络卷积的填充方式卷积原理展示卷积计算量公式卷积核输出的大小计算感受野池化自适应均值化空洞卷积经典卷积神经网络参考 卷积神经网络 前言 为什么要使用卷积神经网络呢&#xff1f; 首先传统的MLP的有什么问题呢&#xff1f; - …

2015年西部数学奥林匹克几何试题

2015/G1 圆 ω 1 \omega_1 ω1​ 与圆 ω 2 \omega_2 ω2​ 内切于点 T T T. M M M, N N N 是圆 ω 1 \omega_1 ω1​ 上不同于 T T T 的不同两点. 圆 ω 2 \omega_2 ω2​ 的两条弦 A B AB AB, C D CD CD 分别过 M M M, N N N. 证明: 若线段 A C AC AC, B D BD …

《Spring Framework实战》14:4.1.4.5.自动装配合作者

欢迎观看《Spring Framework实战》视频教程 自动装配合作者 Spring容器可以自动连接协作bean之间的关系。您可以通过检查ApplicationContext的内容&#xff0c;让Spring自动为您的bean解析协作者&#xff08;其他bean&#xff09;。自动装配具有以下优点&#xff1a; 自动装配…

JVM之垃圾回收器概述(续)的详细解析

ParNew(并行) Par 是 Parallel 并行的缩写&#xff0c;New 是只能处理的是新生代 并行垃圾收集器在串行垃圾收集器的基础之上做了改进&#xff0c;采用复制算法&#xff0c;将单线程改为了多线程进行垃圾回收&#xff0c;可以缩短垃圾回收的时间 对于其他的行为&#xff08;…

有一台服务器可以做哪些很酷的事情

有一台服务器可以做哪些很酷的事情 今天我也来简单分享一下&#xff0c;这几年来&#xff0c;我用云服务器做了哪些有趣的事情。 服务器推荐 1. 个人博客 拥有个人服务器&#xff0c;你可以完全掌控自己的网站或博客。 与使用第三方托管平台相比&#xff0c;你能自由选择网站…

灌区闸门自动化控制系统-精准渠道量测水-灌区现代化建设

项目背景 本项目聚焦于黑龙江某一灌区的现代化改造工程&#xff0c;该灌区覆盖广阔&#xff0c;灌溉面积高达7.5万亩&#xff0c;地域上跨越6个乡镇及涵盖17个村庄。项目核心在于通过全面的信息化建设&#xff0c;强力推动节水灌溉措施的实施&#xff0c;旨在显著提升农业用水的…

3.flask蓝图使用

构建一个目录结构 user_oper.py from flask import Blueprint, request, session, redirect, render_template import functools # 创建蓝图 user Blueprint(xkj, __name__)DATA_DICT {1: {"name": "张三", "age": 22, "gender": …

vue3学习日记1 - Pinia

最近发现职场前端用的框架大多为vue&#xff0c;所以最近也跟着黑马程序员vue3的课程进行学习&#xff0c;以下是我的学习记录 视频网址&#xff1a; Day2-02.Pinia-counter基础使用_哔哩哔哩_bilibili 学习日记&#xff1a; vue3学习日记1 - 环境搭建-CSDN博客 vue3学习日…

IP 地址与蜜罐技术

基于IP的地址的蜜罐技术是一种主动防御策略&#xff0c;它能够通过在网络上布置的一些看似正常没问题的IP地址来吸引恶意者的注意&#xff0c;将恶意者引导到预先布置好的伪装的目标之中。 如何实现蜜罐技术 当恶意攻击者在网络中四处扫描&#xff0c;寻找可入侵的目标时&…

Leetocde516. 最长回文子序列 动态规划

原题链接&#xff1a;Leetocde516. 最长回文子序列 class Solution { public:int longestPalindromeSubseq(string s) {int n s.size();vector<vector<int>> dp(n, vector<int>(n, 1));for (int i 0; i < n; i) {dp[i][i] 1;if (i 1 < n &&…