137. 只出现一次的数字 II
✨核心逻辑
本题采用 按位统计 + 模 3 还原(位运算) 的策略:
- 统计每一位:由于其他数字都出现了 3 次,它们在二进制表示下,每一个比特位
1的个数总和必定是3的倍数。 - 取模剥离:我们遍历整数的 32 位,统计数组中所有元素在某一位上
1出现的总次数。 - 还原结果:将统计的个数对
3取余(count % 3)。如果结果等于1,说明那个“只出现一次”的数字在这个二进制位上也是1。通过按位或运算 (|=) 将这一位还原到答案中。
🔥代码实现(含详细变量注释)
class Solution {
public int singleNumber(int[] nums) {
// ans:用于记录并最终返回那个只出现了一次的数字结果
int ans = 0;
// i:遍历整数的 32 个二进制位(从低位 0 到高位 31)
for (int i = 0; i < 32; i++) {
// count:用于统计数组中所有元素,在第 i 位上,二进制值为 1 的出现次数
int count = 0;
// num:遍历数组中的每一个元素
for (int num : nums) {
// 判断当前数字 num 的第 i 位是否为 1,如果是,则 count 加 1
if (((num >> i) & 1) == 1) {
count++;
}
}
// 如果统计出的第 i 位的总个数,对 3 取余等于 1
// 说明出现一次的数字在这一位上也是 1
if (count % 3 == 1) {
// 将二进制第 i 位设置为 1,并合并进 ans 结果中
ans |= (1 << i);
}
}
// 返回还原出来的只出现一次的数字
return ans;
}
}
- ⏱️复杂度分析
时间复杂度:O(32 * N) = O(N),其中 N 是数组的长度。外层循环固定执行 32 次,内部遍历数组的时间为 O(N),常数 32 可忽略,整体为线性时间复杂度。
空间复杂度:O(1),只使用了 ans、i、count 和循环变量 num 等常数个额外整型变量。
🔍总结一下:
用二进制的思想去写题,遍历32次,内层对每个数组的元素进行二进制表达式中末尾元素1的计算,也就是统计1的次数,如果 %3 ==1
说明当前位就,对1进行移动 i 位即可,是1则ez