【优选算法】位运算

在这里插入图片描述

目录

  • 常见位运算总结
    • 1、基础位运算
    • 2、给一个数n,确定它的二进制位的第x位上是0还是1
    • 3、将一个数n的二进制位的第x位改成1
    • 4、将一个数n的二进制位的第x位改成0
    • 5、位图的思想
    • 6、提取一个数n的二进制位中最右侧的1
    • 7、将一个数n的二进制位中最右侧的1变为0
    • 8、位运算的优先级
    • 9、异或(^)运算的运算律
  • 一、[位1的个数](https://leetcode.cn/problems/number-of-1-bits/description/)
  • 二、[比特位计数](https://leetcode.cn/problems/counting-bits/description/)
  • 三、[汉明距离](https://leetcode.cn/problems/hamming-distance/description/)
  • 四、[只出现一次的数字](https://leetcode.cn/problems/single-number/description/)
  • 五、[只出现一次的数字 III](https://leetcode.cn/problems/single-number-iii/description/)
  • 六、[判定字符是否唯一](https://leetcode.cn/problems/is-unique-lcci/description/)
  • 七、[丢失的数字](https://leetcode.cn/problems/missing-number/description/)
  • 八、[两整数之和](https://leetcode.cn/problems/sum-of-two-integers/description/)
  • 九、[只出现一次的数字 II](https://leetcode.cn/problems/single-number-ii/description/)
  • 十、[消失的两个数字](https://leetcode.cn/problems/missing-two-lcci/description/)
  • 结尾

常见位运算总结

1、基础位运算

左移操作符 >> 、右移操作符 << 、按位取反 ~ ,这三个操作符我不做讲解。

接下来讲解3个操作符以及它使用方法对应的记忆方法

按位与:& 有0就是0
按位或:| 有1就是1
按位异或:^ 相同为0相异为1/无进位相加
在这里插入图片描述


2、给一个数n,确定它的二进制位的第x位上是0还是1

首先我们认为一个整数有32位、它最低位是0位,它的最高位为31位,那么就可以使用(n >> x)&1的操作来判断这个数的第x位是0还是1,因为n>>x能够将数字n上的第x位移动到第0位,1除了第0位上是1,其他位都是0,异或后结果只会出现第0位上为0/1其他位为0的情况,所以结果是0则数n二进制位的第x位上是0,是1则数n二进制位的第x位上是1。

在这里插入图片描述


3、将一个数n的二进制位的第x位改成1

首先我们认为一个整数有32位、它最低位是0位,它的最高位为31位,那么就可以使用n|=(1<<x)的操作将数字n的二进制位的第x位改成1。1<<x能够将1的第x位变为1,异或后无论n上的第x位上是0是1都会变为1。

在这里插入图片描述


4、将一个数n的二进制位的第x位改成0

首先我们认为一个整数有32位、它最低位是0位,它的最高位为31位,那么就可以使用n&=(~(1<<x))的操作将数字n的二进制位的第x位改成0。1<<x能够将1的第x位变为1,按位与后除了第x位上为0其他位上都为1,再与n按位与后,n中的第x位都会被0变为1,其他位都是与1按位与,则都不变。

在这里插入图片描述


5、位图的思想

位图的本质就是哈希表,我们在之前就学习过哈希表,哈希表很多情况下是数组,假设是一个int类型的数组,可以通过在数组中存储某些数组来表示某些意义,现在我们可以通过变量的比特位来表示某些信息,假设一个int类型的变量,一个int类型的变量有32位,其中的每一位存储的0/1都可以分别表示某种信息。

在这里插入图片描述


6、提取一个数n的二进制位中最右侧的1

首先我们认为一个整数有32位、它最低位是0位,它的最高位为31位,那么就可以使用n&-n的操作提取一个数n的二进制位中最右侧的1。这里的-n也就~n+1,-n能够将最右侧1的左侧所有二进制数字变成相反的,+1能将右侧所有二进制数字变为0,按位与后就只剩下最右侧的1。
在这里插入图片描述


7、将一个数n的二进制位中最右侧的1变为0

首先我们认为一个整数有32位、它最低位是0位,它的最高位为31位,那么就可以使用n&(n-1)的操作将一个数n的二进制位中最右侧的1变为0。-1能够将数字n最右侧1的左侧二进制数字变成相反的(包括它本身),按位与后右侧不变,左侧都不同则都变为0,就可将最右侧的1变为1。

在这里插入图片描述


8、位运算的优先级

位运算的优先级大家可以在其他文章中查看,这里建议大家能加括号就加括号。


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

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

一、位1的个数

题目描述
在这里插入图片描述

思路讲解
在上面常见位运算总结中讲到了如何将一个数的二进制位中最右侧的1修改为0,我们只需要重复这个操作,并记录这个操作的次数,当这个数变为0以后,操作次数就是这个数二进制位中1的个数。

编写代码

class Solution {
public:int hammingWeight(int n) {int count = 0;while(n > 0){// 去掉最右侧的一n &= (n - 1);count++;}return count;}
};

二、比特位计数

题目描述
在这里插入图片描述

思路讲解
这题的思路与上一题的思路一致,只是上一题是获取一个数的二进制位中有多少个1,而本题是获取n个数的二进制位中有多少个1,本质上是一样的,这里不做过多讲解。

编写代码

class Solution {
public:int hammingWeight(int n) {int count = 0;while(n > 0){// 去掉最右侧的1n &= (n - 1);count++;}return count;}vector<int> countBits(int n) {vector<int> ans;for(int i = 0 ; i <= n ;i++)ans.push_back(hammingWeight(i));return ans;}
};

三、汉明距离

题目描述
在这里插入图片描述

思路讲解
两个整数之间的 汉明距离 指的是这两个数字对应二进制位不同的位置的数目。所以我们只需要将两个数每个对应的二进制位上的数字获取并对比,记录
二进制位不同的位置的数目即可,我们在上面讲到过可以使用(n >> x)&1的操作获取一个数的第x位上的二进制是0还是1。

编写代码

class Solution {
public:int hammingDistance(int x, int y) {int count = 0;for(int i = 0 ; i <= 31 ;i++){if(((x >> i) & 1) != (((y >> i) & 1)))count++;}return count;}
};

四、只出现一次的数字

题目描述
在这里插入图片描述

思路讲解
在上面异或运算的运算律中我们讲到过a^a=0a^0=a,本题中除了一个数只出现过一次,其他数都出现过两次,将所有的数异或在一起,出现过两次的数全部异或到一起就是0,出现过一次的数与0异或就是我们需要的结果。

编写代码

class Solution {
public:int singleNumber(vector<int>& nums) {int val = 0;for(auto ch : nums){val ^= ch;}return val;}
};

五、只出现一次的数字 III

题目描述
在这里插入图片描述
思路讲解

在上面异或运算的运算律中我们讲到过a^a=0a^0=a,本题中除了两个数只出现过一次,其他数都出现过两次,将所有的数异或在一起,就是两个只出现一次的数相异或的结果。两个数异或的结果的二进制位上有1就代表着两个数在当前位上一定是不同的,我们可以将两数异或结果上某一个1的位置标记,记为pos,将所以pos位上为1的数全部异或在一起,就能够得到其中一个答案,再将两数异或的结果与刚刚得到的一个答案异或,就能够得到另一个答案。

编写代码

class Solution {
public:vector<int> singleNumber(vector<int>& nums) {vector<int> v;v.resize(2 , 0);int xor1 = 0;// 将所有数异或,可以得到需要的两个数的异或for(auto x : nums){xor1 ^= x;}// 我们知道,异或后的二进制位上的 1,// 必定是两个数对应二进制位上的一个,且只有一个 // 那我们只需要将某一位上的1的位置记录下来// 并且将数组遍历一遍,将这个位置上为1的数全部异或就能得到第一个数// 再将第一步中两个数的异或值与第一个数异或就能得到第二个数int pos = 0;for(int i = 0 ; i < 32 ;i++){if( ((xor1 >> i) & 1 ) == 1 ){pos = i;break;}}for(int i = 0 ; i < nums.size() ; i++){if(((nums[i] >> pos) & 1) == 1){v[0] ^= nums[i];}}v[1] = xor1 ^ v[0];return v;}
};

六、判定字符是否唯一

题目描述
在这里插入图片描述

思路讲解
本题最简单的思路就是建立一个数组,将每个字母出现的次数记录下来,当有一个字符出现两次就返回false,但是这样需要花费4*26个字节,而使用位图则只需要4个字节,一个int类型的变量就有32个比特位,将26位小写字母对应到其中的32个比特位中,当遍历到一个字符的时候,就查看对应比特位上是0/1,如果是1就返回false,是0就继续遍历字符串。

本题还有一个优化方案就是雀巢原理,小写字母一共有26个,当字符串的长度超过26时,说明一定有一个字母是出现过两次的。

编写代码

class Solution {
public:bool isUnique(string astr) {// 优化 雀巢原理if(astr.size() > 26)return false;// 因为小写字母只有26个// 而int中有32个比特位// 那么这里使用位图来解决问题int tmp = 0;for(auto e : astr){if(((tmp >> (e - 'a')) & 1) == 1)return false;elsetmp |= (1 << (e - 'a'));}return true;}
};

七、丢失的数字

题目描述
在这里插入图片描述

思路讲解
本题最简单的思路就是建立一个大小为n的数组arr,遍历nums并在arr中标记,当nums遍历完后,再遍历arr查看哪个数字没有被标记就是答案,但是这个方法的缺点就是需要使用额外的空间复杂度。

还有可以使用高斯求和,得到0到n之间的数相加后的结果,减去nums中数组中所有数,就是本题的答案。

还可以使用位运算,上课讲到过a^a=0a^0=a,将0到n中所有的数异或,再与nums数组中所有的数异或,就能够得到本题的答案。使用位运算可以将本题转化为上面只出现一次的数字的那道题。

编写代码

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

八、两整数之和

题目描述
在这里插入图片描述

思路讲解

我们在记忆按位异或使用的时候,按位异或就是无进位相加,那么这里只缺少进位,进位我们可以通过按位与获得,但是需要注意的是获得的进位需要向左侧移动一位。我们将按位异或得到的无进位相加的结果记为tmp1,将按位与获得的进位记为tmp2,持续将tmp1与tmp2按位异或和按位与得到无进位相加与进位,只要当进位tmp2为0时,tmp1就是结果。

在这里插入图片描述

编写代码

class Solution {
public:int getSum(int a, int b) {int tmp1 = (a & b)<<1;  // 两数按位与后向右移动一位,代表着进位int ans = a ^ b;        // 两数异或代表无进位相加while(tmp1 != 0){int tmp2 = tmp1;    // 记录tmp1tmp1 = (tmp1 & ans)<<1; ans ^= tmp2;}return ans;}
};

九、只出现一次的数字 II

题目描述
在这里插入图片描述

思路讲解
题目中讲到了有一个数只出现过一次,其他的数都出现了三次,那么将所有数的二进制位罗列出来,那么将所有数对应每一位相加起来会出现两种情况:3n与3n+1,通过将3n与3n+1进行%3,就能得到0和1的结果,这里得到的1就是只出现过一次的数字对应比特位上的1,只需要将这些1组合到对应的比特位上,得到的数字就是结果。

同理给你一个整数数组 nums ,除某个元素仅出现一次外,其余每个元素都恰出现n次,都可以使用这个方法。

编写代码

class Solution {
public:int singleNumber(vector<int>& nums) {int sum = 0;       // 记录所有数字某个二进制位的和int num = 0;       // 记录答案for(int i = 0 ; i < 32 ; i++){for(int ch : nums){// 将第i个位置上的二进制数字取出来相加sum += ((ch >> i)&1);}if(sum % 3 != 0){num |= (1 << i);}sum = 0;}return num;}
};

十、消失的两个数字

题目描述
在这里插入图片描述

思路讲解
本道题就是上面只出现一次的数字III和丢失的数字两道题的结合,只需要找到丢失两个数的按位异或的结果就可以使用只出现一次的数字III中的思路,分别得到两个数是哪两个数,这里就不做讲解。

编写代码

class Solution {
public:vector<int> missingTwo(vector<int>& nums) {int tmp = 0;int numsLen = nums.size();for(int i = 1 ; i <= numsLen + 2; i++)tmp ^= i;for(auto e : nums)tmp ^= e;int lowbit = (tmp & -tmp);int ans1 = tmp;for(int i = 1 ; i <= numsLen + 2; i++)if((lowbit & i) == lowbit)ans1 ^= i;for(auto e : nums)if((lowbit & e) == lowbit)ans1 ^= e; int ans2 = (tmp ^ ans1);return {ans1,ans2};}
};

结尾

如果有什么建议和疑问,或是有什么错误,大家可以在评论区中提出。
希望大家以后也能和我一起进步!!🌹🌹
如果这篇文章对你有用的话,希望大家给一个三连支持一下!!🌹🌹

在这里插入图片描述

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

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

相关文章

jQuery九宫格抽奖,php处理抽奖信息

功能介绍 jQuery九宫格抽奖是一种基于jQuery库的前端抽奖效果。通过九宫格的形式展示抽奖项&#xff0c;用户点击抽奖按钮后&#xff0c;九宫格开始旋转&#xff0c;最终停在一个随机位置上&#xff0c;此位置对应的抽奖项为用户的中奖结果。 本文实现九宫格的步骤为&#xf…

AI界的信仰危机:单靠“规模化”智能增长的假设,正在面临挑战

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

Unity类银河战士恶魔城学习总结(P149 Screen Fade淡入淡出菜单)

【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili 教程源地址&#xff1a;https://www.udemy.com/course/2d-rpg-alexdev/ 本章节实现了进入游戏和死亡之后的淡入淡出动画效果 UI_FadeScreen.cs 1. Animator 组件的引用 (anim) 该脚本通过 Animator 控制 UI 元…

【C语言篇】探索 C 语言结构体:从基础语法到数据组织的初体验

我的个人主页 我的专栏&#xff1a;C语言&#xff0c;希望能帮助到大家&#xff01;&#xff01;&#xff01;点赞❤ 收藏❤ 目录 什么是结构体结构体的定义与使用结构体内存布局嵌套结构体与指针结构体数组的操作结构体与函数结构体内存对齐机制位域与结构体的结合动态内存分…

COMSOL工作站:配置指南与性能优化

COMSOL Multiphysics 求解的问题类型相当广泛&#xff0c;提供了仿真单一物理场以及灵活耦合多个物理场的功能&#xff0c;供工程师和科研人员来精确分析各个工程领域的设备、工艺和流程。 软件内置的#模型开发器#包含完整的建模工作流程&#xff0c;可实现从几何建模、材料参数…

大语言模型LLM的微调代码详解

代码的摘要说明 一、整体功能概述 这段 Python 代码主要实现了基于 Hugging Face Transformers 库对预训练语言模型&#xff08;具体为 TAIDE-LX-7B-Chat 模型&#xff09;进行微调&#xff08;Fine-tuning&#xff09;的功能&#xff0c;使其能更好地应用于生成唐诗相关内容的…

qt5.14.2跟vs2022配置

1.qt6要在线安装&#xff0c;安装时间比较长&#xff0c;要求网络要稳定&#xff0c;不适合快速安装 2.使用qt5.14.2离线安装包&#xff0c;安装速度快&#xff0c;可以快速安装。 3.安装完qt.5.14.2后打开QtCreate4.0.1&#xff0c;打开 工具->选项->Kits,发现如下图: 没…

【拥抱AI】RAG(Retrieval-Augmented Generation)知识库的切片策略及其改进

1. RAG简介 RAG是一种结合了信息检索和文本生成的技术&#xff0c;它通过从一个外部的知识库中检索相关信息来增强生成模型的能力。这种方法可以提高生成内容的相关性和准确性&#xff0c;特别是在处理长文档时&#xff0c;有效的文本切片策略对于提升检索效率和质量至关重要。…

webrtc ios h264 硬编解码

webrtc ios h264 硬编解码 一 ios 系统支持 从ios8开始&#xff0c;苹果公司开放了硬解码和硬编码API&#xff08;即 VideoToolbox.framework API&#xff09; 二 主要api 1 主要解码函数 VTDecompressionSessionCreate // 创建解码 session VTDecompressionSession…

深入解析 MySQL 启动方式:`systemctl` 与 `mysqld` 的对比与应用

目录 前言1. 使用 systemctl 启动 MySQL1.1 什么是 systemctl1.2 systemctl 启动 MySQL 的方法1.3 应用场景1.4 优缺点优点缺点 2. 使用 mysqld 命令直接启动 MySQL2.1 什么是 mysqld2.2 mysqld 启动 MySQL 的方法2.3 应用场景2.4 优缺点优点缺点 3. 对比分析结语 前言 MySQL …

Ubuntu20.04运行LARVIO

文章目录 1.运行 Toyish 示例程序2.运行 ROS Nodelet参考 1.运行 Toyish 示例程序 LARVIO 提供了一个简化的toyish示例程序&#xff0c;适合快速验证和测试。 编译项目 进入 build 文件夹并通过 CMake 编译项目&#xff1a; mkdir build cd build cmake -D CMAKE_BUILD_TYPER…

[2024年3月10日]第15届蓝桥杯青少组stema选拔赛C++中高级(第二子卷、编程题(2))

方法一&#xff08;string&#xff09;&#xff1a; #include <iostream> #include <string> using namespace std;// 检查是否为回文数 bool isPalindrome(int n) {string str to_string(n);int left 0, right str.size() - 1;while (left < right) {if (s…

HTML 中 a 标签跳转问题总结:从框架页面跳转的困境与突破

在 HTML 网页开发过程中&#xff0c;a 标签作为超链接的常用标记&#xff0c;其跳转功能看似简单&#xff0c;实则在一些特定场景下会遇到诸多复杂问题。本文将围绕一个具体的案例展开&#xff0c;深入探讨在框架页面中使用 a 标签跳转时所面临的挑战以及相应的解决方案&#x…

【Db First】.NET开源 ORM 框架 SqlSugar 系列

.NET开源 ORM 框架 SqlSugar 系列 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列【Code First】.NET开源 ORM 框架 SqlSugar 系列 &#x1f…

课题组自主发展了哪些CMAQ模式预报相关的改进技术?

空气污染问题日益受到各级政府以及社会公众的高度重视&#xff0c;从实时的数据监测公布到空气质量数值预报及预报产品的发布&#xff0c;我国在空气质量监测和预报方面取得了一定进展。随着计算机技术的高速发展、空气污染监测手段的提高和人们对大气物理化学过程认识的深入&a…

扫雷-完整源码(C语言实现)

云边有个稻草人-CSDN博客 在学完C语言函数之后&#xff0c;我们就有能力去实现简易版扫雷游戏了&#xff08;成就感满满&#xff09;&#xff0c;下面是扫雷游戏的源码&#xff0c;快试一试效果如何吧&#xff01; 在test.c里面进行扫雷游戏的测试&#xff0c;game.h和game.c…

uniapp在App端定义全局弹窗,当打开关闭弹窗会触发onShow、onHide生命周期怎么解决?

在uniapp(App端)中实现自定义弹框&#xff0c;可以通过创建一个透明页面来实现。点击进入当前页面时&#xff0c;页面背景会变透明&#xff0c;用户可以根据自己的需求进行自定义&#xff0c;最终效果类似于弹框。 遇到问题&#xff1a;当打开弹窗(进入弹窗页面)就会触发当前页…

【C++】C++新增特性解析:Lambda表达式、包装器与绑定的应用

V可变参数模板与emplace系列 C语法相关知识点可以通过点击以下链接进行学习一起加油&#xff01;命名空间缺省参数与函数重载C相关特性类和对象-上篇类和对象-中篇类和对象-下篇日期类C/C内存管理模板初阶String使用String模拟实现Vector使用及其模拟实现List使用及其模拟实现…

HTB:Chatterbox[WriteUP]

目录 Connect to the HackTheBox server and spawn target machine Infomation Collection Use Rustscan to perform oepn scanning on the TCP port of the target Use Nmap to perform script and service scanning on the TCP port of the target Use Curl accessing p…

远程视频验证如何改变商业安全

如今&#xff0c;商业企业面临着无数的安全挑战。尽管企业的形态和规模各不相同——从餐厅、店面和办公楼到工业地产和购物中心——但诸如入室盗窃、盗窃、破坏和人身攻击等威胁让安全主管时刻保持警惕。 虽然传统的监控摄像头网络帮助组织扩大了其态势感知能力&#xff0c;但…