The number i/ii/iii that appears only once in LeetCode

Keywords: C++ Algorithm leetcode

The number i that appears only once

Title Description

Topic analysis

When I first looked at the question of xxxx, I had no idea at all. The method is too inefficient. Later, I saw on the Internet that the solution uses XOR, but I haven't understood what the principle is. Recently, the school is learning "the principle of computer composition", after learning XOR in detail. Suddenly I had a thorough understanding of the problem. The topic analysis is as follows:

First, let's look at the XOR operator
 XOR(^):The same is 0 and the difference is 1
 Operand 1 ^ Operand 2 Result
  0        0       0
  0        1       1
  1        0       1
  1        1       0
  So this mechanism can be well applied to solve this problem. Because the same number is the same in 32 bits, when the same number is XOR, the result will be 32 ratios
  All special bits are 0. The result is the number 0. At the same time, 0 and any number XOR still get that number.
  The details are shown in the figure below:

It is worth noting that the final XOR result is independent of the order of numbers. Because a bit of all numbers is the same as 0 and 1 numbers, the XOR value is certain and independent of order.

Code implementation:

class Solution {
public:
    int singleNumber(vector<int>& nums) {
    	//The final result is saved to variable a
        int a = 0;
        for(size_t i = 0; i<nums.size(); i++)
        	//a exclusive or with each number
            a ^= nums[i];
        //a is the single number
        return a;
    }
};

Number ii that appears only once

Title Description

Topic analysis

Different from the previous question, only one number appears once and the other numbers appear three times. Obviously, we can't use the solution of the previous topic, but the big idea is to operate with special bits. The breakthrough is to think
 What is the difference between the bits of these numbers and the connection. It's easy to imagine that for each number i Bits (1)≤i≤32)For example, some numbers are either 1 or 0. Then put each number
 When 1 of the same bit is counted, the statistical result is either a multiple of 3 or a multiple of 3+1. Moreover, those multiples of 3+1 The bit of must be the bit with the number 1 that appears only once.
For example:

After counting the number of 1 bits of all the numbers, we can filter out which bits of 1 are multiples of 3+1,These bits are 1 bits that appear only once. Then we can get
 This is the only value.

code implementation

class Solution {
public:
    int singleNumber(vector<int>& nums) {
    	//The cout array is used to store statistics on the number of 1 of 32 bits
        int count[32] = {0};
        for(int i=0;i<nums.size();i++)
        {
            for(int j=0;j<32;j++)
            {
            	//Nums [i] &1 gets whether this is 1 or 0
                count[j] += (nums[i]&1);
                //>>Used to get each bit of a number one at a time
                nums[i] = nums[i]>>1;
            }
        }
        int number = 0;
        for(int i=0;i<32;i++)
        {
        	//If it is a multiple of 3 + 1
            if(count[i]%3 == 1)
            {
            	// Number | = (1 < < I) is difficult to understand, which will be explained below
                number |= (1<<i);
            }
        }
        return number;
    }
};

Detailed interpretation of "number | = (1 < < i)": i ranges from 0 to 31, so 1 < < i is to generate different binary numbers in which there is only one 1 and the rest are all 0. In this way, it can be or calculated in sequence with the position that should be 1 in the bit of the result number. Finally, the results are obtained.
As shown in the figure:

Number iii that appears only once

Title Description

Topic analysis

   Do you feel familiar and kind when you see this question. It seems to feel very similar to the first question above. But why is one simple classification and the other medium difficulty classification. Suddenly my heart was cold. Like on
 When I was studying, I looked so familiar with this problem that I just couldn't do it. I've been on this problem card for a long time. I feel that I need to use the idea of the first question, but there are two numbers that only appear once. It's certainly impossible to copy mechanically
 of The key to the first question that you want to transfer is to separate the two numbers that only appear once. Then we can apply the idea of the first question to the two separate groups of numbers, and find two numbers that only appear once
 Therefore, the key lies in how to divide this group of data into two groups, and ensure that the two once occurring numbers are still in two groups respectively.
   There is no doubt that we still need to use their binary to find a breakthrough. If you want to divide them into two groups, you need to find out their differences. That is, for different numbers, their 32 ratios
 The bits cannot be exactly the same, so there must be some bits that are different. According to this condition, we can divide a group of data into two groups, one with the bit of 1 and the other with the bit of 0. At the same time, other pairs appear
 In the number, it is possible that the bit is 1 or 0.. No matter how specific they are, after they are divided into two groups, each group will degenerate into the first question, that is, there is only one number that appears once, and the other numbers are all
 It appears in pairs. Then use the idea of the first question to solve it.
   But how to find that key bit? We can XOR all numbers. Through the previous knowledge, we know that all numbers are exclusive or, the numbers appearing in pairs are all offset, and the rest are only two
 A number that appears once, and then the number generated by their XOR must not be 0, so one of the bits will have a value of 1, which is one of the different bits of the two numbers.

code implementation

class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
    	//val is used to store the results of all digital XORs
        int val;
        for(int j=0;j<nums.size();j++)
            val ^= nums[j];
        //i is used to store the first few bits. The bit is 1
        int i = 0;
        //Find the value of the first few bits of val is 1
        //If it's not 1, enter the cycle, i++
        while(!(1&(val>>i)))
        {
            i++;
        }
        //Create two vector s to store two groups of data
        vector<int> v1;
        vector<int> v2;
        //grouping
        for(int j=0;j<nums.size();j++)
        {
        	//The first i+1 is v1
            if(nums[j]&(1<<i))
                v1.push_back(nums[j]);
            //Put v2 with i+1 being 0
            else
                v2.push_back(nums[j]);
        }
        //Apply the idea of the first question
        int a = 0,b = 0;
        for(int j=0;j<v1.size();j++)
            a ^= v1[j];
        for(int j=0;j<v2.size();j++)
            b ^= v2[j];
        vector<int> ret;
        ret.push_back(a);
        ret.push_back(b);
        return ret;
    }
};

summary

The answer ideas of these three questions are the same. They all use bit operation. Because numbers are completely unknown, we need to rely on their binary numbers to find the similarities and differences between numbers. The binary numbers of different numbers must be different, and the binary numbers of the same number must be the same.
At the same time, what we need to master is. The same number XOR is 0,0 and any number XOR is itself. This tip is also used to exchange two numbers for temporary variables that are not applicable.
Well, that's the end of this article. If there are any optimizations and improvements in the ideas and code, please post them in the comment area or directly write to me. Let's learn and make progress together!

Posted by taiger on Sun, 05 Sep 2021 11:16:27 -0700