LeetCode 136. 只出现一次的数字(C语言详解 | 哈希表 + 排序 + 位运算)

一、题目描述

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

要求:

  • 时间复杂度 O(n)

  • 空间复杂度 O(1)

示例 1

复制代码
输入:nums = [2,2,1]
输出:1

示例 2

复制代码
输入:nums = [4,1,2,1,2]
输出:4

示例 3

复制代码
输入:nums = [1]
输出:1

提示

复制代码
1 <= nums.length <= 3 * 10^4
-3 * 10^4 <= nums[i] <= 3 * 10^4

二、解题思路

本题核心特点:

  • 只有一个数字出现一次

  • 其他数字都出现两次

可以从三个方向解决:

1️⃣ 哈希表统计次数

2️⃣ 排序后成对查找

3️⃣ 位运算(最优解)

下面逐一介绍。


三、解法一:哈希表

思路

使用哈希表统计每个数字出现的次数:

  1. 遍历数组

  2. 统计每个数字出现次数

  3. 找到出现一次的数字

由于题目范围为:

复制代码
-30000 ~ 30000

可以直接用 数组模拟哈希表


C语言代码

复制代码
#include <stdlib.h>

int singleNumber(int* nums, int numsSize) {
    
    int offset = 30000;
    int hash[60001] = {0};
    
    for(int i = 0; i < numsSize; i++)
    {
        hash[nums[i] + offset]++;
    }
    
    for(int i = 0; i < 60001; i++)
    {
        if(hash[i] == 1)
            return i - offset;
    }
    
    return 0;
}

复杂度分析

复制代码
时间复杂度:O(n)
空间复杂度:O(n)

缺点:不满足题目 常量空间要求


四、解法二:排序

思路

先排序,然后每两个元素检查一次:

复制代码
1 1 2 2 4
      ↑

如果某个元素 和相邻元素不同,说明它只出现一次。


C语言代码

复制代码
#include <stdlib.h>

int cmp(const void* a, const void* b)
{
    return (*(int*)a - *(int*)b);
}

int singleNumber(int* nums, int numsSize) {
    
    qsort(nums, numsSize, sizeof(int), cmp);
    
    for(int i = 0; i < numsSize - 1; i += 2)
    {
        if(nums[i] != nums[i+1])
            return nums[i];
    }
    
    return nums[numsSize - 1];
}

复杂度分析

复制代码
时间复杂度:O(n log n)
空间复杂度:O(1)

缺点:排序导致时间复杂度不满足题目要求。


五、解法三:位运算(最优解)

核心思想

利用 异或 XOR 运算

异或的三个重要性质:

复制代码
a ^ a = 0
a ^ 0 = a
满足交换律和结合律

例如:

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

所有 成对出现的数字都会抵消,最后剩下的就是只出现一次的数字。


算法步骤

  1. 定义变量 res = 0

  2. 遍历数组

  3. 每个元素与 res 做异或

  4. 最终 res 即为答案


C语言代码

复制代码
int singleNumber(int* nums, int numsSize) {
    
    int res = 0;
    
    for(int i = 0; i < numsSize; i++)
    {
        res ^= nums[i];
    }
    
    return res;
}

执行过程示例

输入:

复制代码
[4,1,2,1,2]

计算过程:

复制代码
res = 0

0 ^ 4 = 4
4 ^ 1 = 5
5 ^ 2 = 7
7 ^ 1 = 6
6 ^ 2 = 4

最终结果:

复制代码
4

复杂度分析

复制代码
时间复杂度:O(n)
空间复杂度:O(1)

满足题目要求,是 最优解法


六、总结

解法 时间复杂度 空间复杂度 推荐
哈希表 O(n) O(n)
排序 O(n log n) O(1)
位运算 O(n) O(1) ⭐⭐⭐

最佳方案:位运算(XOR)

原因:

  • 时间复杂度 O(n)

  • 空间复杂度 O(1)

  • 代码简洁


本题属于经典位运算题,也是面试高频题。

相关推荐
怪奇云呼军6 分钟前
G.711、Opus 和重采样会拖慢识别吗?闪电智能VoiceAgent 的音频入口怎么选
java·人工智能·python·算法·云计算·音视频
ZC跨境爬虫19 分钟前
LeetCode 27. 移除元素(双指针详解 + Java Python 多解法对比)
java·python·leetcode
乐观勇敢坚强的老彭1 小时前
C++ 竞赛常用算法模板速查表
开发语言·c++·算法
高洁011 小时前
工信部教考中心证书
人工智能·深度学习·算法·机器学习·知识图谱
我变成萤火虫2 小时前
河南萌新联赛2026第(三)场:郑州轻工业大学
数据结构·c++·算法·贪心算法·stl·深度优先·哈希算法
Dr.kangder2 小时前
嵌入式面试总结(十九)——内存泄露
单片机·算法·面试·职场和发展·架构·硬件架构
白狐_7982 小时前
408数据结构第7章:B树①——基础概念与结构
数据结构·b树
Herbert_hwt2 小时前
【C语言基础】常量、选择结构与运算符全解析
c语言·开发语言·算法
Suxing93 小时前
C语言基础分享:从“租房”到“拆迁”,C语言动态内存管理
java·数据结构·算法
LuminousCPP3 小时前
单链表专题(四)-刷题复盘篇-LeetCode 138 随机链表复制|原地拷贝法突破复杂指针操作
数据结构·笔记·算法·leetcode·链表