这是采访问题。
我们正在开发一个k / v系统,其中一部分已经开发出来,我们需要你完成它。
已经完成的事情 -
1)返回任何字符串的散列,可以假设返回值始终是唯一的,没有碰撞, 这取决于你是否使用它
int hash(char *string);
你需要完成的事情 -
int set(char *key, char *value);
char *get(char *key);
我的回答是
struct kv {
int key;
char *value;
kv *next;
};
struct kv *top;
struct kv *end;
void set(char *key, char *value) {
if(top == NULL) {
top = malloc(struct kv);
end = top;
}
sturct kv *i = top;
int k = hash(key);
while(i != end) {
if(i->key == k) {
i->value = value;
return;
}
i = i->next;
}
i = malloc(struct kv);
i->key = k;
i->value = value;
end = i;
}
char *get(char *key) {
if(top == NULL) {
return NULL;
}
sturct kv *i = top;
int k = hash(key);
while(i != end) {
if(i->key == k) {
return i->value;
}
i = i->next;
}
return NULL;
}
问: - 有更快的方法吗?您认为最快的方式是什么?
答案 0 :(得分:1)
您所做的是创建一个链接列表来存储键值对。但正如您所看到的,搜索复杂度为O(n)
。您可以通过创建哈希表来加快速度。您已经有一个保证0冲突的哈希函数。
你能做的是
char* hash_tables[RANGE_OF_HASH] = {NULL}; // Your interviewer should provide you RANGE_OF_HASH
然后您的set
和get
成为 -
void set(char* key, char* value) {
hash_table[hash(key)] = value; // Can do this because no collisions are guaranteed.
}
char* get(char* key) {
return hash_table[hash(key)];
}
在这种情况下,由于您不必迭代所有插入的密钥,get
复杂度为O(1)
(同样为set
)。
但是你需要意识到这通常比你的方法占用更多的空间。
您的方法占用O(n)
空间但占用O(RANGE_OF_HASH)
。在内存是约束的情况下,这可能是不可接受的。
如果RANGE_OF_HASH
非常大(如INT_MAX
)并且您没有足够的内存用于hash_table,则可以创建多级哈希表。
例如,您的主hash_table
只有256
个广告位。每个条目将指向256个条目的另一个哈希表,依此类推。你将会有
做一些掩码来获取每个级别的哈希值。您可以按需分配每个级别。这样您就可以最大限度地减少内存使用量。
答案 1 :(得分:1)
有很多很好的方法可以做到这一点。这是一个小阅读清单,请仔细阅读。肯定有更多我不知道的事情。
在此之后,休息一下,振作起来,深入研究this article about computer memory。这已经是高级内容,并且会向您显示有时候更糟糕的big-O度量在实际场景中实际上可以表现得更好。这完全取决于将会有什么样的数据以及使用模式是什么。