Sword refers to offer (C++)-JZ56: Two numbers that appear only once in the array (algorithm-bit operation)

Author: Zhai Tianbao Steven
Copyright statement: The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source

Title description:

In an integer array, except for two numbers that only appear once, all other numbers appear twice. Please write a program to find these two numbers that appear only once.

Data range: array length 2≤n≤1000, size of each number in the array 0<val≤1000000
requirements: space complexity O(1), time complexity O(n)

Tip: Sort in non-descending order when outputting.

Example:

enter:

[1,4,1,6]

return value:

[4,6]

illustrate:

Returns the smaller number first   

Problem-solving ideas:

This question examines bit operations. Two ways of solving the problem.

1) Law of Violence

       Use a hash table to record the frequency of occurrence, and output the number with a frequency of 1. The space complexity of this method does not meet the requirements of the title.

2) XOR operation

       The XOR operation means that two numbers are equal to 0 and different to 1. Because except the number you are looking for appears once, other numbers appear twice, so after these numbers are XORed, according to its characteristics, the repeated numbers are offset, and only the number that appears once is retained.

       Such as 4^1^2^1^2. 4 is 100, 1 is 001, 2 is 010, 4^1 gets 101, then ^2 gets 111, then ^1 gets 110, and then ^2 gets 100, which is 4.

       Then if there are two numbers that appear once, the result is equivalent to the XOR of these two numbers. For example, 4^1^2^1^2^3, the final result is 111, which is 4^3.

       This topic requires the output of these two numbers, so how to separate 111? 4 and 3, if a certain bit is not the same, the bit of the XOR result is 1. We define t starting from 001, and operate t with 111 to find which bit appears 1 for the first time; the far right of 111 is 1 , indicating that at the position of 00x, the number 4 and 3 are different; traverse again, and classify all the data according to the number of this bit, so that two groups can be obtained. The group with the number 1 is 3, and the group with the number 0 The group result is 4.

       It has to be said that this topic is tailor-made for this solution. . . Each condition perfectly matches emm

Test code:

1) Law of Violence

class Solution {
public:
    // 寻找出现一次的数字
    vector<int> FindNumsAppearOnce(vector<int>& nums) {
        unordered_map<int,int> um;
        vector<int> result;
        // 遍历数组
        int size = int(nums.size());
        for(int i = 0; i < size; ++i){
            um[nums[i]]++;
        }
        // 寻找出现频率为1的数
        for(int i = 0; i < size; ++i){
   
   {
            if(um[nums[i]] == 1){
                result.emplace_back(nums[i]);
            }
        }}
        // 按大小顺序输出
        if(result[0] < result[1]){
            return result;
        }
        else{
            return { result[1], result[0] };
        }
    }
};

2) XOR operation

class Solution {
public:
    // 寻找出现一次的数字
    vector<int> FindNumsAppearOnce(vector<int>& nums) {
        vector<int> result{ 0, 0};
        // 遍历数组进行异或运算
        int temp = 0;
        int size = int(nums.size());
        for(int i = 0; i < size; ++i){
            temp ^= nums[i];
        }
        // 找到两个数不相同的第一位
        int t = 1;
        while((t & temp) == 0){
            t <<= 1;
        }
        // 再次遍历,将t位为1的数归为1组,为0的数归为1组,这样两组的异或运算得到的结果就是两个不重复数
        for(int i = 0; i < size; ++i){
            if((t & nums[i]) == 0){
                result[0] ^= nums[i];
            }
            else{
                result[1] ^= nums[i];
            }
        }
        // 按大小顺序输出
        if(result[0] < result[1]){
            return result;
        }
        else{
            return { result[1], result[0] };
        }
    }
};

Guess you like

Origin blog.csdn.net/zhaitianbao/article/details/132278174