异或(XOR)在算法中的一些适用情况

今天在做leetcode上的一道题时,发现了一种对异或操作的使用情况。

题目是这样子的:

Given an array of integers, every element appears twice except for one. Find that single one.

给你一个整型的数组,除了一个元素之外其余元素都只出现了两次,找到那一个独立的元素

Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?

算法要求时间复杂度是线性的,并且问你能否改进成不需要多余的内存。

这个题目本身如果没有算法要求是很简单的,如下:

1 int singleNumber(vector<int>& nums) {
2      for(vector<int>::iterator iter = nums.begin(); iter != nums.end(); ++iter){
3           vector<int>::iterator pos = find(iter+1, nums.end(), *iter);
4           if(pos != nums.end())
5           nums.erase(pos);
6      }
7      return nums[0];
8 }

但是for循环遍历需要o(N)的复杂度,而find()也需要最少o(N)的复杂度,所以不满足题目对时间复杂度的要求。

这个时候百思不得其解,看看别人的答案,用到了 ^= ,思考了一下有不明白其中的原理,之前看CSAPP的时候学过XOR的操作,但是不明白为什么要用到这里。最后又搜了一下这个题目,终于明白其中的原委。

因为其他元素都出现了2次,因此根据XOR满足交换律的要求,可以知道其他所有元素(不包括那个只出现一次的元素)异或的结果是各个bit均为0的int,而一个变量各位均为0的话和其他变量进行XOR操作结果就是那个元素,这样就可以求出结果了。代码如下:

1 int singleNumber(vector<int>& nums) {
2         int result = 0;
3         if(nums.size() == 1) return nums[0];
4         for(vector<int>::iterator iter = nums.begin(); iter != nums.end(); ++iter){
5             result ^= *iter;
6         }
7         return result;
8     }

 

这个题目有一个升级版,就是在数组中有两个只出现一次的元素,让你求出,这里只给出一个思路:将数组拆分成两个子数组,每个数组都只包含一个所要求的元素。具体解法在这里。我就不当搬运工了。

这种题目的特点就是 其他元素一定要出现偶数次。

posted on 2015-07-10 15:46  daghlny  阅读(812)  评论(0编辑  收藏  举报

导航