//从高位向低位操作
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;
}