【位运算-3】136.只出现一次的数字

题目描述:

给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。

示例 1 :

**输入:**nums = 2,2,1

**输出:**1

示例 2 :

**输入:**nums = 4,1,2,1,2

**输出:**4

示例 3 :

**输入:**nums = 1

**输出:**1

解题思路:

方法一:位运算

核心思路:异或运算

异或的性质:
性质 说明
a ^ a = 0 相同数异或为 0
a ^ 0 = a 任何数异或 0 等于自身
交换律 a ^ b = b ^ a
结合律 (a ^ b) ^ c = a ^ (b ^ c)
观察:

把所有数异或起来:

  • 出现两次的数异或后变成 0

  • 只出现一次的数异或后保留下来

复制代码
2 ^ 2 ^ 1 = 0 ^ 1 = 1
4 ^ 1 ^ 2 ^ 1 ^ 2 = 4 ^ (1^1) ^ (2^2) = 4 ^ 0 ^ 0 = 4

具体过程示例:

nums = [4,1,2,1,2]

复制代码
4 ^ 1 = 5
5 ^ 2 = 7
7 ^ 1 = 6
6 ^ 2 = 4

结果: 4 ✅

代码实现:

cpp 复制代码
class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int result = 0;
        for (int num : nums) {
            result ^= num;
        }
        return result;
    }
};

复杂度分析:

维度 复杂度 说明
时间复杂度 O(n) 一次遍历
空间复杂度 O(1) 只用一个变量

关键细节:

1. 为什么异或能满足要求?
  • 出现两次的数:a ^ a = 0,互相抵消

  • 只出现一次的数:a ^ 0 = a,保留下来

  • 异或满足交换律和结合律,顺序不影响结果

2. 如果出现三次呢?

异或就不行了,需要用位计数:统计每一位 1 的个数,对 3 取模。

137 题:只出现一次的数字 II(其余出现三次)

cpp 复制代码
class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int result = 0;
        for (int i = 0; i < 32; i++) {
            int count = 0;
            for (int num : nums) {
                count += (num >> i) & 1;
            }
            if (count % 3 != 0) {
                result |= (1 << i);
            }
        }
        return result;
    }
};

3. 如果出现两次的有两个呢?

260 题:只出现一次的数字 III(有两个只出现一次的数)

需要先用异或找到分组依据,再分组异或。

方法二:哈希表(O(n) 空间)

代码实现:

cpp 复制代码
class Solution {
public:
    int singleNumber(vector<int>& nums) {
        unordered_map<int, int> count;
        for (int num : nums) count[num]++;
        
        for (auto& [num, cnt] : count) {
            if (cnt == 1) return num;
        }
        return -1;
    }
};

复杂度:时间 O(n),空间 O(n)

缺点:不满足 O(1) 空间要求。

方法三:排序(O(n log n))

代码实现:

cpp 复制代码
class Solution {
public:
    int singleNumber(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        for (int i = 0; i < nums.size() - 1; i += 2) {
            if (nums[i] != nums[i+1]) return nums[i];
        }
        return nums.back();
    }
};

复杂度:时间 O(n log n),空间 O(1)

三种方法对比:

方法 时间复杂度 空间复杂度 推荐度
异或 O(n) O(1) ⭐⭐⭐⭐⭐
哈希表 O(n) O(n) ⭐⭐⭐
排序 O(n log n) O(1) ⭐⭐

总结:

要点 说明
核心思想 异或:相同为 0,不同为 1
关键性质 a ^ a = 0,a ^ 0 = a
时间复杂度 O(n)
空间复杂度 O(1)
相关推荐
MoRanzhi12031 小时前
106.正则问题(分治)
python·算法·正则表达式·蓝桥杯·递归·分治算法·字符串处理
suhan1 小时前
【数据结构】五、树:7.哈夫曼树、哈夫曼编码
数据结构·算法·排序算法
kkhimself1 小时前
POJ-3126
算法
suhan2 小时前
【数据结构】五、树:6.平衡二叉树AVL
数据结构·算法·排序算法
suhan2 小时前
【数据结构】五、树:5.二叉排序树BST
数据结构·算法·排序算法
爱读书的小胖2 小时前
80. 删除有序数组中的重复项 II
java·数据结构·算法
臻选云栗子2 小时前
PCDN跑不起来?先别甩锅给平台,问题可能出在这
算法·程序员
C++ 老炮儿的技术栈2 小时前
std::atomic 是什么
linux·c语言·网络·c++·visual studio
小画家~3 小时前
vue3 里面的 itemList.reduce
前端·数据结构·算法