题目如下:
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?
分析如下:
借助上一题的惯性思维,考虑用异或之类的位运算方式来解决,但是基本上想不出答案。网上搜了一下,看到一个绝妙的做法。
输入是int型数组,所以可以用32位来表达输入数组的元素。
假设输入中没有single number,那么输入中的每个数字都重复出现了数字,也就是说,对这32位中的每一位i而言,所有的输入加起来之后,第i位一定是3的倍数。
现在增加了single number,那么对这32位中的每一位做相同的处理,也就是说,逐位把所有的输入加起来,并且看看第i位的和除以3的余数,这个余数就是single numer在第i位的取值。这样就得到了single number在第i位的取值。这等价于一个模拟的二进制,接着只需要把这个模拟的二进制转化为十进制输出即可。
为了完成上面的过程,需要使用一个数组 int a[ 32 ]来模拟位运算。
可以看出来,这个做法对于功力的要求非常高,需要看到数字的时候,眼前展现的是数字背后的二进制组成,要不然很难想到可以逐位去处理。
另外,这个做法可以扩展,如果有一堆输入,其中1个数字出现了1次,剩下的数字出现了K次,这样的问题全部可以使用这样的办法来做。
我的代码:
其实是从mitbbs上偷来的。。。
//80ms过大集合
class Solution {
public:
int singleNumber(int A[], int n) {
int count[32]={0};
int result=0;
for(int i=0;i<32;i++){
for(int j=0;j<n;j++){
count[i]+=((A[j]>>i)&1); //首先把输入数字的第i位加起来。
count[i]=count[i]%3; //然后求它们除以3的余数。
}
result|=(count[i]<<i);//把二进制表示的结果转化为十进制表示的结果
}
return result;
}
};
参考资料:
(1) http://www.mitbbs.com/article_t/JobHunting/32547143.html