面试题56 - I. 数组中数字出现的次数

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

 

题解:

1.整型数组 nums 

2.数字有出现两次和两个出现一次的

3.返回这两个出现一次的

4.时间复杂度是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 <= 10000

 

解题思路:位异或分组

题目对时间开销和空间开销要求都很高,放松条件可以考虑哈希表等其它方法;这里考虑二进制异或运算。

  • 出现两次的数字通过异或两两抵消等于0(二进制异或)

  • 因为成对的两两抵消变0,0^x=x,整个数组异或后,即剩余出现一次的这两个数的异或值

  • 如果异或值某位为1,则最后这两个数一个是1一个是0,依此分组

  • 这样出现两次的相同数一定会被分到一组,这样这两个结果数又被分到了两个组里,比如说a被分到了一组,b被分到了二组;这样每组里除了a和b其它都是出现两次的数

  • 再对每一组都异或一次,这样一组异或后的值就是a(其它两两相同的数异或等于0,而0^a=a)

C/C++题解:

 

class Solution {

public:

    vector<int> singleNumbers(vector<int>& nums) {

        int x = 0;

        for (int val : nums) x ^= val;//整个数组异或一次,剩只出现一次的两个数的异或值

        int flag = x & (-x); //选取最低位分组

        int res = 0; 

        for (int val : nums) {

            if ((flag & val) != 0) {//区分成两组

                res ^= val;}//这里只对一组进行全部异或

        }// 因为一开始x是两个数的异或值,分组后再异或一组找到的是其中的一个数

        //所以第二个数也就是用这两个数的异或结果再异或其中一个

        return {res, x ^ res};}};

Debug结果:

面试题56 - I. 数组中数字出现的次数

Java题解:

class Solution {

    public int[] singleNumbers(int[] nums) {

        int x = 0;

        for (int val : nums) x ^= val;//整个数组异或一次,剩只出现一次的两个数的异或值

        int flag = x & (-x); //选取最低位分组

        int res = 0; 

        for (int val : nums) {

            if ((flag & val) != 0) {//区分成两组

                res ^= val;}//这里只对一组进行全部异或

        }// 因为一开始x是两个数的异或值,分组后再异或一组找到的是其中的一个数

        //所以第二个数也就是用这两个数的异或结果再异或其中一个

        return new int[] {res, x ^ res};}}

Debug结果:

面试题56 - I. 数组中数字出现的次数

Python题解:

class Solution(object):

    def singleNumbers(self, nums):

        """:type nums: List[int]:rtype: List[int] """

        x = 0

        for val in nums: x ^= val #整个数组异或一次,剩只出现一次的两个数的异或值

        flag = x & (-x) #选取最低位分组

        res = 0

        for val in nums:

            if ((flag & val) != 0): #区分成两组

                res ^= val#这里只对一组进行全部异或

        #因为一开始x是两个数的异或值,分组后再异或一组找到的是其中的一个数

        #所以第二个数也就是用这两个数的异或结果再异或其中一个

        return [res, x ^ res]

Debug结果:

面试题56 - I. 数组中数字出现的次数

更多题解算法的聚集地可前往公众号获取

面试题56 - I. 数组中数字出现的次数