您的位置:首页 > 其它

LeetCode 260:Single Number III

2016-01-22 17:27 387 查看
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]
.

Note:

The order of the result is not important. So in the above example, 
[5, 3]
 is
also correct.
Your algorithm should run in linear runtime complexity. Could you implement it using only constant space complexity?

给定一个整数数组nums,在该数组中只有两个数出现过一次,其余的数都正好出现两次。找到这两个数。
例如:

给定nums = [1, 2, 1, 3, 2, 5],应当返回[3, 5]

注意:

1.结果的顺序并不重要,因此对于上面的例子来说[5, 3]也是正确的。

2.你的算法应该有线性的时间复杂度,你能用静态的内存大小实现吗?(即空间复杂度不依赖输入n)

思路不是特别复杂,排序后顺序扫描一遍,找到与前后均不相同的两个数即可,最后再判断第一个数与最后一个数。其实之前那道找一个数的题我最开始想到的就是这个方法,而这道题再用异或我就想不出来了,因为有两个不一样的数,异或出来的结果不知道要怎么区分。

class Solution {
public:
vector<int> singleNumber(vector<int>& nums) {
if(nums.size()==2) return nums;
vector<int> ans;
sort(nums.begin(),nums.end());
for(int i=1;i<nums.size()-1;i++)
if(nums[i]!=nums[i-1]&&nums[i]!=nums[i+1]) ans.push_back(nums[i]);
if(nums[0]!=nums[1]) ans.push_back(nums[0]);
if(nums[nums.size()-1]!=nums[nums.size()-2]) ans.push_back(nums[nums.size()-1]);
return ans;
}
};


不过在讨论里发现了别人依然用异或做了出来,这里放上大神的思路和代码:

1.assume that A and B are the two elements which we want to find;

2.use XOR for all elements,the result is : r = A^B,we just need to distinguish A from B next step;

3.if we can find a bit '1' in r,then the bit in corresponding position in A and B must be different.We can use {last = r & (~(r-1))} to get the last bit 1 int r;

4.we use last to divide all numbers into two groups,then A and B must fall into the two distrinct groups.XOR elements in eash group,get the A and B.

1.假定我们要找的数字为A和B;

2.异或(XOR)所有的数字,于是我们得到结果 r = A ^ B ,现在我们只需要区分A和B;

3.如果我们在r中能找到'1'比特位(二进制),那么即代表在这个比特位上A和B一定不同(因为只有0 XOR 1 = 1),我们能够用 last = r & (~(r-1)) 来得到r中的最后一个'1'比特位;

4.于是我们可以用 last 来将所有数字分为两组,而A和B一定在两个不同的组中。对每一组都进行异或操作,得到A和B。

class Solution {
public:
vector<int> singleNumber(vector<int>& nums) {
int r = 0, n = nums.size(), i = 0, last = 0;
vector<int> ret(2, 0);

for (i = 0; i < n; ++i)
r ^= nums[i];

last = r & (~(r - 1));
for (i = 0; i < n; ++i)
{
if ((last & nums[i]) != 0)
ret[0] ^= nums[i];
else
ret[1] ^= nums[i];
}

return ret;
}
};


(这里开始是我自己写的)整体思路在于如何区分A和B,对于分两组之后A和B落入不同组应该比较好理解(因为数字A和B不同,因此至少会在一位上有不同,而我们就利用该位将整个数组划分为两个组),在之后我们只需要再遍历一次原数组即可,而不需关心其余数字是落入A组还是落入B组。因为相同的数字肯定会落入同一个分组,而在同一个分组中异或两次就消除掉了该数。看完之后不得不说一句牛逼啊~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: