您的位置:首页 > 其它

Single Number III

2015-09-15 15:25 417 查看
https://leetcode.com/problems/single-number-iii/

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.

继续位操作

class Solution {
public:
vector<int> singleNumber(vector<int> &nums) {
int res = 0;
for(auto item: nums) res ^= item;
int lastBit = (res & (res - 1)) ^ res;
int i1 = 0, i2 = 0;
for(auto item: nums) {
if(item & lastBit) i1 ^= item;
else i2 ^= item;
}
return vector<int> {i1, i2};
}
};


注意一点,(res & (res - 1)) 作用是删除这个数的最后一个1 bit。

详细解释:引自剑指offer


在分析这种算法之前,我们先來分析把一个数减去1的情况。如果一个整数不等于0,那么该整数的二进制表示中至少有一位是1。先假设这个数的最右边一位是1,那么减去1时,最后一位变成0而其他所有位都保持不变。也就是最后一位相当于做了取反操作,由1变成了0。
接下来假设最后一位不是1而是0的情况。如果该整数的二进制表示中最右边1位于第m位,那么减去1时,第m位由1变成0,而第m位之后的所有0都变成1,整数中第m位之前的所有位都保持不变。举个例子:一个二进制数1100,它的第二位是从最右边数起的一个1。减去1后,第二位变成0,它后面的两位0变成1,而前面的1保持不变,因此得到的结果是1011。
在前面两种情况中,我们发现把一个粮数减去1,都是把最右边的1变成0。如果它的右边还有0的话,所有的0都变成1,而它左边所有位都保持不变。接下来我们把一个整数和它减去1的结果做位与运算,相当于把它最右边的1变成0。还是以前面的1100为例,它减去1的结果是1011。我们再把1100和1011做位与运算,得到的结果是1000。我们把1100最右边的1变成了0,结果刚好就是1000。我们把上面的分析总结起来就是:把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0。



int NumberOf1(int n)
{
int count = 0;
while(n)
{
++count;
n=(n-1)&n;
}
return count;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: