Given an array of numbers nums, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once.
For example:
Given nums = [1, 2, 1, 3, 2, 5], return [3, 5].
解题思路:
题目要求给定数组,数组中有且只有两个元素只出现一次,其他元素都重复出现2次,返回只出现一次的元素。
首先遍历数组,使用异或操作得到一个数tmp,由于有两个元素只出现一次,因此异或出来的结果一定不为0。而这两个只出现一次的元素进行异或一定不为0,即至少有1个位一个元素为0,另一个元素为1。tmp的二进制中为1的位置即可区分两个元素,从tmp中提取出一个1得到的数作为掩码,遍历数组,与掩码进行与操作,若为0,则与元素1异或,否则与元素2异或,这样即可将两个只出现一次的元素分开,同时,重复出现的元素会被分到同一类中,当进行异或时,对结果无影响。
影响运行效率的地方:
从tmp中提取出一个1的方法:
1、首先使用tmp&(tmp-1)得到tmp去掉最低位1的数,再与tmp异或即得到该数(tmp&(tmp-1)^tmp,tmp^(tmp&(tmp-1)),这两个书写方式不同,运行所花费的时间也不同,前者相比于后者快些)
2、tmp&(~(tmp-1))也是取最后一个1的,运行所花费的时间与tmp^(tmp&(tmp-1)相同。
class Solution { public: vector<int> singleNumber(vector<int>& nums) { int n=nums.size(); if(n==2)return nums; vector<int>res=vector<int>(2,0); int a=0,b=0; int tmp=0; for(int i=0;i<n;i++){ tmp^=nums[i]; } // 20ms //tmp&=(~(tmp-1)); // 20ms tmp=tmp^(tmp&(tmp-1)); // 18ms // tmp=tmp&(tmp-1)^tmp; for(int i=0;i<n;i++){ if(nums[i]&tmp)res[0]^=nums[i]; else res[1]^=nums[i]; } return res; } }; |
保存中间变量所使用的变量类型:
1、在开始时就新建vector对象,中间变量保存到vector数组中
class Solution { public: vector<int> singleNumber(vector<int>& nums) { int n=nums.size(); if(n==2)return nums; // 18ms vector<int>res=vector<int>(2,0); int tmp=0; for(int i=0;i<n;i++){ tmp^=nums[i]; } tmp=tmp&(tmp-1)^tmp for(int i=0;i<n;i++){ if(nums[i]&tmp)res[0]^=nums[i]; else res[1]^=nums[i]; } return res; } }; |
2、先使用int类型保存中间变量,最后使用vector<int>{a,b}的方式保存最后结果,该方法比1要快写。
class Solution { public: vector<int> singleNumber(vector<int>& nums) { int n=nums.size(); if(n==2)return nums; // 16ms int a=0,b=0; int tmp=0; for(int i=0;i<n;i++){ tmp^=nums[i]; } tmp=tmp&(tmp-1)^tmp for(int i=0;i<n;i++){ if(nums[i]&tmp)a^=nums[i]; else b^=nums[i]; } return vector<int>{a,b}; } }; |
原文:http://www.cnblogs.com/olivelv/p/5219213.html