【题目】
一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
示例 1:
输入:nums = [4,1,4,6]
输出:[1,6] 或 [6,1]
示例 2:
输入:nums = [1,2,10,4,1,4,3,3]
输出:[2,10] 或 [10,2]
限制:
2 <= nums.length <= 10000
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-lcof
【思路】
1.将数组所有值异或可以得到目标两个数的异或结果z=x^y(出现两次的数异或后都为0了,不会影响结果)
2.接下来就是把这两个数分离 如果这两个数异或后的位数是1,表示两个数异或结果不同,如果是0,表示相同。
用0001,0010,0100...这类数来依次判断异或后的数最低的一个1位在哪里 最后用m来保存,这个数可以在原数组中区分x和y,
这两个数在这一位不同,那么我们只要遍历原数组中每一个数,【与】这个数就能分开。
3.使用m在原数组中遍历与,结果为0的为一组(包含若干出现2次的数和一个出现1次的数),1的为一组(包含若干出现2次的数和一个出现1次的数)
4.然后在这两组数分别异或,就得到了x和y(出现2次的数异或后为0,不影响结果,只有出现1次数会有影响)
【代码】
class Solution { public int[] singleNumbers(int[] nums) { // 将数组所有值异或可以得到目标两个数的异或结果x^y // 接下来就是把这两个数分离 如果这两个数异或后的位数是1,表示两个数异或结果不同,如果是0,表示相同 // 首先用0001,0010,0100...这类数来依次判断异或后的数最低的一个1位在哪里 最后用m来保存,这个数可以在原数组中区分x和y // 使用m在原数组中遍历,结果为0的为一组(包含若干出现2次的数和一个出现1次的数),1的为一组(包含若干出现2次的数和一个出现1次的数) // 然后在这两组数分别异或,就得到了x和y(出现2次的数异或后为0,不影响结果,只有出现1次数会有影响) int z = 0; int x = 0; int y = 0; for(int num:nums){ z = num^z; } int m = 1; while((z&m)==0){ m = m<<1; } for(int num:nums){ if((num&m)==0){ x^=num; }else{ y^=num; } } return new int[]{x,y}; } }