Sword Finger Offer 56-I. The number of times the number appears in the array (C++) Exclusive OR

Except for two numbers in an integer array nums, other numbers appear twice. Please write a program to find these two numbers that only appear once. The required time complexity is O(n), and the space complexity is O(1).

Example 1:

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

Example 2:

输入:nums = [1,2,10,4,1,4,3,3]
输出:[2,10][10,2]

Limit:
2 <= nums.length <= 10000

Grouped XOR

Ideas

Let us first consider a simpler question:
if all numbers except one number appear twice, then how to find the number that appears once?
The answer is simple: all members can perform XOR operation. Consider the nature of the XOR operation: For each bit of the two operands, the same result is 00, and the different result is 11. Then in the calculation process, all the digits of the number appearing in pairs will be offset to 00, and the final result is the number that appears once.
So how does this method extend to find two numbers that appear once?
If we can divide all numbers into two groups, so that:
two numbers that appear only once are in different groups; the
same numbers will be grouped into the same group.

Then XOR the two groups separately to get the two numbers of the answer. This is the key to solving this problem.

Insert picture description here

algorithm

1. Perform an XOR on all numbers first, and get the XOR value of two numbers that appear once.
2. Find any bit that is 1 in the XOR result.
3. Group all the numbers according to this bit.
4. Perform XOR operation in each group to get two numbers.

class Solution {
    
    
public:
    vector<int> singleNumbers(vector<int>& nums) {
    
    
        int ret = 0;
        for (int n : nums)
            ret ^= n;//先对所有数字进行一次异或,得到两个出现一次的数字的异或值。
        int div = 1;
        while ((div & ret) == 0)//(div & ret) == 1时候跳出来,选取的是「不为 0 的最低位」
            div <<= 1;
        int a = 0, b = 0;
        for (int n : nums)
            if (div & n)//如果该位为 1 就分到第一组,否则就分到第二组」
            //可以知道它们被分进了两组,所以满足了条件 1。
                a ^= n;//在每个组内进行异或操作,得到两个数字。
            else
                b ^= n;
        return vector<int>{
    
    a, b};
    }
};

Complexity analysis

Time complexity: O(n), we only need to traverse the array twice.
Space complexity: O(1), only a constant space is needed to store several variables.

Guess you like

Origin blog.csdn.net/qq_30457077/article/details/114995817