137. Single Number II
1、原题
Given an array of integers, every element appears three times except for one, which appears exactly once. Find that single one.
2、题目解析与思路
这道题是从Single NumberI发展过来的。single numberI是比较简单的,就是给我们一个数组,该数组中除了一个数外,其他数都会出现两次,让我们找出该出现一次的数。那道题比较简单,就是使用位运算中的与或运算即可。
这道题的意思是现在数组中除了一个数出现一次外,其他的数都会出现3次。一开始一个很直观的方法就是使用map来存储对应关键字的出现次数,然后再次遍历一遍map就可以找到我们需要的数了。这种比较简单粗暴。
第二种方法就是在原先位运算的基础上进行改进的。我们可以发现当所有其他数字都出现3次的时候,其每一位上1的个数加起来就是3的倍数了。但是很可惜我们二进制是会进位的。所以这时候我们就想到了用一个32位的数组来存储我们的每一位上1的个数。
3、代码实现
第一种:
public int singleNumber(int[] nums) {
//创建记录的map
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int i = 0; i < nums.length; i++) {
//判断是否已经存在该关键字
if (map.containsKey(nums[i])) {
map.put(nums[i], 2);
} else {
map.put(nums[i], 1);
}
}
//遍历mao,找到关键字出现一次的值,输出
for (Map.Entry<Integer, Integer> entry: map.entrySet()) {
if (entry.getValue() == 1) {
return entry.getKey();
}
}
return 0;
}
第二种:
public int singleNumberBetter(int[] nums) {
//初始化记录数组
int[] count = new int[32];
//遍历数组,记录每一位1的个数
for (int i = 0; i < nums.length; i++) {
for (int j = 0; j < 32; j++) {
count[j] += nums[i] & (0x1 << j);
}
}
int single = 0;
//判断其是正数还是负数
if (count[31] % 3 == 0) {
//计算
for (int i = 0; i < 31; i++) {
if (count[i] % 3 != 0) {
single += Math.pow(2, i);
}
}
} else {
//计算负数
for (int i = 0; i < 31; i++) {
if (count[i] % 3 == 0) {
single += Math.pow(2, i);
}
}
single = -(single + 1);
}
return single;
}