一万个无序数查找两个重复数, 异或查找法

今天看到园子里的类似本文标题的文章, 答案中没有使用异或的.

按位异或运算符: ^

两个相同的数按位异或结果为0

任何数和零按位异或结果为这个数本身

 

根据按位异或的以上特性, 我们可以为下面这首题目给出一个简便的算法:

有一个长度为10000的数列, 存放着1-10000的自然数, 连续, 不重复, 但数列并不是有序的

现在随机选取1-10000之间的某个自然数, 加入到这个数列中, 要求用简便的算法找到这个后来加入的数

 

分析一下, 这个问题是肯定不能用序列中数之和减去1-10000数列和的办法的, 这样做可能会造成溢出, 首先排除.

第二, 有的人认为这个题目说的是有序数组, 我觉得应该不是的. 如果数组是有序的, 只要比较前后两个数是否相差1就可以很快速也很容易找到重复数.

而这种问题非常适合异或(如果不是数值类型, 则不适合), 因为上面讲的按位异或运算符的两个特性, 可得1^1=0, 1^1^2=2, 1^2^1^2^3=3…

所以, 数组中10001个数的"异或和"再与1-10000异或可得重复的那个数.

异或查找:

const int Max = 10000;
List<int> list = new List<int>(Max + 1);
for (int i = 0; i < Max; i++)
list.Add(i + 1);

Random rand = new Random(DateTime.Now.Millisecond);
int duplicate = rand.Next(1, Max); //获取随机数
int dupIndex = rand.Next(0, Max); //获取随机插入位置
list.Insert(dupIndex, duplicate); //在随机位置插入随机数, 表示序列是无序的

Console.WriteLine("重复数是: " + duplicate.ToString());

int xor = 0;
for (int i = 0; i <= Max; i++)
{
xor ^= list[i];
xor ^= i;
}

Console.WriteLine("查找结果: " + xor.ToString());
Console.ReadKey();

 

看起来比使用二分查找, 二叉树之类方便一些.

posted on 2009-07-21 23:58 BFL 阅读(494) 评论(3) 编辑 收藏

http://www.cnblogs.com/BFLForever/