解题思路:
在为偶数时,将所有数异或就能得到答案,因为偶数个相同数异或结果为,最终只留下了要求的数,时间复杂度,空间复杂度。
在为奇数时,若利用计数的方式来求答案,那么空间复杂度会来到,不满足题目要求。由于题目要求时间复杂度,空间复杂度。所以选择采用位运算的方式,即计算所有数在每一位的1的数目,再将该数模,最后再复原得到答案。由于int数组最多32位,所以时间复杂度是,空间复杂度是,满足要求。
1:将所有数字的二进制对应位置进行求和,用过 Excel 的胖友应该都知道求和操作,如图:
我们假设有四个数字,其中有三个重复的 2,和一个单独的 3;
2:因为有 3 个数是重复的,所有把所有二进制位求和之后得到的数值进行取模操作,如图
于是就得到了结果。
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param arr int一维数组
* @param k int
* @return int
*/
public int foundOnceNumber (int[] arr, int k) {
int[] count = new int[32]; // Java 中,int 有 32 位
for (int i = 0; i < arr.length; ++i) { // 将所有数的对应二进制位进行求和
for (int j = 0; j < 32; ++j) {
/**
* &同为1时为1,否则为0
* 假如3个2 1个3
* 2的二进制为
* 00000000000000000000000000000010
* & 1 相当于
* 00000000000000000000000000000001
* 第一次 bits[0] = 0 代表2的二进制的低1位是0
*/
count[j] += arr[i] & 1;
/**
* 相当于每次无符号右移1位 高位补0
* 如2 >>> 1
* 2的二进制:
* 00000000000000000000000000000010
* >>> 1
* 00000000000000000000000000000001
* 相当于判断bits中
* 目的让第2次 bits[1] = 1 不停的和1做&运算 即拿2的2进制每一位 从低1位到高32位与1进行比较
* 同为1的时候 说明2的二进制当前位置是1 否则为0
*/
arr[i] >>>= 1;
}
}
int res = 0;
for (int i = 0; i < 32; ++i) { // 求和之后再取出来,同时要取模操作
//从高32位开始 res二进制 = 00000000000000000000000000000000
res <<= 1;
/**
*
* |同为0时为0,否则为1
* bits存的是从低1位到高32位,所以这里要逆向
*/
res |= count[31 - i] % k; // 有 k 个相同的 1, 则 k % k == 0,剩下的就是多出来的那个数
}
return res;
}
}


京公网安备 11010502036488号