当前位置: 首页 > news >正文

代码随想录笔记-哈希表

哈希表理论基础

哈希表是根据关键码的值而直接进行访问的数据结构。

  1. 哈希函数
  2. 哈希碰撞:有拉链法和线性探测法,后者需要保证哈希表size大于数据的size
  3. 常见hash结构
    • 数组
    • set
    • map
      带有unordered_x的数据结构底层是哈希表,并且无序,否则是 红黑树,底层有序,但是哈希表查询增删效率为 O ( 1 ) O(1) O(1),红黑树为 O ( l o g n ) O(logn) O(logn),红黑树的key不可修改,可以通过erase再insert的方式修改。

leetcode 242. 有效的字母异位词

class Solution {
public:bool isAnagram(string s, string t) {int cnts[26];int cntt[26];for (int i = 0; i < 26; i++)cnts[i] = cntt[i] = 0;for (char c : s)cnts[c - 'a']++;for (char c : t)cntt[c - 'a']++;for (int i = 0; i < 26; i++)if (cnts[i] != cntt[i])return false;return true;}
};

相关题目

leetcode 383. 赎金信

class Solution {
public:bool canConstruct(string ransomNote, string magazine) {int cnt[26] = {0};int cnt2[26] = {0};for (char c : ransomNote)cnt[c - 'a']++;for (char c : magazine)cnt2[c - 'a']++;for (int i = 0; i < 26; i++) {if (cnt[i] > cnt2[i])return false;}return true;}
};

49. 字母异位词分组

class Solution {
public:bool isAnagram(string& s, string& t) {if(s.size()!=t.size())return false;int cnts[26];int cntt[26];for (int i = 0; i < 26; i++)cnts[i] = cntt[i] = 0;for (char c : s)cnts[c - 'a']++;for (char c : t)cntt[c - 'a']++;for (int i = 0; i < 26; i++)if (cnts[i] != cntt[i])return false;return true;}vector<vector<string>> groupAnagrams(vector<string>& strs) {vector<vector<string>> res;vector<bool> used = vector<bool>(strs.size(), false);for (int i = 0; i < strs.size(); i++) {if (used[i])continue;res.push_back(vector<string>(1, strs[i]));used[i] = true;for (int j = i + 1; j < strs.size(); j++)if (isAnagram(strs[i], strs[j])) {res.back().push_back(strs[j]);used[j] = true;}}return res;}
};

leetcode 438. 找到字符串中所有字母异位词

// O(n^2)
class Solution {
public:bool isAnagram(string s, string t) {if (s.size() != t.size())return false;int cnts[26];int cntt[26];for (int i = 0; i < 26; i++)cnts[i] = cntt[i] = 0;for (char c : s)cnts[c - 'a']++;for (char c : t)cntt[c - 'a']++;for (int i = 0; i < 26; i++)if (cnts[i] != cntt[i])return false;return true;}vector<int> findAnagrams(string s, string p) {vector<int> res;if (s.size() < p.size())return {};for (int i = 0; i < s.size(); i++) {if (isAnagram(s.substr(i, p.size()), p)) {res.push_back(i);}}return res;}
};

统计滑动窗口和字符串 p 中每种字母数量的差;并引入变量 differ 来记录当前窗口与字符串 p 中数量不同的字母的个数,并在滑动窗口的过程中维护它。

在判断滑动窗口中每种字母的数量与字符串 p 中每种字母的数量是否相同时,只需要判断 differ 是否为零即可。

class Solution {
public:vector<int> findAnagrams(string s, string p) {int differ = 0;vector<int> cnt(26, 0);if (s.size() < p.size())return {};for (int i = 0; i < p.size(); i++) {cnt[s[i] - 'a']++;cnt[p[i] - 'a']--;}for (int i = 0; i < 26; i++) {if (cnt[i] != 0)differ++;}vector<int> res;if (differ == 0)res.push_back(0);for (int i = 0; i < s.size() - p.size(); i++) {cnt[s[i] - 'a']--;if (cnt[s[i] - 'a'] == 0)differ--;else if (cnt[s[i] - 'a'] == -1)differ++;cnt[s[i + p.size()] - 'a']++;if (cnt[s[i + p.size()] - 'a'] == 0)differ--;else if (cnt[s[i + p.size()] - 'a'] == 1)differ++;if (differ == 0)res.push_back(i + 1);}return res;}
};

leetcode 349. 两个数组的交集

class Solution {
public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {unordered_set<int> s1, s2;for (int i : nums1)s1.insert(i);for (int i : nums2)if (s1.count(i))s2.insert(i);return vector<int>(s2.begin(), s2.end());}
};

相关题目

350. 两个数组的交集 II
排序加双指针

class Solution {
public:vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {sort(nums1.begin(), nums1.end());sort(nums2.begin(), nums2.end());int p1 = 0, p2 = 0;vector<int> res;while (p1 < nums1.size() && p2 < nums2.size()) {if (nums1[p1] == nums2[p2]) {res.push_back(nums1[p1]);p1++;p2++;} else if (nums1[p1] > nums2[p2]) {while (p2 < nums2.size() && nums1[p1] > nums2[p2])p2++;} else {while (p1 < nums1.size() && nums1[p1] < nums2[p2])p1++;}}return res;}
};

leetcode 202. 快乐数

注意循环

class Solution {
public:int trans(int n) {int res = 0;while (n != 0) {res += (n % 10) * (n % 10);n /= 10;}return res;}bool isHappy(int n) {unordered_set<int> s;while (1) {n = trans(n);if (n == 1)return true;if (s.count(n))return false;elses.insert(n);}}
};

leetcode 1. 两数之和

分组+哈希表

class Solution {
public:vector<int> twoSum(vector<int>& nums, int target) {unordered_map<int, int> m;for (int i = 0; i < nums.size(); i++) {m.insert({target - nums[i], i});}for (int i = 0; i < nums.size(); i++) {if (m.count(nums[i]) && i != m[nums[i]])return {i, m[nums[i]]};}return {};}
};

leetcode 454. 四数相加 II

class Solution {
public:int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3,vector<int>& nums4) {unordered_map<int, int> m1;unordered_map<int, int> m2;for (int i = 0; i < nums1.size(); i++) {for (int j = 0; j < nums2.size(); j++) {int sum = nums1[i] + nums2[j];if (m1.count(sum))m1[sum]++;elsem1[sum] = 1;}}for (int k = 0; k < nums3.size(); k++) {for (int l = 0; l < nums4.size(); l++) {int sum = nums3[k] + nums4[l];if (m2.count(sum))m2[sum]++;elsem2[sum] = 1;}}int res = 0;for (auto& it : m1) {if (m2.count(-it.first)) {res += m1[it.first] * m2[-it.first];}}return res;}
};

leetcode 15. 三数之和

class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {// 排序+指针sort(nums.begin(), nums.end());vector<vector<int>> res;for (int i = 0; i < nums.size(); i++) {int left = i + 1, right = nums.size() - 1;if (i > 0 && nums[i] == nums[i - 1]) { // 去重continue;}while (left < right) {if (nums[i] + nums[left] + nums[right] == 0) {res.push_back({nums[i], nums[left], nums[right]});// 去重while (right > left && nums[right] == nums[right - 1])right--;while (right > left && nums[left] == nums[left + 1])left++;// 收缩right--;left++;} else if (nums[i] + nums[left] + nums[right] > 0) {right--;} else {left++;}}}return res;}
};

leetcode 18. 四数之和

class Solution {
public:vector<vector<int>> fourSum(vector<int>& nums, int target) {// 排序+指针sort(nums.begin(), nums.end());vector<vector<int>> res;for (int i = 0; i < nums.size(); i++) {if (i > 0 && nums[i] == nums[i - 1]) { // 去重continue;}for (int j = i + 1; j < nums.size(); j++) {if (j > i + 1 && nums[j] == nums[j - 1]) { // 去重continue;}int left = j + 1, right = nums.size() - 1;while (left < right) {if (nums[i] + nums[j] + nums[left] + nums[right] == target) {res.push_back({nums[i], nums[j], nums[left], nums[right]});// 去重while (right > left && nums[right] == nums[right - 1])right--;while (right > left && nums[left] == nums[left + 1])left++;// 收缩right--;left++;} else if (nums[i] + nums[j] + nums[left] + nums[right] >target) {right--;} else {left++;}}}}return res;}
};

相关文章:

  • 万字长篇————C语言指针学习汇总
  • 数据库表设计五层分类系统表设计
  • 测试定时发布
  • How AI could empower any business - Andrew Ng
  • VueDOMPurifyHTML 防止 ​​XSS(跨站脚本攻击)​​ 风险
  • 组合数哭唧唧
  • C# 基类型和派生类型之间的转型
  • DDS信号发生器设计(Quartus)
  • 35. 搜索插入位置
  • python数据类型处理题,输出素数题
  • Flink SQL SavePoint最佳实践
  • 【项目(一)】-仿mudou库one thread oneloop式并发服务器实现
  • 【Qt】界面优化
  • 4.1.1 Redis相关命令详解及其原理
  • 深入解析分类模型评估指标:ROC曲线、AUC值、F1分数与分类报告
  • OCCT 入门(3)核心模块与架构
  • 游戏测试入门知识
  • matlab中进行海浪模型仿真
  • 利用pnpm patch命令实现依赖包热更新:精准打补丁指南
  • ARM Cortex汇编宏定义
  • 华侨城A:一季度营收53.63亿元,净利润亏损14.19亿元
  • 绵阳造AI机器狗参与警务工作,演练中辅助民警控制“嫌疑人员”
  • 伊朗港口爆炸已致40人死亡
  • 凝聚多方力量,中国农科院油菜产业专家团部署单产提升新任务
  • 报告:到2030年我国无人机产业将率先实现万亿规模
  • 洗冤录·巴县档案|道咸年间一起家暴案