前言:昨天晚上做蓝桥杯的时候,发现了一道有意思的题目。在网上查找了关于位运算的运用后,发现很有意思,因此决定把他们记录下来。
异或运算的性质:
任何数字异或它自己都等于0;
0异或任何数,等于任何数;
1异或任何数,等于取反任何数。
下面列出几道题目:
1、异或去重
给定大小为n+1的数组,元素大小在[1 : n]之间,只有一个元素会重复出现两次,找到重复的那个元素。 要求,时间复杂度是O(n),空间复杂度是O(1)。
分析:
原数组大小为n+1,其中有一个元素重复了两次(假设为x),那么将该数组与1-1000的所有数字进行异或,则x出现了3次,其他数字只出现了2次。那么该异或得到得结果便是x!
例如下面这段代码(将1000个数据改成了10个,但道理还是一样的哈):
#include <iostream>
using namespace std;
int main()
{
int a[11] = {1, 2, 3, 4 ,5, 6 ,7 ,8, 9, 10, 3}; //可以看到,在该数组中3出现了两次
int x = 0; //存储重复的数字
for (int i = 0; i < 11; ++i)
{
x = x^a[i]; //先将数组a中的数字全部进行异或
}
for (int i = 1; i < 11; ++i)
{
x = x^i; //将数组a异或后,再与1~10中的数字异或
}
cout << x << endl; //得到重复的这个数字
return 0;
}
类似的更多复杂运用:https://blog.csdn.net/hulamua/article/details/52411446
emmmm补充一道题:leetcode 之 Single Number II
2、交换数值
在面试中,经常会碰到这样一道题:不定义临时变量,交互两个数的值。一般的解法如下:
void exchange(int * a, int * b)
{
*a = *a + *b;
*b = *a - *b;
*a = *a - *b;
}
这种解法主要是通过加减和赋值运算来实现,但它有两个缺陷:
1)未考虑极限情况下的加法溢出问题;
2)仅适用于交互可以进行加减运算的变量的值。
而使用异或可以弥补这两个缺陷,且运算速度更快:
void exchange(int * a, int * b)
{
*a = *a ^ *b;
*b = *a ^ *b;
*a = *a ^ *b;
}
本文介绍了异或运算的特性,包括任何数字异或自身等于0,0异或任何数等于任何数,1异或任何数等于取反。通过异或运算解决了一道寻找数组中重复元素的问题,提出在O(n)时间和O(1)空间复杂度下,通过异或所有数字找出重复元素。此外,还讨论了异或在交换数值时的优势,避免了加法溢出和适用于不可直接加减的数值交互。
1295

被折叠的 条评论
为什么被折叠?



