一、题目概述
首先道个歉,昨天看S12总决赛去了,上午看完下午任务太多了,就只把题写了,没来写总结。。。那个题也不是太难,没什么好说的,就先不说了。
但是每日任务没完成,还是一个非常不好的行为TuT
今天这个题还是一道简单题,三天两道简单题,我还是蛮开心的,但是一直做简单题,我怕我的能力上不去,期待一下明天是我只是范围外的中档题。
这个题会涉及到一些之前哈希表的知识,有兴趣的可以翻一下第二篇每日一题看一下,那里介绍了一部分。
二、个人思路
设计哈希映射,我第一眼看到这个的时候,我的反应是,让我们自己设计函数嘛,那不是有很多种答案?然后看了一眼题,原来是让我们实现一些函数功能,有点像运算符重载。这个题型还是挺新颖的,实现成员函数。
我的代码如下:
class MyHashMap {
public:
MyHashMap() {
}
vector<int> keys;
vector<int> values;
void put(int key, int value) {
for(int i=0;i<keys.size();i++){
if(keys[i]==key)
values[i]=value;
return;
}
keys.push_back(key);
values.push_back(value);
return ;
}
int get(int key) {
for(int i=0;i<keys.size();i++){
if(keys[i]==key)
return values[i];
}
return -1;
}
void remove(int key) {
for(int i=0;i<keys.size();i++){
if(keys[i]==key){
keys.erase(keys.begin()+i);
values.erase(values.begin()+i);
return ;
}
}
return ;
}
};
/**
* Your MyHashMap object will be instantiated and called as such:
* MyHashMap* obj = new MyHashMap();
* obj->put(key,value);
* int param_2 = obj->get(key);
* obj->remove(key);
*/
我的思路简单粗暴,把哈希表看成几个并列的一维数组,相同下标标着同一组的key和value,然后三个函数分别对两个数组操作,简单易懂,就是时间复杂度估计不小,应该是O(n)这样,空间的话随着数据增加,我占的空间也多了。
但是还是,没把所有点都过去,应该是put出问题了,更新实现的不好。
三、大佬思路
这么说吧,基本我都没看懂,首先官方题解,给出来一大堆东西,我一点都没看懂,然后再看看其他人的题解,有用拉链法的,有用超大数组法的,我感觉拉链法和超大数组法都不是太好,所以我决定硬啃官方题解。
class MyHashMap {
private:
vector<list<pair<int, int>>> data;
static const int base = 769;
static int hash(int key) {
return key % base;
}
public:
/** Initialize your data structure here. */
MyHashMap(): data(base) {}
/** value will always be non-negative. */
void put(int key, int value) {
int h = hash(key);
for (auto it = data[h].begin(); it != data[h].end(); it++) {
if ((*it).first == key) {
(*it).second = value;
return;
}
}
data[h].push_back(make_pair(key, value));
}
/** Returns the value to which the specified key is mapped, or -1 if this map contains no mapping for the key */
int get(int key) {
int h = hash(key);
for (auto it = data[h].begin(); it != data[h].end(); it++) {
if ((*it).first == key) {
return (*it).second;
}
}
return -1;
}
/** Removes the mapping of the specified value key if this map contains a mapping for the key */
void remove(int key) {
int h = hash(key);
for (auto it = data[h].begin(); it != data[h].end(); it++) {
if ((*it).first == key) {
data[h].erase(it);
return;
}
}
}
};
时间复杂度:O(n/b)。其中 n 为哈希表中的元素数量,b 为链表的数量。假设哈希值是均匀分布的,则每个链表大概长度为 n/b 。
空间复杂度:O(n+b)。
作者:LeetCode-Solution
链接:https://leetcode.cn/problems/design-hashmap/solution/she-ji-ha-xi-ying-she-by-leetcode-soluti-klu9/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
首先第一行那个套娃,我就没看懂,然后查了一下。vector不说了,list就是链表,pair是C++中一种模板类型。每个pair对象可以存储两个值,这两个值可以是不同的数据类型。存储的值可以是基本数据类型也可以是自定义数据类型。
以下一些内容参考C++中pair用法,C++中vector,list,map用法。
那这句话就是一个能存一对数据的链表所做成的vector,挺绕的,但是好好捋顺一下还是能看懂。
后面那个,设哈希表的大小为 base,则可以设计一个简单的哈希函数:hash(x)=x mod base。
我们开辟一个大小为 base 的数组,数组的每个位置是一个链表。当计算出哈希值之后,就插入到对应位置的链表当中。
由于我们使用整数除法作为哈希函数,为了尽可能避免冲突,应当将 \textit{base}base 取为一个质数。在这里,我们取 base=769。
data(base) 是一个vector的初始化,弄出来一个base这么大的vector。
下面那个auto是自动数据类型,他根据你后面的数值来确定你这个变量是什么类型,比如 auto a=5,那a就是int型。这里面的auto是迭代器型iterator,但那个for语句跟我写的也没什么区别,意思是一样的。
在下面的make_pair函数就是pair的一个简化,生成一对数据用的,要不然每次都要
pair<int,int>(1,1),太麻烦了,我们用 make_pair(1,1) ,能简单不少。
别的,感觉没什么好讲的了,这个代码,我第一眼看上去挺复杂,但是搜索一下慢慢学,还是能学懂,有的虽然没学过,但是看那个英语也能看懂。
看懂是一回事,希望下次我自己也能写出这样的代码。
四、总结
今天我们复习了一下vector的一些操作,然后给哈希表的一些操作自己实现了一遍,加深了印象。
新知识的话,我们了解了List,Pair这两个新的数据结构,然后学习了auto这一自动数据类型。list的相关操作有很多,和vector差不多,语法也差不多,想都学会都记住,是需要下功夫的,我们还是那个打法,遇到哪个就记哪个,慢慢学就好了。