LeetCode Medium 260 找单独的数III Python

75 篇文章 0 订阅
72 篇文章 0 订阅

    算法:bit位运算法

    思路:

        首先联想136题中异或运算XOR的作用

        N^0 = N

            N^N = 0

            A^B^A = (A^A)^B = 0^B = B

        但是本题中要找两个数,那么就可以想一下,可以依照某种规则,将数组中的元素划分为两组,在每一组中寻找那个单独的目标x和y

 

            一个理想的方式就是根据某一位是0还是1来划分,因为二进制下,不论任何数,某一位一定不是0就是1,自然就分成两组了

        所以可以先将所有元素异或xor一遍,得到一个bit,因为重复的元素N^N=0,所以最后的bit一定=X^Y,bit = X^Y,这个bit中

        的每一位都标识了这个位置上X,Y的取值是否相同

            如bit = 101,则代表X,Y的第一位不同,第二位相同,第三位不同。

            那么就可以根据bit来将元素划分为两组,且X,Y一定分别在其中一组中,取bit的某一位的1,其他位为0。

            一种简单的方式就是bit&-bit,就会取出最末尾的1,并且其他位置为0,以此为依据进行分组

            随后再次遍历数组,

            如果num&bit == 0,说明num这一位是0,划分到A组,A组内元素也要异或来运算取出重复元素,剩下的就是单独的那个

        不重复数字

            否则划分到B组,也是进行异或运算

            最后经历两次遍历后就可以求出这两个分别的值


    假设数组中两个不同的数字为 A 和 B;

        1. 通过遍历整个数组并求整个数组所有数字之间的 XOR,根据 XOR 的特性可以得到最终的结果为 AXORB = A XOR B;

        2. 通过某种特定的方式,我们可以通过 AXORB 得到在数字 A 和数字 B 的二进制下某一位不相同的位;因为A 和 B 是不相同的,

        所以他们的二进制数字有且至少有一位是不相同的。我们将这一位设置为 1,并将所有的其他位设置为 0,我们假设我们得到的这

        个数字为 bitFlag;

        3. 那么现在,我们很容易知道,数字 A 和 数字 B 中必然有一个数字与上 bitFlag 为 0;因为bitFlag 标志了数字 A 和数字 B

        中的某一位不同,那么在数字 A 和 B 中的这一位必然是一个为 0,另一个为 1;而我们在 bitFlag 中将其他位都设置为 0,那么该

        位为 0 的数字与上 bitFlag 就等于 0,而该位为 1 的数字与上 bitFlag 就等于 bitFlag

        4.现在问题就简单了,我们只需要在循环一次数组,将与上 bitFlag 为 0 的数字进行 XOR 运算,与上 bitFlag 不为 0 的数组进

        行独立的 XOR 运算。那么最后我们得到的这两个数字就是 A 和 B。

    复杂度分析:

        时间:ON,两次ON遍历

        空间:O1,常数级

def singleNumber(nums):

    bit = 0

    for num in nums:

        bit ^= num

    bit &= -bit

    #或者bit =bit &(~(bit-1))

    ans = [0, 0]

    for num in nums:

        if num & bit == 0:

            ans[0] ^= num

        else:

            ans[1] ^= num

    return ans
def singleNumber1(self, nums):

    """

    算法:哈希表

    思路:

        统计一下,统计值==1的加入答案

    复杂度分析:

        时间:ON,

        空间:ON

    """

    record = {}

    result = []

    for num in nums:

        record.setdefault(num, 0)

        record[num] += 1

    for k, v in record.items():

        if v == 1:

            result.append(k)

    return result

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值