LeetCode 热题 100-哈希表
哈希表
使用哈希表,可以将寻找 target - x 的时间复杂度降低到从 O(N) 降低到 O(1)。
创建一个哈希表,对于每一个 x,首先查询哈希表中是否存在 target - x,然后将 x 插入到哈希表中,即可保证不会让 x 和自己匹配。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { unordered_map<int, int> hash; for(int i = 0; i < nums.size(); i++){ if(hash.find(target - nums[i]) != hash.end()){ return {i, hash[target - nums[i]]}; } hash[nums[i]] = i; } return {}; } };
|
排序
把每个单词进行排序,异位词排序后的结果是一样的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Solution { public: vector<vector<string>> groupAnagrams(vector<string>& strs) { unordered_map<string, vector<string>> hash; for(string& s : strs){ string sortedS = s; sort(sortedS.begin(), sortedS.end()); hash[sortedS].push_back(s); }
vector<vector<string>> ans; for(auto &[_, value] : hash){ ans.push_back(value); }
return ans; } };
|
- 时间复杂度:O(nklogk),其中 n 是 strs 中的字符串的数量,k 是 strs 中的字符串的的最大长度。
- 空间复杂度:O(nk)
计数
对于每个字符串,首先使用哈希表统计每个字母出现的频率,然后将频率表转换为字符串作为键。这样处理完之后就得到与上一种方法类似的哈希表。最后将哈希表中的结果移到结果数组中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| class Solution { public: vector<vector<string>> groupAnagrams(vector<string>& strs) { unordered_map<string, vector<string>> hash;
for(const string& s : strs){ vector<int> cnt(26); for(char ch : s){ cnt[ch - 'a']++; } string freq; for(int i = 0; i < 26; i++){ freq += '#' + to_string(cnt[i]); } hash[freq].push_back(s); } vector<vector<string>> ans; for(auto& [_, value] : hash){ ans.push_back(value); } return ans; } };
|
哈希表
- 先将数组存储到集合中进行去重,用变量curLen和ans记录当前序列和最长序列的长度。
- 遍历集合,判断当前元素num的num-1是否在集合中,如果不在集合中,说明num是序列的起始,如果在集合中,直接跳过。
- 对于起始元素num,判断num+1,num+2,…是否在集合中,并更新序列长度,最后更新ans。
- 返回ans。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| class Solution { public: int longestConsecutive(vector<int>& nums) { int ans = 0; unordered_set<int> set; for(const int& num : nums){ set.insert(num); } for(const int& num : set){ if(!set.count(num - 1)){ int curLen = 1, curNum = num; while(set.count(curNum + 1)){ curNum++; curLen++; } ans = max(ans, curLen); } } return ans; } };
|
并查集
在刷剑指offer时还用过并查集的方法,这里仅复习一遍思路,因为其实现起来要比上面的方法复杂一些。简单理解,每个序列的起始相当于并查集的父亲。具体见这里。