这里我将分享几道编程题目,主要使用移位和位操作符进行解答。
我们首先要知道两个数字进行异或操作的时候结果是位0的,即 a ^ a = 0,并且我们还要知道 0 和任何数字异或的结果都是这个数字的本身,即 0 ^ a = a;
不能创建临时变量(第三个变量),实现两个数的交换
既然不能创建变量,那么我们可以尝试从位操作符入手,首先 a ^ b 的结果放入 a 中,再异或 b 就会得到原先 a 的值,把异或的结果放入 b 中, a 异或这个 b 的话,就会得到这个 b 的值。
#include
int main()
{
int a = 5, b = 10;
a = a ^ b; // 注意斜杠后面的 a 和 b 是原先的值
b = a ^ b; // a ^ b ^ b = a ^ 0 = a
a = a ^ b; // a ^ b ^ a = b ^ 0 = b
printf("%d\n%d\n", a, b);
return 0;
}
我们可以使用一个 1 进行左移操作,遍历三十二位 (y因为整型是四个字节就是32个比特位),用计数器count 来记录有多少个 1 ,这样就可以了
#include
int main()
{
int n;
scanf("%d", &n);
int count = 0;
for (int i = 0; i < 32; i++)
{
if (n & (1 << i))
{
count++;
}
}
printf("%d\n", n);
return 0;
}
我们可以使用一个公式就是 n & (n - 1) , 这个公式能帮我们去掉每一位上的 1 ,这样的话,我们就可以用循环来遍历待测的数字的二进制上的每一位。
#include
int main()
{
unsigned int n;
scanf("%d", &n);
int count = 0;
while (n)
{
n = n & (n - 1);
count++;
}
printf("%d\n", n);
return 0;
}
你们猜猜看为什么我要使用unsigned ,因为害怕整型溢出,很简单如果 n 的二进制位是32个1,是个负数,你减去一就会整型溢出,所以为了避免这一种情况出现,我们使用unsigned 来接受 n 的数值。
将数字13的二进制序列的第五位设置为1,之后再改为0.
这道题很简单,对 1 进行移位操作,将结果与13 进行a按位或( | )操作即可。再改为 0 也是一样的,就是将 1 移位操作再按位取反加 ( & )操作即可。
#include
int main()
{
int n = 13;
n = n | (1 << 4);
printf("%d\n", n);
n = n & (~(1 << 4));
printf("%d\n", n);
return 0;
}
在一个整型数组中,只有一个数字出现一次,其他数组都是成对出现的,请找出那个只出现一次的数字。
例如:
数组中有:1 2 3 4 5 1 2 3 4,只有5出现一次,其他数字都出现2次,找出5
我们设置一个 tmp 为0,然后用循环来遍历每一个数字与tmp进行异或,最后打印tmp的值就是那个“单身狗”!
#include
int main()
{
int arr[9] = { 1,2,3,4,5,1,2,3,4 };
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0, tmp = 0;
for (i = 0; i < sz; i++)
{
tmp ^= arr[i];
}
printf("%d\n", tmp);
return 0;
}
一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。
编写一个函数找出这两个只出现一次的数字。
例如:
有数组的元素是:1,2,3,4,5,1,2,3,4,6
只有5和6只出现1次,要找出5和6.
在有了单身狗1 的基础上,我们知道所有数字异或之后就会找到那个落单的数字,但是这道题是有两个落单的数字,那么我们将所有数字进行异或后,得到的结果就是这两个落单的数字异或的结果。既然如此,这个结果能不能进行二次加工来分离这两个数字呢?在二进制的基础上,异或是相同的为0,不同的为1,两个不同的数字必然在某些二进制位是不同的,那么我们就可以将这个结果第几位为 1 作为分界线,来区分这两个数字,我们可以将它们分开来,然后对这两组进行分别异或,就会得到这两个数字。
#include
void Find_Single_Dog(int* p, int n, int *num1, int *num2)
{
int tmp = 0;
int i = 0;
for (i = 0; i < n; i++)
{
tmp ^= p[i];
}
int k = 0;
for (i = 0; i < 32; i++) //找到第几位为1
{
if (tmp & (1 << i))
{
break;
}
}
k = i;
for (i = 0; i < n; i++)
{
if (p[i] & (i << k))
{
*num1 ^= p[i];
}
else
{
*num2 ^= p[i];
}
}
}
int main()
{
int arr[] = { 1,2,3,4,5,1,2,3,4,6 };
int sz = sizeof(arr) / sizeof(arr[0]);
int num1, num2;
num1 = num2 = 0;
Find_Single_Dog(arr, sz, &num1, &num2);
printf("%d\n%d\n", num1, num2);
return 0;
}