leetcode——哈希表与哈希集合总结

一、基础介绍

无序容器

二、高频题目

两数之和——哈希表记录数字与索引
1、遍历数字,哈希表中查找target-nums[i]
2、找不到,count[nums[i]]=i
3、找得到,返回{i,count[target-nums[i]]}

350. 两个数组的交集 II——哈希表记录数字与出现次数
1、哈希表记录nums1数字出现次数
2、遍历nums2,如果元素在hashtable出现次数大于0,计数-1,加入ans

128. 最长连续序列——哈希集合去重
1、哈希集合去重nums
2、遍历哈希集合
3、确保每次从最小元素开始,即count[i-1]==0,否则contine
4、当前值+1,在哈希集合while查找,直到没有连续值
5、保留最大maxlength

73. 矩阵置零
——两哈希集合,分别记录矩阵哪行,哪列会被置为0 (空间复杂度O(m+n))
1、创建两哈希集合
2、遍历矩阵,当元素为0,对应行对应列被加入
3、原地更新矩阵,当对应行或列被标记,该元素被置为0
——利用矩阵第一行第一列作为标记数组,设置两个变量记录 (空间复杂度O(1))
1、记录第一行
2、记录第一列
3、利用第一行第一列,更新标记数组
4、利用标记数组,更新矩阵
5、根据标记更新第一行
6、根据标记更新第一列
(第一行与第一列的0 对应列对应行的效果还是保存在标记数组中的)

49. 字母异位词分组——哈希表统计单词,key为排序后,value为原单词
1、遍历字符串数组,哈希表统计key对应的单词向量
2、将哈希表的第二个元素,即value,进行二维字符串数组的转换

380. O(1) 时间插入、删除和获取随机元素——向量+哈希表
1、结合向量的索引查找O(1) 和哈希表key查询k O(1)
2、插入元素,判断元素是否重复,不重复则在map和nums插入元素
3、删除元素,判断元素是否存在,存在则
3.1 找到nums的最后一个元素
3.2 map中更新最后一个元素的索引
3.3 nums中更新最后一个元素的值
3.4 在map和nums中删除元素
4、随机返回元素,利用随机产生的索引访问nums

299. 猜数字游戏——哈希表记录guess数字出现次数
1、哈希表记录guess数字出现次数
2、遍历secret guess 若单词相同位置元素相等 则countA++ 同时用计数–
3、遍历secret guess 若单词不相等但哈希表内有计数 则countB++ 同时计数–
4、将答案连接成字符串
(一个for会导致hashcount提前被不匹配的位置用完,所以一定要两个for)

348.设计井字棋——两个标记向量,一个对角线标记变量,一个副对角线标记变量
1、申请行、列、对角线标记空间
2、判断是两个玩家在放棋,1玩家为+1操作,2玩家为-1操作
3、玩家放棋子,对应行,列,(对角线)发生变化
3.1 row[i]+=tmp,column[j]+=tmp
3.2 若i=j,dig+=tmp
3.3 若i+j=size-1,a_dig+=tmp
4、根据每行每列或每对角线的放置棋子个数,判断是否有玩家胜出

146. LRU 缓存机制——哈希表+双向链表
1、双向链表的实现——删除尾部,删除节点,移到头部,加入头部
2、缓存初始化——获取容量,申请链表的头尾指针
3、插入元素
3.1 若不存在,生成节点,插入头部,插入哈希,size++,判断size是否超过容量…
3.2 若存在,哈希定位,更改value,移到头部
4、 获取元素——哈希定位,移到头部,返回value

//双向链表结构体
struct DLinkedNode {
    int key, value;
    DLinkedNode* prev;
    DLinkedNode* next;
    DLinkedNode(): key(0), value(0), prev(nullptr), next(nullptr) {}
    DLinkedNode(int _key, int _value): key(_key), value(_value), prev(nullptr), next(nullptr) {}
};
// 初始化链表
void init(){
		head = new DLinkedNode();
        tail = new DLinkedNode();
        head->next = tail;
        tail->prev = head;
}
//添加到头部——修改node前后指针,修改后元素前指针,修改前元素后指针
void addToHead(DLinkedNode* node) {
    node->prev = head;
    node->next = head->next;
    head->next->prev = node;
    head->next = node;
}
//移除结点——修改node前元素后指针,修改node后元素前指针
void removeNode(DLinkedNode* node) {
    node->prev->next = node->next;
    node->next->prev = node->prev;
}
//移动到头部——删除节点,加入头部
void moveToHead(DLinkedNode* node) {
    removeNode(node);
    addToHead(node);
}
//移除尾部——删除tail的前一个节点
DLinkedNode* removeTail() {
    DLinkedNode* node = tail->prev;
    removeNode(node);
    return node;
}

三、思考与收获

1、什么时候使用哈希表?
1)对出现次数进行计数
2)需要key到value的映射
3)需要快速根据key进行查询

2、什么时候使用哈希集合?
1)元素去重
2)无需key到value的映射
3)需要快速根据key进行查询
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值