哈希表最大的优点,就是把数据的存储和查找消耗的时间大大降低,时间复杂度为O(1);而代价仅仅是消耗比较多的内存。
-
两数之和: https://leetcode-cn.com/problems/two-sum/
方法二:哈希表 思路及算法 创建一个哈希表,对于每一个x,首先查询哈希表中是否存在target-x,然后将x插入到哈希表中,即可保证不会让x 和自己匹配。 class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { unordered_map<int, int> hashtable; //unordered_map创建一个哈希表 for (int i = 0; i < nums.size(); ++i) { auto it = hashtable.find(target - nums[i]); //it 表示的是hashtable的第一整个元素; //it->first 表示的是这个元素的key的值; //it->second 表示的是这个元素的value的值。 if (it != hashtable.end()) { return {it->second, i}; //??? it->second不是指向的是value? } hashtable[nums[i]] = i; } return {}; } }; 复杂度分析 时间复杂度:O(N),其中 N 是数组中的元素数量。对于每一个元素 x,我们可以 O(1) 地寻找 target - x。 空间复杂度:O(N),其中 N 是数组中的元素数量。主要为哈希表的开销。
-
存在重复元素: https://leetcode-cn.com/problems/contains-duplicate/
class Solution { public: bool containsDuplicate(vector<int>& nums) { unordered_set<int> s; for (int x: nums) { //查找函数 find() 通过给定主键查找元素 //如果s.find()要找的值在set中则返回一个指向该值的迭代器, //如果没有找到则返回s.end()。 if (s.find(x) != s.end()) { return true; } s.insert(x); } return false; } }; 复杂度分析 时间复杂度:O(N),其中 N 为数组的长度。 空间复杂度:O(N),其中 N 为数组的长度。
-
最长和谐子序列: https://leetcode-cn.com/problems/longest-harmonious-subsequence/
方法二:哈希表 思路与算法 遍历数组找出所有的 x 和x+1的出现的次数,用一个哈希映射来存储每个数出现的次数,这样就能在O(1) 的时间内得到x和x+1 出现的次数。 我们首先遍历一遍数组,得到哈希映射。随后遍历哈希映射,设当前遍历到的键值对为(x, value),那么我们就查询x+1 在哈希映射中对应的统计次数,就得到了x和x+1 出现的次数,和谐子序列的长度等于 x 和 x+1 出现的次数之和。 class Solution { public: int findLHS(vector<int>& nums) { unordered_map<int, int> cnt; int res = 0; for (int num : nums) { cnt[num]++; } for (auto [key, val] : cnt) { if (cnt.count(key + 1)) { res = max(res, val + cnt[key + 1]); } } return res; } }; 复杂度分析 时间复杂度:O(N),其中N为数组的长度。 空间复杂度:O(N),其中N为数组的长度。数组中最多有N个不同元素,因此哈希表最多存储N个数据。
-
最长连续序列: https://leetcode-cn.com/problems/longest-consecutive-sequence/
class Solution { public: int longestConsecutive(vector<int>& nums) { unordered_set<int> num_set; //创建一个哈希表 for (const int& num : nums) { num_set.insert(num); //去掉重复的值 } int longestStreak = 0; for (const int& num : num_set) { if (!num_set.count(num - 1)) { //当存在x-1的数时,则跳过,否则就执行下面当前值加1的操作 int currentNum = num; int currentStreak = 1; while (num_set.count(currentNum + 1)) { currentNum += 1; currentStreak += 1; } longestStreak = max(longestStreak, currentStreak); } } return longestStreak; } }; 复杂度分析 时间复杂度:O(n),其中 n 为数组的长度。 空间复杂度:O(n)。哈希表存储数组中所有的数需要 O(n) 的空间。