//从高位向低位操作
int foundOnceNumber(int* arr, int arrLen, int k ) {
int num = 0;
for(int i = 31; i >= 0; i--) //从右移31位到右移0位
{
int cnt = 0; //每趟循环就是求某个位置的1的个数,每趟开始置0
for(int j = 0; j < arrLen; j++)
{
cnt += (arr[j] >> i) & 1;
// 先右移i位,再和1相与,即可知从高到低第(32-i)位是几
}
num = num * 2 + cnt % k; //乘权加余就可以求出这个数
}
return num;
}
外循环是移动的位数在变化,从右移31位到右移0位,分别求从高到低第1位到第32位上的数字的和。
内循环是针对每个位置,求所有arrLen个数的这个位置上的数之和
对于其他均出现k次的数,内循环for结束后再%k都会=0,但是如果加上一个独行者
若它在某个位置是0,则cnt % k 就会=0或者=1,且刚好是这个数每个位上的值
即根据从高到低每个位上的数求出这个十进制数。
或者从低位向高位比较
int foundOnceNumber(int* arr, int arrLen, int k ) {
int sum = 0;
int ret = 0;
for(int i = 0; i < 32; i++){ //从右移0位到右移31位
sum = 0;
for(int j = 0; j < arrLen; j++){
sum += ((arr[j])>>i)&1; //计算所有数在这个位上的值之和
}
ret+=((sum%k)<<i);
//对于从低到高处理每个位上的数时,还原这个数需要左移i位
}
return ret;
}

京公网安备 11010502036488号