算法——位运算

news2024/12/28 19:28:02

常见位运算总结

  1. 基础位运算

    1. << >> ~
    2. 与&:有0就是0
    3. 或|:有1就是1
    4. 异或^:相同为0,相异为1 / 无进位相加image.png
  2. 给一个数n,确定他的二进制表示中的第x位是0还是1

    1. 让第x位与上1即可
    2. 先让n右移x位
    3. &上一个1(仅需考虑最低位,即最右边),所以与上1(0000001,只有最低位是1)image.png
  3. 将一个数n的二进制表示的第x位修改成1

    1. 和1进行或运算|,这样其他位置上的数字保持不变,只需要让第x位或1就行
    2. 先让1左移x位,然后和1进行或等运算

image.png

  1. 将一个数n的二进制表示的第x位修改成0

    1. 让第x位与上一个0即可,使其余位保持不变(决定权在上面自身)
    2. 让1左移x位后,按位取反
    3. n与等上这样一个数image.png
  2. 位图的思想

    1. 本质是一个哈希表,大多情况是数组的形式方便增删查改,可以用O(1)的时间复杂度来查找
    2. 现在用一个变量的二进制位记录信息。存储0表示一种信息,存储1表示一种信息。此时用一个变量我们就能实现增删查改。这里我们哈希表是一个变量,然后用变量中某一位的比特位的0、1来帮助我们记录信息。(2、3、4都是为位图服务的)image.jpeg
  3. 提取一个数(n)二进制表示中最右侧的1(该操作又称为lowbit,即把最低位的1提取出来)

    1. 即过这个操作后,image.png上面的数变为下面的数
    2. n按位与-n即可(负数是按位取反再加1)image.png
  4. 干掉一个数n二进制表示中最右侧的1

    1. n &(n-1)
    2. n-1本质上是当n从最右侧开始出现连续的0,做减法时会一直借位,一直借到最右边的1.即以最右侧的1作为分界线,让他右边的区域都变成相反数image.jpeg
    3. 然后再与&上nimage.png就能达到干掉最右侧的1的效果
  5. 位运算的优先级:能加括号就加括号

  6. 异或(^)运算的运算律

    1. a ^ 0 = a
    2. a ^ a = 0 (消消乐)
    3. a ^ b ^ c = a ^ (b ^ c)

一大堆数随便异或(不考虑运算顺序),结果是唯一的image.png
运用6、7
LeetCode191. 位1的个数
LeetCode318. 比特位计数
LeetCode461. 汉明距离
运用9
LeetCode136. 只出现一次的数字
LeetCode260. 只出现一次的数字III

判断字符是否唯一

判定字符是否唯一

题目解析

  • 确定一个字符串 s 的所有字符是否全都不同。
  • s[i]仅包含小写字母
  • 如果你不使用额外的数据结构,会很加分。

算法原理

  1. 解法一:哈希表(哈希数组hash[26]):因为题中已经说明仅包含小写字母,判断字符是否在哈希表里,如果不在放进哈希表,移动下一个位置。时间复杂度O(n),空间复杂度O(n)
  2. 位图思想:

image.png

  1. 优化点:鸽巢原理:因为一共有26个英文字母,当字符串的长度大于26时,一定会有重复的字符

代码实现

class Solution {
public:
    bool isUnique(string astr) {
        // 利⽤鸽巢原理来做的优化
        if(astr.size() > 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;
    }
};

丢失的数字

丢失的数字

题目解析

给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数。

算法原理

  1. hash表:创建一个大小为n+1的数组,这样下标刚好是0~n,然后一一对应去找。时间复杂度O(n),空间复杂度O(n)image.png
  2. 高斯求和:求出0~n所有数字的和,然后减去数组中的和,得出的结果就是缺失的结果.时间复杂度O(n),空间复杂度O(1)

image.png

  1. 位运算(异或运算的运算律):将数组中的数和0n全部进行异或,所有重复的数异或结果都是0,0n数剩下的一个和数组中的0异或(数组缺失),得出的结果就是缺失的。时间复杂度O(n),空间复杂度O(1)。image.png

代码实现

class Solution {
public:
    int missingNumber(vector<int>& nums) {
        int ret = 0;
        for(auto x : nums) ret ^= x;
        for(int i = 0; i <= nums.size(); i++) ret ^= i;
        return ret;
    }
};

两整数之和

两整数之和

题目解析

不使用 运算符 + 和 - ,计算并返回两整数之和。

算法原理

  1. 笔试场上,不讲武德:直接return a+b
  2. 位运算(异或运算——无进位相加):
    1. 我们只需要找到进位即可。进位的情况是只有1和1会出现。这样就和按位与&的情况一样。并且进位是进到数字左边的位置上,所以我们还需让其进行左移,这样我们就得到了进位的结果,得到这两个结果之后,让其相加。直到进位全部为0即可
    2. 先算出无进位相加的结果,在算出进位的结果。
    3. 继续(无进位)“相加”两个结果,直至进位全部变为0.

image.png

代码实现

class Solution {
public:
    int getSum(int a, int b) 
    {
        while(b != 0)
        {
            int x = a ^ b; // 先算出⽆进位相加的结果
            //这里排除-1这种情况,-1二进制全是1
            unsigned int carry = (unsigned int)(a & b) << 1; // 算出进位  
            a = x;
            b = carry;
        }
            return a;
    }
};

只出现一次的数字II

只出现一次的数字II

题目解析

  • 给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 **三次 。**请你找出并返回那个只出现了一次的元素。
  • 要求时间复杂度O(n),空间复杂度O(1)

算法原理

  1. 位图思想:
    1. 列出如下某一个比特位的所有情况image.png

    2. 将这些和相加后,%3,我们会发现一个规律:最终模完之后的结果和a(只出现一次的数)保持一致。image.png

    3. 将nums数组中所有的数的比特位第0位统统加起来%3,如果结果是0,不变,结果是1,修改位1;同理最终结果的倒数第二位也是如此,以此类推,直至将32位比特位全部修改完毕。

(设要找的数位 ret 。由于整个数组中,需要找的元素只出现了「⼀次」,其余的数都出现的「三次」,因此我们可以根据所有数的「某⼀个⽐特位」的总和 %3 的结果,快速定位到 ret 的「⼀个⽐特位上」的值是0 还是1 。这样,我们通过 ret 的每⼀个⽐特位上的值,就可以将ret 给还原出来 。)

我们如果想得到ret结果其中的某一位时,我们将nums中所有的数的这一位相加起来,再模上一个3(题中所要求的出现三次,如果是出现n次,就模上n),如果是0,就修改成0;如果是1,就修改成1。image.png

代码实现

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int ret = 0;
        for(int i = 0; i < 32; i++) // 依次去修改 ret 中的每⼀位
        {
            int sum = 0;
            for(int x : nums) // 计算nums中所有的数的第 i 位的和
            if(((x >> i) & 1) == 1)
            sum++;
            sum %= 3;
        if(sum == 1) ret |= 1 << i;
        }
        return ret;
    }
};

消失的两个数字

消失的两个数字

题目解析

  1. 用时间复杂度O(n),空间复杂度O(1)来解决。
  2. 数组区间n+2

image.png

算法原理

这道题其实是之前“丢失的数字”+“只出现一次的数字III

  1. 1~N这里相当于nums数组+a+b(缺失的两个数字——丢失的数字

image.png

  1. 将nums和1~N统称为一个整体,那么问题就转换为有两个数字出现了1次,剩下的一堆数字出现了2次(丢失的数字III

位运算思想:

  1. 将所有的数字异或在一起,记为tmp,因为出现两次的数字都异或被抵消了,所有tmp=a^b。接下来,我们将a、b两个数字分开
  2. 找到tmp中,比特位上为1的那一位。因为a和b这两个数字是不一样的,所以最终异或的结果是不等于0的。所以tmp中他的比特位上一定有一位上是1(记为x)。此时将刚刚所有的数字(nums和1~N)又可以划分为两大类,一类是x位上是0,一类上是x位上是1。在分别让这些数字和1、0进行异或,就能分离出a和b。image.png

代码实现

class Solution {
public:
    vector<int> missingTwo(vector<int>& nums) {
        // 1. 将所有的数异或在⼀起
        int tmp = 0;
        for(auto x : nums) tmp ^= x;
        for(int i = 1; i <= nums.size() + 2; i++) tmp ^= i;
        
        // 2. 找出 a,b 中⽐特位不同的那⼀位
        int diff = 0;

        while(1)
        {
            //因为一定会有一个比特位上是1,所以一定回跳出这个死循环
            if(((tmp >> diff) & 1) == 1) break;
            else diff++;
        }
        // 3. 根据 diff 位的不同,将所有的数划分为两类来异或
        int a = 0, b = 0;
        for(int x : nums)
            if(((x >> diff) & 1) == 1) b ^= x;
            else a ^= x;

        for(int i = 1; i <= nums.size() + 2; i++)
            if(((i >> diff) & 1) == 1) b ^= i;
            else a ^= i;
        
            return {a,b};
    }
};

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Docker入门安装gerrit软件

Windows上运行docker 什么是Docker Desktop docker desktop是Docker在Windows 10和macOS操作系统上的官方安装方式&#xff0c;这个方法依然属于先在 Windows 上部署 Docker 的方法都是先安装一个虚拟机&#xff0c;并在安装 Linux 系统的的虚拟机中运行 Docker。 开启Hyper-…

moogose使用

概念 Node.js 的优雅 mongodb 对象建模 Mongoose 提供了一种直接的、基于模式的解决方案来对应用程序数据进行建模。它包括开箱即用的内置类型转换、验证、查询构建、业务逻辑挂钩等 安装 npm i mongoose具体例子 E:\Nextjs\mongoose-use-demo\app\api[crud]\route.ts 连接…

数据结构:栈(Stack)的各种操作(入栈,出栈,判断栈非空,判断栈已满,附源码)

前言&#xff1a;在前面的文章中&#xff0c;我们讲解了顺序表&#xff0c;单链表&#xff0c;双向链表。而我们今天要分享的栈则是基于之前的数据结构上搭建的&#xff0c;但是相较于顺序表和链表来说&#xff0c;栈的实现就非常简单了。 目录 一.栈(Stack)的概念 二.栈的数…

TOWE 高品质220V/380V工业插头插座:插座篇

在不同工业场合和环境中&#xff0c;对工业用插头插座和耦合器的配置有着不同的要求。在实际应用中&#xff0c;我们要根据用途、工作环境、规格大小、外观造型、安装形式、功能等方面进行选择。只有确保正确选择产品&#xff0c;才能确保现实用电环境的安全、高效。 同为科技&…

什么是 web 组态?web 组态与传统组态的区别是什么?

组态软件是一种用于控制和监控各种设备的软件&#xff0c;也是指在自动控制系统监控层一级的软件平台和开发环境。这类软件实际上也是一种通过灵活的组态方式&#xff0c;为用户提供快速构建工业自动控制系统监控功能的、通用层次的软件工具。通常用于工业控制&#xff0c;自动…

数据库——字段拆分与合并

一、GP或PostgreSQL 1.字段拆分成行 unnest(string_to_array(test, ,)) 例如某一字段值为"a,b,c,d"&#xff0c;使用string_to_array将其拆分为数组&#xff0c;然后使用unnest将数组平铺成一张表 SELECT unnest(string_to_array(555,666,777, ,)) 2.字段拆分成列…

一文告诉您企业为什么这么关注数字资产指纹

数字资产指纹 在互联网数字资产管理中&#xff0c;数字资产指纹就是数字资产的“身份证”&#xff0c;也是信息系统安全管理工作的基础。通过网络资产探测&#xff08;指纹&#xff09;可以在0day&#xff08;通常是指还没有补丁的漏洞&#xff09; 爆发时快速匹配到受影响的信…

B029-JDBC增强

目录 PreparedStatement 查询1.sql注入2.Statement分析 (面试题)3.PreparedStatement (面试题) 登录功能的完善事务链接池概念实现DBCP连接池实现第一种配置方式第二种配置方式 返回主键BaseDao的抽取 PreparedStatement 查询 1.sql注入 就是在sql的字符串拼接的时候&#xf…

ChibiOS简介3/5

ChibiOS简介3/5 1. 源由2. ChibiOS基础知识3/52.7 Chapter 7 - RT Time and Intervals2.7.1 Basic concepts2.7.2 APIs 2.8 Chapter 8 - RT Virtual Timers2.8.1 Basic concepts2.8.2 Tickless Mode2.8.3 APIs 2.9 Chapter 9 - RT Scheduler2.9.1 Basic concepts2.9.2 System C…

两线制无源 4-20mA 回路供电隔离变送器

两线制无源 4-20mA 回路供电隔离变送器 一入一出两线制无源 4-20mA 回路供电隔离变送器 概述&#xff1a;JSD TAW-1001D-100L-F 系列隔离变送器是 4-20mA 两线制回路供电的电流隔离变送配电器,该隔离变送器采用电磁隔离技术,并通过输入端馈电方式,给输入端两线制仪器仪表设备供…

数据库 02-03补充 聚合函数--一般聚合分组和having

聚合函数&#xff1a; 01.一般的聚合函数&#xff1a; 举个例子&#xff1a; 一般聚合函数是用于单个元祖&#xff0c;就是返回一个数值。 02.分组聚合&#xff1a;可以返回多个元祖 举个例子&#xff1a; 分组的注意&#xff1a; 主要的是根据分组的话&#xff0c;一个…

【git push ERROR: commit id: missing Change-Id in message footer】

使用 gerrit 后&#xff0c;提交代码会出现如下截图问题&#xff1a; 临时解决&#xff1a; step1: 把上面红色的那条gitidir复制下来执行下&#xff1a; step2:执行下面的命令会添加change_id git commit --amendstep3: 然后推送代码到服务器上 git push origin HEAD:refs/fo…

万界星空科技电子装配行业MES解决方案

电子电器装配属于劳动密集型、科技含量较高的行业&#xff0c;产品零部件种类繁多&#xff0c;生产组装困难&#xff0c;生产过程存在盲点&#xff0c;同时也决定了生产流水线多且对自动化水平要求较高。 万界星空科技提供的电子行业MES解决方案&#xff0c;提供从仓储管理、生…

排序算法:【选择排序]

一、选择排序——时间复杂度 定义&#xff1a;第一趟排序&#xff0c;从整个序列中找到最小的数&#xff0c;把它放到序列的第一个位置上&#xff0c;第二趟排序&#xff0c;再从无序区找到最小的数&#xff0c;把它放到序列的第二个位置上&#xff0c;以此类推。 也就是说&am…

STM32 CAN多节点组网项目实操 挖坑与填坑记录

摘要 CAN线性组网项目开发过程中遇到的数据丢包问题&#xff0c;并尝试解决的记录和推测分析。 关键词 CAN串联多节点通讯、CAN10节点通讯、CAN数据丢包、STM32 CAN 背景/项目介绍 概述&#xff1a; 开发了一个多节点线性组网采集数据的项目。 系统包含1个供电和数据网关板还有…

如何利用Guava优化Java网络编程

第1章&#xff1a;引言 大家好&#xff01;今天小黑要和咱们聊聊一个很酷的话题&#xff1a;如何利用Google的Guava库来优化Java网络编程。网络编程&#xff0c;这玩意儿听起来就高大上&#xff0c;不是吗&#xff1f;但实际上&#xff0c;它充满了各种挑战。从处理复杂的数据…

【二分查找】【滑动窗口】LeeCode2528:最大化城市的最小电量

作者推荐 【动态规划】【广度优先】LeetCode2258:逃离火灾 本文涉及的基础知识点 二分查找算法合集 滑动窗口 题目 给你一个下标从 0 开始长度为 n 的整数数组 stations &#xff0c;其中 stations[i] 表示第 i 座城市的供电站数目。 每个供电站可以在一定 范围 内给所有城…

OpenHarmony创新赛人气投票活动,最佳人气作品由你来定!

12月1日至12月15日 十大入围作品线上投票激战正酣 最佳人气作品&#xff0c;由你来定&#xff01; 投票链接&#xff1a;OpenHarmony创新赛人气作品投票正式开启——最佳人气作品&#xff0c;由你来定&#xff01; - 文章 OpenHarmony开发者论坛

uniCloud(一) 新建项目、初始化服务空间、云对象访问测试

一、新建一个带有unicloud 二、创建一个服务空间 1. 右键uniCloud&#xff0c;关联云服务空间 我当前没有服务空间&#xff0c;需要新建一个服务空间&#xff0c;之后将其关联。初始化服务空间需要的时间有点长 服务空间初始化成功后&#xff0c;刷新HBuilder&#xff0c;勾选…

vue3使用Mars3D写区块地图

效果图 引入相关文件 因为我也是第一次使用&#xff0c;所以我是把插件和源文件都引入了&#xff0c;能使用启动 源文件 下载地址&#xff1a; http://mars3d.cn/download.html 放入位置 在index.html中引入 <!--引入cesium基础lib--><link href"/static/C…