操作符题目练习

63 阅读4分钟

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,当ab的值过大时可能会溢出。**按位异或 ****^**能很好的解决这个问题,因为其直接操作的是ab的二进制码。(提醒:这种方法只能针对整数交换且可读性不高、效率不高)

代码实现:

#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

132 进制序列:   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;
}

正文完