【刷题】一篇文章搞定“位运算”

在这里插入图片描述
只要春天不死,就有迎春的花朵年年岁岁开放,生命讲涅槃,生生不息,并会以另一种形式永存。 – 路遥 《平凡的世界》

(◦′ᆺ‵◦) ♬° ✧❥✧¸.•¨✧♡✧ ℒℴѵℯ ✧♡✧¨•.❥
(◦′ᆺ‵◦) ♬° ✧❥✧¸.•¨✧♡✧ ℒℴѵℯ ✧♡✧¨•.❥
(◦′ᆺ‵◦) ♬° ✧❥✧¸.•¨✧♡✧ ℒℴѵℯ ✧♡✧¨•.❥


一篇文章搞定“位运算”

  • 1 前言
  • 2 位运算
  • 3 基础题目
  • 4 进阶题目
    • 4.1 Leetcode 260. 只出现一次的数字 III
    • 4.2 面试题 01.01. 判定字符是否唯一
    • 4.3 Leetcode 268. 丢失的数字
    • 4.4 Leetcode 371. 两整数之和
    • 4.5 Leetcode 137. 只出现一次的数字 II
  • 4 精通题目
    • 面试题 17.19. 消失的两个数字
  • Thanks♪(・ω・)ノ谢谢阅读!!!
  • 下一篇文章见!!!

1 前言

面试中经常会出现一类问题:它们看起来并不复杂,内容也很容易理解,但是它们往往带有一个额外的挑战条件——不允许使用额外的空间,或者说空间复杂度必须保持在O(1)。这类问题通常是为了考察应聘者对算法的深入理解以及对编程语言的掌握程度。

如果涉及到数组或者运算,经常就需要使用位运算来巧妙的解决这些问题。那么接下来我们来学习这个算法

2 位运算

我们熟知的位运算以下几种:

  1. & 按位或 :有 0 就为 0
  2. | 按位与 :有 1 就为 1
  3. ^ 按位异或 :相同为 0 ,不同为 1 / 无进位相加
  4. ~ 按位取反 :0 变 1 ,1 变 0
  5. << 向左移动 : 把二进制的每一位依次向左移动,右边补0
  6. >> 向右移动 : 把二进制的每一位依次向右移动,左边补0
  7. - 取负:先按位取反,然后在加1 。以最右侧的 1 为分割,左边的区域全部变成相反的 ,右边都变成 0
  8. 注意 一定一定要加上括号,位运算的优先级比较复杂。

通过这四种基础的位运算我们可以衍生出一些常用公式:

  • 判断一个数 x 的第 n 位是 0 / 1 : (x << n ) & 1 ,计算得到 1 那么第 n 位就是 1 ,反之是 0 。
  • 将一个数 x 的第 n 位修改为 1 : x |= (1 << n) ,直接就修改了
  • 将一个数 x 的第 n 位修改为 0 : x & ~(1 << n) ,这个比较复杂,(1 << n)会得到...00100...,按位取反后变成...11011...,然后按位或就可以不改变其他位置,就将第 n 位修改为 0了
  • 提取一个数 x 二进制的最右侧的 1 (lowbit):x & -x ,首先-x 会将x先按位取反,然后在加1。比如x是11010,那么-x就是 ->00101 -> 00110 。然后 x & -x 就会得到00010。十分巧妙!
  • 干掉一个数 x 最右侧的1 : x & x - 1x - 1这个操作就将最右侧的1左边不变,右边变成相反的。

另外提一个重要的东西:位图。通过比特位来进行判断是否存在。

3 基础题目

Leetcode 191. 位1的个数
Leetcode 338. 比特位计数
Leetcode 461. 汉明距离
Leetcode 136. 只出现一次的数字
这些题目比较基础,读懂题目,然后使用合理的位运算就可以了!

4 进阶题目

4.1 Leetcode 260. 只出现一次的数字 III

链接:Leetcode 260. 只出现一次的数字 III

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

数组里面有两个元素只出现一次,其余出现两次,那么我们需要找到这两个元素

算法思路
首先因为其余元素都是出现两次,那么我们直接进行一次遍历,并依次进行按位异或操作。就会得到一个结果,这个结果是只出现两次的元素的异或和。

又因为这两个元素是不同的,所以异或和必然有一位是 1 ,那么就以这个1来将所有元素进行分类。这样两个不同的元素就必然处于两个不同的组之中,那么就是找只出现一次的数字了!!!

    vector<int> singleNumber(vector<int>& nums) {//先得到异或和unsigned int  tmp = 0;for(auto s :nums){tmp ^= s;}//因为要取出一个 1 不妨就取最右边的 1 int lowbit = tmp & -tmp;//进行分类分析vector<int> ans(2);//容器的0 1 分别进行两组的异或处理for(auto s :nums)ans[(s & lowbit) != 0] ^= s;return ans;}

提交:过啦!!!

4.2 面试题 01.01. 判定字符是否唯一

链接:面试题 01.01. 判定字符是否唯一
题目描述
在这里插入图片描述

题目非常好理解!

算法思路
这道题有很多解法:哈希表 , 双指针 , 位运算
我们采取位运算的位图来解决问题,让面试官眼前一亮。位图其实就是简略的哈希表(但是运算更快),我们进行储存的时候需要将1向左移动对应的距离,这个距离是独一无二的ch - 'a'

    bool isUnique(string astr) {//抽屉原理优化if(astr.size() > 26 ) return false;//位图int map = 0;//遍历进行位图的读取for( auto ch : astr){//位图的位置如果是 1 ,那么就说明已经有该字母了if(map & ( 1 << (ch - 'a'))) return false;//反正位图该位置变为 1 else map |= ( 1 << (ch - 'a'));}return true;}

提交: 过啦!!!

4.3 Leetcode 268. 丢失的数字

链接:268. 丢失的数字
题目描述
在这里插入图片描述

题目很好理解!

算法思路
这道题也有很多算法:哈希表,数学方法,位运算
这里也是采取位运算的方法,我们将[0 , n]的所有元素都进行按位异或。然后再把数组中的元素进行按位异或。得到的两个异或和再进行一次异或,就可以得到没有出现的元素了!因为只有这个元素是单身狗!

    int missingNumber(vector<int>& nums) {int n1 = 0 , n2 = 0 ;//一起处理,效率更高for(int i = 1 ; i <= nums.size() ; i++ ) {n1 ^= i;n2 ^= nums[i - 1];}   return n1 ^ n2;}

提交:过啦!!!

4.4 Leetcode 371. 两整数之和

链接 :371. 两整数之和
题目描述
在这里插入图片描述

题目一如既往的好理解!

算法思路
这道题还是使用位运算奥:
那么如何进行呢???
通过这两个法宝就可以:

  • ^ 按位异或 :相同为 0 ,不同为 1 / 无进位相加
  • & 按位或 :有 0 就为 0 -> 因为都为 1 才得 1 所以可以判断是否需要进位
  1. 首先按位异或得到没有进位的数 b1
  2. 然后按位或 在向左移动 一位得到进位 a1
  3. 在把a1 , b1重复 1 - 2直到没有进位为止!
    int getSum(int a, int b) {//位运算while(a){int a1 = 0, b1 = 0;b1 = a ^ b ;  //无进位相加a1 = (a & b) << 1;//进位//更新数值a = a1 , b = b1;} return b;}

4.5 Leetcode 137. 只出现一次的数字 II

链接:137. 只出现一次的数字 II
题目描述
在这里插入图片描述

题目很好理解!

算法思路
这个与之前出现的只出现一次的数字不同,其他数字出现了3次。这要如何进行?
首先每个int类型数字都是由比特位组合成的:
那么我们就来看每个比特位相加会发生什么:
在这里插入图片描述
发现了吗? 无论什么情况,该比特位的数字相加完再余上 3 就变成了只出现一次的数字对应的比特位!!!
那么我们只要报每个比特位都进行如下操作就可以了:

    int singleNumber(vector<int>& nums) {//位运算int ans = 0 ;//答案//开始遍历每一位比特位for(int i = 0 ; i < 32 ;i++ ){int bit = 0;//把每个元素的该位都进行相加for(auto s : nums)bit += (s >> i) & 1;//除3得到的余数就是该位的结果bit %= 3;ans |= (bit << i);}        return ans;}

提交:过啦!!!

4 精通题目

面试题 17.19. 消失的两个数字

链接:面试题 17.19. 消失的两个数字
题目描述
在这里插入图片描述

这是一道困难题,但是在经过了上面的题目后,我们就能发现这道题其实超级简单

算法思路
首先这道题是要求我们找到[1 , N]中缺少的两个数字,那么其实就是:
丢失的数字 + 只出现一次的数字 III
为什么呢?
来看我们把数组的元素当做一个整体 sum
那么[1 , n]的元素相当于 sum + a + b。是不是这样???
分析到这一步就简单了,按照 丢失的数字 + 只出现一次的数字 III就ok了:

    vector<int> missingTwo(vector<int>& nums) {//位运算//[0 , n] 进行按位异或//数组元素进行按位异或//他们再进行按位异或int tmp = 0;for(int i = 1 ; i <= nums.size() + 2 ; i++)tmp ^= i;for(auto x:nums)tmp ^= x;//会得到消失两个数字的按位异或结果//这两个数字是不同的//所以取出最右边一位//分别进行按位异或,就可以得到对应的数字int lowbit = tmp & -tmp;vector<int> ans(2);for(int i = 1 ; i <= nums.size() + 2 ; i++)ans[(lowbit & i) != 0] ^= i;for(auto x:nums)ans[(lowbit & x) != 0] ^= x;return ans;}

Thanks♪(・ω・)ノ谢谢阅读!!!

下一篇文章见!!!

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

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

相关文章

C++——缺省参数与重载函数

目录 ​前言 一.缺省参数 1.1缺省参数概念 1.2缺省参数分类 注意事项&#xff1a; 二.函数重载 2.1函数重载概念 2.2c支持函数重载原理——命名修饰 前言 本篇文章主要讲述c中有关于缺少参数与函数重载的相关概念与实例&#xff0c;以下是本人拙见&#xff0c;如有错误…

Apple store 静安·苹果店欣赏

官网&#xff1a; https://www.apple.com/today/Apple 亚洲第一大商店&#xff1a;Apple 静安零售店现已在上海开幕 静安苹果欣赏

MS31912半桥电机驱动器可pin to pin替代DRV8912

主要特点 工作电压 4.5V-32V 每个半桥支持1A电流&#xff0c;并联输出支持6A最大电流 支持3.3V和5V逻辑输入 低功耗睡眠模式 (1.5μA) 带菊花链功能的5MHz 16位SPI通信 可通过SPI&#xff0c;配置PWM发生器的频率和占空比 集成多种保护和诊断功能nFAULT引脚输出、VM欠压锁定 、…

家政服务新体验——家政小程序开发,让生活更轻松!

一、引言 随着现代生活节奏的加快&#xff0c;家政服务已经成为越来越多家庭不可或缺的一部分。然而&#xff0c;传统家政服务方式往往存在预约不便、服务质量参差不齐等问题。为了解决这些问题&#xff0c;我们精心打造了一款家政小程序&#xff0c;为您带来全新的家政服务体…

电子作业指导书系统如何提升医疗设备工厂的生产效率

在医疗设备工厂中&#xff0c;电子作业指导书&#xff08;ESOP&#xff09;正逐渐成为提升生产效率的关键因素。 一、电子作业指导书系统提供了即时可得的准确信息。 电子作业指导书系统与传统的纸质作业指导书相比&#xff0c;员工可以在工作现场通过电子设备随时查阅最新、最…

【数据库原理及应用】期末复习汇总高校期末真题试卷11

试卷 一、填空题(每题 1 分&#xff0c;共10 分)    1. 数据库管理技术的发展经历了三个阶段&#xff1a;人工管理阶段&#xff0c;文件系统阶段和__________阶段。 2.实体完整性约束规定__________的取值不能为空值。 3. 计算机系统有三类安全性问题&#xff0c;即_____…

【机器学习】人力资源管理的新篇章:AI驱动的高效与智能化

&#x1f9d1; 作者简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…

Cocos 2048从创建到发布上线

一、制作2048小游戏过程 扫描体验2048小游戏 场景搭建&#xff0c;4X4棋盘和基础设置绘制背景板&#xff0c;包含预制体等信息考虑在棋盘中随机出现两个数字方块&#xff0c;数字为2&#xff0c;初始化操作滑动事件部分&#xff0c;让方块移动起来&#xff0c;每滑动一次就生成…

vin查询接口如何对接

vin查询接口是VIN车辆识别代码查询接口的简称&#xff0c;也叫vin查询车辆信息接口、车架号查询接口&#xff0c;指的是输入车辆VIN识别码&#xff08;车架号&#xff09;&#xff0c;返回车辆相关信息&#xff0c;如车辆品牌、车型、油耗、车身形式、排量等。那么vin查询接口如…

8种常见的CMD命令

1.怎么打开CMD窗口 步骤1&#xff1a;winr 步骤2&#xff1a;在弹出的窗口输入cmd&#xff0c;然后点击确认&#xff0c;就会出现一个cmd的窗口 2.CMD的8种常见命令 2.1盘符名称冒号 说明&#xff1a;切换盘的路径 打开CMD窗口这里默认的是C盘的Users的27823路径底下&#xf…

嗨动PDF编辑器怎么进行PDF编辑?看完了解

嗨动PDF编辑器怎么进行PDF编辑&#xff1f;PDF作为一种通用的文档格式&#xff0c;被广泛应用于商务交流、学术研究、电子出版等多个领域。但当面对需要修改或调整PDF文件内容时&#xff0c;就需要一款功能强大的PDF编辑器。嗨动PDF编辑器&#xff0c;它拥有对用户友好的界面设…

软件验收测试需要做哪些测试?

软件验收测试是在软件开发完成后的最后一个阶段&#xff0c;用来验证软件是否符合需求和预期的功能。在进行软件验收测试时&#xff0c;需要进行以下几种测试&#xff1a; 功能测试&#xff1a;验证软件的各项功能是否符合需求和预期。包括输入输出的正确性、功能的完整性、功能…