【leetcode】136.只出现一次的数字

文章目录


碎碎念

好!自此已经刷完hot100的所有简单题!只是还欠了好多篇题解还没写,一点一点跟上吧!今天还学了一点简单的响应式布局,还差一个flex布局就真的算小小小小入门前端啦,项目也有一点点在拉起来了,今天很好很好!


一、题目

二、思路和题解

1.思路

这题首先想到的是用集合,遍历整个整个nums,出现第一次就加入集合,出现第二次再从集合中删除,当遍历完整个数组,就只剩下只出现一次的数啦。但是!思路很美好,苯人技术还是有比较大的进步空间的...我不是很会用集合...

所以还是看了一下题解学到一个思路,是用异或来做。

我们知道异或是 "同0异1" ,基本的运算规则如下:
0 ⊕ 0 = 0 0 ⊕ 1 = 1 1 ⊕ 0 = 1 1 ⊕ 1 = 0 0 \oplus 0=0\\ 0 \oplus 1=1\\ 1 \oplus 0=1\\ 1 \oplus 1=0 0⊕0=00⊕1=11⊕0=11⊕1=0

所以当我们初始化一个res=0,之后遍历整个数组,对每个数都做异或运算,这样只要出现两次的数就会自己和自己异或"消除掉"了,最后剩下的数就相当于与0异或还是它自己,也就是我们要找的只出现一次的数了。

2.代码(位运算,异或)

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

三、其他解法

这里当然就得补充一下咱们刚刚提到的集合的做法了(在学了在学了!)

1.集合增删法

思路就不赘述了,直接上代码。

cpp 复制代码
class Solution {
public:
    int singleNumber(vector<int>& nums) {
    	// acm的话记得包含<unordered_set>头文件
        unordered_set<int> s; // 定义无序集合,查询/增删效率为O(1)
        
        for (int num : nums) {
            if (s.count(num)) { // 集合中已有该数字(出现第二次)
                s.erase(num);   // 从集合删除
            } else {            // 集合中无该数字(出现第一次)
                s.insert(num);  // 加入集合
            }
        }
        
        // 最终集合中只有一个元素,返回该元素(*s.begin()取第一个元素)
        return *s.begin();
    }
};

2.哈希表统计次数

先用哈希表来存储「数字 → 出现次数」,接着遍历数组统计每个数字的出现次数,最后再遍历哈希表,找到出现次数是1次的数字,就是我们的答案啦。

cpp 复制代码
#include <vector>
#include <unordered_map> // 哈希表头文件
using namespace std;

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        unordered_map<int, int> count_map; // key=数字,value=出现次数
        
        // 统计每个数字的出现次数
        for (int num : nums) {
            count_map[num]++; // 不存在的key会自动初始化为0,再+1
            /*也可以写成下面这样,更好理解一点:
            看一下num在不在这个哈希表中,如果不在哈希表中,则查找到的是哈希表的尾后迭代器,那就需要新增。
            if (count_map.find(num) != count_map.end()) {
			    count_map[num] += 1;
			} else {
			    count_map[num] = 1;
			}*/
        }
        
        // 遍历哈希表找次数=1的数字
        for (auto& pair : count_map) {
            if (pair.second == 1) { // pair.second 是次数
                return pair.first;  // pair.first 是数字
            }
        }
        
        return -1; // 题目保证有解,仅防止编译报错
    }
};

3.集合求和差值

这个稍微有点技巧性(我觉得),这里我们用到的是这样一个公式:
唯一数 = 2 × ( 集合所有元素和 ) − ( 数组所有元素和 ) 唯一数=2×(集合所有元素和)−(数组所有元素和) 唯一数=2×(集合所有元素和)−(数组所有元素和)

  • 集合存储所有唯一元素,因此「集合和 ×2」等价于「所有元素都出现 2 次的总和」;
  • 数组总和 = 「唯一数 ×1」 + 「其余数 ×2」;
  • 两者的差值就是唯一数(其余数的 2 倍被抵消,只剩唯一数)。
cpp 复制代码
#include <vector>
#include <unordered_set>
#include <numeric> // 求和函数 accumulate 的头文件
using namespace std;

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        unordered_set<int> s(nums.begin(), nums.end()); // 集合存储所有唯一元素
        
        // 手动遍历求和
        long long sum_set = 0;
        for (int num : s) {
            sum_set += num;
        }
        
        // 也可以用STL的accumulate函数,但acm要记得包含<numeric>头文件
        // long long sum_set = accumulate(s.begin(), s.end(), 0LL);//0LL表示以 long long 类型初始化累加值,否则 accumulate 会默认用 int 累加,可能溢出
        
        // 计算数组所有元素的和
        long long sum_nums = accumulate(nums.begin(), nums.end(), 0LL);
        
        return 2 * sum_set - sum_nums;
    }
};

四、错误回顾

不会用集合和哈希表。

相关推荐
CoovallyAIHub1 天前
Moonshine:比 Whisper 快 100 倍的端侧语音识别神器,Star 6.6K!
深度学习·算法·计算机视觉
CoovallyAIHub1 天前
速度暴涨10倍、成本暴降6倍!Mercury 2用扩散取代自回归,重新定义LLM推理速度
深度学习·算法·计算机视觉
CoovallyAIHub1 天前
实时视觉AI智能体框架来了!Vision Agents 狂揽7K Star,延迟低至30ms,YOLO+Gemini实时联动!
算法·架构·github
CoovallyAIHub1 天前
开源:YOLO最强对手?D-FINE目标检测与实例分割框架深度解析
人工智能·算法·github
CoovallyAIHub1 天前
OpenClaw:从“19万星标”到“行业封杀”,这只“赛博龙虾”究竟触动了谁的神经?
算法·架构·github
刀法如飞1 天前
程序员必须知道的核心算法思想
算法·编程开发·算法思想
徐小夕1 天前
pxcharts Ultra V2.3更新:多维表一键导出 PDF,渲染兼容性拉满!
vue.js·算法·github
CoovallyAIHub1 天前
OpenClaw一脚踩碎传统CV?机器终于不再只是看世界
深度学习·算法·计算机视觉
CoovallyAIHub1 天前
仅凭单目相机实现3D锥桶定位?UNet-RKNet破解自动驾驶锥桶检测难题
深度学习·算法·计算机视觉