⓺➀ Insert Delete GetRandom O(1)

Top Interview 150, Data Structure, Leetcode medium, Algorithm, C++

Stu
彼得潘的 Swift iOS / Flutter App 開發教室
5 min readJun 6, 2024

--

Today’s code

Idea

這裡利用了map與vector兩個資料結構共同去解決此問題,map中的兩個鍵值(key, value)分別儲存:

key: key值儲存所輸入的val,我們可以利用val去搜尋是否以經有val的存在且時間複雜度為O(1)。

value: value值所儲存的是val在vector之中的索引(index),用於我們隨機存取。

這裡有一個有趣的規劃是,我們新增新的val值在vector時,都是從後面加入的也就是push_back,如此我們可以透過運算(vector.size() — 1)來確保目前要新增的值的索引值(index)並將其儲存在map所對應的value值中。

當然我們要移除元素時,我們事先透過map.find(val)搜尋,是否已經有val存在了,若有則取出他的value(也就是我們所儲存的val在vector之中的索引值index)

接著,我們將vector的最後一個元素賦值我們所搜尋到的索引的值,也就是說我們的目標移除的元素已經不在了,他變成了原本vector最後一個元素。

好的問題來了,目前vector有兩個元素是相同的,那就是vector的最後一個元素(vector.back()),我們只需要把vector的最後一個元素消除(erase)之後vector之中的每一個元素就會都是獨一無二的了。

更新完vector之後還要再更新map,因為原先map之中vector.back()的value已經改變,變成了我們最一開始要消除的val的索引值(pop.back())。

所以,map[vector[欲刪除的索引值]] = 欲刪除的索引值。用來更新整理map中vector的最後一個元素的index值(map的value值)。

最後再把map中的val刪掉。

class RandomizedSet {
private:
unordered_map<int, int>test_map;
vector<int> myvector;

public:
RandomizedSet() {
srand(time(NULL));
}

bool insert(int val) {
if(test_map.find(val) == test_map.end()){

myvector.push_back(val);
test_map[val] = myvector.size() - 1;
return true;
}else{
return false;
}
}

bool remove(int val) {
if(test_map.find(val) == test_map.end()){
return false;
}else{
auto tmp_it = test_map.find(val);
myvector[tmp_it->second] = myvector.back();
myvector.pop_back();
test_map[myvector[tmp_it->second]] = tmp_it->second;
test_map.erase(val);
return true;
}
}

int getRandom() {

int index = rand() % myvector.size();


return myvector[index];
}
};

/**
* Your RandomizedSet object will be instantiated and called as such:
* RandomizedSet* obj = new RandomizedSet();
* bool param_1 = obj->insert(val);
* bool param_2 = obj->remove(val);
* int param_3 = obj->getRandom();
*/

參考

--

--