【Sword Finger Offer】 —— Problemas resueltos por operación de bits


La operación de bit se refiere a la operación de 0 o 1 en cada bit después de representar el número en binario. Hay 5 operaciones en total: AND, OR, XOR, desplazamiento a la izquierda y desplazamiento a la derecha

1. El número de 1s en binario

Requisitos del problema:
implemente una función, ingrese un número entero y genere el número de 1s en la representación binaria del número. Por ejemplo, representar 9 como binario es 1001, y 2 bits son 1. Entonces, si ingresa 9, la función genera 2.

Análisis del problema:
Método 1: puede hacer que un bucle infinito
juzgue el bit más a la derecha en el binario cada vez. Use n & 1 para ver si el resultado es 1, si es 1, significa que el bit más a la derecha del entero es 1, de lo contrario es 0 . Después del juicio, muévase n hacia la derecha.
Pero este método caerá en un bucle infinito si encuentra un número negativo.

Método 2: La eficacia de la solución no es alta
. En el último método, movemos el número n cada vez, pero en este método, nuestra idea es mover el número 1 a la izquierda cada vez. Determinemos si cada bit binario en el número n es 1.
El número de tales ciclos de solución es igual al número de dígitos binarios enteros.

Método 3: La forma más efectiva
Consideremos esta regla: si un número no es 0, habrá al menos un 1 en su representación binaria. Luego, cuando el número n se reduce en 1. Habrá dos casos
: el primero: el lado derecho de n es 1. Después de disminuir en 1, el último bit se convierte en 0 y todos los demás bits permanecen sin cambios.
Inserte la descripción de la imagen aquí
El segundo tipo: el lado derecho de n no es 1. Como se muestra en la figura, el segundo bit cambia de 1 a 0, y el 0 después del segundo bit se convierte en 1. Todos los bits a su izquierda permanecen sin cambios.
Inserte la descripción de la imagen aquí
En resumen: restar 1 de un número entero y realizar una operación AND con el número entero original cambiará el 1 más a la derecha del número entero a 0. Luego, tantos números enteros como 1 hay en el binario de un número entero, tales operaciones se pueden realizar tantas veces.

int NumberofN(int n)
{
	int count = 0;
	while (n)
	{
		n = n & (n - 1);
		count++;
	}
	return count;
}

Segundo, el número de ocurrencias de números en la matriz.

Requisitos del tema:
dos números que aparecen solo una vez en la matriz. Excepto por dos números, una matriz entera aparece dos veces. Escriba un programa para encontrar estos dos números que solo aparecen una vez. La complejidad del tiempo es O (n) y la complejidad del espacio es O (1).

Análisis del problema:
primero obtenga esta pregunta, podemos sentirnos más ignorantes. Pero pensemos de esta manera. Simplifiquemos un poco el problema: en una matriz, solo aparece un número una vez, y los números restantes aparecen dos veces.
De esta manera, podemos usar la propiedad XOR de las operaciones de bits para resolver problemas. ** Debido a que cualquier número XOR mismo es igual a 0, ** entonces los números en la matriz son XOR uno por uno o el número que queda después del final es el número único. Como sigue:
Inserte la descripción de la imagen aquí

Entonces, a continuación, tenemos que pensar en cómo dividir la matriz en dos matrices con un solo número.
Hacemos XOR de cada número de la matriz de principio a fin, luego el resultado final es el resultado XOR de dos números que aparecen solo una vez. Tal como la matriz {2,4,3,6,3,2,5,5}. 4 ^ 6 = 0010
Inserte la descripción de la imagen aquí
Según el cálculo anterior, podemos saber que al menos un bit es 1 en la representación binaria del número resultante. Entonces dividimos la matriz en dos sub-matrices en función de si el penúltimo dígito es 1. La primera matriz es {2,3,6,3,2}. La segunda matriz es {4,5,5}. Luego, haga una XOR de las dos matrices por separado para encontrar que el número que aparece solo una vez en la primera matriz de palabras es 6, y el número que aparece solo una vez en la segunda matriz es 4.

Con el análisis anterior. El siguiente paso es implementar el código.
Primero, encuentre el bit más a la derecha en la representación binaria del número entero.

unsigned int FindFirstBitIs(int num)
{
	int indexBit = 0;
	while( ((num & 1) == 0) && (indexBit < 8 * sizeof(int)))
	{
		num = num >> 1;
		++indexBit;
	}
	return indexBit;
}

Determinemos si el bit indexBit de la derecha en la representación binaria de num es 1

bool IsBit1(int num, unsigned int indexBit)
{
	num = num >> indexBit;
	return (num & 1);
}

Se implementa el código final,
donde los datos son la matriz entrante, num1 y num2 son las dos matrices después de la división

void FindNumsAppearOnce(int data[], int length, int* num1, int* num2)
{
	if (data == nullptr || length < 2)
		return;

	int resultExclusiveOR = 0;//数组中所有数字异或过后的结果
	for (int i = 0; i < length; i++)
	{
		resultExclusiveOR ^= data[i];
	}

	unsigned int indexof1 = FindFirstBitIs(resultExclusiveOR);//找到异或后二进制结果中1的位置

	*num1 = *num2 = 0;
	for (int j = 0; j < length; j++)
	{
		if(IsBit1(data[j],indexof1)//数组中该位置为1的数在num1数组中进行异或,最后异或完剩下的值即为单出来的值
			*num1 ^= data[j];
		else
			*num2 ^= data[j];
	}
}

3. El único número en la matriz que aparece solo una vez

La idea principal:
además de un número que solo aparece una vez en una matriz, otros números aparecen tres veces. Encuentra el número que aparece solo una vez.
Análisis del
problema : Mire más de cerca esta pregunta, descubrimos que tiene muchas similitudes con la pregunta anterior, pero es ligeramente diferente. Si los otros números en la matriz aparecen solo dos veces, entonces XOR puede obtener el número único. Pero ahora han aparecido otros tres números tres veces, y el resultado de XORing tres números idénticos sigue siendo ese número, por lo que las ideas anteriores no son factibles.
A continuación, pensemos en la aritmética de bits.
Supongamos que la matriz es {5,5,5,2}. Sabemos que si un número aparece tres veces, cada bit de su representación binaria también aparece tres veces. Si sumamos cada dígito de la representación binaria de las tres ocurrencias del dígito por separado, entonces la suma de cada dígito se puede dividir por 3 de la siguiente manera:
Inserte la descripción de la imagen aquí
en este momento, sumamos cada dígito de la representación binaria de todos los dígitos Lo
Inserte la descripción de la imagen aquí
que encontraremos Encontramos que si la suma de un cierto dígito es divisible por 3, entonces el número que aparece solo una vez, como 2, en el título, el bit correspondiente en la representación binaria es 0, de lo contrario es 1.
Con lo anterior Leyes, podemos escribir código. Necesitamos una matriz auxiliar de longitud 32 para almacenar la suma de cada bit de la representación binaria.

int FindNumberAppearingOnce(int numbers[], int length)
{
	if (numbers == nullptr || length <= 0)
		throw new std::exception("Invalid input.");

	int bitSum[32] = { 0 };
	//外层循环主要用于遍历数组中的每一个数字
	for (int i = 0; i < length; i++)
	{
		//通过移动bitMask和数字中的每一位进行与操作,判断该位是否为1
		int bitMask = 1;

		//内层循环主要用于遍历该数字中的每一位
		for (int j = 32; j >= 0; j--)
		{
			int bit = numbers[i] & bitMask;
			if (bit & 1 != 0)
				bitSum[j] += 1;
		}
		bitMask << 1;
	}

	//依次输出只出现一次数字的每一位
	int result = 0;
	for (int i = 0; i < 32; i++)
	{
		result = result << 1;//移动每一位
		result += bitSum[i] % 3;//每一位和被3整除的结果即为只出现一次数字的该位
	}
	return result;
}

Cuarto, no sumar, restar, multiplicar y dividir para sumar

Requisitos de título:
escriba una función para encontrar la suma de dos enteros. Se requiere que los cuatro operadores "+", "-", "*" y "/" no se usen en el cuerpo de la función.

Análisis del problema:
antes de analizar este problema, simplifiquemos e imaginemos que es nuestra solución más convencional. Cuando hacemos suma decimal, por ejemplo, obtenemos el resultado 5 + 17 = 22.
En el primer paso, solo agrega los miembros, no los lleva, y el resultado es 12.
El segundo paso es hacer un carry, con un carry de 10 de 5 + 7.
El tercer paso es agregar los dos resultados anteriores 12 + 10 = 22

A continuación, se utiliza el mismo método. Aplicamos este método a la suma binaria y usamos la operación de bits. Por ejemplo, el binario de 5 es 101 más el binario de 7 es 10001.
El primer paso es agregar cada bit independientemente del acarreo. Porque en la operación binaria, 0 + 0 = 0, 1 + 1 = 0; 0 + 1 = 1, 1 + 0 = 1. Curiosamente, encontramos que el resultado de tal adición es exactamente el resultado de XOR.
Inserte la descripción de la imagen aquí
Paso 2: Considere llevar, sabemos que para 0 + 0,0 + 1,1 + 0, no se generará ningún acarreo, solo 1 + 1 generará un acarreo. Operación de bit de analogía, inmediatamente pensamos en la operación. El proceso de acarreo es como realizar una operación AND en estos dos números binarios, y finalmente desplazar el resultado después de la operación AND un bit hacia la izquierda.
Inserte la descripción de la imagen aquí
Paso 3: El proceso de suma aún repite los dos pasos anteriores hasta que no se genera el acarreo. El
Inserte la descripción de la imagen aquí
código se implementa de la siguiente manera :

int Add(int num1, int num2)
{
	int sum, carry;
	do
	{
		sum = num1 ^ num2;
		carry = (num1 & num2) << 1;
		num1 = sum;
		num2 = carry;
	} while (num2 != 0);

	return num1;
}
Publicado 98 artículos originales · ganado elogios 9 · vistas 3651

Supongo que te gusta

Origin blog.csdn.net/qq_43412060/article/details/105359129
Recomendado
Clasificación