LeetCode 260. Single Number III
2021/7/28 6:05:50
本文主要是介绍LeetCode 260. Single Number III,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
题目描述
题目链接
思路
原始题目其实可以扩展成:
一个数组中有两种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这两种数
解法也是一样。
先看一个更简单的题目:
如果一个数组中只有一个数出现了奇数次,其他数都是偶数次,如何找到这个出现了奇数次个数的数
解法是通过异或计算,把所有数求异或值,最后剩下的数就是那个出现了奇数次的数,因为出现偶数次的数通过异或计算都抵消了。
那么回到原题目:
一个数组中有两种数出现了奇数次,其他数都出现了偶数次
我们假设出现了奇数次的数是a和b,如果把数组所有数都异或一下,最后的结果一定是:
a^b
因为a和b是两种不同的数,所以 a^b
的结果一定不等于0。
所以:
a^b
的结果如果转换成二进制的话,一定有某位是1。我们假设a^b
转换成二进制后最右侧位置的1在i位置,由此可以得出一个结论:
a和b的二进制在i位置一定一个为0,一个为1
不妨假设a的i位置为0,b的i位置为1。
此外,容易得知,整个数组中的数,i位置为0的数除了a以外,其他数一定有偶数个,
i位置为1的数除了b之外,其他数一定有偶数个。
那么我们可以只对i位置为1的数求异或,最后得到的值一定是b,然后通过
b^(a^b) = a
可以得到a的值。
最后只剩下一个问题,那么如何求一个数最右侧的1呢?
假设 某个数x二进制为:
00010010
其最右侧的1是:
00000010
算法是:x & ((~x) + 1) 或者 x & (-x)
上述中
a^b
的最右侧1就是:
(a^b) & (~(a^b) + 1)
用这个值去 & 数组中每个值,如果为1,说明i位置是1,如果是0说明i位置是0
完整算法
public class LeetCode_0260_SingleNumberIII { public static int[] singleNumber(int[] arr) { int eor = 0; for (int n : arr) { eor ^= n; } // 假设出现奇数次的两种数为 a和b // eor = a ^ b // 获取最右侧的1 int a = 0; int rightOne = eor & ((~eor) + 1); for (int n : arr) { if ((n & rightOne) == 0) { a ^= n; } } int b = a ^ eor; return new int[]{a, b}; } }
更多
算法和数据结构笔记
参考资料
- 程序员代码面试指南(第2版)
- 算法和数据结构基础班-左程云
- 极客时间-数据结构与算法之美-王争
- 算法(第四版)
这篇关于LeetCode 260. Single Number III的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享
- 2024-11-23oss直传有什么好处?-icode9专业技术文章分享
- 2024-11-23如何将oss直传封装成一个组件在其他页面调用时都可以使用?-icode9专业技术文章分享
- 2024-11-23怎么使用laravel 11在代码里获取路由列表?-icode9专业技术文章分享
- 2024-11-22怎么实现ansible playbook 备份代码中命名包含时间戳功能?-icode9专业技术文章分享