剑指 Offer 56 - II. 数组中数字出现的次数 II
在一个数组 nums 中除一个数字只出现一次之外,其他数字都出现了三次。请找出那个只出现一次的数字。
示例 1:
输入:nums = [3,4,3,3]
输出:4
示例 2:
输入:nums = [9,1,7,9,7,9,7]
输出:1
思路:我们记录每个二进制位出现1的次数,统计完成之后将记录的数据对3求余,就可以得到那个只出现一次的那个数字该二进制的情况。
class Solution {
public int singleNumber(int[] nums) {
int[] register = new int[32];
for(int num:nums){
// 记录num每个二进制位有几个1
// >>> 无符号位移 即右移后前面的空位用0补
for(int i = 0;i < 32;i++){
register[i] += (num&1);
num >>>= 1;
}
}
//记录完毕 开始求余;
int res = 0;
for(int i = 0;i < 32;i++){
// 更新
res <<= 1;
// 求出现一次的数字该位置是0 还是 1,%3可改成%m,即可求除一个数字只出现一次之外,其他数字都出现了m次的情况
res |= register[31-i] % 3;
}
return res;
}
}
其实也可以用HashMap来做,虽然乍一看HashMap的时间复杂度是O(n),本方法的时间复杂度好像是O(n方),但实际上仔细观察就可以看出,第一个for循环当中嵌套的for循环是固定次数的,也就是与原题给定的数组长度是无关的,所以本题也应该是O(n)。并且,HashMap的方法不管是存取和读取都跟数组长度n有关,理论上应该是2n的复杂度,同时HashMap需要的空间应该是大于本方法,本方法开辟的是固定长度的数组,故空间复杂度为O(1)。总的来说,本方法优于看似简洁的HashMap。