最长连续序列(每天刷力扣hot100系列)
目录
题目介绍:
哈希表法:
复杂度分析:
思路分析:
unordered_set 和 unordered_map的比较:
1. 核心区别
2. 使用场景
3. 在本题中的选择
4. 性能对比
5. 成员函数差异
unordered_table.begin()函数是返回的键还是值,unordered_set.begin()函数返回的又是什么呢?
1. unordered_map 的 begin()
2. unordered_set 的 begin()
关键区别
题目介绍:
哈希表法:
#include <unordered_set>
#include <algorithm> // for max()class Solution {
public:int longestConsecutive(vector<int>& nums) {if (nums.empty()) return 0; // 处理空数组unordered_set<int> numSet(nums.begin(), nums.end()); // 存储所有数字int maxLen = 0;for (int num : numSet) {// 只处理序列起点(num-1不在集合中)if (numSet.find(num - 1) == numSet.end()) {int currentNum = num;int currentLen = 1;// 扩展连续序列while (numSet.find(currentNum + 1) != numSet.end()) {currentNum++;currentLen++;}maxLen = std::max(maxLen, currentLen); // 更新最大长度}}return maxLen;}
};
复杂度分析:
时间复杂度:O(n),其中 n 为数组的长度。具体分析已在上面正文中给出。
空间复杂度:O(n)。哈希表存储数组中所有的数需要 O(n) 的空间。
思路分析:
这题的思路就是先用哈希表unordered_set装初始nums数组,不需要索引所以用unordered_set而不是unordered_table。
首先遍历哈希表:
1.进入条件是必须所在num-1的位置不是连续的
2.这时候currentnum和currentlen初始化,currentnum指向num这个数,currentlen为1
3.然后while循环用来计算出在这之后有多少连续的整数:
4.如果下一个数字不再连续了,则记录更新maxlen,接着下一轮的循环
5.如果num-1都是连续的,则直接下一轮,直到num-1断了重新初始化(即第2步)
最后返回manlen值。
unordered_set
和 unordered_map的比较:
unordered_set
和 unordered_map
是 C++ STL 中的两种哈希容器
1. 核心区别
特性 | unordered_set | unordered_map |
---|---|---|
存储内容 | 仅存储键(key) | 存储键值对(key-value pairs) |
用途 | 快速判断元素是否存在(去重、集合操作) | 通过键快速查找/访问关联的值(字典) |
元素访问 | 直接通过键访问 | 通过键访问对应的值(map[key] ) |
内存占用 | 更低(仅存储键) | 更高(需存储键和值) |
是否允许重复键 | 不允许(自动去重) | 不允许重复键(但值可重复) |
2. 使用场景
-
unordered_set
-
检测元素是否存在(如“是否包含数字 5”)。
-
去重(如统计唯一元素个数)。
-
集合运算(并集、交集等)。
示例:
unordered_set<int> s = {1, 2, 3}; if (s.find(2) != s.end()) { /* 2存在 */ }
-
-
unordered_map
-
建立键到值的映射(如“学生ID到成绩”)。
-
需要记录额外信息(如数字的出现次数)。
示例:
unordered_map<int, string> m = {{1, "Alice"}, {2, "Bob"}}; cout << m[1]; // 输出 "Alice"
-
3. 在本题中的选择
-
为什么用
unordered_set
?
您只需要判断数字是否存在,无需存储额外信息(如索引)。unordered_set
更节省内存且语义更直接。错误用法(原代码):
unordered_map<int, int> hashtable; // 存储了无用的索引 hashtable[nums[i]] = i; // 值(i)未被使用
正确用法:
unordered_set<int> numSet(nums.begin(), nums.end()); if (numSet.find(5) != numSet.end()) { /* 5存在 */ }
4. 性能对比
-
插入/查找时间复杂度:两者均为平均 O(1)(最坏 O(n),哈希冲突时)。
-
空间效率:
unordered_set
更优(无需存储值)。
5. 成员函数差异
操作 | unordered_set | unordered_map |
---|---|---|
插入元素 | insert(key) | insert({key, value}) |
访问元素 | 只能通过迭代器遍历 | map[key] 或 map.at(key) |
删除元素 | erase(key) | erase(key) |
unordered_table.begin()函数是返回的键还是值,unordered_set.begin()函数返回的又是什么呢?
在 C++ 的 unordered_map
和 unordered_set
中,begin()
函数返回的是 迭代器(iterator),但它们的解引用行为不同,具体取决于容器类型:
1. unordered_map
的 begin()
-
返回内容:返回指向第一个键值对(
std::pair<const Key, Value>
)的迭代器。 -
访问键和值:
-
键:用
it->first
或(*it).first
。 -
值:用
it->second
或(*it).second
。
-
-
示例:
unordered_map<int, string> m = {{1, "Alice"}, {2, "Bob"}}; auto it = m.begin(); cout << it->first; // 输出键:1 cout << it->second; // 输出值:"Alice"
2. unordered_set
的 begin()
-
返回内容:返回指向第一个元素(键本身)的迭代器。
-
访问元素:直接解引用迭代器(
*it
)。 -
示例:
unordered_set<int> s = {1, 2, 3}; auto it = s.begin(); cout << *it; // 输出元素:1(键本身)
关键区别
容器 | begin() 返回的迭代器解引用结果 | 访问方式 |
---|---|---|
unordered_map | std::pair<const Key, Value> | it->first (键)it->second (值) |
unordered_set | 直接是键(Key ) | *it |
求三连~~~