先说第一种题
题目:
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?
我的解法:对数组排序,两个两个跳着比较直到找到不等的,时间复杂度O(NlogN)
class Solution {
public:
int singleNumber(vector<int>& nums)
{
sort(nums.begin(),nums.end());
int size = nums.size();
if (size == 1)
return nums[0];
for (int i = 1; i < size; i += 2)
if (nums[i] != nums[i - 1])
return nums[i - 1];
return nums[size -1];
}
};
参考其他解法,知道了这类题考察的是位运算
AC解:
class Solution {
public:
int singleNumber(vector<int>& nums)
{
int x = 0;
int size = nums.size();
for (int i = 0; i < size; i++)
x ^= nums[i];
return x;
}
};
或者直接 return accumulate(nums.begin(),nums.end(),0,bit_xor<int>());
升级版题目:
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?
用一个数组来存储所有元素每个位上1的个数,模3剩下的就是所有元素此位上的数字
class Solution {
public:
int singleNumber(vector<int>& nums)
{
const int length = sizeof(int) * 8;
int count[length];
fill(count,count + length,0);
int size = nums.size();
for (int i = 0 ; i < size; i++)
for (int j = 0; j < length; j++)
{
count[j] += (nums[i] >> j) & 0x1;
count[j] %= 3;
}
int result = 0;
for (int i = 0; i < length; i++)
result += (count[i] << i);
return result;
}
};
再次升级版:
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]
.
1.对所有数字进行异或运算,diff的值为要求的两个数进行异或运算的结果,再diff &= -diff,得到的结果为diff中从右到左第一个位为1的的数,例如0x1010 其负数为0x0110,与运算的结果为0x0010。并且可以知道这两个数的此位必定一个为0一个为1
2.根据此位是否为1将数分为了两部分,分别对两部分进行异或运算,因为相同的两个数异或操作后结果为0,所以两组数的最终结果就是所要求得的数
class Solution {
public:
vector<int> singleNumber(vector<int>& nums)
{
//数组中所有位进行异或,diff为所求的两个数异或的结果
int diff = accumulate(nums.begin(),nums.end(),0,bit_xor<int>());
//取得从右到左第一个为1的位,并且这两个数的此位一定不同
diff &= -diff;
vector<int> ans(2,0);
//分离两个数
for (auto a : nums)
if (a & diff)//当前元素的此位为1
ans[0] ^= a; //不算这两个数,当前位为0或1的数肯定是成对出现的
else //相同的数异或操作后为0
ans[1] ^= a;
return ans;
}
};