【优先算法】专题——位运算

在讲解位运算之前我们来总结一下常见的位运算

一、常见的位运算

1.基础为运算

<<      &:有0就是0

>>      |:有1就是1

~        ^:相同为0,相异位1 /无进位相加


2.给一个数 n,确定它的二进制表示中的第x 位是0还是1

n:0 1 1 0 1 0 1 0 0 1

(n >> x) & 1


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

               x

0 1 1 0 1 0 1 0 1 1

0 0 0 0 0 1 0 0 0 0

0 1 1 0 1 1 1 0 1 1(使用|)

n |=(1 << x)

n = n | (1 << x)


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

            x

0 1 1 0 1 0 1 1 0 0

1 1 1 1 0 1 1 1 1 1(取反得到:0 0 0 0 0 1 0 0 0 0)

0 1 1 0 0 0 1 1 0 0(使用&)

n &= (~(1<<x))

n = n &(~(1<<x))


5.位图思想

我们可以使用一个哈希表来存储我们的信息方便我们增删查改主要还是为了 我们查找因为可以使用O(1)的时间复杂度来查找,但是现在我们可以使用一个int变量来进行,一个int类型4个字节32个bit位,我们可以用某一位bit位上的0或者1来表示我们的信息,0表示一个信息1表示一个信息,本质还是一个哈希表。

位图会大量用到我们2、3、4这几个操作,专门为位图服务


6.提取一个数(n)二进制中最右侧的1

n & -n 将最右侧的1,左边的区域全部变成相反

0 1 1 0 1 0 1 0 0 0(原码)

1 0 0 1 0 1 0 1 1 1(反码)

1 0 0 1 0 1 1 0 0 0(+1,补码)

0 1 1 0 1 0 1 0 0 0(原码)

0 0 0 0 0 0 1 0 0 0(原码和补码进行&)


7.干掉一个数(n)二进制表示中最右侧的1

n & (n-1)将最右侧的1,右边的区域(包含1)全部变成相反

n :   0 1 1 0 1 0 1 0 0

n -1:0 1 1 0 1 0 0 1 1

&        0 1 1 0 1 0 1 0 0

___________________

           0 1 1 0 1 0 0 0 0


8.位运算的优先级

能加括号就加括号


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

1.a ^ 0 = a

2.a ^ a = 0(消消乐)

3.a ^ b ^ c = a ^(b ^ c)

一个奇数,一堆偶数最终的结果为奇数,因为偶数抵消了为0


通过上面的总结我们可以尝试写一下如下五个题

191.位一个的个数

题目链接:位一个的个数

题目描述:

参考代码:
class Solution {
public:
    int hammingWeight(int n) {
       int count = 0;
       while(n != 0) 
       {
            count++;
            n = n & (n-1);//把最低位1的右边互为相反数(包含1)
       }
       return count;
    }
};

338.比特位计数

题目链接:比特位计数

题目描述:

参考代码:
class Solution {
public:
    vector<int> countBits(int n) {
        vector<int>ans(n+1,0);
        for(int i = 1;i <= n;i++)
        {
           ans[i] = ans[i>>1] + (i & 1);
        }
        return ans;
    }
};

461.汉明距离

题目链接:汉明距离

题目描述:

参考代码:
//对应的位置值不相同的个数。例如,假设有两个十进制数a=93和b=73,
// 如果将这两个数用二进制表示的话,有
// a=1011101
// b=1001001,
// 可以看出,二者的从右往左数的第3位、第5位不同(从1开始数)
// 因此,a和b的汉明距离是2。
class Solution {
public:
    int hammingDistance(int x, int y) {
        int s = x ^ y, ret = 0;
        while (s)
        {
            ret += s & 1;
            s >>= 1;
        }
        return ret;
    }
};

136.只出现一次的数字

题目链接:只出现一次的数字

题目描述:

参考代码:
class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int ret = 0;
        for(auto n :nums)
        {
            ret ^= n;

        }
        return ret;
    }
};

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

题目链接:只出现一次的数字|||

题目描述:

参考代码:
class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
        unsigned int s = 0;
        
        for(auto n : nums)
        {
            s ^= n;
        }
        int low = s & -s;//取出最右侧的1
        int a = 0,b = 0;
        for(auto n : nums)
        {
            if((low & n) == low)
            {
                a ^= n;
            }
            else
            {
                b ^= n;
            }
        }
        return vector<int>{a,b};
    }
};

二、判断字符是否唯一

题目链接:判断字符是否唯一

题目描述:

解法一:我们可以使用哈希表

class Solution1 {
public:
    bool isUnique(string astr) {
        unordered_set<int>hash;
        for (auto ch : astr)
        {
            if (hash.count(ch)) return false;
            hash.emplace(ch);
        }
        return true;
    }
};

解法二:位图

我们用0表示没出现过,1表示出现过

可以利用鸽巢原理来进行优化,鸽巢原理已经在双指针那里讲过了这里就不过多赘述,一共有26个字母如果字符串的长度超过则肯定有重复字符,如果字符串的长度大于26那么直接返回false

参考代码:

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出现标记一下,1出现标记一下,3出现标记一下....

解法二:高斯求和

(首项 + 尾项) * 项数 / 2这样就算出了0~5的和然后我们再减去数组里面所有数之和这样就得出来了

参考代码:

class Solution1 {
public:
    int missingNumber(vector<int>& nums) {
        int n = nums.size();
        int sum = n * (n + 1) / 2;
        int ret = 0;
        for (auto n : nums)
        {
            ret += n;
        }
        return sum - ret;
    }
};

解法三:位运算(异或运算的运算律)

参考代码:

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

四、两整数之和

题目链接:两整数之和

题目描述:

在笔试中我们不讲武德直接return a + b;

解法:位运算(异或运算-无进位相加)

13+28=41

a:       0 0 1 1 0 1

b:       0 1 1 1 0 0

——————————

a^b:   0 1 0 0 0 1(a)   无进位

进位(a & b)<<1   0 1 1 0 0 0         我们进位是往前进位所以这里我们右移一位

我们继续重复如上操作,先无进位相加再进位

a:               0 1 0 0 0 1

b:               0 1 1 0 0 0 

a^b:           0 0 1 0 0 1  无进位

(a & b) <<1  1 0 0 0 0 0  进位

 a:              0 0 1 0 0 1 

 b :             1 0 0 0 0 0 

a^b:           1 0 1 0 0 1  无进位    41

(a & b) <<1   0 0 0 0 0 0 进位

进位变成0就结束了,最后的无进位相加就是我们的最终结果

参考代码:

class Solution {
public:
    int getSum(int a, int b) 
    {
        while(b != 0)
        {
            int x = a ^ b;//无进位相加
            unsigned carry = (unsigned)(a & b) <<1;//算出进位
            a = x;
            b = carry;
        }
        return a;
    }
};

五、只出现一次的数字|| 

题目链接:只出现一次的数字|| 

题目描述:

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

 参考代码:

class Solution {
public:
    int singleNumber(vector<int>& nums) 
    {
        int ret = 0;
        for(int i = 0;i < 32;i++)
        {
            int sum = 0;
            for(int x : nums)
                if(((x>>i) & 1) == 1)
                    sum++;
            sum %= 3;
            if(sum == 1) ret |= 1<<i;
        }
        return ret;
    }
    
};

六、消失的两个数字

题目链接:消失的两个数字

题目描述:

这道题其实是丢失的数字+只出现一次的数字|||融合一起,本题的算法原理就是用到了这两道题的一个算法原理。

nums中消失了两个数字,1~N这堆数中假设a和b是消失的两个数字,nums这一堆数和1~N这一堆数异或,其他的数出现了2次a和b出现了一次,那么其实就是a ^ b

解法:位运算

1.将所有的数异或在一起,tmp

tmp = a ^ b

2.找到tmp中,比特位上为1的那一位

a^b的结果肯定不为0因为他们是不同的数,所以它们的比特位上肯定有一位是1,a和b的第x位上肯定是不同的

3.根据x位的不同,划分成两类异或

我们可以把x位是0的分为一类,x位上是1的分一类,然后对两组数据分别进行异或。

参考代码:

class Solution {
public:
    vector<int> missingTwo(vector<int>& nums) 
    {
        //1.把所有数异或起来
        int tmp = 0;
        for(auto n : nums) tmp ^= n;
        for(int i = 1;i<=nums.size()+2;i++) tmp ^= i;
        int diff = 0;
        //找出a,b比特位不同的那一位
        while(1)
        {
            if(((tmp >>diff) & 1) == 1) break;
            else diff++;
        }
        //3.根据diff位的不同,将所有数划分两类来异或
        int a = 0,b = 0;
        for(auto n : nums)
            if(((n >> diff) & 1) == 1) b ^= n;
            else a ^= n;
        for(int i = 1;i<=nums.size()+2;i++)
        {
            if(((i >> diff) & 1) == 1) b ^= i;
            else a ^= i;
        }
        return {a,b};
    }
};

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

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

相关文章

Android --- handler详解

handler 理解 handler 是一套Android 消息传递机制&#xff0c;主要用于线程间通信。 tips&#xff1a; binder/socket 用于进程间通信。 参考&#xff1a; Android 进程间通信-CSDN博客 handler 就是主线程在起了一个子线程&#xff0c;子线程运行并生成message &#xff0c;l…

【线程】基于阻塞队列的生产者消费者模型

文章目录 1 生产者消费者模型2 阻塞队列2.1 成员变量2.2 消费者操作2.3 生产者生产 3 总结 1 生产者消费者模型 在多线程环境中&#xff0c;生产者消费者模型是一种经典的线程同步模型&#xff0c;用于处理生产者线程与消费者线程之间的工作调度和资源共享问题。在这个模型中&a…

解决PyG安装中torch-sparse安装失败问题:详细指南

1 问题描述 最近在学习GNN&#xff0c;需要使用PyTorch Geometric&#xff08;PyG&#xff09;库。在安装PyG的过程中&#xff0c;遇到了torch-sparse安装失败的问题&#xff0c;错误提示为&#xff1a; ERROR: Failed building wheel for torch-sparse本文将详细记录问题的解…

4 [危机13小时追踪一场GitHub投毒事件]

事件概要 自北京时间 2024.12.4 晚间6点起&#xff0c; GitHub 上不断出现“幽灵仓库”&#xff0c;仓库中没有任何代码&#xff0c;只有诱导性的病毒文件。当天&#xff0c;他们成为了 GitHub 上 star 增速最快的仓库。超过 180 个虚假僵尸账户正在传播病毒&#xff0c;等待不…

【B站保姆级视频教程:Jetson配置YOLOv11环境(六)PyTorchTorchvision安装】

Jetson配置YOLOv11环境&#xff08;6&#xff09;PyTorch&Torchvision安装 文章目录 1. 安装PyTorch1.1安装依赖项1.2 下载torch wheel 安装包1.3 安装 2. 安装torchvisiion2.1 安装依赖2.2 编译安装torchvision2.2.1 Torchvisiion版本选择2.2.2 下载torchvisiion到Downloa…

自动化软件测试的基本流程

一、自动化测试的准备 1.1 了解测试系统 首先对于需要测试的系统我们需要按照软件需求说明书明确软件功能。这里以智慧养老系统作为案例进行测试&#xff0c;先让我们看看该系统的登录界面和用户管理界面。 登录界面&#xff1a; 登录成功默认界面&#xff1a; 用户管理界面…

前端力扣刷题 | 6:hot100之 矩阵

73. 矩阵置零 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 法一&#xff1a; var setZeroes function(matrix) {let setX new Set(); // 用于存储需要置零的行索引let setY new Set(); //…

SLAM技术栈 ——《视觉SLAM十四讲》学习笔记(一)

《视觉SLAM十四讲》学习笔记&#xff08;一&#xff09; 第2讲 初识SLAM习题部分 第3讲 三维空间刚体运动3.1 左手系与右手系3.2 齐次坐标3.3 旋转矩阵与变换矩阵3.4 正交群与欧式群3.5 旋转向量与欧拉角3.6 实践Eigen线性代数库3.6.1 QR分解(QR decomposition) 3.7 四元数到其…

自动驾驶---两轮自行车的自主导航

1 背景 无人驾驶汽车最早出现在DARPA的比赛中&#xff0c;从那个时刻开始&#xff0c;逐渐引起全球学者的注意&#xff0c;于是从上个世纪开始各大高校院所开始了无人汽车的研发。直到这两年&#xff0c;无人驾驶汽车才开始走进寻常百姓家&#xff0c;虽然目前市面上的乘用车还…

Spring Boot 2 快速教程:WebFlux处理流程(五)

WebFlux请求处理流程 下面是spring mvc的请求处理流程 具体步骤&#xff1a; 第一步&#xff1a;发起请求到前端控制器(DispatcherServlet) 第二步&#xff1a;前端控制器请求HandlerMapping查找 Handler &#xff08;可以根据xml配置、注解进行查找&#xff09; 匹配条件包括…

优选算法的灵动之章:双指针专题(一)

个人主页&#xff1a;手握风云 专栏&#xff1a;算法 一、双指针算法思想 双指针算法主要用于处理数组、链表等线性数据结构中的问题。它通过设置两个指针&#xff0c;在数据结构上进行遍历和操作&#xff0c;从而实现高效解决问题。 二、算法题精讲 2.1. 查找总价格为目标值…

Intel 与 Yocto 项目的深度融合:全面解析与平台对比

在嵌入式 Linux 领域&#xff0c;Yocto 项目已成为构建定制化 Linux 发行版的事实标准&#xff0c;广泛应用于不同架构的 SoC 平台。Intel 作为 x86 架构的领导者&#xff0c;在 Yocto 生态中投入了大量资源&#xff0c;为其嵌入式处理器、FPGA 和 AI 加速硬件提供了完整的支持…

算法刷题Day29:BM67 不同路径的数目(一)

题目链接 描述 解题思路&#xff1a; 二维dp数组初始化。 dp[i][0] 1, dp[0][j] 1 。因为到达第一行第一列的每个格子只能有一条路。状态转移 dp[i][j] dp[i-1][j] dp[i][j-1] 代码&#xff1a; class Solution: def uniquePaths(self , m: int, n: int) -> int: #…

98,【6】 buuctf web [ISITDTU 2019]EasyPHP

进入靶场 代码 <?php // 高亮显示当前 PHP 文件的源代码&#xff0c;通常用于调试或展示代码&#xff0c;方便用户查看代码逻辑 highlight_file(__FILE__);// 从 GET 请求中获取名为 _ 的参数值&#xff0c;并赋值给变量 $_ // 符号用于抑制可能出现的错误信息&#xff…

C++中常用的十大排序方法之4——希尔排序

成长路上不孤单&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【&#x1f60a;///计算机爱好者&#x1f60a;///持续分享所学&#x1f60a;///如有需要欢迎收藏转发///&#x1f60a;】 今日分享关于C中常用的排序方法之4——希尔排序的相…

字节iOS面试经验分享:HTTP与网络编程

字节iOS面试经验分享&#xff1a;HTTP与网络编程 &#x1f31f; 嗨&#xff0c;我是LucianaiB&#xff01; &#x1f30d; 总有人间一两风&#xff0c;填我十万八千梦。 &#x1f680; 路漫漫其修远兮&#xff0c;吾将上下而求索。 目录 字节iOS面试经验分享&#xff1a;HTT…

音视频入门基础:RTP专题(7)——RTP协议简介

一、引言 本文对RTP协议进行简介。在简介之前&#xff0c;请各位先下载RTP的官方文档《RFC 3550》和《RFC 3551》。《RFC 3550》总共有89页&#xff0c;《RFC 3551》总共有44页。本文下面所说的“页数”是指在pdf阅读器中显示的页数&#xff1a; 二、RTP协议简介 根据《RFC 35…

SQLGlot:用SQLGlot解析SQL

几十年来&#xff0c;结构化查询语言&#xff08;SQL&#xff09;一直是与数据库交互的实际语言。在一段时间内&#xff0c;不同的数据库在支持通用SQL语法的同时演变出了不同的SQL风格&#xff0c;也就是方言。这可能是SQL被广泛采用和流行的原因之一。 SQL解析是解构SQL查询…

Java 大视界 -- Java 大数据在智能电网中的应用与发展趋势(71)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

想表示消息返回值为Customer集合

道奈特(240***10) 14:34:55 EA中序列图。我想表示消息返回值为 Customer 集合。目前只有一个Customer实体类&#xff0c;我需要另外新建一个CustomerList 类吗&#xff1f; 潘加宇(35***47) 17:01:26 不需要。如果是分析&#xff0c;在类的操作中&#xff0c;定义一个参数&…