56-02 数组中唯一只出现一次的数字
题目
在一个数组中除一个数字只出现一次之外,其他数字都出现了三次。请找出那个只出现一次的数字。
C++ 题解
如果题目中的“三次”换成“两次”,这道题目将非常简单,因此两个相同的数字异或,每一位都会变成0,其实亦或也可以看成两个数字的每一个二进制位对应进行加法后对2取模后的结果。按照这种思路,对于出现三次的数字,改成对3取模即可。
举个例子说明下(10,4,5,5,4,4,5)
:
相关数字对应二进制表示:10 = 1010 4 = 0100 5 = 0101
1)申请一个长度为32(因为int占32bit)的int型数组bitsum,用于记录整型数字每一位出现1的次数。
bitsum = 00000000 00000000 00000000 00000000
2)将每个数字计入到bitsum[]中
10-> 00000000 00000000 00000000 00001010
4 -> 00000000 00000000 00000000 00001110
5 -> 00000000 00000000 00000000 00001211
5 -> 00000000 00000000 00000000 00001312
4 -> 00000000 00000000 00000000 00001412
4 -> 00000000 00000000 00000000 00001512
5 -> 00000000 00000000 00000000 00001613
3)bitsum的每一个元素对3取模:
bitsum = 00000000 00000000 00000000 00001010
4)将bitsum作为一个32bit的整数:
result = 00000000 00000000 00000000 00001010 = 10
class Solution {
public:
int singleNumber(vector<int>& nums) {
int ret = 0;
// 遍历int类型的32个bit
for(int i=0;i<32;i++)
{
int bitnums = 0;
int bit = 1 << i;
// 遍历整个数组,如果某个数字的某个bit上出现的数字不是0则累加
for (auto num :nums)
{
if (num & bit)
bitnums++;
}
// 如果某个bit上对3取余不为0,则是最终结果在这个bit上应该出现的数字
if(bitnums % 3)
ret |= bit;
}
return ret;
}
};
python 题解
方法一
利用python中的set
特性求集合中所有数据和的3倍再减去原数组中的数据之和,结果恰好为只出现一次数字的和之两倍:
class Solution(object):
def singleNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
numset = set(nums)
sumA = sum(numset) * 3
sumB = sum(nums)
return (sumA - sumB) >> 1
方法二
与 C++ 题解思路相同
class Solution(object):
def singleNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
res = 0
for i in range(32):
bitscount = 0
for num in nums:
bitscount += ((num>>i) & 1)
if bitscount % 3!=0:
res += (1<<i)
return res if (res & (1<<31)) == 0 else res - (1<<32)
注意:
- 最后对于正负数的处理需要特别注意。