ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

LeetCode 260. Single Number III

2021-07-28 01:00:07  阅读:279  来源: 互联网

标签:int 位置 算法 偶数 eor Single 260 数次 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};
    }
}

更多

算法和数据结构笔记

参考资料

标签:int,位置,算法,偶数,eor,Single,260,数次,III
来源: https://www.cnblogs.com/greyzeng/p/14858425.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有