先說第一種題
題目:
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;
}
};