问题描述
在一个班级中,每位同学都拿到了一张卡片,上面有一个整数。有趣的是,除了一个数字之外,所有的数字都恰好出现了两次。现在需要你帮助班长小C快速找到那个拿了独特数字卡片的同学手上的数字是什么。
要求:
- 设计一个算法,使其时间复杂度为 O(n),其中 n 是班级的人数。
- 尽量减少额外空间的使用,以体现你的算法优化能力。
解题思路
思路一:第一反应是使用unordered_map,既能统计数量,占用空间也比数组小。
先问一下MarsCode AI unordered_map的基本使用方法
unordered_map 是 C++ 标准库中的一个关联容器,用于存储键值对。它基于哈希表实现,提供了快速的查找、插入和删除操作。下面是 unordered_map 的基本使用方法:
1. 包含头文件
首先,你需要包含 unordered_map 的头文件:
#include <unordered_map>
2. 声明和初始化
你可以声明一个 unordered_map,并指定键和值的类型:
std::unordered_map<int,
std::string> myMap;
3. 访问元素
你可以使用 [] 运算符或 at 方法来访问元素:
std::string value1 = myMap
[1]; // 访问键为1的元素
std::string value2 = myMap.
at(2); // 访问键为2的元素
4. 遍历元素
你可以使用范围for循环或迭代器来遍历 unordered_map:
for (const auto& pair :
myMap) {
std::cout << "Key: " <<
pair.first << ", Value:
" << pair.second <<
std::endl;
} 这样我们就知道可以使用unordered_map遍历数组,记录每个数字出现的次数,然后用第二次遍历找出只出现一次的数字。就像下面这样
int res=0;
std::unordered_map<int, int>f;
for(int i:cards){
f[i]++;
}
for(int i:cards){
if(f[i]==1) res=i;
}
思路二:为了尽量减少额外空间的使用,可以考虑使用位运算来解决这个问题。之前位运算用的很少,根本就没想到这方面,可以看到我们的豆包AI助手还是非常强大的。
算法步骤
-
异或运算的性质:异或运算(XOR)有一个非常有用的性质:
a ^ a = 0(任何数与自己异或结果为0)a ^ 0 = a(任何数与0异或结果为它本身)- 异或运算满足交换律和结合律,即
a ^ b ^ a = (a ^ a) ^ b = 0 ^ b = b
-
利用异或运算:我们可以遍历整个数组,对所有元素进行异或运算。由于相同的数字异或结果为0,最终剩下的就是那个唯一出现一次的数字。 这样只使用一次遍历即可得到答案,代码如下
int res=0;
for(int i:cards){
res^=i;
}