【LeetCode】一个整型数组里除两个数字之外,其他数字都出现了两次,请找出这两个只出现一次的数字(数组、分组异或)

题目难度:中等

(1)题目描述

一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。

示例1

输入:nums = [4, 1, 4, 6]

输出:[1, 6] 或 [6, 1]

示例2

输入:nums = [1, 2, 3, 4, 5, 6, 1, 2, 3, 4]

输出:[5, 6] 或 [6, 5]

LeetCode链接:剑指 Offer 56 - I. 数组中数字出现的次数


(2)解题思路:分组异或

  • 先来思考一下这个问题

一个整型数组里出现一次的数只有一个,其他数字都出现了两次,请找出这个只出现一次的数字。

要解决这个问题,利用异或的特性(两数相同异或等于0,0和一个数异或就等于其本身),所以数组中只有一个出现一次的数,那么只需要异或整个数组就可以得到这个只出现一次的数。

  • 回到本题,出现一次的数有两个

假设输入:nums = [1, 2, 3, 4, 5, 6, 1, 2, 3, 4],我们需要从中找到 5 和 6

类比前面问题的解法,异或整个数组,得到的是 5 和 6 的异或结果,显然是不行。

那么我们能不能把要找的这两个数字,分成两组,一组放一个,这样分别异或这两组数,就得到了这两个数字。

  • 分组的要求

1)两个只出现一次的数必须在不同组

2)两个相同的数必须出现在同一组

比如分为(1 3 1 3 5)和(2 4 2 4 6),这样就很容易找到这两个数字了。

  • 如何分组呢?(问题核心)

异或整个数组的结果就是这两个出现一次的数异或的结果,是一定不等于 0 的,那么说明这个异或结果的二进制序列中一定是有 1 的,找到这个 1,我们就可以利用这个来分组

nums = [1, 2, 3, 4, 5, 6, 1, 2, 3, 4],全部异或的结果就是 5 和 6 异或的结果,即 0101 和 0110 异或的结果 0011

0011 中为1 的二进制位表示什么意思呢,分析不难知道,异或相同为 0 ,相异为 1,所以二进制位是 1,就表示 5 和 6 的二进制数在第一、二位上的数是不同的。这就是分组依据。

我们就以第一个为 1 二进制位为分组条件,将数组中第一个二进制位为 1 的数分为一组,第二个二进制位为 0 的数分为另一组,这样就把 5 和 6 成功分到不同的组,而剩下的那些相同的数(1 和 1、2 和 2,3 和 3、4 和 4),因为数值相同,所以它们的第一个二进制位一定是相同的。这样就同时把两个相同的数划分到同一组了。

  • 为了能够更清晰的看到分组情况,我画了一个表格:
数组 二进制序列 第一个二进制位
1 0001 1
1 0001 1
2 0010 0
2 0010 0
3
评论 25
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值