刷题笔记2:用位运算找“只出现一次的一个数”

2024-06-13 05:52

本文主要是介绍刷题笔记2:用位运算找“只出现一次的一个数”,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. & 和 | 的基本操作

137. 只出现一次的数字 II - 力扣(LeetCode)

先对位运算的操作进行复习:

1、>> 右移操作符

移位规则:⾸先右移运算分两种:
1. 逻辑右移:左边⽤0填充,右边丢弃
2. 算术右移:左边⽤原该值的符号位填充,右边丢弃
一般的编译器都默认使用算术右移。

2. << 左移操作符

移位规则:左边抛弃、右边补0  

 注意,所有的操作符只能移动整数。

3. & 和 |

& //按位与
| //按位或
&:两位数都为1时为1,其余时候为0
|  :  两位数只要有一个为1,就为1,其余时候为0
并且,| ^ &的优先级都是低于==和!=的, 需要判断语句时记得加括号
意义

& :

  • 清零特定位 (m中特定位置0,其它位为1,s=s&m或s&=m)
  • 取某数中指定位 (m中特定位置1,其它位为0,s=s&m或s&=m)  比如 最经典的
    for(i=0;i<32;++i) //int是32位二进制整数
    int ans =(x>>i)& 1;

           由于1的补码是 000...0001,x每次右移1位来将每一位分别和0000....0001进行按位与,因此每一轮循环都能将x的一位赋值给ans,让ans依次得到x的每一个二进制位。

| :

多用于将左操作数某些位置1,其它位不变 (m特定位置为1,其余位置为0,希望将s的特定位置改为1,s |= m)

经典:根据特定的条件将ans中的某几位调整为1(将0000..0001中的1一位一位的往前挪)

if(.....)
ans |= (1 << i);


有了以上铺垫,我们再学习思路:

  由于除了答案,其余每个数字出现三次,所以这三个相同数字为一组中,就有三个一模一样的32为二进制数据(3个1或3个0),我们将第n位上的所有数据加在一起再对3取模,得到的数据就是ans在这一个二进制位上该有的数据。(很多个3和0取出来的模都为0,此时不论ans对应的这一位是1或0,都能被正确赋值) 

答案:

int singleNumber(vector<int>& nums) {int ans = 0;for (int i = 0; i < 32; ++i) {int x = 0;for (int j = 0; j < nums.size(); ++j) {x += (nums[j] >> i) & 1;}if (x % 3) {ans |= (1 << i);}}return ans;}

 2.小试牛刀

136. 只出现一次的数字 - 力扣(LeetCode)

 

依然是找出只出现一次的数据,不过按位异或就可以了

^  : 双目运算符按位异或,相异位1,相同为0

 int singleNumber(vector<int>& nums) {int ans=0;for(auto e:nums){ans^=e;}return ans;}

3.位运算 x & -x 来获取x的lowbit(取出二进制下X最低位的1)

        假设x为正数(位操作符都只对整数有用),在x变成-x时,除了第一位的符号位变化外,在由原码变到反码再到补码(取反加一)时,取反加一中的 “加一”,一定会加到反码由低到高的第一个0上,而反码所有的0都对应的是原码(正数)的1,(所以反码的第一个0对应的就是原码的第一个1)当反码的第一个0(假定这个0在p位置)被加成1后,就可以通过&运算或得  “最低位在p位置并且是1”的数据。

       我们可以认为x &-x是一种取得最低位1的技巧,并且这个用法对负数也凑效。

并且,在y = x & -x后,y是个除了符号位和p位置以外,其余位置都是0的数。

来个大的:

260. 只出现一次的数字 III - 力扣(LeetCode)

                    

     就像刚刚的小试牛刀,我们可以用异或消掉除了ans数组(用于存放两个只出现一次的数a, b)之外的所有数据。不过这两个被异或在一起的数据(x = a^b)该怎么分开呢?

分开的方法:

    对于x,x的每一个1,一定都是由一个数的1和另一个数的0组成的。

在这个理论的基础上,我们通过x & -x来获得一个和x的最低位1(假设在位置p)相同,其他(除最高位)都是0的数字y。我们通过 判断位置p是否为1将nums数组分成两组,所以ans数组中的两个数字一定就被分开了,两组中剩下的其他数字一定是成对出现的,将两个组分别全部异或就能得到答案。

没有全部通过,原因是当测试用例中有x为-2^31时,-x(2^31)没法被放进int

 我们处理如下:

会在x处出现-2^31次方的,答案一定是0和-2^31,否则x不会等于-2^31

并且在下文中,0和-2^31也的确会分开,因此达到目的。

各位都是工科生,仔细想想按位异或的最后一步就明白了。

这篇关于刷题笔记2:用位运算找“只出现一次的一个数”的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1056451

相关文章

Spring定时任务只执行一次的原因分析与解决方案

《Spring定时任务只执行一次的原因分析与解决方案》在使用Spring的@Scheduled定时任务时,你是否遇到过任务只执行一次,后续不再触发的情况?这种情况可能由多种原因导致,如未启用调度、线程... 目录1. 问题背景2. Spring定时任务的基本用法3. 为什么定时任务只执行一次?3.1 未启用

Python判断for循环最后一次的6种方法

《Python判断for循环最后一次的6种方法》在Python中,通常我们不会直接判断for循环是否正在执行最后一次迭代,因为Python的for循环是基于可迭代对象的,它不知道也不关心迭代的内部状态... 目录1.使用enuhttp://www.chinasem.cnmerate()和len()来判断for

电脑多久清理一次灰尘合? 合理清理电脑上灰尘的科普文

《电脑多久清理一次灰尘合?合理清理电脑上灰尘的科普文》聊起电脑清理灰尘这个话题,我可有不少话要说,你知道吗,电脑就像个勤劳的工人,每天不停地为我们服务,但时间一长,它也会“出汗”——也就是积累灰尘,... 灰尘的堆积几乎是所有电脑用户面临的问题。无论你的房间有多干净,或者你的电脑是否安装了灰尘过滤器,灰尘都

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

uva 575 Skew Binary(位运算)

求第一个以(2^(k+1)-1)为进制的数。 数据不大,可以直接搞。 代码: #include <stdio.h>#include <string.h>const int maxn = 100 + 5;int main(){char num[maxn];while (scanf("%s", num) == 1){if (num[0] == '0')break;int len =

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

论文阅读笔记: Segment Anything

文章目录 Segment Anything摘要引言任务模型数据引擎数据集负责任的人工智能 Segment Anything Model图像编码器提示编码器mask解码器解决歧义损失和训练 Segment Anything 论文地址: https://arxiv.org/abs/2304.02643 代码地址:https://github.com/facebookresear

数学建模笔记—— 非线性规划

数学建模笔记—— 非线性规划 非线性规划1. 模型原理1.1 非线性规划的标准型1.2 非线性规划求解的Matlab函数 2. 典型例题3. matlab代码求解3.1 例1 一个简单示例3.2 例2 选址问题1. 第一问 线性规划2. 第二问 非线性规划 非线性规划 非线性规划是一种求解目标函数或约束条件中有一个或几个非线性函数的最优化问题的方法。运筹学的一个重要分支。2

【C++学习笔记 20】C++中的智能指针

智能指针的功能 在上一篇笔记提到了在栈和堆上创建变量的区别,使用new关键字创建变量时,需要搭配delete关键字销毁变量。而智能指针的作用就是调用new分配内存时,不必自己去调用delete,甚至不用调用new。 智能指针实际上就是对原始指针的包装。 unique_ptr 最简单的智能指针,是一种作用域指针,意思是当指针超出该作用域时,会自动调用delete。它名为unique的原因是这个