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?
注:时间复杂度需要O(n),空间复杂度O(1)
题目有点坑,正常人想不到,不正常的人才想的到。关键点在于学会位上的异或运算方式,异或既不同为真,相同为假。
1 )假设a = 10101,则有 a ^ a = 00000,0 ^ a = a,a ^ 0 = a。
2 ) 异或运算符满足交换律和结合律:a ^ b = b ^ a ,( a ^ b ) ^ c = a ^ ( b ^ c )
3 )假设数组为 a b b c e a c d d,那么 a ^ b ^ b ^ c ^ e ^ a ^ c ^ d ^ d = ( a ^ a ) ^ ( b ^ b ) ^ ( c ^ c ) ^ e = 0 ^ 0 ^ 0 ^ e = e
那么e就是题目所求的答案,代码如下:
class Solution {
public:
int singleNumber(int A[], int n) {
int ans = 0;
for (int i=0; i<n; i++) {
ans ^= A[i];
}
return ans;
}
};
Single Number II
Given an array of integers, every element appears three times except for one. Find that single one.
Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
这题与上题有些不同,可以用普遍意义的方法来解决。由于数组中有且仅有一个数出现1次,其他数字均出现了3次,那么要找出仅出现1次的数,最笨的就是扫一遍,统计,在扫一遍发现统计次数为1次的数,这样时间复杂度为O(n + n),空间复杂度至少也是O( n ),这样就不符合题目要求。
那么可以参照Single Number I,从位上来考虑,直接看例子:
假设数组A元素整型且为4位的二进制,数组元素为 1101,0111,1101,1101四个二进制数
A[0] 1 1 0 1
A[1] 0 1 1 1
A[2] 1 1 0 1
A[3] 1 1 0 1
统计每一位上1的个数 3 4 1 4
将每一位上1的个数mod3 0 1 1 1,0111二进制数结果就是题目所要求的。
基本思想:由于数出现3次,那么在第i位上1出现的个数也为3的倍数,而仅出现1次的数,在第i位上1出现的次数便是多余的1次。
代码如下:
class Solution {
public:
int singleNumber(int A[], int n) {
const int LEN = 32; //int型在32位机器里面为32位
int cnt[LEN]; //用来统计每位上1的个数
int res = 0;
memset(cnt, 0, sizeof(cnt));
for(int i=0; i<LEN; ++i) {
for(int j=0; j<n; ++j) { //遍历数组,判断第i位上是否为1
if( A[j]>>i & 1 )
++cnt[i];
}
res |= (cnt[i]%3)<<i; //第i位上1的个数mod3后结果即为仅出现1次的元素的第i位上的取值
}
return res;
}
};