Sword se refiere a la oferta (C++) -JZ15: el número 1 en binario (operación de algoritmo-bit)

Autor: Zhai Tianbao Steven
Declaración de derechos de autor: Los derechos de autor pertenecen al autor. Para reimpresión comercial, comuníquese con el autor para obtener autorización. Para reimpresión no comercial, indique la fuente

Descripción del Título:

Ingrese un número entero n y genere el número de unos en la representación binaria de 32 bits del número. Los números negativos se expresan en complemento a dos.

Rango de datos: −2^31<=n<=2^31−1

Es decir, el rango es: −2147483648<=n<=2147483647

Ejemplo:

ingresar:

10

valor de retorno:

2

ilustrar:

La representación binaria de 32 bits de 10 en decimal es 0000 0000 0000 0000 0000 0000 0000 1010, con dos unos.

Ideas para resolver problemas:

Esta pregunta examina las operaciones de bits. Tres formas de resolver problemas.

1) Comparación cíclica bit a bit

       Para un ciclo violento basta con contar el 1 de cada bit.

2) Fórmula de operación de bits n&(n-1)

       La fórmula de operación de bits n&(n-1) puede cambiar el 1 más a la derecha del número a 0. Por ejemplo, 1011 es 1010 después de restar uno y 1010 se obtiene mediante la operación AND; otro ejemplo es 1010, que es 1001 después de restar uno y 1000 se obtiene mediante la operación AND.

       Utilice esta propiedad para realizar un bucle, cuando n sea 0, simplemente salga del bucle y deje de contar.

3) Divide y vencerás

       Tome el número A de 32 bits como ejemplo, 1111 1111 1111 1111 1111 1111 1111 1111. Utilizando la idea de divide y vencerás para resolver problemas, a continuación te mostrará el proceso de divide y vencerás paso a paso.

3.1) dividido en 16 grupos

       Los 32 bits son un grupo de dos dígitos, establezca 16 grupos de 01 y luego 16 grupos de 10.

       0x55555555 = 0101 0101 0101 0101 0101 0101 0101 0101

       0xaaaaaaaa = 1010 1010 1010 1010 1010 1010 1010 1010

       Y la operación con el número A puede obtener el número 1 en cada grupo, por ejemplo, 11 y 01 obtienen 01, 11 y 10 obtienen 10, y luego 10 se desplaza 1 a la derecha para convertirse en 01, 01+01 obtiene 10, que es 2, que es 11 El número de 1.

       Después del cálculo anterior, el número A se convierte en A1: 1010 1010 1010 1010 1010 1010 1010 1010.

3.2) dividido en 8 grupos

       El de 32 bits es un grupo de cuatro, establezca 8 grupos de 0011 y luego 8 grupos de 1100.

       0x33333333 = 0011 0011 0011 0011 0011 0011 0011 0011

       0xcccccccc = 1100 1100 1100 1100 1100 1100 1100 1100

       Y la operación con el número A1 puede obtener el número 1 en cada grupo, por ejemplo, 1010 y 0011 obtienen 0010, 1010 y 1100 obtienen 1000, luego 1000 se desplaza 2 a la derecha para convertirse en 0010, 0010+0010 obtiene 0100, que es 4. , que es 1111 El número de 1. Los estudiantes inteligentes han descubierto el patrón aquí, que puede considerarse como dos conjuntos de números de dos dígitos combinados en un conjunto de números de cuatro dígitos.

       Después del cálculo anterior, el número A1 se convierte en A2: 0100 0100 0100 0100 0100 0100 0100 0100.

3.3) dividido en 4 grupos

       El de 32 bits es un grupo de ocho bits, configura 4 grupos de 0000 1111 y luego 4 grupos de 1111 0000.

       0x0f0f0f0f = 0000 1111 0000 1111 0000 1111 0000 1111

       0xf0f0f0f0 = 1111 0000 1111 0000 1111 0000 1111 0000

       Y la operación con el número A2 puede obtener el número 1 en cada grupo, como 0100 0100 y 0000 1111 para obtener 0000 0100, 0100 0100 y 1111 0000 para obtener 0100 0000, luego 0100 0000 desplazamiento a la derecha 4 se convierte en 0000 0100, 0000 0 100 +0000 0100 obtiene 0000 1000 que es 8, que es el número de 1 en 1111 1111. El resultado final de cada grupo de números es en realidad el número de unos en el grupo de números.

       Después del cálculo anterior, el número A2 se convierte en A3: 0000 1000 0000 1000 0000 1000 0000 1000.

3.4) dividido en 2 grupos

       Los 32 bits se configuran como un grupo de dieciséis bits, se configuran 2 grupos de 0000 0000 1111 1111 y luego 2 grupos de 1111 1111 0000 0000.

       0x00ff00ff = 0000 0000 1111 1111 0000 0000 1111 1111

       0xff00ff00 = 1111 1111 0000 0000 1111 1111 0000 0000

       Y la operación con el número A3 puede obtener el número 1 en cada grupo, como 0000 1000 0000 1000 y 0000 0000 1111 1111 para obtener 0000 0000 0000 1000,0000 1000 0000 1000 y 1111 1111 0000 00 00 para obtener 000 0 1000 0000 0000 , entonces 0000 1000 0000 0000 desplazado a la derecha en 8 se convierte en 0000 0000 0000 1000, 0000 0000 0000 1000+0000 0000 0000 1000 para obtener 0000 0000 0001 0000 que es 16, que es el número de 1 en 1111 1111 1111 1111 .

       Después del cálculo anterior, el número A3 se convierte en A4: 0000 0000 0001 0000 0000 0000 0001 0000.

3.5) Dividir en 1 grupo

       32 bits como conjunto.

       0x0000ffff = 0000 0000 0000 0000 1111 1111 1111 1111

       0xffff0000 = 1111 1111 1111 1111 0000 0000 0000 0000

       La operación Y con el número A4 puede obtener el número de unos en cada grupo, es decir, 0000 0000 0001 0000 más 0000 0000 0001 0000 es igual a 0000 0000 0010 0000, que es 32.

       La razón por la que se utiliza este número A es porque este número se puede obtener intuitivamente según la lógica de este método.

       Después del cálculo anterior, el número A4 se convierte en A5: 0000 0000 0000 0000 0000 0000 0010 0000. Ese es el resultado final.

Código de prueba:

1) Comparación cíclica bit a bit

class Solution {
public:
    // 1的个数
    int  NumberOf1(int n) {
        int count = 0;
        //遍历32位
        for(int i = 0; i < 32; ++i){
            //按位比较
            if((n & (1 << i)) != 0)   
                count++;
        }
        return count;
     }
};

2) Fórmula de operación de bits n&(n-1)

class Solution {
public:
    // 1的个数
    int NumberOf1(int n) {
        int count = 0;
        // 当n为0时停止比较
        while(n){  
            n &= n - 1;
            count++;
        }
        return count;
     }
};

3) Divide y vencerás

class Solution {
public:
    // 1的个数
    int NumberOf1(int n) {
        int temp = n;
 
        // 0x55555555 = 0101 0101 0101 0101  0101 0101 0101 0101
        // 0xaaaaaaaa = 1010 1010 1010 1010  1010 1010 1010 1010
        temp = (temp & 0x55555555) + ((temp & 0xaaaaaaaa) >> 1);
 
        // 0x33333333 = 0011 0011 0011 0011  0011 0011 0011 0011
        // 0xcccccccc = 1100 1100 1100 1100  1100 1100 1100 1100
        temp = (temp & 0x33333333) + ((temp & 0xcccccccc) >> 2);
 
        // 0x0f0f0f0f = 0000 1111 0000 1111  0000 1111 0000 1111
        // 0xf0f0f0f0 = 1111 0000 1111 0000  1111 0000 1111 0000
        temp = (temp & 0x0f0f0f0f) + ((temp & 0xf0f0f0f0) >> 4);
 
        // 0x00ff00ff = 0000 0000 1111 1111  0000 0000 1111 1111
        // 0xff00ff00 = 1111 1111 0000 0000  1111 1111 0000 0000
        temp = (temp & 0x00ff00ff) + ((temp & 0xff00ff00) >> 8);
 
        // 0x0000ffff = 0000 0000 0000 0000  1111 1111 1111 1111
        // 0xffff0000 = 1111 1111 1111 1111  0000 0000 0000 0000
        temp = (temp & 0x0000ffff) + ((temp & 0xffff0000) >> 16);
        return temp;
     }
};

Supongo que te gusta

Origin blog.csdn.net/zhaitianbao/article/details/131892751
Recomendado
Clasificación