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)

  • 代码简洁


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

相关推荐
gumichef2 分钟前
*链表OJ
数据结构·链表
tankeven4 分钟前
动态规划专题(10):最优三角剖分问题
c++·算法·动态规划
黑眼圈子8 分钟前
动态规划问题专项练习(未编辑完成...
学习·算法·动态规划
探物 AI10 分钟前
【感知·车道线检测】UFLDv2车道线检测与车道偏离预警(LDWS)实战
人工智能·算法·目标检测·计算机视觉
菜鸟丁小真13 分钟前
LeetCode hot100 -54.螺旋矩阵
算法·leetcode·矩阵·知识点总结
如君愿18 分钟前
考研复习 Day 21 | 数据结构与算法--排序(上)
数据结构·考研·排序算法·记录考研
weixin_4684668522 分钟前
排列组合算法之隔板问题与错排公式
c++·算法·数学建模·排列组合·竞赛·错排·隔板
wsoz33 分钟前
Leetcode链表-day9
c++·算法·leetcode·链表
hnjzsyjyj1 小时前
全排列问题DFS实现执行示意图
数据结构·dfs
Lumos_7771 小时前
Linux -- 系统调用
linux·运维·算法