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

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

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


一篇文章搞定“位运算”

  • 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.mzph.cn/diannao/11458.shtml

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

相关文章

NL6621 WIFI模块烧录及其他

某宝淘得NL6621: 测了一下引脚&#xff1a; 做了以下功课&#xff1a; 新岸线物联网NL6621解决方案是高性价比、完全开源、高成熟度的解决方案&#xff0c;特别为高数据吞吐率低成本的无线局域网产品而设计。它集成了MCU&#xff0c; MAC&#xff0c;1T1R基带和带功放RF收发机于…

数据结构的二叉树(c语言版)

一.二叉树的概念 1.二叉树的基本概念 二叉树是一种常见的树状数据结构&#xff0c;它由若干个节点组成&#xff0c;这些节点通过边连接起来。每个节点最多可以有两个子节点&#xff0c;分别称为左子节点和右子节点。 二叉树的特点是每个节点最多有两个子节点&#xff0c;而且…

Eplan2.9版本安装教程指南【附安装包】

文章目录 前言一、Eplan是什么&#xff1f;二、安装指南1、安装包获取2、安装步骤在这里插入图片描述 总结 前言 随着人工智能的不断发展&#xff0c;机器学习这门技术也越来越重要&#xff0c;很多人都开启了学习机器学习&#xff0c;本文就介绍了机器学习的基础内容。 提示&…

【报错合集】完美解决“虚拟机使用的是此版本 VMware Workstation 不支持的硬件版本”

文章目录 解决方案&#xff1a;更改设置的硬件版本 今天我需要将别人的虚拟机克隆到我的VMware Workstation上运行&#xff0c;结果发生了以下的错误&#xff1a; 刚开始以为是VMware Workstation的版本问题太低导致的&#xff0c;所以我删除了原来的那个版本&#xff0c;下载…

开源分布式爬虫管理平台:性能强悍!!【送源码】

简介 基于 Golang 的分布式爬虫管理平台&#xff0c;支持 Python、NodeJS、Go、Java、PHP 等多种编程语言以及多种爬虫框架。 谁适合使用 Crawlab? 网路爬虫工程师&#xff1a; 通过集成爬虫程序到 Crawlab&#xff0c;网路爬虫工程师可以聚焦于爬虫的核心解析逻辑&#xff0…

WCF 双工 回调模式

wcfInterface 项目 》》》wcf服务端提供的服务协议 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.ServiceModel; namespace wcfInterface {[ServiceContract(CallbackContract typeo…

【软考网络工程师】每日练题学知识

1.在EIGRP协议中&#xff0c;某个路由器收到了两条路径到达目标网络&#xff0c;路径1的带宽为100Mbps&#xff0c;延迟2ms&#xff0c;路径2的带宽为50Mbps&#xff0c;迟为4ms&#xff0c;如果EIGRP使用带宽和延迟的综合度量标准&#xff0c;那么该路由器选择的最佳路径是&am…

鸿蒙内核源码分析(工作模式篇) | CPU的七种工作模式

本篇说清楚CPU的工作模式 工作模式(Working mode) 也叫操作模式&#xff08;Operating mode&#xff09;又叫处理器模式&#xff08;Processor mode&#xff09;&#xff0c;是 CPU 运行的重要参数&#xff0c;决定着处理器的工作方式&#xff0c;比如如何裁决特权级别和报告异…

实时追踪维修进度,报修管理小程序让你省心又省力!

随着生活、工作节奏的日益加快&#xff0c;日常的售后报修、故障报修处理流程给我们带来种种困扰。我们都知道大多数企业、个人用户还在使用传统报修方式&#xff0c;如电话报修、纸质报修单等方式&#xff0c;不仅效率低下&#xff0c;而且难以追踪维修进度&#xff0c;给我们…

AI游戏外挂为何违法?

尊敬的读者们&#xff0c;大家好&#xff01;今天我想和大家探讨一个备受争议的话题——AI游戏外挂的合法性。近年来&#xff0c;随着人工智能技术的飞速发展&#xff0c;AI外挂逐渐成为游戏领域的一大毒瘤。那么&#xff0c;为什么AI游戏外挂会被视为违法行为呢&#xff1f;本…

【中级软件设计师】上午题16-算法(应试考试简略版)

上午题16-算法 1 回溯法1.1 n皇后问题 2 分治法3 动态规划3.1 0-1背包问题3.2 最长公共子序列3.3 矩阵连乘 4 贪心算法5 分支限界法总结 1 回溯法 深度优先方法搜索 1.1 n皇后问题 2 分治法 一般来说&#xff0c;分治算法在每一层递归上都有3个步骤 &#xff08;1&#xff…

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

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

【Linux学习笔记】一篇文章彻底搞定“Linux生产者与消费者“!

本章重点 1.生产者消费者模型2.posix信号量&#xff0c;以及读写锁。3. 理解基于读写锁的读者写者问题。 一. 生产者消费者模型 为何要使用生产者消费者模型 生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯&#xff0…

专业音频修复软件:iZotope RX 11 for Mac 激活版

iZotope RX 专为满足后期制作专业人士的苛刻需求而设计的一款专业音频修复软件。iZotope RX 10添加了新的特性和功能&#xff0c;以解决当今后期项目中存在的一些最常见的修复问题&#xff0c;使其成为音频后期制作的最终选择。虽然包含许多其他新功能&#xff0c;但这里是新的…

微信小程序的设计与实现

微信小程序的设计与实现 目录 1.系统简述&#xff1a; 2.开发工具及相关技术&#xff1a; 2.1 HTML、WXSS、JAVASCRIPT技术 2.2 Vanilla框架 2.3 uni-app框架 2.4 MYSQL数据库 3.工程结构及其说明&#xff1a; 4.主要功能展示 4.1登录 4.2 注册 4.3 首页…

【C++11】C++11类与模板语法的完善

目录 一&#xff0c;新的类功能 1-1&#xff0c;默认成员函数 1-2&#xff0c;强制生成关键字 二&#xff0c;可变参数模板 2-1&#xff0c;模板参数包 2-3&#xff0c;模板参数包的实际运用 2-2&#xff0c;STL容器empalce的相关接口 三&#xff0c;模板参数包和empla…

002.反应式编程的必要性

在实际应用程序中&#xff0c;您可以在许多情况下发现可能的时变变量—例如&#xff0c;GPS位置、温度、鼠标坐标&#xff0c;甚至文本框的内容。所有这些都有一个随时间变化的值应用程序会发生反应&#xff0c;因此是时变的。还有一点值得一提时间本身就是一个时变;它的值一直…

Unicode字符集和UTF编码

文章目录 前言一、字符集和编码方式二、unicode字符集utf32编码utf8编码utf8编码函数示例utf8解码函数示例 utf16编码utf16编码解码函数示例 总结 前言 本文详细介绍 u n i c o d e unicode unicode 字符集和其相关的三种编码方式&#xff1a; u t f 8 utf8 utf8&#xff0c;…

华为认证存储HCIE有用吗?

首先&#xff0c;对于个人来说&#xff0c;获得华为存储认证可以证明其具备信息存储技术的专业能力 1.专业认可&#xff1a;获得华为存储认证&#xff0c;尤其是HCIE-Storage级别的证书&#xff0c;意味着持有者对信息存储技术有着全面深入的理解&#xff0c;能够设计、部署、…

JPA@Entry报错Could not determine recommended JdbcType for Java type

问题很明显&#xff0c;无法自动决定类型&#xff0c;那就手动告诉该字段。 一、直接上解决方案 如果是一对一的关系用 OneToOne 如果是一对多的关系用 OneToMany 如果是多对一的关系用 ManyToOne 二、另一个无空构造函数的问题 使用注解后&#xff0c;注解报错找不到空的…