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

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

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


一篇文章搞定“位运算”

  • 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♪(・ω・)ノ谢谢阅读!!!

下一篇文章见!!!

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

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

相关文章

变分自编码器(Variational Autoencoder, VAE)

目录 why VAE&#xff1a; 关于变分自编码器&#xff0c;这篇文章讲的不错 1. 自编码器&#xff08;Autoencoder&#xff09;的基础 2. 引入概率图模型 3. 重参数化技巧 4. 损失函数 5. 应用 变分自编码器&#xff08;Variational Autoencoder, VAE&#xff09; why VAE…

opencv车道偏离系统-代码+原理-人工智能-自动驾驶

车道偏离预警系统&#xff08;Lane Departure Warning System, LDWS&#xff09;是一种主动安全技术&#xff0c;旨在帮助驾驶员避免因无意中偏离车道而引发的事故。从原理到实战应用&#xff0c;其工作流程大致如下&#xff1a; 传感器采集 &#xff1a;系统通常配备有一个或…

探索未知:风靡硅谷开发者的 Unstructured Data Meetup 即将登陆中国

“最硅谷”的 Unstructured Data Meetup 即将来袭&#xff01; 众所周知&#xff0c;AI 三要素包括&#xff1a;算力、算法和数据。数据的价值愈发凸显&#xff0c;而其中非结构化数据更是备受关注。IDC 预测&#xff0c;到 2025 年&#xff0c;全球数据总量中将有超过 80% 的数…

Linux提权--SUDO(CVE-2021-3156)Polkit(CVE-2021-4034)

免责声明:本文仅做技术学习与交流... 目录 SUDO(CVE-2021-3156) 影响版本 -判断&#xff1a; -利用&#xff1a; Polkit(CVE-2021-4034&#xff09; ​ -判断&#xff1a; -利用: 添加用户 SUDO(CVE-2021-3156) another: SUDO权限配置不当. 影响版本 由系统的内核和发…

运维安全管理系统:“四集中”管理 解决迫切问题

日前&#xff0c;国内专注于保密与非密领域的分级保护、等级保护、业务连续性安全和大数据安全产品解决方案与相关技术研究开发的领军企业——国联易安依托自身强大的研发能力&#xff0c;丰富的行业经验&#xff0c;自主研发了新一代软硬件一体化统一安全运维平台——国联易安…

【XSRP软件无线电】基于软件无线电平台的QPSK频带通信系统设计

目录&#xff1a; 目录&#xff1a; 一、绪论 1.1 设计背景 1.2 设计目的 二、系统总体方案 2.1 专题调研题目 2.2 调研背景 2.3 设计任务解读 2.4 设计原理 2.4.1 原理框图 2.4.2 功能验证 三、软件设计 3.1 程序解读 3.2 程序设计 3.3 仿真结果&#xff1a; 四、程序代码分析…

Day26 代码随想录打卡|栈与队列篇---有效的括号

题目&#xff08;leecode T20&#xff09;&#xff1a; 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。左括号必须以…

JAVA智慧工地管理系统源码,智慧工地扬如何实现对工地扬尘的实时监测

智慧工地扬尘监测系统概述 智慧工地扬尘监测系统是一种利用现代信息技术&#xff0c;如光电传感技术和无线传输技术&#xff0c;对工地扬尘污染进行实时监测和管理的高效工具。该系统的目的是为了保护环境&#xff0c;减少因建筑施工产生的扬尘对周边地区的影响&#xff0c;同…

新增柱线组合图、象限图,新增钉钉、飞书、企业微信客户端免密登录,DataEase开源数据可视化分析工具v2.6.0发布

2024年5月13日&#xff0c;人人可用的开源数据可视化分析工具DataEase正式发布v2.6.0版本。 这一版本的功能升级包括&#xff1a;图表方面&#xff0c;新增了柱线组合图、象限图&#xff1b;仪表板方面&#xff0c;支持批量拖拽字段&#xff0c;外部参数新增支持配置过滤组件&…

【中级软件设计师】上午题3-数据结构(查漏补缺版)

上午题3-数据结构 0 前言1 时间、空间复杂度2 串2.1 串的模式匹配 3 矩阵4 图4.1 邻接矩阵和邻接表 5 查找6 哈希表、7 树7.1 B树 0 前言 因为我之前考研系统地学习过数据结构和操作系统&#xff0c;这两部分的笔记不完整 1 时间、空间复杂度 指数<阶乘<n次方阶 使用队…

华为认证存储HCIE有用吗?

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

ABeam德硕 | 大语言模型系列(3):企业如何拥抱大语言模型

继前两期我们分享了大语言模型的概要简介及商业模式、商业价值之后&#xff0c;作为大语言模型系列的收尾篇&#xff0c;本期我们将聚焦在大语言模型的落地&#xff0c;结合案例简单分析拥抱大语言模型的思路&#xff0c;为企业提供ABeam见解。 往期回顾 ABeam Insight | 大语…

Bootloader+升级方案

随着设备的功能越来越强大&#xff0c;系统也越来越复杂&#xff0c;产品升级也成为了开发过程不可或缺的一道程序。在工程应用中&#xff0c;如何在不更改硬件的前提下通过软件的方式实现产品升级。通过Bootloader来实现固件的升级是一种极好的方式&#xff0c;Bootloader是单…

巴奴火锅翻车,杜中兵后悔暗讽海底捞

曾经喊出“服务不过度&#xff0c;样样都讲究”、内涵海底捞的巴奴火锅&#xff0c;又改回了2012年的广告语&#xff0c;试图重回“产品主义”。 巴奴火锅于2001年创立于河南安阳&#xff0c;彼时被视作火锅界的黑马。巴奴火锅创始人的杜中兵&#xff0c;坚信“产品主义”一定…

周进院长受邀出席2024第四届屈光手术国际论坛获多项荣誉称号!

周进院长受邀出席2024第四届屈光手术国际论坛获“全国首批EVOICL&#xff08;V5&#xff09;新技术临床应用专家”等多项荣誉称号&#xff01; 5月10-12日&#xff0c;由爱尔眼科医院集团主办、长沙爱尔眼科医院协办的2024第四届屈光手术国际论坛&#xff08;IRSS 2024&#x…

攻防世界PHP2

1、打开靶机链接http://61.147.171.105:49513/&#xff0c;没有发现任何线索 2、尝试访问http://61.147.171.105:49513/index.php&#xff0c;页面没有发生跳转 3、尝试将访问 尝试访问http://61.147.171.105:49513/index.phps index.php 和 index.phps 文件之间的主要区别在于…

智能自助终端主板RK3288/RK3568在酒店前台自助机方案的应用,支持鸿蒙,支持免费定制

酒店前台自助机解决方案是一款基于自助服务终端&#xff0c;能够让客人通过简单的操作完成入住登记/退房的解决方案&#xff0c;大幅提高酒店的工作效率&#xff0c;提升客人体验&#xff0c;降低人力成本。 该方案解决了以下传统前台登记入住方式的痛点&#xff1a; 1、人流量…

智能仓储物流系统(WMS)系列-出库分配发货

好的应用系统应是细分简单&#xff0c;界面简洁易操作&#xff0c;程序代码简洁易懂的。

8种常见的CMD命令

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

Star CCM+衍生零部件的创建

前言 在一个仿真计算项目中&#xff0c;分配零部件至区域、划分网格后。下一步可以先将需要监测的点、面建立出来&#xff0c;方便后续创建报告。Star中需要创建点、面是在衍生零部件下创建。衍生零部件→右键→新建&#xff08;如下图1所示&#xff09;。通过衍生零部件可以创…