499,位运算解只出现一次的数字 III

Wesley13
• 阅读 356

499,位运算解只出现一次的数字 III

It’s not the load that breaks you down, it’s the way you carry it.

压垮你的不是那些重担,而是你背负的方式。

问题描述

给定一个整数数组nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。找出只出现一次的那两个元素。

示例 :

输入: [1,2,1,3,2,5]

输出: [3,5]

位运算解决

前面刚讲过一个和这题类似的题494,位运算解只出现一次的数字,只不过第494题只有一个数字出现一次,但这题是有两个数字只出现一次。我们知道在位运算中异或运算具有交换律,也就是

A^B^C=A^C^B

我们还知道一个数字和自己异或,结果是0,也就是

A^A=0;

任何数字和0异或结果还是他自己

A^0=A;

有了上面的3个公式,这题就很容易解了,假如数组的元素是

[a,e,f,h,b,f,h,e]

我们看到这个数组中只有a和b出现了一次,其他的元素都出现了2次。如果我们把数组中的所有元素全部都异或一遍,也就是下面这样

a^e^f^h^b^f^h^e

因为异或具有交换律,我们可以把它整理成

a^b^(f^f)^(h^h)^(e^e)

结果就是a^b^0^0^0=a^b

因为a和b是不相等的,所以他俩的异或结果不可能是0,只要不为0,那么这个结果转化为二进制的时候肯定有1。关于异或运算有下面几个规律

1^1=0;

1^0=1;

0^1=1;

0^0=0;

我们看到结果为1的要么是0和1异或,要么是1和0异或。也就是说我们可以根据a和b某一位是否是0和1来把数组分为两组,并且a和b都不在同一组

举个例子,比如数组

[12,13,14,17,14,12]

那么他们异或的结果就是13^17

499,位运算解只出现一次的数字 III

我们看到异或结果最右边的1,也就是红色部分,根据这个位置是0还是1把原数组分为两组,那么13和17肯定不在同一组。那么每组就变成了只有一个数字出现一次,其他数字都出现两次。然后我们就可以使用494,位运算解只出现一次的数字的方式来解了。代码如下

 1public int[] singleNumber(int[] nums) { 2    int bitmask = 0; 3    //把数组中的所有元素全部都异或一遍 4    for (int num : nums) { 5        bitmask ^= num; 6    } 7    //因为异或运算的结果不一定都是2的n次幂, 8    //在二进制中可能会有多个1,为了方便计算 9    //我们只需保留其中的任何一个1,其他的都10    //让他变为0,这里保留的是最右边的111    bitmask &= -bitmask;12    int[] rets = {0, 0};13    for (int num : nums) {14        //然后再把数组分为两部分,每部分在15        //分别异或16        if ((num & bitmask) == 0) {17            rets[0] ^= num;18        } else {19            rets[1] ^= num;20        }21    }22    return rets;23}

上面的位运算bitmask &= -bitmask;表示的是把bitmask二进制中最右边的1保留,其他位置全部变为0,随便找个数据打印一下

499,位运算解只出现一次的数字 III

再来看一下运算结果

499,位运算解只出现一次的数字 III

总结

这题不是很难,但做这题需要对异或运算熟练掌握才行。

499,位运算解只出现一次的数字 III

469,位运算求最小的2的n次方

451,回溯和位运算解子集

425,剑指 Offer-二进制中1的个数

417,BFS和DFS两种方式求岛屿的最大面积

499,位运算解只出现一次的数字 III

长按上图,识别图中二维码之后即可关注。

如果觉得有用就点个"赞"吧

本文分享自微信公众号 - 数据结构和算法(sjjghsf)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Easter79 Easter79
3年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这