問題1:數組中只出現一次的兩個數字
一個整型數組裏除了兩個數字之外,其他的數字都出現了兩次。請寫程序找出這兩個只出現一次的數字。
2 <= nums <= 10000
思路:異或
首先,對數組的每個數字依次進行異或,得到異或後的結果value。
然後,記value最右邊第一位爲1的位爲i,依據第i位爲1/0將數組分爲兩組。
最後,在每個子數組中,依次進行異或,異或後的結果爲兩個只出現一次的數字。
代碼:
class Solution {
public:
int FindFirstBisIs1(int num)
{
int index=0;
while(((num&1)==0)&&(index<8*sizeof(int)))
{
num=num>>1;
++index;
}
return index;
}
bool IsBit1(int num,int index)
{
num=num>>index;
return (num&1);
}
void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
if(data.empty())
return;
int resOR=0;
int len=data.size();
for(int i=0;i<len;++i)
{
resOR^=data[i];
}
int index=FindFirstBisIs1(resOR);
*num1=*num2=0;
for(int j=0;j<len;++j)
{
if(IsBit1(data[j],index))
*num1^=data[j];
else
*num2^=data[j];
}
}
};
複雜度分析:時間複雜度是O(n),空間複雜度是O(1)。
問題2:數組中唯一隻出現一次的數字
在一個數組 nums 中除一個數字只出現一次之外,其他數字都出現了三次。請找出那個只出現一次的數字。
1 <= nums.length <= 10000
1 <= nums[i] < 2^31
思路:位運算
如果一個數字出現三次,那麼它的二進制表示的每一個也出現三次,把二進制表示的每一位加起來,能被三整除。
某一位不能被整除的說明要求的數字在該位上爲1,否則爲0.
代碼:
class Solution {
public:
int singleNumber(vector<int>& nums) {
int bitSum[32]={0};
int len=nums.size();
for(int i=0;i<len;++i)
{
unsigned int bitMask=1; // int 不能被右移
for(int j=31;j>=0;--j)
{
int bit=nums[i]&bitMask;
if(bit!=0)
bitSum[j]+=1;
bitMask=bitMask<<1;
}
}
int res=0;
for(int i=0;i<32;++i)
{
res=res<<1;
res+=bitSum[i]%3;
}
return res;
}
};
複雜度分析:時間複雜度是O(n),空間複雜度是O(1)。