[Java basic knowledge] several common bit operations

1. Determine the odd and even number

If a number n is expressed as a binary number, we only need to determine whether the last binary digit is 1 or 0. If it is 1, it represents an odd number, otherwise it is an even number. code show as below:

if(n & 1 == 1){
    // n是奇数
}

2. Exchange two numbers

x = x ^ y; // (1)
y = x ^ y; // (2)
x = x ^ y; // (3)

We all know that the result of the exclusive OR of two identical numbers is 0, that is, n ^ n = 0, and any number is equal to itself after being XORed with 0, that is, n ^ 0 = n.

So we substitute x in (1) into x in (2), there are: y = x ^ y = (x ^ y) ^ y = x ^ (y ^ y) = x ^ 0 = x The value is assigned to y.

For (3), the derivation is as follows: x = x ^ y = (x ^ y) ^ x = (x ^ x) ^ y = 0 ^ y = y, so the value of y is assigned to x.

The exclusive OR operation supports the commutative and associative laws of operations.

3. Find the number that is not repeated

Give you a set of integer data. Among these data, one of the numbers appears only once, and the other numbers appear twice. Let you find a number

Many people may use a hash table to store this question. Each time it is stored, the number of occurrences of a certain number is recorded, and finally the hash table is traversed to find the number of occurrences that only occur once. The time complexity of this method is O(n), and the space complexity is also O(n).

In fact, this problem can also be bitwise arithmetic. We can XOR all the integers. Since the result of the XOR of two identical numbers is 0, the result of the XOR of a number with 0 is itself, so The result of the exclusive OR is the number that appears only once. For example, this set of data is: 1, 2, 3, 4, 5, 1, 2, 3, 4. Five of them appear only once, and the others appear twice. XOR all of them. The result is as follows:

1 ^ 2 ^ 3 ^ 4 ^ 5 ^ 1 ^ 2 ^ 3 ^ 4 = (1 ^ 1) ^ (2 ^ 2) ^ (3 ^ 3) ^ (4 ^ 4) ^ 5 = 0 ^ 0 ^ 0 ^ 0 ^ 5 = 5

code show as below:

int find(int[] nums){
    int tmp = nums[0];
    for(int i = 1;i < nums.length; i++)
        tmp ^= arr[i];
    
    return tmp;
}

4, 2 to the nth power

Solve to the nth power of 2, and cannot use the pow function that comes with the system

Many people who see this question may think that it is enough to multiply n 2s. If you do this, the time complexity is O(n). So how do you do it with bit operations?

For example, n = 13, the binary number of n is 1101, then the 13th power of 2 can be broken down as: 2 ^ 1101 = 2 ^ 0001 * 2 ^ 0100 * 2 ^ 1000. We can read 1101 bit by bit through & 1 and >>1. When it is 1, the multiplier represented by this bit is multiplied to the final result. The final code is as follows:

int pow(int n) {
    int sum = 1;
    int tmp = 2;
    while(n != 0) {
        if(n & 1 == 1)
            sum *= tmp;
        
        temp *= temp;
        n >>= 1;
    }
    return sum;
}

5. Find the largest power of 2 exponent not greater than N

For example, N = 19, then the conversion to binary is 00010011 (here for convenience, I use 8-bit binary to represent). Then the number we are looking for is to keep the leftmost 1 in the binary, and all the subsequent 1s become 0 . That is, our target number is 00010000. So how to get this number? The corresponding solution is as follows:

1. Find the leftmost 1 and change all 0s to the right into 1

2. Add 1 to the obtained value, you can get 00100000, that is, 000111111 + 1 = 00100000.

3. Move the obtained 00100000 one place to the right to get 00010000, that is, 00100000 >> 1 = 00010000.

So the question is, how can I get the 0 after the leftmost 1 in the first step?

code show as below:

n |= n >> 1;
n |= n >> 2;
n |= n >> 4;

It can be obtained by shifting n to the right and doing an OR operation. Let me explain. Let’s assume that the leftmost 1 is at the k-th position in the binary digits (counting from left to right). After shifting n to the right by one place, the k+1-th position in the result must also be 1. , And then do an OR operation on the result of n and the right shift, then the kth and k + 1 digits of the result obtained must be 1; in the same way, again shift n to the right by two bits, then the kth digit in the result obtained +2 and the k+3th place must be 1, and then do the OR operation again, then you can get the kth, k+1, k+2, k+3 are all 1, and so on...

The final code is as follows:

int findN(int n){
    n |= n >> 1;
    n |= n >> 2;
    n |= n >> 4;
    n |= n >> 8 // 整型一般是 32 位,上面我是假设 8 位。
    return (n + 1) >> 1;
}

The time complexity of this approach is approximately O(1).

Guess you like

Origin blog.csdn.net/qq_41893274/article/details/112759540