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?
题目:其他数字都出现3此,除了有个数不是三次,找出那个数。
这道题目不会,只看得懂简单的做法。
我的答案:
看了思路一,自己写了个差不多思路的代码
int singleNumber(vector<int>& nums) {
vector<int>vec(32,0);
int res= 0;
for(int j = 0; j < 32; j++){
int count = 0;
for(int i = 0; i <nums.size(); i++){
if((nums[i]&(1<<j)) != 0)
count++;
}
count %= 3;
if(count != 0)
res |= (1 << j);
}
return res;
}
1.简单做法
将每个数字,转换为二进制,计算每位上出现的次数,再对这个次数取余。
int singleNumber(vector<int>A) {
int n = A.size();
int bitnum[32]={0};
int res=0;
for(int i=0; i<32; i++){
for(int j=0; j<n; j++){
bitnum[i]+=(A[j]>>i)&1;
}
res|=(bitnum[i]%3)<<i;
}
return res;
}
时间:O(32*N),这是一个通用的解法,如果把出现3次改为 k 次,那么只需模k就行了。
2.这种做法没看懂
貌似是有这么一张表
a b 用两位记录满3次的状态,c是输入的数字
public class Solution {
public int singleNumber(int[] nums) {
//we need to implement a tree-time counter(base 3) that if a bit appears three time ,it will be zero.
//#curent income ouput
//# ab c/c ab/ab
//# 00 1/0 01/00
//# 01 1/0 10/01
//# 10 1/0 00/10
// a=~abc+a~b~c;
// b=~a~bc+~ab~c;
int a=0;
int b=0;
for(int c:nums){
int ta=(~a&b&c)|(a&~b&~c);
b=(~a&~b&c)|(~a&b&~c);
a=ta;
}
//we need find the number that is 01,10 => 1, 00 => 0.
return a|b;
}
}
3.这种我也看不懂
解释:
这是一个更快一些的解法,利用三个变量分别保存各个二进制位上 1 出现一次、两次、三次的分布情况,最后只需返回变量一就行了。
每次循环先计算 twos,即出现两次的 1 的分布,然后计算出现一次的 1 的分布,接着 二者进行与操作得到出现三次的 1 的分布情况,然后对 threes 取反,再与 ones、twos进行与操作,这样的目的是将出现了三次的位置清零。
int singleNumber1(int A[], int n) {
int one=0, two=0, three=0;
for(int i=0; i<n; i++){
two |= one&A[i];
one^=A[i];
//cout<<one<<endl;
three=one&two;
one&= ~three;
two&= ~three;
}
return one;
}