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

news2024/11/27 21:52:19

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

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


一篇文章搞定“位运算”

  • 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.coloradmin.cn/o/1670978.html

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

相关文章

工作组PTH

文章目录 简述RID 500本地管理员密码喷洒何为RIP 500 安全标识符SID与RIDPTH为何必须是RID 500CrackMapExec进行密码喷洒 简述 在工作组PTH中为什么只有administrator账号可以,下面进行讲解与利用。RID 500本地管理员密码喷洒 何为RIP 500 安全标识符 安全标识符 安全标识符…

太速科技-基于VU3P的双路100G光纤加速计算卡

基于VU3P的双路100G光纤加速计算卡 一、板卡概述 基于Xilinx UltraScale16 nm VU3P芯片方案基础上研发的一款双口100 G FPGA光纤以太网PCI-Express v3.0 x16智能加速计算卡&#xff0c;该智能卡拥有高吞吐量、低延时的网络处理能力以及辅助CPU进行网络功能卸载的能力…

P5490.扫描线(python)

这个洛谷怎么对于python不太友好呢&#xff0c;没几次能全过的 本题使用扫描线的模板&#xff0c;首先把所有x坐标排序去重&#xff0c;放进列表X中。把所有横线lines排序。这样把所有矩阵都分成了块。对于每一块&#xff0c;高lines[i1]-lines[i]&#xff0c;宽就等于在这一块…

js图片回显的方法

直接上代码&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title></head><body>// HTML部分<input type"file" id"fileInput"><button onclick"show…

AI虚拟伴侣方案

打造类似Character AI的产品,现成的训练好的模型方案,适合做陪伴型虚拟女友等项目,近期看到的最佳项目: 1、项目背景: (1)项目动机:角色扮演LLM是AI的第二大消费用例,但通常被开源社区忽视。 (2)行业现状:缺乏与https://character.ai/提供的角色扮演LLM相对应的…

SpringBoot集成Curator实现Watch事件监听

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 Zookeeper是一个Ap…

jenkis

文章目录 安装插件配置构建超时自动停止 安装插件 在线安装&#xff1a;安装jenkins后&#xff0c;初次启动的时候安装插件 在线安装&#xff1a;插件管理&#xff0c;可选插件中 离线安装&#xff1a;下载插件(.hpi格式) 使用该方法安装插件每次只能安装一个插件&#xff0c;…

软件设计中的数字:7

“ 使软件更易理解的秘密&#xff1a;米勒法则” 小游戏 学习之前先一起玩一个小游戏。 3秒钟时间&#xff0c;看看下面的图片中有多少个小块&#xff1f; 3秒到了&#xff0c;数出来了吗&#xff1f;22个。 没数出来也没关系&#xff0c;我也没数出来o(╥﹏╥)o 现在&…

CentOs搭建Kubernetes集群

kubeadm minikube 还是太“迷你”了&#xff0c;方便的同时也隐藏了很多细节&#xff0c;离真正生产环境里的计算集群有一些差距&#xff0c;毕竟许多需求、任务只有在多节点的大集群里才能够遇到&#xff0c;相比起来&#xff0c;minikube 真的只能算是一个“玩具”。 Kuber…

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

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

数字绘画教学实训解决方案

一、建设背景 1.1政策背景 教育信息化政策推动&#xff1a;近年来&#xff0c;随着教育信息化政策的不断推动&#xff0c;各级教育部门纷纷出台相关政策&#xff0c;鼓励和支持教育信息化的发展。数字绘画作为现代艺术教育的重要组成部分&#xff0c;其教学实训解决方案的建设…

5.13号模拟前端面试10问

1.介绍箭头函数和普通函数的区别 箭头函数和普通函数在JavaScript中有一些重要的区别。以下是关于这些区别的详细解释&#xff1a; 语法结构上的差异&#xff1a; 箭头函数使用更简洁的语法&#xff0c;它不需要使用function关键字&#xff0c;而是使用一个箭头&#xff08;…

数据可视化(十):Pandas数据分析师职位信息表分析——箱线图、水平柱状图、学历城市双维分析等高级操作

Tips&#xff1a;"分享是快乐的源泉&#x1f4a7;&#xff0c;在我的博客里&#xff0c;不仅有知识的海洋&#x1f30a;&#xff0c;还有满满的正能量加持&#x1f4aa;&#xff0c;快来和我一起分享这份快乐吧&#x1f60a;&#xff01; 喜欢我的博客的话&#xff0c;记得…

苹果手机系统恢复工具:轻松解决iPhone各类系统问题!

随着苹果手机的iOS系统不断升级&#xff0c;越来越多的系统问题不断出现&#xff0c;如卡在恢复模式、系统崩溃白苹果、应用无响应、等&#xff0c;这些问题不仅影响用户体验&#xff0c;还可能导致手机无法正常使用。 遇到系统问题&#xff0c;一般我们可以先尝试使用强制重启…

云原生技术发展概述:投身云计算,从拥抱云原生开始

一、云原生的起源 云计算领域正在进行着一场革命&#xff0c;主机虚拟化实现了主机资源的池化&#xff0c;可以看作是云计算的上半场。以容器为基础的云原生真正实现了应用层的弹性&#xff0c;可以看作是云计算的下半场。 图来源&#xff1a;CNCF公开资料 有人说&#xff0c…

使用非官网购买Chatgpt的api调用

测试代码 from openai import OpenAI client OpenAI(api_key用户密钥) import json import os import timeclass ChatGPT:def __init__(self, user):self.user userself.messages [{"role": "system", "content": "Agent"}]def as…

嗨动PDF编辑器适合你的pdf编辑器,试试吧!

pdf编辑器有哪些&#xff1f;在数字化办公日益普及的今天&#xff0c;PDF文档因其跨平台、高保真度的特性而备受欢迎。无论是工作汇报、学术研究还是日常学习&#xff0c;我们都需要对PDF文档进行编辑、修改和整理。然而&#xff0c;如何选择合适的PDF编辑器却成了许多人头疼的…

算法题解记录25+++验证二叉搜索树(百日筑基)

题目描述&#xff1a; 难度&#xff1a;中等 给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左 子树 只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右子树自身必…

讯方·智汇云校4月HCIE通过28人!证书量总计123!

智汇云校捷报 —4月华为认证证书量123本— 智汇云校4月IE捷报来了 讯方技术2024年PMP第一期3月考期顺利结班&#xff0c;考试全员通过~ 2024年4月&#xff0c;云校HCIA、HCIP、HCIE共通过123人&#xff01; 62人通过HCIA 33人通过HCIP 28人通过HCIE 祝贺以下学员通过HC…

基于Echarts的大数据可视化模板:服务器运营监控

目录 引言背景介绍研究现状与相关工作服务器运营监控技术综述服务器运营监控概述监控指标与数据采集可视化界面设计与实现数据存储与查询优化Echarts与大数据可视化Echarts库以及其在大数据可视化领域的应用优势开发过程和所选设计方案模板如何满足管理的特定需求模板功能与特性…