Go語(yǔ)言LeetCode題解706設(shè)計(jì)哈希映射
題目描述
不使用任何內(nèi)建的哈希表庫(kù)設(shè)計(jì)一個(gè)哈希映射(HashMap)。
實(shí)現(xiàn) MyHashMap 類:
- MyHashMap() 用空映射初始化對(duì)象
- void put(int key, int value) 向 HashMap 插入一個(gè)鍵值對(duì) (key, value) 。如果 key 已經(jīng)存在于映射中,則更新其對(duì)應(yīng)的值 value 。
- int get(int key) 返回特定的 key 所映射的 value ;如果映射中不包含 key 的映射,返回 -1 。
- void remove(key) 如果映射中存在 key 的映射,則移除 key 和它所對(duì)應(yīng)的 value 。
示例:
輸入: ["MyHashMap", "put", "put", "get", "get", "put", "get", "remove", "get"] [[], [1, 1], [2, 2], [1], [3], [2, 1], [2], [2], [2]] 輸出: [null, null, null, 1, -1, null, 1, null, -1] 解釋: MyHashMap myHashMap = new MyHashMap(); myHashMap.put(1, 1); // myHashMap 現(xiàn)在為 [[1,1]] myHashMap.put(2, 2); // myHashMap 現(xiàn)在為 [[1,1], [2,2]] myHashMap.get(1); // 返回 1 ,myHashMap 現(xiàn)在為 [[1,1], [2,2]] myHashMap.get(3); // 返回 -1(未找到),myHashMap 現(xiàn)在為 [[1,1], [2,2]] myHashMap.put(2, 1); // myHashMap 現(xiàn)在為 [[1,1], [2,1]](更新已有的值) myHashMap.get(2); // 返回 1 ,myHashMap 現(xiàn)在為 [[1,1], [2,1]] myHashMap.remove(2); // 刪除鍵為 2 的數(shù)據(jù),myHashMap 現(xiàn)在為 [[1,1]] myHashMap.get(2); // 返回 -1(未找到),myHashMap 現(xiàn)在為 [[1,1]]
提示:
- 0 <= key, value <= 10^6
- 最多調(diào)用 104 次 put、get 和 remove 方法
思路分析
- 用切片+鏈表來(lái)作為散列表數(shù)據(jù)結(jié)構(gòu),利用切片的下標(biāo)快速定位槽,用鏈表作為槽存放真正的數(shù)據(jù)
- 最開始槽用的數(shù)組結(jié)構(gòu),但發(fā)現(xiàn)數(shù)組增刪元素時(shí)存在內(nèi)存的動(dòng)態(tài)申請(qǐng)和釋放,每次執(zhí)行耗時(shí)比較長(zhǎng),后來(lái)改用鏈表耗時(shí)有明顯下降;
- 通過(guò)key的哈希值對(duì)鏈表長(zhǎng)度取模來(lái)定位到槽位;
- 每個(gè)槽位有數(shù)據(jù)時(shí)才鏈接到鏈表頭,沒有數(shù)據(jù)時(shí)空間自然釋放;
- 具體增、刪元素的細(xì)節(jié)邏輯參考代碼注釋。
AC 代碼
type MyHashMap struct {
data []*Node // 切片+鏈表構(gòu)成散列表
cap int // 容量
}
// 鏈表節(jié)點(diǎn)
type Node struct {
k int
v int
next *Node
}
/** Initialize your data structure here. */
func Constructor() MyHashMap {
return MyHashMap{
data: make([]*Node, 1000),
cap: 1000,
}
}
/** value will always be non-negative. */
func (this *MyHashMap) Put(key int, value int) {
index := key % this.cap
// put時(shí)有三種Case:
// 1.槽不存在,直接新創(chuàng)建一個(gè)槽添加該元素
// 2.槽存在且已經(jīng)包含該元素,修改元素值,由于元素是值拷貝方式,需要重新賦值回去才能生效
// 3.槽存在但不包含該元素,追加元素
node := this.data[index]
if node == nil {
this.data[index] = &Node{key, value, nil}
return
}
for {
if node.k == key {
node.v = value
return
}
if node.next == nil {
node.next = &Node{key, value, nil}
return
}
node = node.next
}
}
/** Returns the value to which the specified key is mapped, or -1 if this map contains no mapping for the key */
func (this *MyHashMap) Get(key int) int {
node := this.data[key % this.cap]
for node != nil {
if node.k == key {
return node.v
}
node = node.next
}
return -1
}
/** Removes the mapping of the specified value key if this map contains a mapping for the key */
func (this *MyHashMap) Remove(key int) {
node := this.data[key % this.cap]
var pre *Node
for node != nil {
if node.k == key {
break
}
pre, node = node, node.next
}
// 未找到待刪除元素
if node == nil {
return
}
// 如果找到元素,有兩種情況:
// 1.待刪除元素是頭節(jié)點(diǎn),需要將新的頭節(jié)點(diǎn)更新到散列表中
// 2.待刪除元素是普通節(jié)點(diǎn),則直接讓前驅(qū)節(jié)點(diǎn)指向下一個(gè)節(jié)點(diǎn)
if pre == nil {
this.data[key % this.cap] = node.next
}else {
pre.next = node.next
}
}
/**
* Your MyHashMap object will be instantiated and called as such:
* obj := Constructor();
* obj.Put(key,value);
* param_2 := obj.Get(key);
* obj.Remove(key);
*/以上就是Go語(yǔ)言LeetCode題解706設(shè)計(jì)哈希映射的詳細(xì)內(nèi)容,更多關(guān)于Go語(yǔ)言設(shè)計(jì)哈希映射的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用Golang的gomail庫(kù)實(shí)現(xiàn)郵件發(fā)送功能
本篇博客詳細(xì)介紹了如何使用Golang語(yǔ)言中的gomail庫(kù)來(lái)實(shí)現(xiàn)郵件發(fā)送的功能,首先,需要準(zhǔn)備工作,包括安裝Golang環(huán)境、gomail庫(kù),以及申請(qǐng)126郵箱的SMTP服務(wù)和獲取授權(quán)碼,其次,介紹了在config文件中配置SMTP服務(wù)器信息的步驟2024-10-10
golang實(shí)現(xiàn)微信支付v3版本的方法
這篇文章主要介紹了golang實(shí)現(xiàn)微信支付v3版本的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03
golang 實(shí)現(xiàn)一個(gè)restful微服務(wù)的操作
這篇文章主要介紹了golang 實(shí)現(xiàn)一個(gè)restful微服務(wù)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-04-04
golang 64位linux環(huán)境下編譯出32位程序操作
這篇文章主要介紹了golang 64位linux環(huán)境下編譯出32位程序操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12
go語(yǔ)言題解LeetCode1299將每個(gè)元素替換為右側(cè)最大元素
這篇文章主要為大家介紹了go語(yǔ)言LeetCode刷題1299將每個(gè)元素替換為右側(cè)最大元素示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
golang 執(zhí)行命令行的實(shí)現(xiàn)
本文主要介紹了golang 執(zhí)行命令行的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
Golang線上內(nèi)存爆掉問(wèn)題排查(pprof)與解決
這篇文章主要介紹了Golang線上內(nèi)存爆掉問(wèn)題排查(pprof)與解決,涉及到數(shù)據(jù)敏感,文中代碼是我模擬線上故障的一個(gè)情況,好在我們程序都有添加pprof監(jiān)控,于是直接通過(guò)go tool pprof分析,需要的朋友可以參考下2024-04-04

