代码结构
class Solution { public: int singleNumber(int* A, int n) { int bitCount[32] = {0}; // 统计每一位的1的个数 for (int i = 0; i < n; ++i) { for (int j = 0; j < 32; ++j) { bitCount[j] += (A[i] >> j) & 1; // 更新每一位的计数 } } int result = 0; for (int j = 0; j < 32; ++j) { result |= (bitCount[j] % 3) << j; // 只取模3的结果 } return result; } };
详细步骤解析
- bitCount数组的初始化:这个数组用来记录每一位上1的出现次数。我们使用32个元素来处理32位整数。
- 外层循环:遍历输入数组A中的每一个元素。这里的n是数组的长度。
- 内层循环:对于每一个元素,我们需要检查它的每一位(从第0位到第31位)。
- 统计每一位的1的个数:A[i] >> j:将当前元素A[i]右移j位,这样我们可以检查当前位。& 1:与1进行位与运算,提取出最低位。如果当前位是1,结果将为1;如果是0,结果为0。bitCount[j] += ...:将当前位的统计结果加到bitCount[j]中。
- 构建结果:初始化result为0,用于存储只出现一次的元素。再次遍历bitCount数组,对于每一位: bitCount[j] % 3:由于其他数字出现了三次,所以在每一位上只出现一次的元素的1会在bitCount中留下非零值。<< j:将这个结果左移j位,以放置在正确的位置。result |= ...:使用按位或运算将结果累加到result中。
- 返回结果:最后返回构建出的只出现一次的元素。
复杂度分析
- 时间复杂度:O(n),其中n是数组的长度。我们只需要一次遍历数组和32次位操作。
- 空间复杂度:O(1)。虽然使用了bitCount数组,但它的大小是固定的(32),不随输入规模而变化,因此认为是常量空间。
示例解释
假设输入数组为A = [2, 2, 3, 2]
:
- 统计过程: 对于2,二进制为0000 0010,统计后bitCount会变为[0, 1, 0, ..., 0](第1位为1,其他为0)。对于3,二进制为0000 0011,统计后bitCount会变为[0, 2, 0, ..., 0](第1和第2位为1,其他为0)。
- 最终,
bitCount
为[0, 3, 0, ..., 0]
,因为第1位的1出现了三次,result
最终会只留下3
。
总结
该方法高效利用位运算统计每一位的出现次数,并通过模运算找出只出现一次的元素,避免了使用额外的数据结构,从而节省空间。