C++ std::vector中push_back操作空間溢位
今天在做leetcode 705、706時候遇到一個錯誤。
題連結:https://leetcode.com/problems/design-hashmap/description/
- [817] Design HashMap * *
https://leetcode.com/problems/design-hashmap/description/ * *
algorithms * Easy (48.96%) * Total Accepted: 9.2K * Total
Submissions: 18.8K * Testcase Example:
‘[“MyHashMap”,“put”,“put”,“get”,“get”,“put”,“get”, “remove”,
“get”]\n[[],[1,1],[2,2],[1],[3],[2,1],[2],[2],[2]]’ * * Design a
HashMap without using any built-in hash table libraries. * * To be
specific, your design should include these functions: * * *
put(key, value) : Insert a (key, value) pair into the HashMap. If the
value * already exists in the HashMap, update the value. * get(key):
Returns the value to which the specified key is mapped, or -1 if *
this map contains no mapping for the key. * remove(key) : Remove the
mapping for the value key if this map contains the * mapping for the
key. * * * * Example: * * * MyHashMap hashMap = new
MyHashMap(); * hashMap.put(1, 1); * hashMap.put(2, 2);- hashMap.get(1); // returns 1 * hashMap.get(3); // returns -1 (not found) * hashMap.put(2, 1); // update the
existing value * hashMap.get(2); // returns 1 *
hashMap.remove(2); // remove the mapping for 2 *
hashMap.get(2); // returns -1 (not found) * * * *
Note: * * * All keys and values will be in the range of [0,
1000000]. * The number of operations will be in the range of [1,
10000]. * Please do not use the built-in HashMap library.
題目要求實現一個hash表
在實現過程中使用了vector<int>
進行模擬,但是令人想不到的是不是時間超時,而是空間溢位。QAQ???納尼?
程式碼:
class MyHashMap {
private:
vector<int>m;
public:
/** Initialize your data structure here. */
MyHashMap() {
for(int i=0;i<=1000000;i++)
{
m.push_back(-1);
}
}
/** value will always be non-negative. */
void put(int key, int value) {
m[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) {
return m[key];
}
/** Removes the mapping of the specified value key if this map contains a mapping for the key */
void remove(int key) {
m[key]=-1;
}
};
/**
* 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);
*/
額好吧,到底怎麼回事呢?QAQ
以下引自:https://blog.csdn.net/u011417820/article/details/79959825
我們在使用 vector 時,最常使用的操作恐怕就是插入操作了(push_back),那麼當執行該操作時,該函式都做了哪些工作呢?
該函式首先檢查是否還有備用空間,如果有就直接在備用空間上構造元素,並調整迭代器 finish,使
vector變大。如果沒有備用空間了,就擴充空間,重新配置、移動資料,釋放原空間。其中判斷是否有備用空間,就是判斷 finish是否與 end_of_storage 相等.如果
finish != end_of_storage,說明還有備用空間,否則已無備用空間。
當執行 push_back 操作,該 vector 需要分配更多空間時,它的容量(capacity)會增大到原來的 m
倍。現在我們來均攤分析方法來計算 push_back 操作的時間複雜度。假定有 n 個元素,倍增因子為 m。那麼完成這 n 個元素往一個 vector 中的push_back操作,需要重新分配記憶體的次數大約為
logm(n),第 i 次重新分配將會導致複製 m^i (也就是當前的vector.size() 大小)箇舊空間中元素,因此 n 次
push_back操作所花費的總時間約為 n*m/(m - 1):
也就是說push_back會檢查記憶體空間是不是夠用(有沒有備用空間),如果不夠用,則從最後一個元素開始開闢空間。
程式碼修改過後!
class MyHashMap
{
private:
vector<int> m;
public:
/** Initialize your data structure here. */
MyHashMap()
{
m = std::vector<int>(1000001, -1);
}
/** value will always be non-negative. */
void put(int key, int value)
{
m[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)
{
return m[key];
}
/** Removes the mapping of the specified value key if this map contains a mapping for the key */
void remove(int key)
{
m[key] = -1;
}
};
/**
* 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);
*/
AC。