136. Single Number
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?
不能用额外空间,所以map也不行
本题非常巧妙的运用 异或运算符^
class Solution {
public:
int singleNumber(vector<int>& nums)
{
int ret = 0;
for(int i = 0; i < nums.size(); i++)
ret ^= nums[i];
return ret;
}
};137. Single Number II
Given an array of integers, every element appears three times except for one, which appears exactly once. Find that single one.
Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
class Solution {
public:
int singleNumber(vector<int>& nums)
{
int count[32]={0};
int ret=0;
for(int i=0;i<32;i++)
{
for(int j=0;j<nums.size();j++)
{
count[i]+=(nums[j]>>i)&1;//一定不能用求余数,因为余数可能为-1,一定要用这种 位操作
}
count[i]=count[i]%3;
ret|=count[i]<<i;//也可以为ret+=count[i]<<i; |(或)位操作
}
return ret;
}
};260.
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.
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?
way-2:位操作
思路:
我们知道如果一个数组中只有一个元素是出现一次,其他元素是出现两次的解题思路。只需要把所有的元素异或之后,那么异或的结果就是那个最终的单个的元素。这个思路很简单,就是把每个数理解为对应的二进制位,那么那些出现两次的元素,他们在1出现的所有位置,1都出现两次,异或完就还是0。而对于那个单出现一次得元素,它每个二进制位对应的数字出现一次。所以最终的异或结果就相当于把出现两次的元素全部去除。
有了上面的基本的思路,我们可以将数组分成两个部分,每个部分里只有一个元素出现一次,其余元素都出现两次。那么使用这种方法就可以找出这两个元素了。不妨假设这两个元素是x,y,而且x!=y,那么最终所有的元素异或的结果就是res = x^y.很显然,res!= 0,如果res=0,那么x=y,与题意不符。既然res!=0,那么我们可以找出其二进制表示中的某一位是1,我们从低位往高位找,找到第一个二进制位是1的位置。对于原来的数组,我们可以根据这个位置是不是1就可以将数组分成两个部分。x,y在不同的两个子数组中。而且对于其他成对出现的元素,要么在x所在的那个数组,要么在y所在的那个数组。假设不是的话,那说明这一对数在这一位上一个是0一个是1,很显然不符它们是一对相等数的条件。
class Solution {
public:
vector<int> singleNumber(vector<int>& nums)
{
//way-1
/*
map<int,int> mm;
for(int i=0;i<nums.size();i++)
mm[nums[i]]++;
vector<int> ret;
for(auto it=mm.begin();it!=mm.end();it++)
{
if(it->second==1)
ret.push_back(it->first);
}
return ret;
*/
//way-2
int res = 0;
for (auto num : nums)
res ^= num;
int flag = 1;
while(1)
{
if (res & flag)
break;
flag <<= 1;
}
int res1 = 0, res2 = 0;
for(auto num : nums)
{
if (num & flag)
res1 ^= num;
else
res2 ^= num;
}
vector<int> ret = {res1,res2};
return ret;
}
};
本文介绍了三种寻找数组中唯一单例元素的算法解决方案,包括单例出现一次、三次及两次的情况。利用位操作技巧实现线性时间和常数空间复杂度的要求。
411

被折叠的 条评论
为什么被折叠?



