1 单身狗
在一个整型数组中,只有一个数字出现一次,其他数组都是成对出现的,请找出那个只出现一次的数字。
例如:数组中有:1 2 3 4 5 1 2 3 4,只有5出现一次,其他数字都出现2次,找出5
需要用到的知识:
按位异或 ^ 将其第一操作数的每个位(补码)与其第二操作数的相应位进行比较。如果其中一个操作数中的位为 0,而另一个操作数中的位为 1,则相应的结果位设置为 1(即标记不同)。 否则,将对应的结果位设置为 0。(该运算符的两个操作数必须为整型类型)
按位异或运算有以下有趣的特点:
//1. a ^ a = 0
//2. 0 ^ a = a
//3. 3 ^ 3 ^ 5 = 5
// 3 ^ 5 ^ 3 = 5 即支持交换律
由于数组中除5外其他数字均成对出现,而按位异或运算中相同数字的结果为0,我们可以利用这一特性找出单独的数字。
代码实现:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int Func(int arr[], int len)
{
int ret = 0;
for (int i = 0; i < len; i++)
{
ret ^= arr[i];//对arr数组的每一个值,按位异或
}
return ret;
}
int main()
{
int arr[] = { 1,2,3,4,5,1,2,3,4 };
int len = sizeof(arr) / sizeof(arr[0]);
printf("%d\n", Func(arr, len));
return 0;
}
运行结果:
2 交换两个变量(不创建临时变量)
不允许创建临时变量,交换两个整数的内容
需要用到的知识:
先演示一种方法。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
int a = 1;
int b = 5;
printf("交换前:%d %d\n", a, b);
a = a + b;//可能溢出
b = a - b;//b = (a + b) - b = a
a = a - b;//a = (a + b) - a = b
printf("交换后:%d %d\n", a, b);
return 0;
}
由于存在a = a + b,当a、b的值过大时可能会溢出。**按位异或 ****^**能很好的解决这个问题,因为其直接操作的是a、b的二进制码。(提醒:这种方法只能针对整数交换且可读性不高、效率不高)
代码实现:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
int a = 1;
int b = 5;
printf("交换前:%d %d\n", a, b);
a = a ^ b;
b = a ^ b;//b = (a ^ b) ^ b = a
a = a ^ b;//a = (a ^ b) ^ a = b
printf("交换后:%d %d\n", a, b);
return 0;
}
运行结果:
3 统计二进制中1的个数
写一个函数返回参数二进制中 1 的个数。
比如: 15 0000 1111 4个1
需要用到的知识:按位与&,移位操作符<<、>>
代码实现:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
//法1
int main()
{
int num = 15;
int count = 0;
for (int i = 0; i < 32; i++)
{
if ((num >> i) & 1)
count++;
}
printf("%d\n", count);
return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
//法2
int main()
{
int num = 15;
int count = 0;
while (num)
{
count++;
num = num & (num - 1);//关键点
}
printf("%d\n", count);
return 0;
}
4 二进制位置0或者置1
编写代码将13二进制序列的第5位修改为1 ,然后再改回0
13 的 2 进制序列: 00000000 00000000 00000000 00001101
将第 5 位置为 1 后: 00000000 00000000 00000000 00011101
将第 5 位再置为 0 : 00000000 00000000 00000000 00001101
需要用到的知识:按位与&,按位或|,按位取反~,移位操作符<<、>>
代码实现:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
int a = 13;
a = a | (1 << 4);
printf("%d\n", a);
a = a & ~(1 << 4);
printf("%d\n", a);
return 0;
}
5 打印整数二进制的奇数位和偶数位
获取一个整数二进制序列中所有的偶数位和奇数位,分别打印出二进制序列
需要用到的知识:按位与&,移位操作符<<、>>
代码实现:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
int a = 13;
//13 00000000 00000000 00000000 00001101
//1 00000000 00000000 00000000 00000001
printf("13的二进制偶数位:");
// 0010
for (int i = 31; i >= 0; i-=2)
{
printf("%d ", (a>>i) & 1);
}
printf("\n");
printf("13的二进制奇数位:");
// 0011
for (int i = 30; i >= 0; i -= 2)
{
printf("%d ", (a >> i) & 1);
}
printf("\n");
return 0;
}
6 求两个数二进制中不同位的个数
编程实现:两个int(32位)整数m和n的二进制表达中,有多少个位(bit)不同?
输入例子:1999 2299
输出例子:7
需要用到的知识:按位异或 ^,按位与&,第3题
代码实现:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
int a = 1999;
int b = 2299;
int c = a ^ b;
int count = 0;
while (c)
{
count++;
c = c & (c - 1);
}
printf("%d\n", count);
return 0;
}