【LeetCode】 338. Número de bits

1. Título

Dado un número entero no negativo num . Para cada dígito i en el rango de 0 ≤ i ≤ num , cuente el número de 1 en su número binario y devuélvalos como una matriz.

Ejemplo 1:

输入: 2
输出: [0,1,1]

Ejemplo 2:

输入: 5
输出: [0,1,1,2,1,2]

Avanzado:

  • Es muy fácil dar una solución con una complejidad temporal de O (n * sizeof (integer)) . Pero, ¿puede hacerlo con un escaneo en tiempo lineal O (n)?
  • La complejidad espacial del algoritmo requerido es O (n) .
  • ¿Puede refinar aún más la solución? Se requiere que no se utilicen funciones integradas (como __builtin_popcount en C ++) en C ++ o cualquier otro lenguaje para realizar esta operación.

Dos, resolver

1. Violencia

Ideas:

Realice el cálculo de bits en cualquier número x (0 <= x <= num). Llame a la función de biblioteca directamente aquí, por supuesto, también puede escribir usted mismo.

Código:

class Solution {
    
    
    public int[] countBits(int num) {
    
    
        int[] cnt = new int[num+1];
        for (int i=0; i<=num; i++) {
    
    
            cnt[i] = Integer.bitCount(i);
        }
        return cnt;
    }
}

Complejidad de tiempo: O (n) O (n)O ( n ) , bitCount () se puede obtener mediante 5 operaciones, el código fuente se puede ver:191. El número de bits 1
complejidad del espacio: O (n) O (n)O ( n )

2. Turno general

Ideas:

Para cualquier número i, su representación binaria es el número cnt de 1, y existe tal relación: cnt (i) = cnt (i / 2) + i% 2.

Bajo simple entendimiento:

Si x = = 2 y + 0 x == 2y + 0X==2 y+0, 则cnt (x) = = cnt (y) cnt (x) == cnt (y)c n t ( x )==c n t ( y )
x = = 2 y + zx == 2y + zX==2 y+z, 则cnt (x) = = cnt (y) + cnt (z) cnt (x) == cnt (y) + cnt (z)c n t ( x )==c n t ( y )+c n t ( z ) .

Donde z = x% 2 z = x \% 2con=x % 2zz¿Por qué z es igual a este valor? Ahora pon y en binario, luegoxxx y y y se desplaza a la izquierda como un todo, y luego al final eszzz , dos posibilidades, 0 o 1, usexx% 2x significa eso. Luego, enumere los números, las representaciones binarias y el número de 1 a continuación para su verificación y comprensión.

x    二进制    1个数
0     0        0
1     1        1
2     10       1
3     11       2
4     100      1
5     101      2
6     110      2
7     111      3
8     1000     1
9     1001     2
10    1010     2
11    1011     3
12    1100     2
13    1101     3
14    1110     3
15    1111     4
16    10000    1

Código: Versión 1.

class Solution {
    
    
    public int[] countBits(int num) {
    
    
        int[] cnt= new int[num+1];
        for (int i=0; i<=num; i++) {
    
    
            cnt[i] = cnt[i/2] + i%2;
        }
        return cnt;
    }
}

Código: Versión 2, reemplazada por operación de bits, que puede ser más rápida en operación.

class Solution {
    
    
    public int[] countBits(int num) {
    
    
        int[] cnt= new int[num+1];
        for (int i=0; i<=num; i++) {
    
    
            cnt[i] = cnt[i>>1] + (i&1);
        }
        return cnt;
    }
}

Complejidad de tiempo: O (n) O (n)O ( n )
complejidad espacial: O (n) O (n)O ( n )

3. Operación de bits

Ideas:

因为 :i & (i - 1) i \ & (i-1)yo & ( yo-1 ) Rol: ClaroiiEl último 1 de i .
Entonces:iii 1 的 个数 ==i & (i - 1) i \ & (i-1)yo & ( yo-1 ) Número de 1 + 1

Código:

class Solution {
    
    
    public int[] countBits(int num) {
    
    
        int[] cnt= new int[num+1];
        for (int i=1; i<=num; i++) {
    
    
            cnt[i] = cnt[i&(i-1)] + 1;
        }
        return cnt;
    }
}

Complejidad de tiempo: O (n) O (n)O ( n )
complejidad espacial: O (n) O (n)O ( n )

4. Planificación dinámica

Ideas:

analizar de la siguiente manera:

Index   : 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
num of 1: 0 1 1 2 1 2 2 3 1 2 2  3  2  3  3  4

由上得出:
dp[0] = 0;
dp[1] = dp[0] + 1;
dp[2] = dp[0] + 1;
dp[3] = dp[1] +1;
dp[4] = dp[0] + 1;
dp[5] = dp[1] + 1;
dp[6] = dp[2] + 1;
dp[7] = dp[3] + 1;
dp[8] = dp[0] + 1;

dp[1] = dp[1-1] + 1;
dp[2] = dp[2-2] + 1;
dp[3] = dp[3-2] +1;
dp[4] = dp[4-4] + 1;
dp[5] = dp[5-4] + 1;
dp[6] = dp[6-4] + 1;
dp[7] = dp[7-4] + 1;
dp[8] = dp[8-8] + 1;

dp[index] = dp[index - offset] + 1;

Oye, la ley es realmente difícil de resumir, porque el desplazamiento de la variable independiente interna también está cambiando. Estudiémoslo para obtener una pista más adelante.

Código:

public int[] countBits(int num) {
    
    
    int result[] = new int[num + 1];
    int offset = 1;
    for (int index = 1; index < num + 1; ++index){
    
    
        if (offset * 2 == index){
    
    
            offset *= 2;
        }
        result[index] = result[index - offset] + 1;
    }
    return result;
}

Complejidad de tiempo: O (n) O (n)O ( n )
complejidad espacial: O (n) O (n)O ( n )

Tres, referencia

1. Solución Java de tres líneas
2. Cómo manejamos esta pregunta en la entrevista [Proceso de pensamiento + solución DP]
3. Fácil comprensión de DP y Bit Solución Java
4, recursividad Java O (n) tiempo O (1) espacio extra 4ms
5. Conteo de bits
6, conocimientos básicos de operaciones con bits

Supongo que te gusta

Origin blog.csdn.net/HeavenDan/article/details/108753304
Recomendado
Clasificación