code第一部分数组:第二十三题 奇数次中查找单独出现一次的数
code第一部分数组:第二十三题 奇数次中查找单独出现一次的数
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次,那么这样子分析,计算机存数假设是32位来存的,那么
可以建立一个32位的数字,来统计每一位上1出现的个数,我们知道如果某一位上为1的话,那么如果该整数出现了三次,对3去余为0,我们把每个数的对应位都加起来对3取余,最终剩下来的那个数就是单独的数字。
解决方法2
用3个整数来表示INT的各位的出现次数情况,one表示出现了1次,two表示出现了2次。当出现3次的时候该位清零。最后答案就是one的值。
- ones 代表第ith 位只出现一次的掩码变量
- twos 代表第ith 位只出现两次次的掩码变量
- threes 代表第ith 位只出现三次的掩码变量
解决方法3
我们把数组中数字的每一位累加起来对3取余,剩下的结果就是那个单独数组该位上的数字,由于我们累加的过程都要对3取余,那么每一位上累加的过程就是0->1->2->0,换成二进制的表示为00->01->10->00,那么我们可以写出对应关系:
00 (+) 1 = 01
01 (+) 1 = 10
10 (+) 1 = 00 ( mod 3)
那么我们用ab来表示开始的状态,对于加1操作后,得到的新状态的ab的算法如下:
b = b xor r & ~a;
a = a xor r & ~b;
明白了上面的分析过程,就能写出代码如下;
#include <iostream> using namespace std; int singleNumber1(int a[],int n) { int result=0; for (int i = 0; i < 32; i++) { int sum=0; for (int j = 0; j < n; j++) { sum+=(a[j]>>i)&1; } result|=(sum%3)<<i; } return result; } int singleNumber2(int A[], int n) { int ones = 0, twos = 0, threes = 0; for (int i = 0; i < n; ++i) { twos |= (ones & A[i]); ones ^= A[i]; threes = ~(ones & twos); ones &= threes; twos &= threes; } return ones; } int singleNumber3(int A[],int n) { int a = 0; int b = 0; for (int i = 0; i < n; i++) { b = (b ^ A[i]) & ~a; a = (a ^ A[i]) & ~b; } return b; } int main() { int a[10]={2,2,2,4,4,4,6,7,7,7}; int ans=singleNumber1(a,10); cout<<"the ans is "<<ans<<endl; int ans2=singleNumber2(a,10); cout<<"the ans is "<<ans2<<endl; int ans3=singleNumber3(a,10); cout<<"the ans3 is "<<ans3<<endl; return 0; }