[LeetCode]137. 只出现一次的数字 II(java实现)位运算
1. 题目
2. 读题(需要重点注意的东西)
思路(位运算、有限状态自动机):
要求:时间复杂度为O(n)
空间复杂度为O(1)
假设有如下数组 [2 2 3 2] ===> 转换为二进制数如下:
2 ===> 10
2 ===> 10
3 ===> 11
2 ===> 10
计算每一位上1的个数: 由于除某个元素仅出现一次外,其余每个元素都恰出现三次 ,因此这一位(设为 i )上1的个数不是3的倍数
就是3的倍数+1
,如果+1,则一定是由那个单独的元素贡献的,那么就说明最终的结果中这一位是1,则使得 res += 2i ,即res += 1 << i
即可。
计算第0位: 统计1的个数有1个,不是3的倍数,说明这一位是由单独的一个数贡献的,因此在最后的结果中,这一位是1
计算第1为: 统计1的个数为4个,不是3的倍数,说明说明这一位是由单独的一个数贡献的,因此在最后的结果中,这一位是1
因此 2 0 * 1 + 21 * 1 = 3,为最终的结果
3. 解法
---------------------------------------------------解法---------------------------------------------------:
class Solution {
public int singleNumber(int[] nums) {
int n = nums.length;
int res = 0;
// 每个数都有32位,考虑每一位
for(int i = 0;i < 32;i++){
int cnt = 0;
// 在每一位上,考虑每个数,如果该位置为1,则加到cnt中,最后计算cnt是不是3的倍数
for(int j = 0 ;j < n;j++)
// 当前数右移i与与1等于1,说明右移i位后当前位为1,cnt++
if((nums[j] >> i & 1)== 1) cnt++;
// 如果出现 1 的次数不是3的倍数,则证明这一位是由那个单独的数贡献的
if(cnt % 3 != 0) res += 1 << i;
}
return res;
}
}
可能存在的问题:
4. 可能有帮助的前置习题
5. 所用到的数据结构与算法思想
6. 总结
统计每一位i上1的数量,如果结果不为3的倍数
,则说明多出来的数是由那个单独的数贡献的,使得res加上2i 即可,将所有位都统计完后,res的值就是那个单独的数。