提交 4af00fc2 编写于 作者: 每日一练社区's avatar 每日一练社区

add 6 leetcode exercises

上级 668811cd
......@@ -56,7 +56,8 @@ lRUCache.get(4); // 返回 4
## aop
### before
```cpp
#include <bits/stdc++.h>
using namespace std;
```
### after
```cpp
......@@ -65,21 +66,249 @@ lRUCache.get(4); // 返回 4
## 答案
```cpp
class LRUCache
{
public:
LRUCache(int capacity) : cap(capacity) {}
int get(int key)
{
if (m.count(key) != 0)
{
int val = m[key]->second;
l.erase(m[key]);
l.push_front({key, val});
m[key] = l.begin();
return val;
}
return -1;
}
void put(int key, int value)
{
if (m.count(key) != 0)
{
l.erase(m[key]);
l.push_front({key, value});
m[key] = l.begin();
}
else
{
m.erase(l.back().first);
l.pop_back();
l.push_front({key, value});
m[key] = l.begin();
}
}
private:
int cap;
list<pair<int, int>> l;
unordered_map<int, list<pair<int, int>>::iterator> m;
};
```
## 选项
### A
```cpp
class LRUCache
{
private:
unordered_map<int, DLinkedNode *> cache;
DLinkedNode *head;
DLinkedNode *tail;
int size;
int capacity;
public:
LRUCache(int _capacity) : capacity(_capacity), size(0)
{
head = new DLinkedNode();
tail = new DLinkedNode();
head->next = tail;
tail->prev = head;
}
int get(int key)
{
if (!cache.count(key))
{
return -1;
}
DLinkedNode *node = cache[key];
moveToHead(node);
return node->value;
}
void put(int key, int value)
{
if (!cache.count(key))
{
DLinkedNode *node = new DLinkedNode(key, value);
cache[key] = node;
addToHead(node);
++size;
if (size > capacity)
{
DLinkedNode *removed = removeTail();
cache.erase(removed->key);
delete removed;
--size;
}
}
else
{
DLinkedNode *node = cache[key];
node->value = value;
moveToHead(node);
}
}
void addToHead(DLinkedNode *node)
{
node->prev = head;
node->next = head->next;
head->next->prev = node;
head->next = node;
}
void removeNode(DLinkedNode *node)
{
node->prev->next = node->next;
node->next->prev = node->prev;
}
void moveToHead(DLinkedNode *node)
{
removeNode(node);
addToHead(node);
}
DLinkedNode *removeTail()
{
DLinkedNode *node = tail->prev;
removeNode(node);
return node;
}
};
```
### B
```cpp
class LRUCache
{
private:
int capacity;
list<pair<int, int>> cl;
unordered_map<int, list<pair<int, int>>::iterator> cm;
public:
LRUCache(int capacity)
{
this->capacity = capacity;
}
int get(int key)
{
auto it = cm.find(key);
if (it != cm.end())
{
pair<int, int> p = *cm[key];
int value = p.second;
cl.erase(cm[key]);
cl.push_front(p);
cm[key] = cl.begin();
return value;
}
else
return -1;
}
void put(int key, int value)
{
auto it = cm.find(key);
if (it != cm.end())
{
cl.erase(cm[key]);
cl.push_front({key, value});
cm[key] = cl.begin();
}
else
{
if (cl.size() == capacity)
{
int old_key = cl.back().first;
cl.pop_back();
cm.erase(old_key);
}
cl.push_front({key, value});
cm.insert({key, cl.begin()});
}
}
};
```
### C
```cpp
class LRUCache
{
private:
int capacity, size;
list<int> cl;
unordered_map<int, int> cm;
public:
LRUCache(int capacity)
{
this->capacity = capacity;
size = 0;
}
int get(int key)
{
auto it = cm.find(key);
if (it != cm.end())
{
cl.remove(key);
cl.push_back(key);
return it->second;
}
else
return -1;
}
void put(int key, int value)
{
auto it = cm.find(key);
if (it != cm.end())
{
it->second = value;
cl.remove(key);
cl.push_back(key);
}
else
{
if (size == capacity)
{
int old_key = cl.front();
cl.pop_front();
cm.erase(old_key);
size--;
}
cl.push_back(key);
cm.insert({key, value});
size++;
}
}
};
```
#include <bits/stdc++.h>
using namespace std;
class Solution
{
public:
bool isIsomorphic(string s, string t)
{
unordered_map<char, char> map1;
unordered_map<char, char> map2;
int n = s.size();
for (int i = 0; i < n; i++)
{
char x = s[i], y = t[i];
if ((map1.count(x) && map1[x] != y) || (map2.count(y) && map2[y] != x))
return false;
map1[x] = y;
map2[y] = x;
}
return true;
}
};
\ No newline at end of file
......@@ -38,30 +38,155 @@
## aop
### before
```cpp
#include <bits/stdc++.h>
using namespace std;
```
### after
```cpp
int main()
{
Solution sol;
string a = "egg";
string b = "add";
bool res;
res = sol.isIsomorphic(a, b);
cout << res;
return 0;
}
```
## 答案
```cpp
class Solution
{
public:
bool isIsomorphic(string s, string t)
{
if (s.size() != t.size())
return false;
for (int i = 0; i < s.size(); i++)
{
int pos = s.find_first_of(s[i], i + 1);
while (pos != -1)
{
if (t[i] == t[pos + 1])
{
s.erase(pos, 1);
t.erase(pos, 1);
pos = s.find_first_of(s[i], pos + 1);
}
else
return false;
}
}
for (int i = 0; i < t.size(); i++)
{
int pos = t.find_first_of(t[i], i + 1);
while (pos != -1)
{
if (s[i] == s[pos + 1])
{
s.erase(pos, 1);
t.erase(pos, 1);
pos = t.find_first_of(t[i], pos + 1);
}
else
return false;
}
}
return true;
}
};
```
## 选项
### A
```cpp
class Solution
{
public:
bool isIsomorphic(string s, string t)
{
if (s.size() != t.size())
return false;
for (int i = 0; i < s.size(); i++)
{
if (s.find(s[i]) != t.find(t[i]))
return false;
}
return true;
}
};
```
### B
```cpp
class Solution
{
public:
bool isIsomorphic(string s, string t)
{
if (s.size() != t.size())
return false;
for (int i = 0; i < s.size(); i++)
{
if (s[i] == s[i + 1])
{
s.erase(i + 1, 1);
i--;
}
}
for (int i = 0; i < t.size(); i++)
{
if (t[i] == t[i + 1])
{
t.erase(i + 1, 1);
i--;
}
}
if (s.size() != t.size())
return false;
for (int i = 0; i < s.size(); i++)
{
int pos = s.find_first_of(s[i], i + 1);
while (pos != -1)
{
if (t[i] == t[pos])
{
s.erase(pos, 1);
t.erase(pos, 1);
pos = s.find_first_of(s[i], pos + 1);
}
else
return false;
}
}
return true;
}
};
```
### C
```cpp
class Solution
{
public:
bool isIsomorphic(string s, string t)
{
unordered_map<char, char> map1;
unordered_map<char, char> map2;
int n = s.size();
for (int i = 0; i < n; i++)
{
char x = s[i], y = t[i];
if ((map1.count(x) && map1[x] != y) || (map2.count(y) && map2[y] != x))
return false;
map1[x] = y;
map2[y] = x;
}
return true;
}
};
```
#include <bits/stdc++.h>
using namespace std;
class Twitter
{
public:
/** Initialize your data structure here. */
Twitter()
{
}
/** Compose a new tweet. */
void postTweet(int userId, int tweetId)
{
context.push_back(make_pair(userId, tweetId));
}
/** Retrieve the 10 most recent tweet ids in the user's news feed. Each item in the news feed must be posted by users who the user followed or by the user herself. Tweets must be ordered from most recent to least recent. */
vector<int> getNewsFeed(int userId)
{
int n = context.size();
int count = 0;
vector<int> res;
int k = n - 1;
while (count < 10 && k >= 0)
{
auto it = context[k];
if (it.first == userId || tmp[make_pair(userId, it.first)])
{
res.push_back(context[k].second);
count++;
}
k--;
}
return res;
}
/** Follower follows a followee. If the operation is invalid, it should be a no-op. */
void follow(int followerId, int followeeId)
{
tmp[make_pair(followerId, followeeId)] = 1;
}
/** Follower unfollows a followee. If the operation is invalid, it should be a no-op. */
void unfollow(int followerId, int followeeId)
{
tmp[make_pair(followerId, followeeId)] = 0;
}
private:
map<pair<int, int>, int> tmp;
vector<pair<int, int>> context;
};
/**
* Your Twitter object will be instantiated and called as such:
* Twitter* obj = new Twitter();
* obj->postTweet(userId,tweetId);
* vector<int> param_2 = obj->getNewsFeed(userId);
* obj->follow(followerId,followeeId);
* obj->unfollow(followerId,followeeId);
*/
......@@ -47,7 +47,8 @@ twitter.getNewsFeed(1); // 用户 1 获取推文应当返回一个列表,其
## aop
### before
```cpp
#include <bits/stdc++.h>
using namespace std;
```
### after
```cpp
......@@ -56,21 +57,294 @@ twitter.getNewsFeed(1); // 用户 1 获取推文应当返回一个列表,其
## 答案
```cpp
class Twitter
{
public:
/** Initialize your data structure here. */
Twitter()
{
}
/** Compose a new tweet. */
void postTweet(int userId, int tweetId)
{
tweets[userId].push_back(make_pair(time++, tweetId));
}
/** Retrieve the 10 most recent tweet ids in the user's news feed. Each item in the news feed must be posted by users who the user followed or by the user herself. Tweets must be ordered from most recent to least recent. */
vector<int> getNewsFeed(int userId)
{
vector<int> userIds({userId});
if (following.find(userId) != following.end())
{
userIds.insert(userIds.begin(), following[userId].begin(), following[userId].end());
}
vector<int> index(userIds.size());
for (int i = 0; i < userIds.size(); ++i)
{
index[i] = tweets[userIds[i]].size();
}
vector<int> res;
while (res.size() < 10)
{
int mxi = 0, mxtime = INT_MIN, mxTweet = 0;
for (int i = 0; i < index.size(); ++i)
{
int idx = index[i];
if (idx > 0)
{
int ui = userIds[i];
int time = tweets[ui][idx].first;
if (time > mxtime)
{
mxi = i;
mxtime = time;
mxTweet = tweets[ui][idx].second;
}
}
}
if (mxtime == INT_MIN)
{
break;
}
++index[mxi];
res.push_back(mxTweet);
}
return res;
}
/** Follower follows a followee. If the operation is invalid, it should be a no-op. */
void follow(int followerId, int followeeId)
{
if (followerId != followeeId)
{
following[followerId].insert(followeeId);
}
}
/** Follower unfollows a followee. If the operation is invalid, it should be a no-op. */
void unfollow(int followerId, int followeeId)
{
if (following.find(followerId) == following.end())
{
return;
}
following[followerId].erase(followeeId);
if (following[followerId].empty())
{
following.erase(followerId);
}
}
private:
int time{0};
unordered_map<int, unordered_set<int>> following;
unordered_map<int, vector<pair<int, int>>> tweets;
};
/**
* Your Twitter object will be instantiated and called as such:
* Twitter obj = new Twitter();
* obj.postTweet(userId,tweetId);
* vector<int> param_2 = obj.getNewsFeed(userId);
* obj.follow(followerId,followeeId);
* obj.unfollow(followerId,followeeId);
*/
```
## 选项
### A
```cpp
class Twitter
{
private:
list<pair<int, int>> twitterNews;
map<int, map<int, bool>> followMap;
public:
/** Initialize your data structure here. */
Twitter()
{
}
/** Compose a new tweet. */
void postTweet(int userId, int tweetId)
{
twitterNews.insert(twitterNews.begin(), pair<int, int>(userId, tweetId));
}
/** Retrieve the 10 most recent tweet ids in the user's news feed. Each item in the news feed must be posted by users who the user followed or by the user herself. Tweets must be ordered from most recent to least recent. */
vector<int> getNewsFeed(int userId)
{
vector<int> result;
list<pair<int, int>>::iterator it = twitterNews.begin();
while (it != twitterNews.end() && result.size() < 10)
{
if (it->first == userId || followMap[userId][it->first])
{
result.push_back(it->second);
}
it++;
}
return result;
}
/** Follower follows a followee. If the operation is invalid, it should be a no-op. */
void follow(int followerId, int followeeId)
{
followMap[followerId][followeeId] = true;
}
/** Follower unfollows a followee. If the operation is invalid, it should be a no-op. */
void unfollow(int followerId, int followeeId)
{
followMap[followerId][followeeId] = false;
}
};
/**
* Your Twitter object will be instantiated and called as such:
* Twitter obj = new Twitter();
* obj.postTweet(userId,tweetId);
* vector<int> param_2 = obj.getNewsFeed(userId);
* obj.follow(followerId,followeeId);
* obj.unfollow(followerId,followeeId);
*/
```
### B
```cpp
class Twitter
{
public:
/** Initialize your data structure here. */
Twitter()
{
}
/** Compose a new tweet. */
void postTweet(int userId, int tweetId)
{
context.push_back(make_pair(userId, tweetId));
}
/** Retrieve the 10 most recent tweet ids in the user's news feed. Each item in the news feed must be posted by users who the user followed or by the user herself. Tweets must be ordered from most recent to least recent. */
vector<int> getNewsFeed(int userId)
{
int n = context.size();
int count = 0;
vector<int> res;
int k = n - 1;
while (count < 10 && k >= 0)
{
auto it = context[k];
if (it.first == userId || tmp[make_pair(userId, it.first)])
{
res.push_back(context[k].second);
count++;
}
k--;
}
return res;
}
/** Follower follows a followee. If the operation is invalid, it should be a no-op. */
void follow(int followerId, int followeeId)
{
tmp[make_pair(followerId, followeeId)] = 1;
}
/** Follower unfollows a followee. If the operation is invalid, it should be a no-op. */
void unfollow(int followerId, int followeeId)
{
tmp[make_pair(followerId, followeeId)] = 0;
}
private:
map<pair<int, int>, int> tmp;
vector<pair<int, int>> context;
};
/**
* Your Twitter object will be instantiated and called as such:
* Twitter* obj = new Twitter();
* obj->postTweet(userId,tweetId);
* vector<int> param_2 = obj->getNewsFeed(userId);
* obj->follow(followerId,followeeId);
* obj->unfollow(followerId,followeeId);
*/
```
### C
```cpp
class Twitter
{
public:
/** Initialize your data structure here. */
Twitter()
{
}
/** Compose a new tweet. */
void postTweet(int userId, int tweetId)
{
context.push_back(make_pair(userId, tweetId));
}
/** Retrieve the 10 most recent tweet ids in the user's news feed. Each item in the news feed must be posted by users who the user followed or by the user herself. Tweets must be ordered from most recent to least recent. */
vector<int> getNewsFeed(int userId)
{
int n = context.size();
int count = 0;
vector<int> res;
int k = n - 1;
while (count < 10 && k >= 0)
{
auto it = context[k];
if (it.first == userId || tmp[make_pair(userId, it.first)])
{
res.push_back(context[k].second);
count++;
}
k--;
}
return res;
}
/** Follower follows a followee. If the operation is invalid, it should be a no-op. */
void follow(int followerId, int followeeId)
{
tmp[make_pair(followerId, followeeId)] = 1;
}
/** Follower unfollows a followee. If the operation is invalid, it should be a no-op. */
void unfollow(int followerId, int followeeId)
{
tmp[make_pair(followerId, followeeId)] = 0;
}
private:
map<pair<int, int>, int> tmp;
vector<pair<int, int>> context;
};
/**
* Your Twitter object will be instantiated and called as such:
* Twitter* obj = new Twitter();
* obj->postTweet(userId,tweetId);
* vector<int> param_2 = obj->getNewsFeed(userId);
* obj->follow(followerId,followeeId);
* obj->unfollow(followerId,followeeId);
*/
```
#include <bits/stdc++.h>
using namespace std;
class RandomizedSet
{
public:
vector<int> nums;
unordered_map<int, int> nums_inds;
/** Initialize your data structure here. */
RandomizedSet()
{
}
/** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
bool insert(int val)
{
if (nums_inds.count(val) != 0)
return false;
nums.push_back(val);
nums_inds[val] = nums.size() - 1;
return true;
}
/** Removes a value from the set. Returns true if the set contained the specified element. */
bool remove(int val)
{
if (nums_inds.count(val) == 0)
return false;
int last = nums.back();
int ind = nums_inds[val];
nums[ind] = last;
nums_inds[last] = ind;
nums.pop_back();
nums_inds.erase(val);
return true;
}
/** Get a random element from the set. */
int getRandom()
{
int ind = rand() % nums.size();
return nums[ind];
}
};
......@@ -50,6 +50,8 @@ randomizedSet.getRandom(); // 由于 2 是集合中唯一的数字,getRandom
## aop
### before
```cpp
#include <bits/stdc++.h>
using namespace std;
```
### after
......@@ -59,21 +61,193 @@ randomizedSet.getRandom(); // 由于 2 是集合中唯一的数字,getRandom
## 答案
```cpp
class RandomizedSet
{
unordered_map<int, int> dict;
vector<int> list;
public:
/** Initialize your data structure here. */
RandomizedSet()
{
srand(time(0));
}
/** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
bool insert(int val)
{
if (dict.find(val) != dict.end())
return false;
list.push_back(val);
dict[val] = list.size();
return true;
}
/** Removes a value from the set. Returns true if the set contained the specified element. */
bool remove(int val)
{
if (dict.find(val) == dict.end())
return false;
dict[list.back()] = dict[val];
swap(list.back(), list[dict[val]]);
list.pop_back();
dict.erase(val);
return true;
}
/** Get a random element from the set. */
int getRandom()
{
int pos = list.empty() ? 0 : rand() % list.size();
return list[pos];
}
};
```
## 选项
### A
```cpp
class RandomizedSet
{
public:
/** Initialize your data structure here. */
RandomizedSet()
{
}
/** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
bool insert(int val)
{
if (mMap.count(val) > 0)
return false;
mData.push_back(val);
mMap[val] = mData.size() - 1;
return true;
}
/** Removes a value from the set. Returns true if the set contained the specified element. */
bool remove(int val)
{
if (mMap.count(val) > 0)
{
int last_num = mData.back();
int val_index = mMap[val];
mData[val_index] = last_num;
mMap[last_num] = val_index;
mData.pop_back();
mMap.erase(val);
return true;
}
return false;
}
/** Get a random element from the set. */
int getRandom()
{
int index = rand() % mData.size();
return mData[index];
}
private:
vector<int> mData;
unordered_map<int, int> mMap;
};
```
### B
```cpp
class RandomizedSet
{
public:
unordered_set<int> ust;
/** Initialize your data structure here. */
RandomizedSet()
{
}
/** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
bool insert(int val)
{
if (ust.find(val) != ust.end())
return false;
ust.insert(val);
return true;
}
/** Removes a value from the set. Returns true if the set contained the specified element. */
bool remove(int val)
{
if (ust.find(val) == ust.end())
return false;
ust.erase(val);
return true;
}
/** Get a random element from the set. */
int getRandom()
{
int ind = rand() % ust.size();
auto it = ust.begin();
for (int i = 0; i < ind; i++)
{
it++;
}
return *it;
}
};
```
### C
```cpp
class RandomizedSet
{
public:
vector<int> nums;
unordered_map<int, int> nums_inds;
/** Initialize your data structure here. */
RandomizedSet()
{
}
/** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
bool insert(int val)
{
if (nums_inds.count(val) != 0)
return false;
nums.push_back(val);
nums_inds[val] = nums.size() - 1;
return true;
}
/** Removes a value from the set. Returns true if the set contained the specified element. */
bool remove(int val)
{
if (nums_inds.count(val) == 0)
return false;
int last = nums.back();
int ind = nums_inds[val];
nums[ind] = last;
nums_inds[last] = ind;
nums.pop_back();
nums_inds.erase(val);
return true;
}
/** Get a random element from the set. */
int getRandom()
{
int ind = rand() % nums.size();
return nums[ind];
}
};
```
#include <bits/stdc++.h>
using namespace std;
class RandomizedCollection
{
public:
vector<int> nums;
unordered_map<int, unordered_set<int>> numsIndex;
int size;
/** Initialize your data structure here. */
RandomizedCollection()
{
size = 0;
}
/** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */
bool insert(int val)
{
nums.push_back(val);
numsIndex[val].insert(size);
size++;
return numsIndex[val].size() == 1;
}
/** Removes a value from the collection. Returns true if the collection contained the specified element. */
bool remove(int val)
{
if (numsIndex.count(val) == 0)
return false;
int last = nums.back();
int id = size - 1;
if (last != val)
{
id = *(numsIndex[val].begin());
numsIndex[last].erase(size - 1);
numsIndex[last].insert(id);
nums[id] = last;
}
nums.pop_back();
size--;
numsIndex[val].erase(id);
if (numsIndex[val].empty())
numsIndex.erase(val);
return true;
}
/** Get a random element from the collection. */
int getRandom()
{
return nums[random() % size];
}
};
/**
* Your RandomizedCollection object will be instantiated and called as such:
* RandomizedCollection* obj = new RandomizedCollection();
* bool param_1 = obj->insert(val);
* bool param_2 = obj->remove(val);
* int param_3 = obj->getRandom();
*/
......@@ -37,7 +37,8 @@ collection.getRandom();
## aop
### before
```cpp
#include <bits/stdc++.h>
using namespace std;
```
### after
```cpp
......@@ -46,21 +47,220 @@ collection.getRandom();
## 答案
```cpp
class RandomizedCollection
{
public:
/** Initialize your data structure here. */
RandomizedCollection()
{
this->num = 0;
}
/** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */
bool insert(int val)
{
this->num++;
bool res;
if (this->M.find(val) == this->M.end() || this->M[val] == 0)
{
this->M[val] = 1;
res = true;
}
else
{
this->M[val]++;
res = false;
}
return res;
}
/** Removes a value from the collection. Returns true if the collection contained the specified element. */
bool remove(int val)
{
if (this->M.find(val) == this->M.end() || this->M[val] == 0)
{
return false;
}
else
{
M[val]--;
this->num--;
return true;
}
}
/** Get a random element from the collection. */
int getRandom()
{
if (this->num > 0)
{
srand((unsigned)time(NULL));
int randomValue = rand() % (this->num) + 1;
for (auto it : M)
{
randomValue -= it.second;
if (randomValue <= 0)
return it.first;
}
}
return 0;
}
private:
unordered_map<int, int> M;
int num;
};
```
## 选项
### A
```cpp
class RandomizedSet
{
public:
vector<int> nums;
unordered_map<int, int> numIndex;
int size;
/** Initialize your data structure here. */
RandomizedSet()
{
size = 0;
}
/** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
bool insert(int val)
{
if (numIndex.count(val) == 1)
return false;
nums.push_back(val);
numIndex[val] = size;
size++;
return true;
}
/** Removes a value from the set. Returns true if the set contained the specified element. */
bool remove(int val)
{
if (numIndex.count(val) == 0)
return false;
int last = nums.back();
nums[numIndex[val]] = last;
numIndex[last] = numIndex[val];
nums.pop_back();
numIndex.erase(val);
size--;
return true;
}
/** Get a random element from the set. */
int getRandom()
{
return nums[random() % size];
}
};
```
### B
```cpp
class RandomizedCollection
{
public:
unordered_map<int, unordered_set<int>> idx;
vector<int> nums;
/** Initialize your data structure here. */
RandomizedCollection()
{
}
/** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */
bool insert(int val)
{
nums.push_back(val);
idx[val].insert(nums.size() - 1);
return idx[val].size() == 1;
}
/** Removes a value from the collection. Returns true if the collection contained the specified element. */
bool remove(int val)
{
if (idx.find(val) == idx.end())
{
return false;
}
int i = *(idx[val].begin());
nums[i] = nums.back();
idx[val].erase(i);
idx[nums[i]].erase(nums.size() - 1);
if (i < nums.size() - 1)
{
idx[nums[i]].insert(i);
}
if (idx[val].size() == 0)
{
idx.erase(val);
}
nums.pop_back();
return true;
}
/** Get a random element from the collection. */
int getRandom()
{
return nums[rand() % nums.size()];
}
};
```
### C
```cpp
class RandomizedCollection
{
public:
vector<int> nums;
unordered_map<int, unordered_set<int>> numsIndex;
int size;
/** Initialize your data structure here. */
RandomizedCollection()
{
size = 0;
}
/** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */
bool insert(int val)
{
nums.push_back(val);
numsIndex[val].insert(size);
size++;
return numsIndex[val].size() == 1;
}
/** Removes a value from the collection. Returns true if the collection contained the specified element. */
bool remove(int val)
{
if (numsIndex.count(val) == 0)
return false;
int last = nums.back();
int id = size - 1;
if (last != val)
{
id = *(numsIndex[val].begin());
numsIndex[last].erase(size - 1);
numsIndex[last].insert(id);
nums[id] = last;
}
nums.pop_back();
size--;
numsIndex[val].erase(id);
if (numsIndex[val].empty())
numsIndex.erase(val);
return true;
}
/** Get a random element from the collection. */
int getRandom()
{
return nums[random() % size];
}
};
```
#include <bits/stdc++.h>
using namespace std;
struct Value
{
Value(int count_, int time_, int key_, int value_)
: count(count_),
key(key_),
value(value_),
time(time_) {}
bool operator<(const Value &a) const
{
return count == a.count ? time < a.time : count < a.count;
}
int key;
int value;
int count;
int time;
};
class LFUCache
{
public:
LFUCache(int capacity_)
: capacity(capacity_),
time(0) {}
int get(int key)
{
if (capacity == 0)
return -1;
auto it = table.find(key);
if (it == table.end())
return -1;
Value cache = it->second;
judge.erase(cache);
cache.count++;
cache.time = ++time;
judge.insert(cache);
it->second = cache;
return cache.value;
}
void put(int key, int value)
{
if (capacity == 0)
return;
auto it = table.find(key);
if (it == table.end())
{
if (table.size() == capacity)
{
table.erase(judge.begin()->key);
judge.erase(judge.begin());
}
Value put_(0, ++time, key, value);
table.insert({key, put_});
judge.insert(put_);
}
else
{
Value temp = it->second;
judge.erase(temp);
Value put_(++temp.count, ++time, key, value);
it->second = put_;
judge.insert(put_);
}
}
private:
const int capacity;
int time;
unordered_map<int, Value> table;
set<Value> judge;
};
......@@ -64,7 +64,8 @@ lFUCache.get(4); // 返回 4
## aop
### before
```cpp
#include <bits/stdc++.h>
using namespace std;
```
### after
```cpp
......@@ -73,21 +74,319 @@ lFUCache.get(4); // 返回 4
## 答案
```cpp
class LFUCache
{
private:
int cap;
int size;
int minfre;
unordered_map<int, pair<int, int>> m;
unordered_map<int, list<int>> hash_fre;
unordered_map<int, list<int>::iterator> hash_node;
public:
LFUCache(int capacity) : cap(capacity), size(0) {}
int get(int key)
{
if (m.count(key) == 0)
return -1;
hash_fre[m[key].second].erase(hash_node[key]);
m[key].second++;
hash_fre[m[key].second].push_back(key);
hash_node[key] = --hash_fre[m[key].second].end();
if (hash_fre[minfre].size() == 0)
{
minfre++;
}
return m[key].first;
}
void put(int key, int value)
{
if (cap <= 0)
return;
if (get(key) != -1)
{
m[key].first = value;
return;
}
if (size >= cap)
{
m.erase(hash_fre[minfre].front());
hash_node.erase(hash_fre[minfre].front());
hash_fre[minfre].pop_front();
}
m[key] = {value, 1};
hash_fre[1].push_back(key);
hash_node[key] = hash_fre[1].end();
minfre = 1;
if (size < cap)
size++;
}
};
```
## 选项
### A
```cpp
class Node
{
public:
int cnt;
int time;
int key;
int val;
Node(int cnt, int time, int key, int val)
{
this->cnt = cnt;
this->time = time;
this->key = key;
this->val = val;
}
bool operator<(const Node &n) const
{
if (n.cnt == cnt)
return time < n.time;
return cnt < n.cnt;
}
};
class LFUCache
{
public:
int size;
int time;
unordered_map<int, Node> LFU;
set<Node> tree;
LFUCache(int capacity)
{
time = 0;
size = capacity;
}
int get(int key)
{
if (LFU.count(key) == 0)
return -1;
unordered_map<int, Node>::iterator iter = LFU.find(key);
Node now = (*iter).second;
tree.erase(now);
now.cnt++;
now.time = time++;
tree.insert(now);
(*iter).second = now;
return now.val;
}
void put(int key, int value)
{
if (LFU.count(key) == 0)
{
Node newNode = Node(1, time++, key, value);
if (size == 0)
{
if (tree.empty())
return;
LFU.erase((*(tree.begin())).key);
tree.erase(tree.begin());
}
else
{
size--;
}
LFU.insert(make_pair(key, newNode));
tree.insert(newNode);
}
else
{
unordered_map<int, Node>::iterator iter = LFU.find(key);
Node now = (*iter).second;
tree.erase(now);
now.cnt++;
now.time = time++;
now.val = value;
tree.insert(now);
(*iter).second = now;
}
}
};
```
### B
```cpp
class LFUCache
{
public:
LFUCache(int capacity_)
: capacity(capacity_),
minfreq(0)
{
iter_table.clear();
freq_table.clear();
}
int get(int key)
{
if (capacity == 0)
return -1;
auto it = iter_table.find(key);
if (it == iter_table.end())
return -1;
list<Value>::iterator iter = it->second;
int value = iter->value;
int freq = iter->freq;
Value new_node(key, value, freq + 1);
freq_table[freq].erase(iter);
if (freq_table[freq].size() == 0)
{
freq_table.erase(freq);
if (minfreq == freq)
minfreq += 1;
}
freq_table[freq + 1].push_front(new_node);
iter_table[key] = freq_table[freq + 1].begin();
return new_node.value;
}
void put(int key, int value)
{
if (capacity == 0)
return;
auto it = iter_table.find(key);
if (it == iter_table.end())
{
if (iter_table.size() == capacity)
{
auto it2 = freq_table[minfreq].back();
iter_table.erase(it2.key);
freq_table[minfreq].pop_back();
if (freq_table[minfreq].size() == 0)
{
freq_table.erase(minfreq);
}
}
freq_table[1].push_front(Value{key, value, 1});
iter_table[key] = freq_table[1].begin();
minfreq = 1;
}
else
{
list<Value>::iterator iter = it->second;
int freq = iter->freq;
Value new_node(iter->key, value, freq + 1);
freq_table[iter->freq].erase(iter);
if (freq_table[freq].size() == 0)
{
freq_table.erase(freq);
if (minfreq == freq)
minfreq += 1;
}
freq_table[freq + 1].push_front(new_node);
iter_table[key] = freq_table[freq + 1].begin();
}
}
private:
struct Value
{
Value(int key_, int value_, int freq_)
: key(key_),
value(value_),
freq(freq_) {}
int key;
int value;
int freq;
};
int capacity;
int minfreq;
unordered_map<int, list<Value>::iterator> iter_table;
unordered_map<int, list<Value>> freq_table;
};
```
### C
```cpp
struct Value
{
Value(int count_, int time_, int key_, int value_)
: count(count_),
key(key_),
value(value_),
time(time_) {}
bool operator<(const Value &a) const
{
return count == a.count ? time < a.time : count < a.count;
}
int key;
int value;
int count;
int time;
};
class LFUCache
{
public:
LFUCache(int capacity_)
: capacity(capacity_),
time(0) {}
int get(int key)
{
if (capacity == 0)
return -1;
auto it = table.find(key);
if (it == table.end())
return -1;
Value cache = it->second;
judge.erase(cache);
cache.count++;
cache.time = ++time;
judge.insert(cache);
it->second = cache;
return cache.value;
}
void put(int key, int value)
{
if (capacity == 0)
return;
auto it = table.find(key);
if (it == table.end())
{
if (table.size() == capacity)
{
table.erase(judge.begin()->key);
judge.erase(judge.begin());
}
Value put_(0, ++time, key, value);
table.insert({key, put_});
judge.insert(put_);
}
else
{
Value temp = it->second;
judge.erase(temp);
Value put_(++temp.count, ++time, key, value);
it->second = put_;
judge.insert(put_);
}
}
private:
const int capacity;
int time;
unordered_map<int, Value> table;
set<Value> judge;
};
```
{
"node_id": "569d5e11c4fc5de7844053d9a733c5e8",
"keywords": [
"leetcode",
"同构字符串"
],
"children": [],
"export": [
"solution.json"
],
"title": "同构字符串"
}
\ No newline at end of file
<p>给定两个字符串 <em><strong></strong></em>和 <strong><em>t</em></strong>,判断它们是否是同构的。</p>
<p>如果 <em><strong></strong></em>中的字符可以按某种映射关系替换得到 <strong><em></em></strong>,那么这两个字符串是同构的。</p>
<p>每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,相同字符只能映射到同一个字符上,字符可以映射到自己本身。</p>
<p> </p>
<p><strong>示例 1:</strong></p>
<pre>
<strong>输入:</strong><strong><em>s</em></strong> = <code>"egg", </code><strong><em>t = </em></strong><code>"add"</code>
<strong>输出:</strong>true
</pre>
<p><strong>示例 2:</strong></p>
<pre>
<strong>输入:</strong><strong><em>s</em></strong> = <code>"foo", </code><strong><em>t = </em></strong><code>"bar"</code>
<strong>输出:</strong>false</pre>
<p><strong>示例 3:</strong></p>
<pre>
<strong>输入:</strong><strong><em>s</em></strong> = <code>"paper", </code><strong><em>t = </em></strong><code>"title"</code>
<strong>输出:</strong>true</pre>
<p> </p>
<p><strong>提示:</strong></p>
<ul>
<li>可以假设 <em><strong></strong></em><strong><em>t </em></strong>长度相同。</li>
</ul>
#include <bits/stdc++.h>
using namespace std;
class Solution
{
public:
bool isIsomorphic(string s, string t)
{
unordered_map<char, char> map1;
unordered_map<char, char> map2;
int n = s.size();
for (int i = 0; i < n; i++)
{
char x = s[i], y = t[i];
if ((map1.count(x) && map1[x] != y) || (map2.count(y) && map2[y] != x))
return false;
map1[x] = y;
map2[y] = x;
}
return true;
}
};
\ No newline at end of file
{
"type": "code_options",
"author": "CSDN.net",
"source": "solution.md",
"exercise_id": "a015883ffc3d4b288ff1f75539a84980"
}
\ No newline at end of file
# 同构字符串
<p>给定两个字符串 <em><strong></strong></em>和 <strong><em>t</em></strong>,判断它们是否是同构的。</p>
<p>如果 <em><strong></strong></em>中的字符可以按某种映射关系替换得到 <strong><em></em></strong>,那么这两个字符串是同构的。</p>
<p>每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,相同字符只能映射到同一个字符上,字符可以映射到自己本身。</p>
<p> </p>
<p><strong>示例 1:</strong></p>
<pre>
<strong>输入:</strong><strong><em>s</em></strong> = <code>"egg", </code><strong><em>t = </em></strong><code>"add"</code>
<strong>输出:</strong>true
</pre>
<p><strong>示例 2:</strong></p>
<pre>
<strong>输入:</strong><strong><em>s</em></strong> = <code>"foo", </code><strong><em>t = </em></strong><code>"bar"</code>
<strong>输出:</strong>false</pre>
<p><strong>示例 3:</strong></p>
<pre>
<strong>输入:</strong><strong><em>s</em></strong> = <code>"paper", </code><strong><em>t = </em></strong><code>"title"</code>
<strong>输出:</strong>true</pre>
<p> </p>
<p><strong>提示:</strong></p>
<ul>
<li>可以假设 <em><strong></strong></em><strong><em>t </em></strong>长度相同。</li>
</ul>
<p>以下错误的选项是?</p>
## aop
### before
```cpp
#include <bits/stdc++.h>
using namespace std;
```
### after
```cpp
int main()
{
Solution sol;
string a = "egg";
string b = "add";
bool res;
res = sol.isIsomorphic(a, b);
cout << res;
return 0;
}
```
## 答案
```cpp
class Solution
{
public:
bool isIsomorphic(string s, string t)
{
if (s.size() != t.size())
return false;
for (int i = 0; i < s.size(); i++)
{
int pos = s.find_first_of(s[i], i + 1);
while (pos != -1)
{
if (t[i] == t[pos + 1])
{
s.erase(pos, 1);
t.erase(pos, 1);
pos = s.find_first_of(s[i], pos + 1);
}
else
return false;
}
}
for (int i = 0; i < t.size(); i++)
{
int pos = t.find_first_of(t[i], i + 1);
while (pos != -1)
{
if (s[i] == s[pos + 1])
{
s.erase(pos, 1);
t.erase(pos, 1);
pos = t.find_first_of(t[i], pos + 1);
}
else
return false;
}
}
return true;
}
};
```
## 选项
### A
```cpp
class Solution
{
public:
bool isIsomorphic(string s, string t)
{
if (s.size() != t.size())
return false;
for (int i = 0; i < s.size(); i++)
{
if (s.find(s[i]) != t.find(t[i]))
return false;
}
return true;
}
};
```
### B
```cpp
class Solution
{
public:
bool isIsomorphic(string s, string t)
{
if (s.size() != t.size())
return false;
for (int i = 0; i < s.size(); i++)
{
if (s[i] == s[i + 1])
{
s.erase(i + 1, 1);
i--;
}
}
for (int i = 0; i < t.size(); i++)
{
if (t[i] == t[i + 1])
{
t.erase(i + 1, 1);
i--;
}
}
if (s.size() != t.size())
return false;
for (int i = 0; i < s.size(); i++)
{
int pos = s.find_first_of(s[i], i + 1);
while (pos != -1)
{
if (t[i] == t[pos])
{
s.erase(pos, 1);
t.erase(pos, 1);
pos = s.find_first_of(s[i], pos + 1);
}
else
return false;
}
}
return true;
}
};
```
### C
```cpp
class Solution
{
public:
bool isIsomorphic(string s, string t)
{
unordered_map<char, char> map1;
unordered_map<char, char> map2;
int n = s.size();
for (int i = 0; i < n; i++)
{
char x = s[i], y = t[i];
if ((map1.count(x) && map1[x] != y) || (map2.count(y) && map2[y] != x))
return false;
map1[x] = y;
map2[y] = x;
}
return true;
}
};
```
{
"node_id": "569d5e11c4fc5de7844053d9a733c5e8",
"keywords": [
"leetcode",
"LRU 缓存机制"
],
"children": [],
"export": [
"solution.json"
],
"title": "LRU 缓存机制"
}
\ No newline at end of file
<div class="title__3Vvk">运用你所掌握的数据结构,设计和实现一个  <a href="https://baike.baidu.com/item/LRU" target="_blank">LRU (最近最少使用) 缓存机制</a></div>
<div class="original__bRMd">
<div>
<p>实现 <code>LRUCache</code> 类:</p>
<ul>
<li><code>LRUCache(int capacity)</code> 以正整数作为容量 <code>capacity</code> 初始化 LRU 缓存</li>
<li><code>int get(int key)</code> 如果关键字 <code>key</code> 存在于缓存中,则返回关键字的值,否则返回 <code>-1</code></li>
<li><code>void put(int key, int value)</code> 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字-值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。</li>
</ul>
<p> </p>
</div>
</div>
<p><strong>进阶</strong>:你是否可以在 <code>O(1)</code> 时间复杂度内完成这两种操作?</p>
<p> </p>
<p><strong>示例:</strong></p>
<pre>
<strong>输入</strong>
["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
<strong>输出</strong>
[null, null, null, 1, null, -1, null, -1, 3, 4]
<strong>解释</strong>
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // 缓存是 {1=1}
lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
lRUCache.get(1); // 返回 1
lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
lRUCache.get(2); // 返回 -1 (未找到)
lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
lRUCache.get(1); // 返回 -1 (未找到)
lRUCache.get(3); // 返回 3
lRUCache.get(4); // 返回 4
</pre>
<p> </p>
<p><strong>提示:</strong></p>
<ul>
<li><code>1 <= capacity <= 3000</code></li>
<li><code>0 <= key <= 10000</code></li>
<li><code>0 <= value <= 10<sup>5</sup></code></li>
<li>最多调用 <code>2 * 10<sup>5</sup></code><code>get</code><code>put</code></li>
</ul>
class LRUCache
{
public:
LRUCache(int capacity) : cap(capacity) {}
int get(int key)
{
if (m.count(key) != 0)
{
int val = m[key]->second;
l.erase(m[key]);
l.push_front({key, val}); //访问过的元素移动到头部
m[key] = l.begin();
return val;
}
return -1;
}
void put(int key, int value)
{
if (m.count(key) != 0)
{ //已经存在
l.erase(m[key]);
l.push_front({key, value});
m[key] = l.begin();
}
else
{
if (l.size() == cap)
{ //同步删除
m.erase(l.back().first);
l.pop_back();
}
l.push_front({key, value});
m[key] = l.begin();
}
}
private:
int cap;
list<pair<int, int>> l;
unordered_map<int, list<pair<int, int>>::iterator> m;
};
{
"type": "code_options",
"author": "CSDN.net",
"source": "solution.md",
"exercise_id": "97c15992ec93466ba46bf6a7ca1463e0"
}
\ No newline at end of file
# LRU 缓存机制
<div class="title__3Vvk">运用你所掌握的数据结构,设计和实现一个  <a href="https://baike.baidu.com/item/LRU" target="_blank">LRU (最近最少使用) 缓存机制</a></div>
<div class="original__bRMd">
<div>
<p>实现 <code>LRUCache</code> 类:</p>
<ul>
<li><code>LRUCache(int capacity)</code> 以正整数作为容量 <code>capacity</code> 初始化 LRU 缓存</li>
<li><code>int get(int key)</code> 如果关键字 <code>key</code> 存在于缓存中,则返回关键字的值,否则返回 <code>-1</code></li>
<li><code>void put(int key, int value)</code> 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字-值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。</li>
</ul>
<p> </p>
</div>
</div>
<p><strong>进阶</strong>:你是否可以在 <code>O(1)</code> 时间复杂度内完成这两种操作?</p>
<p> </p>
<p><strong>示例:</strong></p>
<pre>
<strong>输入</strong>
["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
<strong>输出</strong>
[null, null, null, 1, null, -1, null, -1, 3, 4]
<strong>解释</strong>
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // 缓存是 {1=1}
lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
lRUCache.get(1); // 返回 1
lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
lRUCache.get(2); // 返回 -1 (未找到)
lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
lRUCache.get(1); // 返回 -1 (未找到)
lRUCache.get(3); // 返回 3
lRUCache.get(4); // 返回 4
</pre>
<p> </p>
<p><strong>提示:</strong></p>
<ul>
<li><code>1 <= capacity <= 3000</code></li>
<li><code>0 <= key <= 10000</code></li>
<li><code>0 <= value <= 10<sup>5</sup></code></li>
<li>最多调用 <code>2 * 10<sup>5</sup></code><code>get</code><code>put</code></li>
</ul>
<p>以下错误的选项是?</p>
## aop
### before
```cpp
#include <bits/stdc++.h>
using namespace std;
```
### after
```cpp
```
## 答案
```cpp
class LRUCache
{
public:
LRUCache(int capacity) : cap(capacity) {}
int get(int key)
{
if (m.count(key) != 0)
{
int val = m[key]->second;
l.erase(m[key]);
l.push_front({key, val});
m[key] = l.begin();
return val;
}
return -1;
}
void put(int key, int value)
{
if (m.count(key) != 0)
{
l.erase(m[key]);
l.push_front({key, value});
m[key] = l.begin();
}
else
{
m.erase(l.back().first);
l.pop_back();
l.push_front({key, value});
m[key] = l.begin();
}
}
private:
int cap;
list<pair<int, int>> l;
unordered_map<int, list<pair<int, int>>::iterator> m;
};
```
## 选项
### A
```cpp
class LRUCache
{
private:
unordered_map<int, DLinkedNode *> cache;
DLinkedNode *head;
DLinkedNode *tail;
int size;
int capacity;
public:
LRUCache(int _capacity) : capacity(_capacity), size(0)
{
head = new DLinkedNode();
tail = new DLinkedNode();
head->next = tail;
tail->prev = head;
}
int get(int key)
{
if (!cache.count(key))
{
return -1;
}
DLinkedNode *node = cache[key];
moveToHead(node);
return node->value;
}
void put(int key, int value)
{
if (!cache.count(key))
{
DLinkedNode *node = new DLinkedNode(key, value);
cache[key] = node;
addToHead(node);
++size;
if (size > capacity)
{
DLinkedNode *removed = removeTail();
cache.erase(removed->key);
delete removed;
--size;
}
}
else
{
DLinkedNode *node = cache[key];
node->value = value;
moveToHead(node);
}
}
void addToHead(DLinkedNode *node)
{
node->prev = head;
node->next = head->next;
head->next->prev = node;
head->next = node;
}
void removeNode(DLinkedNode *node)
{
node->prev->next = node->next;
node->next->prev = node->prev;
}
void moveToHead(DLinkedNode *node)
{
removeNode(node);
addToHead(node);
}
DLinkedNode *removeTail()
{
DLinkedNode *node = tail->prev;
removeNode(node);
return node;
}
};
```
### B
```cpp
class LRUCache
{
private:
int capacity;
list<pair<int, int>> cl;
unordered_map<int, list<pair<int, int>>::iterator> cm;
public:
LRUCache(int capacity)
{
this->capacity = capacity;
}
int get(int key)
{
auto it = cm.find(key);
if (it != cm.end())
{
pair<int, int> p = *cm[key];
int value = p.second;
cl.erase(cm[key]);
cl.push_front(p);
cm[key] = cl.begin();
return value;
}
else
return -1;
}
void put(int key, int value)
{
auto it = cm.find(key);
if (it != cm.end())
{
cl.erase(cm[key]);
cl.push_front({key, value});
cm[key] = cl.begin();
}
else
{
if (cl.size() == capacity)
{
int old_key = cl.back().first;
cl.pop_back();
cm.erase(old_key);
}
cl.push_front({key, value});
cm.insert({key, cl.begin()});
}
}
};
```
### C
```cpp
class LRUCache
{
private:
int capacity, size;
list<int> cl;
unordered_map<int, int> cm;
public:
LRUCache(int capacity)
{
this->capacity = capacity;
size = 0;
}
int get(int key)
{
auto it = cm.find(key);
if (it != cm.end())
{
cl.remove(key);
cl.push_back(key);
return it->second;
}
else
return -1;
}
void put(int key, int value)
{
auto it = cm.find(key);
if (it != cm.end())
{
it->second = value;
cl.remove(key);
cl.push_back(key);
}
else
{
if (size == capacity)
{
int old_key = cl.front();
cl.pop_front();
cm.erase(old_key);
size--;
}
cl.push_back(key);
cm.insert({key, value});
size++;
}
}
};
```
{
"node_id": "569d5e11c4fc5de7844053d9a733c5e8",
"keywords": [
"leetcode",
"设计推特"
],
"children": [],
"export": [
"solution.json"
],
"title": "设计推特"
}
\ No newline at end of file
<p>设计一个简化版的推特(Twitter),可以让用户实现发送推文,关注/取消关注其他用户,能够看见关注人(包括自己)的最近 <code>10</code> 条推文。</p>
<p>实现 <code>Twitter</code> 类:</p>
<ul>
<li><code>Twitter()</code> 初始化简易版推特对象</li>
<li><code>void postTweet(int userId, int tweetId)</code> 根据给定的 <code>tweetId</code><code>userId</code> 创建一条新推文。每次调用次函数都会使用一个不同的 <code>tweetId</code></li>
<li><code>List&lt;Integer&gt; getNewsFeed(int userId)</code> 检索当前用户新闻推送中最近&nbsp; <code>10</code> 条推文的 ID 。新闻推送中的每一项都必须是由用户关注的人或者是用户自己发布的推文。推文必须 <strong>按照时间顺序由最近到最远排序</strong></li>
<li><code>void follow(int followerId, int followeeId)</code> ID 为 <code>followerId</code> 的用户开始关注 ID 为 <code>followeeId</code> 的用户。</li>
<li><code>void unfollow(int followerId, int followeeId)</code> ID 为 <code>followerId</code> 的用户不再关注 ID 为 <code>followeeId</code> 的用户。</li>
</ul>
<p>&nbsp;</p>
<p><strong>示例:</strong></p>
<pre>
<strong>输入</strong>
["Twitter", "postTweet", "getNewsFeed", "follow", "postTweet", "getNewsFeed", "unfollow", "getNewsFeed"]
[[], [1, 5], [1], [1, 2], [2, 6], [1], [1, 2], [1]]
<strong>输出</strong>
[null, null, [5], null, null, [6, 5], null, [5]]
<strong>解释</strong>
Twitter twitter = new Twitter();
twitter.postTweet(1, 5); // 用户 1 发送了一条新推文 (用户 id = 1, 推文 id = 5)
twitter.getNewsFeed(1); // 用户 1 的获取推文应当返回一个列表,其中包含一个 id 为 5 的推文
twitter.follow(1, 2); // 用户 1 关注了用户 2
twitter.postTweet(2, 6); // 用户 2 发送了一个新推文 (推文 id = 6)
twitter.getNewsFeed(1); // 用户 1 的获取推文应当返回一个列表,其中包含两个推文,id 分别为 -&gt; [6, 5] 。推文 id 6 应当在推文 id 5 之前,因为它是在 5 之后发送的
twitter.unfollow(1, 2); // 用户 1 取消关注了用户 2
twitter.getNewsFeed(1); // 用户 1 获取推文应当返回一个列表,其中包含一个 id 为 5 的推文。因为用户 1 已经不再关注用户 2</pre>
<p>&nbsp;</p>
<p><strong>提示:</strong></p>
<ul>
<li><code>1 &lt;= userId, followerId, followeeId &lt;= 500</code></li>
<li><code>0 &lt;= tweetId &lt;= 10<sup>4</sup></code></li>
<li>所有推特的 ID 都互不相同</li>
<li><code>postTweet</code><code>getNewsFeed</code><code>follow</code><code>unfollow</code> 方法最多调用 <code>3 * 10<sup>4</sup></code></li>
</ul>
#include <bits/stdc++.h>
using namespace std;
class Twitter
{
public:
/** Initialize your data structure here. */
Twitter()
{
}
/** Compose a new tweet. */
void postTweet(int userId, int tweetId)
{
context.push_back(make_pair(userId, tweetId));
}
/** Retrieve the 10 most recent tweet ids in the user's news feed. Each item in the news feed must be posted by users who the user followed or by the user herself. Tweets must be ordered from most recent to least recent. */
vector<int> getNewsFeed(int userId)
{
int n = context.size();
int count = 0;
vector<int> res;
int k = n - 1;
while (count < 10 && k >= 0)
{
auto it = context[k];
if (it.first == userId || tmp[make_pair(userId, it.first)])
{
res.push_back(context[k].second);
count++;
}
k--;
}
return res;
}
/** Follower follows a followee. If the operation is invalid, it should be a no-op. */
void follow(int followerId, int followeeId)
{
tmp[make_pair(followerId, followeeId)] = 1;
}
/** Follower unfollows a followee. If the operation is invalid, it should be a no-op. */
void unfollow(int followerId, int followeeId)
{
tmp[make_pair(followerId, followeeId)] = 0;
}
private:
map<pair<int, int>, int> tmp;
vector<pair<int, int>> context;
};
/**
* Your Twitter object will be instantiated and called as such:
* Twitter* obj = new Twitter();
* obj->postTweet(userId,tweetId);
* vector<int> param_2 = obj->getNewsFeed(userId);
* obj->follow(followerId,followeeId);
* obj->unfollow(followerId,followeeId);
*/
{
"type": "code_options",
"author": "CSDN.net",
"source": "solution.md",
"exercise_id": "513aa99c029d4aa6a7b04c2008a13dbf"
}
\ No newline at end of file
# 设计推特
<p>设计一个简化版的推特(Twitter),可以让用户实现发送推文,关注/取消关注其他用户,能够看见关注人(包括自己)的最近 <code>10</code> 条推文。</p>
<p>实现 <code>Twitter</code> 类:</p>
<ul>
<li><code>Twitter()</code> 初始化简易版推特对象</li>
<li><code>void postTweet(int userId, int tweetId)</code> 根据给定的 <code>tweetId</code><code>userId</code> 创建一条新推文。每次调用次函数都会使用一个不同的 <code>tweetId</code></li>
<li><code>List&lt;Integer&gt; getNewsFeed(int userId)</code> 检索当前用户新闻推送中最近&nbsp; <code>10</code> 条推文的 ID 。新闻推送中的每一项都必须是由用户关注的人或者是用户自己发布的推文。推文必须 <strong>按照时间顺序由最近到最远排序</strong></li>
<li><code>void follow(int followerId, int followeeId)</code> ID 为 <code>followerId</code> 的用户开始关注 ID 为 <code>followeeId</code> 的用户。</li>
<li><code>void unfollow(int followerId, int followeeId)</code> ID 为 <code>followerId</code> 的用户不再关注 ID 为 <code>followeeId</code> 的用户。</li>
</ul>
<p>&nbsp;</p>
<p><strong>示例:</strong></p>
<pre>
<strong>输入</strong>
["Twitter", "postTweet", "getNewsFeed", "follow", "postTweet", "getNewsFeed", "unfollow", "getNewsFeed"]
[[], [1, 5], [1], [1, 2], [2, 6], [1], [1, 2], [1]]
<strong>输出</strong>
[null, null, [5], null, null, [6, 5], null, [5]]
<strong>解释</strong>
Twitter twitter = new Twitter();
twitter.postTweet(1, 5); // 用户 1 发送了一条新推文 (用户 id = 1, 推文 id = 5)
twitter.getNewsFeed(1); // 用户 1 的获取推文应当返回一个列表,其中包含一个 id 为 5 的推文
twitter.follow(1, 2); // 用户 1 关注了用户 2
twitter.postTweet(2, 6); // 用户 2 发送了一个新推文 (推文 id = 6)
twitter.getNewsFeed(1); // 用户 1 的获取推文应当返回一个列表,其中包含两个推文,id 分别为 -&gt; [6, 5] 。推文 id 6 应当在推文 id 5 之前,因为它是在 5 之后发送的
twitter.unfollow(1, 2); // 用户 1 取消关注了用户 2
twitter.getNewsFeed(1); // 用户 1 获取推文应当返回一个列表,其中包含一个 id 为 5 的推文。因为用户 1 已经不再关注用户 2</pre>
<p>&nbsp;</p>
<p><strong>提示:</strong></p>
<ul>
<li><code>1 &lt;= userId, followerId, followeeId &lt;= 500</code></li>
<li><code>0 &lt;= tweetId &lt;= 10<sup>4</sup></code></li>
<li>所有推特的 ID 都互不相同</li>
<li><code>postTweet</code><code>getNewsFeed</code><code>follow</code><code>unfollow</code> 方法最多调用 <code>3 * 10<sup>4</sup></code></li>
</ul>
<p>以下错误的选项是?</p>
## aop
### before
```cpp
#include <bits/stdc++.h>
using namespace std;
```
### after
```cpp
```
## 答案
```cpp
class Twitter
{
public:
/** Initialize your data structure here. */
Twitter()
{
}
/** Compose a new tweet. */
void postTweet(int userId, int tweetId)
{
tweets[userId].push_back(make_pair(time++, tweetId));
}
/** Retrieve the 10 most recent tweet ids in the user's news feed. Each item in the news feed must be posted by users who the user followed or by the user herself. Tweets must be ordered from most recent to least recent. */
vector<int> getNewsFeed(int userId)
{
vector<int> userIds({userId});
if (following.find(userId) != following.end())
{
userIds.insert(userIds.begin(), following[userId].begin(), following[userId].end());
}
vector<int> index(userIds.size());
for (int i = 0; i < userIds.size(); ++i)
{
index[i] = tweets[userIds[i]].size();
}
vector<int> res;
while (res.size() < 10)
{
int mxi = 0, mxtime = INT_MIN, mxTweet = 0;
for (int i = 0; i < index.size(); ++i)
{
int idx = index[i];
if (idx > 0)
{
int ui = userIds[i];
int time = tweets[ui][idx].first;
if (time > mxtime)
{
mxi = i;
mxtime = time;
mxTweet = tweets[ui][idx].second;
}
}
}
if (mxtime == INT_MIN)
{
break;
}
++index[mxi];
res.push_back(mxTweet);
}
return res;
}
/** Follower follows a followee. If the operation is invalid, it should be a no-op. */
void follow(int followerId, int followeeId)
{
if (followerId != followeeId)
{
following[followerId].insert(followeeId);
}
}
/** Follower unfollows a followee. If the operation is invalid, it should be a no-op. */
void unfollow(int followerId, int followeeId)
{
if (following.find(followerId) == following.end())
{
return;
}
following[followerId].erase(followeeId);
if (following[followerId].empty())
{
following.erase(followerId);
}
}
private:
int time{0};
unordered_map<int, unordered_set<int>> following;
unordered_map<int, vector<pair<int, int>>> tweets;
};
/**
* Your Twitter object will be instantiated and called as such:
* Twitter obj = new Twitter();
* obj.postTweet(userId,tweetId);
* vector<int> param_2 = obj.getNewsFeed(userId);
* obj.follow(followerId,followeeId);
* obj.unfollow(followerId,followeeId);
*/
```
## 选项
### A
```cpp
class Twitter
{
private:
list<pair<int, int>> twitterNews;
map<int, map<int, bool>> followMap;
public:
/** Initialize your data structure here. */
Twitter()
{
}
/** Compose a new tweet. */
void postTweet(int userId, int tweetId)
{
twitterNews.insert(twitterNews.begin(), pair<int, int>(userId, tweetId));
}
/** Retrieve the 10 most recent tweet ids in the user's news feed. Each item in the news feed must be posted by users who the user followed or by the user herself. Tweets must be ordered from most recent to least recent. */
vector<int> getNewsFeed(int userId)
{
vector<int> result;
list<pair<int, int>>::iterator it = twitterNews.begin();
while (it != twitterNews.end() && result.size() < 10)
{
if (it->first == userId || followMap[userId][it->first])
{
result.push_back(it->second);
}
it++;
}
return result;
}
/** Follower follows a followee. If the operation is invalid, it should be a no-op. */
void follow(int followerId, int followeeId)
{
followMap[followerId][followeeId] = true;
}
/** Follower unfollows a followee. If the operation is invalid, it should be a no-op. */
void unfollow(int followerId, int followeeId)
{
followMap[followerId][followeeId] = false;
}
};
/**
* Your Twitter object will be instantiated and called as such:
* Twitter obj = new Twitter();
* obj.postTweet(userId,tweetId);
* vector<int> param_2 = obj.getNewsFeed(userId);
* obj.follow(followerId,followeeId);
* obj.unfollow(followerId,followeeId);
*/
```
### B
```cpp
class Twitter
{
public:
/** Initialize your data structure here. */
Twitter()
{
}
/** Compose a new tweet. */
void postTweet(int userId, int tweetId)
{
context.push_back(make_pair(userId, tweetId));
}
/** Retrieve the 10 most recent tweet ids in the user's news feed. Each item in the news feed must be posted by users who the user followed or by the user herself. Tweets must be ordered from most recent to least recent. */
vector<int> getNewsFeed(int userId)
{
int n = context.size();
int count = 0;
vector<int> res;
int k = n - 1;
while (count < 10 && k >= 0)
{
auto it = context[k];
if (it.first == userId || tmp[make_pair(userId, it.first)])
{
res.push_back(context[k].second);
count++;
}
k--;
}
return res;
}
/** Follower follows a followee. If the operation is invalid, it should be a no-op. */
void follow(int followerId, int followeeId)
{
tmp[make_pair(followerId, followeeId)] = 1;
}
/** Follower unfollows a followee. If the operation is invalid, it should be a no-op. */
void unfollow(int followerId, int followeeId)
{
tmp[make_pair(followerId, followeeId)] = 0;
}
private:
map<pair<int, int>, int> tmp;
vector<pair<int, int>> context;
};
/**
* Your Twitter object will be instantiated and called as such:
* Twitter* obj = new Twitter();
* obj->postTweet(userId,tweetId);
* vector<int> param_2 = obj->getNewsFeed(userId);
* obj->follow(followerId,followeeId);
* obj->unfollow(followerId,followeeId);
*/
```
### C
```cpp
class Twitter
{
public:
/** Initialize your data structure here. */
Twitter()
{
}
/** Compose a new tweet. */
void postTweet(int userId, int tweetId)
{
context.push_back(make_pair(userId, tweetId));
}
/** Retrieve the 10 most recent tweet ids in the user's news feed. Each item in the news feed must be posted by users who the user followed or by the user herself. Tweets must be ordered from most recent to least recent. */
vector<int> getNewsFeed(int userId)
{
int n = context.size();
int count = 0;
vector<int> res;
int k = n - 1;
while (count < 10 && k >= 0)
{
auto it = context[k];
if (it.first == userId || tmp[make_pair(userId, it.first)])
{
res.push_back(context[k].second);
count++;
}
k--;
}
return res;
}
/** Follower follows a followee. If the operation is invalid, it should be a no-op. */
void follow(int followerId, int followeeId)
{
tmp[make_pair(followerId, followeeId)] = 1;
}
/** Follower unfollows a followee. If the operation is invalid, it should be a no-op. */
void unfollow(int followerId, int followeeId)
{
tmp[make_pair(followerId, followeeId)] = 0;
}
private:
map<pair<int, int>, int> tmp;
vector<pair<int, int>> context;
};
/**
* Your Twitter object will be instantiated and called as such:
* Twitter* obj = new Twitter();
* obj->postTweet(userId,tweetId);
* vector<int> param_2 = obj->getNewsFeed(userId);
* obj->follow(followerId,followeeId);
* obj->unfollow(followerId,followeeId);
*/
```
{
"node_id": "569d5e11c4fc5de7844053d9a733c5e8",
"keywords": [
"leetcode",
"O(1) 时间插入、删除和获取随机元素"
],
"children": [],
"export": [
"solution.json"
],
"title": "O(1) 时间插入、删除和获取随机元素"
}
\ No newline at end of file
<p>实现<code>RandomizedSet</code> 类:</p>
<div class="original__bRMd">
<div>
<ul>
<li><code>RandomizedSet()</code> 初始化 <code>RandomizedSet</code> 对象</li>
<li><code>bool insert(int val)</code> 当元素 <code>val</code> 不存在时,向集合中插入该项,并返回 <code>true</code> ;否则,返回 <code>false</code></li>
<li><code>bool remove(int val)</code> 当元素 <code>val</code> 存在时,从集合中移除该项,并返回 <code>true</code> ;否则,返回 <code>false</code></li>
<li><code>int getRandom()</code> 随机返回现有集合中的一项(测试用例保证调用此方法时集合中至少存在一个元素)。每个元素应该有 <strong>相同的概率</strong> 被返回。</li>
</ul>
<p>你必须实现类的所有函数,并满足每个函数的 <strong>平均</strong> 时间复杂度为 <code>O(1)</code></p>
<p>&nbsp;</p>
<p><strong>示例:</strong></p>
<pre>
<strong>输入</strong>
["RandomizedSet", "insert", "remove", "insert", "getRandom", "remove", "insert", "getRandom"]
[[], [1], [2], [2], [], [1], [2], []]
<strong>输出</strong>
[null, true, false, true, 2, true, false, 2]
<strong>解释</strong>
RandomizedSet randomizedSet = new RandomizedSet();
randomizedSet.insert(1); // 向集合中插入 1 。返回 true 表示 1 被成功地插入。
randomizedSet.remove(2); // 返回 false ,表示集合中不存在 2 。
randomizedSet.insert(2); // 向集合中插入 2 。返回 true 。集合现在包含 [1,2] 。
randomizedSet.getRandom(); // getRandom 应随机返回 1 或 2 。
randomizedSet.remove(1); // 从集合中移除 1 ,返回 true 。集合现在包含 [2] 。
randomizedSet.insert(2); // 2 已在集合中,所以返回 false 。
randomizedSet.getRandom(); // 由于 2 是集合中唯一的数字,getRandom 总是返回 2 。
</pre>
<p>&nbsp;</p>
<p><strong>提示:</strong></p>
<ul>
<li><code>-2<sup>31</sup> &lt;= val &lt;= 2<sup>31</sup> - 1</code></li>
<li>最多调用 <code>insert</code><code>remove</code><code>getRandom</code> 函数 <code>2 *&nbsp;</code><code>10<sup>5</sup></code></li>
<li>在调用 <code>getRandom</code> 方法时,数据结构中 <strong>至少存在一个</strong> 元素。</li>
</ul>
</div>
</div>
#include <bits/stdc++.h>
using namespace std;
class RandomizedSet
{
public:
vector<int> nums;
unordered_map<int, int> nums_inds;
/** Initialize your data structure here. */
RandomizedSet()
{
}
/** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
bool insert(int val)
{
if (nums_inds.count(val) != 0)
return false;
nums.push_back(val);
nums_inds[val] = nums.size() - 1;
return true;
}
/** Removes a value from the set. Returns true if the set contained the specified element. */
bool remove(int val)
{
if (nums_inds.count(val) == 0)
return false;
int last = nums.back();
int ind = nums_inds[val];
nums[ind] = last;
nums_inds[last] = ind;
nums.pop_back();
nums_inds.erase(val);
return true;
}
/** Get a random element from the set. */
int getRandom()
{
int ind = rand() % nums.size();
return nums[ind];
}
};
{
"type": "code_options",
"author": "CSDN.net",
"source": "solution.md",
"exercise_id": "af4861dc9e9b4bdba981f858f56483e7"
}
\ No newline at end of file
# O(1) 时间插入、删除和获取随机元素
<p>实现<code>RandomizedSet</code> 类:</p>
<div class="original__bRMd">
<div>
<ul>
<li><code>RandomizedSet()</code> 初始化 <code>RandomizedSet</code> 对象</li>
<li><code>bool insert(int val)</code> 当元素 <code>val</code> 不存在时,向集合中插入该项,并返回 <code>true</code> ;否则,返回 <code>false</code></li>
<li><code>bool remove(int val)</code> 当元素 <code>val</code> 存在时,从集合中移除该项,并返回 <code>true</code> ;否则,返回 <code>false</code></li>
<li><code>int getRandom()</code> 随机返回现有集合中的一项(测试用例保证调用此方法时集合中至少存在一个元素)。每个元素应该有 <strong>相同的概率</strong> 被返回。</li>
</ul>
<p>你必须实现类的所有函数,并满足每个函数的 <strong>平均</strong> 时间复杂度为 <code>O(1)</code></p>
<p>&nbsp;</p>
<p><strong>示例:</strong></p>
<pre>
<strong>输入</strong>
["RandomizedSet", "insert", "remove", "insert", "getRandom", "remove", "insert", "getRandom"]
[[], [1], [2], [2], [], [1], [2], []]
<strong>输出</strong>
[null, true, false, true, 2, true, false, 2]
<strong>解释</strong>
RandomizedSet randomizedSet = new RandomizedSet();
randomizedSet.insert(1); // 向集合中插入 1 。返回 true 表示 1 被成功地插入。
randomizedSet.remove(2); // 返回 false ,表示集合中不存在 2 。
randomizedSet.insert(2); // 向集合中插入 2 。返回 true 。集合现在包含 [1,2] 。
randomizedSet.getRandom(); // getRandom 应随机返回 1 或 2 。
randomizedSet.remove(1); // 从集合中移除 1 ,返回 true 。集合现在包含 [2] 。
randomizedSet.insert(2); // 2 已在集合中,所以返回 false 。
randomizedSet.getRandom(); // 由于 2 是集合中唯一的数字,getRandom 总是返回 2 。
</pre>
<p>&nbsp;</p>
<p><strong>提示:</strong></p>
<ul>
<li><code>-2<sup>31</sup> &lt;= val &lt;= 2<sup>31</sup> - 1</code></li>
<li>最多调用 <code>insert</code><code>remove</code><code>getRandom</code> 函数 <code>2 *&nbsp;</code><code>10<sup>5</sup></code></li>
<li>在调用 <code>getRandom</code> 方法时,数据结构中 <strong>至少存在一个</strong> 元素。</li>
</ul>
</div>
</div>
<p>以下错误的选项是?</p>
## aop
### before
```cpp
#include <bits/stdc++.h>
using namespace std;
```
### after
```cpp
```
## 答案
```cpp
class RandomizedSet
{
unordered_map<int, int> dict;
vector<int> list;
public:
/** Initialize your data structure here. */
RandomizedSet()
{
srand(time(0));
}
/** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
bool insert(int val)
{
if (dict.find(val) != dict.end())
return false;
list.push_back(val);
dict[val] = list.size();
return true;
}
/** Removes a value from the set. Returns true if the set contained the specified element. */
bool remove(int val)
{
if (dict.find(val) == dict.end())
return false;
dict[list.back()] = dict[val];
swap(list.back(), list[dict[val]]);
list.pop_back();
dict.erase(val);
return true;
}
/** Get a random element from the set. */
int getRandom()
{
int pos = list.empty() ? 0 : rand() % list.size();
return list[pos];
}
};
```
## 选项
### A
```cpp
class RandomizedSet
{
public:
/** Initialize your data structure here. */
RandomizedSet()
{
}
/** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
bool insert(int val)
{
if (mMap.count(val) > 0)
return false;
mData.push_back(val);
mMap[val] = mData.size() - 1;
return true;
}
/** Removes a value from the set. Returns true if the set contained the specified element. */
bool remove(int val)
{
if (mMap.count(val) > 0)
{
int last_num = mData.back();
int val_index = mMap[val];
mData[val_index] = last_num;
mMap[last_num] = val_index;
mData.pop_back();
mMap.erase(val);
return true;
}
return false;
}
/** Get a random element from the set. */
int getRandom()
{
int index = rand() % mData.size();
return mData[index];
}
private:
vector<int> mData;
unordered_map<int, int> mMap;
};
```
### B
```cpp
class RandomizedSet
{
public:
unordered_set<int> ust;
/** Initialize your data structure here. */
RandomizedSet()
{
}
/** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
bool insert(int val)
{
if (ust.find(val) != ust.end())
return false;
ust.insert(val);
return true;
}
/** Removes a value from the set. Returns true if the set contained the specified element. */
bool remove(int val)
{
if (ust.find(val) == ust.end())
return false;
ust.erase(val);
return true;
}
/** Get a random element from the set. */
int getRandom()
{
int ind = rand() % ust.size();
auto it = ust.begin();
for (int i = 0; i < ind; i++)
{
it++;
}
return *it;
}
};
```
### C
```cpp
class RandomizedSet
{
public:
vector<int> nums;
unordered_map<int, int> nums_inds;
/** Initialize your data structure here. */
RandomizedSet()
{
}
/** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
bool insert(int val)
{
if (nums_inds.count(val) != 0)
return false;
nums.push_back(val);
nums_inds[val] = nums.size() - 1;
return true;
}
/** Removes a value from the set. Returns true if the set contained the specified element. */
bool remove(int val)
{
if (nums_inds.count(val) == 0)
return false;
int last = nums.back();
int ind = nums_inds[val];
nums[ind] = last;
nums_inds[last] = ind;
nums.pop_back();
nums_inds.erase(val);
return true;
}
/** Get a random element from the set. */
int getRandom()
{
int ind = rand() % nums.size();
return nums[ind];
}
};
```
{
"node_id": "569d5e11c4fc5de7844053d9a733c5e8",
"keywords": [
"leetcode",
"O(1) 时间插入、删除和获取随机元素 - 允许重复"
],
"children": [],
"export": [
"solution.json"
],
"title": "O(1) 时间插入、删除和获取随机元素 - 允许重复"
}
\ No newline at end of file
<p>设计一个支持在<em>平均&nbsp;</em>时间复杂度&nbsp;<strong>O(1)&nbsp;</strong><strong>&nbsp;</strong>执行以下操作的数据结构。</p>
<p><strong>注意: 允许出现重复元素。</strong></p>
<ol>
<li><code>insert(val)</code>:向集合中插入元素 val。</li>
<li><code>remove(val)</code>:当 val 存在时,从集合中移除一个 val。</li>
<li><code>getRandom</code>:从现有集合中随机获取一个元素。每个元素被返回的概率应该与其在集合中的数量呈线性相关。</li>
</ol>
<p><strong>示例:</strong></p>
<pre>// 初始化一个空的集合。
RandomizedCollection collection = new RandomizedCollection();
// 向集合中插入 1 。返回 true 表示集合不包含 1 。
collection.insert(1);
// 向集合中插入另一个 1 。返回 false 表示集合包含 1 。集合现在包含 [1,1] 。
collection.insert(1);
// 向集合中插入 2 ,返回 true 。集合现在包含 [1,1,2] 。
collection.insert(2);
// getRandom 应当有 2/3 的概率返回 1 ,1/3 的概率返回 2 。
collection.getRandom();
// 从集合中删除 1 ,返回 true 。集合现在包含 [1,2] 。
collection.remove(1);
// getRandom 应有相同概率返回 1 和 2 。
collection.getRandom();
</pre>
#include <bits/stdc++.h>
using namespace std;
class RandomizedCollection
{
public:
vector<int> nums;
unordered_map<int, unordered_set<int>> numsIndex;
int size;
/** Initialize your data structure here. */
RandomizedCollection()
{
size = 0;
}
/** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */
bool insert(int val)
{
nums.push_back(val);
numsIndex[val].insert(size);
size++;
return numsIndex[val].size() == 1;
}
/** Removes a value from the collection. Returns true if the collection contained the specified element. */
bool remove(int val)
{
if (numsIndex.count(val) == 0)
return false;
int last = nums.back();
int id = size - 1;
if (last != val)
{
id = *(numsIndex[val].begin());
numsIndex[last].erase(size - 1);
numsIndex[last].insert(id);
nums[id] = last;
}
nums.pop_back();
size--;
numsIndex[val].erase(id);
if (numsIndex[val].empty())
numsIndex.erase(val);
return true;
}
/** Get a random element from the collection. */
int getRandom()
{
return nums[random() % size];
}
};
/**
* Your RandomizedCollection object will be instantiated and called as such:
* RandomizedCollection* obj = new RandomizedCollection();
* bool param_1 = obj->insert(val);
* bool param_2 = obj->remove(val);
* int param_3 = obj->getRandom();
*/
{
"type": "code_options",
"author": "CSDN.net",
"source": "solution.md",
"exercise_id": "d2333bf24b234247806d53c1ec803df7"
}
\ No newline at end of file
# O(1) 时间插入、删除和获取随机元素 - 允许重复
<p>设计一个支持在<em>平均&nbsp;</em>时间复杂度&nbsp;<strong>O(1)&nbsp;</strong><strong>&nbsp;</strong>执行以下操作的数据结构。</p>
<p><strong>注意: 允许出现重复元素。</strong></p>
<ol>
<li><code>insert(val)</code>:向集合中插入元素 val。</li>
<li><code>remove(val)</code>:当 val 存在时,从集合中移除一个 val。</li>
<li><code>getRandom</code>:从现有集合中随机获取一个元素。每个元素被返回的概率应该与其在集合中的数量呈线性相关。</li>
</ol>
<p><strong>示例:</strong></p>
<pre>// 初始化一个空的集合。
RandomizedCollection collection = new RandomizedCollection();
// 向集合中插入 1 。返回 true 表示集合不包含 1 。
collection.insert(1);
// 向集合中插入另一个 1 。返回 false 表示集合包含 1 。集合现在包含 [1,1] 。
collection.insert(1);
// 向集合中插入 2 ,返回 true 。集合现在包含 [1,1,2] 。
collection.insert(2);
// getRandom 应当有 2/3 的概率返回 1 ,1/3 的概率返回 2 。
collection.getRandom();
// 从集合中删除 1 ,返回 true 。集合现在包含 [1,2] 。
collection.remove(1);
// getRandom 应有相同概率返回 1 和 2 。
collection.getRandom();
</pre>
<p>以下错误的选项是?</p>
## aop
### before
```cpp
#include <bits/stdc++.h>
using namespace std;
```
### after
```cpp
```
## 答案
```cpp
class RandomizedCollection
{
public:
/** Initialize your data structure here. */
RandomizedCollection()
{
this->num = 0;
}
/** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */
bool insert(int val)
{
this->num++;
bool res;
if (this->M.find(val) == this->M.end() || this->M[val] == 0)
{
this->M[val] = 1;
res = true;
}
else
{
this->M[val]++;
res = false;
}
return res;
}
/** Removes a value from the collection. Returns true if the collection contained the specified element. */
bool remove(int val)
{
if (this->M.find(val) == this->M.end() || this->M[val] == 0)
{
return false;
}
else
{
M[val]--;
this->num--;
return true;
}
}
/** Get a random element from the collection. */
int getRandom()
{
if (this->num > 0)
{
srand((unsigned)time(NULL));
int randomValue = rand() % (this->num) + 1;
for (auto it : M)
{
randomValue -= it.second;
if (randomValue <= 0)
return it.first;
}
}
return 0;
}
private:
unordered_map<int, int> M;
int num;
};
```
## 选项
### A
```cpp
class RandomizedSet
{
public:
vector<int> nums;
unordered_map<int, int> numIndex;
int size;
/** Initialize your data structure here. */
RandomizedSet()
{
size = 0;
}
/** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
bool insert(int val)
{
if (numIndex.count(val) == 1)
return false;
nums.push_back(val);
numIndex[val] = size;
size++;
return true;
}
/** Removes a value from the set. Returns true if the set contained the specified element. */
bool remove(int val)
{
if (numIndex.count(val) == 0)
return false;
int last = nums.back();
nums[numIndex[val]] = last;
numIndex[last] = numIndex[val];
nums.pop_back();
numIndex.erase(val);
size--;
return true;
}
/** Get a random element from the set. */
int getRandom()
{
return nums[random() % size];
}
};
```
### B
```cpp
class RandomizedCollection
{
public:
unordered_map<int, unordered_set<int>> idx;
vector<int> nums;
/** Initialize your data structure here. */
RandomizedCollection()
{
}
/** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */
bool insert(int val)
{
nums.push_back(val);
idx[val].insert(nums.size() - 1);
return idx[val].size() == 1;
}
/** Removes a value from the collection. Returns true if the collection contained the specified element. */
bool remove(int val)
{
if (idx.find(val) == idx.end())
{
return false;
}
int i = *(idx[val].begin());
nums[i] = nums.back();
idx[val].erase(i);
idx[nums[i]].erase(nums.size() - 1);
if (i < nums.size() - 1)
{
idx[nums[i]].insert(i);
}
if (idx[val].size() == 0)
{
idx.erase(val);
}
nums.pop_back();
return true;
}
/** Get a random element from the collection. */
int getRandom()
{
return nums[rand() % nums.size()];
}
};
```
### C
```cpp
class RandomizedCollection
{
public:
vector<int> nums;
unordered_map<int, unordered_set<int>> numsIndex;
int size;
/** Initialize your data structure here. */
RandomizedCollection()
{
size = 0;
}
/** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */
bool insert(int val)
{
nums.push_back(val);
numsIndex[val].insert(size);
size++;
return numsIndex[val].size() == 1;
}
/** Removes a value from the collection. Returns true if the collection contained the specified element. */
bool remove(int val)
{
if (numsIndex.count(val) == 0)
return false;
int last = nums.back();
int id = size - 1;
if (last != val)
{
id = *(numsIndex[val].begin());
numsIndex[last].erase(size - 1);
numsIndex[last].insert(id);
nums[id] = last;
}
nums.pop_back();
size--;
numsIndex[val].erase(id);
if (numsIndex[val].empty())
numsIndex.erase(val);
return true;
}
/** Get a random element from the collection. */
int getRandom()
{
return nums[random() % size];
}
};
```
{
"node_id": "569d5e11c4fc5de7844053d9a733c5e8",
"keywords": [
"leetcode",
"LFU 缓存"
],
"children": [],
"export": [
"solution.json"
],
"title": "LFU 缓存"
}
\ No newline at end of file
<p>请你为 <a href="https://baike.baidu.com/item/%E7%BC%93%E5%AD%98%E7%AE%97%E6%B3%95">最不经常使用(LFU)</a>缓存算法设计并实现数据结构。</p>
<p>实现 <code>LFUCache</code> 类:</p>
<ul>
<li><code>LFUCache(int capacity)</code> - 用数据结构的容量 <code>capacity</code> 初始化对象</li>
<li><code>int get(int key)</code> - 如果键存在于缓存中,则获取键的值,否则返回 -1。</li>
<li><code>void put(int key, int value)</code> - 如果键已存在,则变更其值;如果键不存在,请插入键值对。当缓存达到其容量时,则应该在插入新项之前,使最不经常使用的项无效。在此问题中,当存在平局(即两个或更多个键具有相同使用频率)时,应该去除 <strong>最近最久未使用</strong> 的键。</li>
</ul>
<p><strong>注意</strong>「项的使用次数」就是自插入该项以来对其调用 <code>get</code><code>put</code> 函数的次数之和。使用次数会在对应项被移除后置为 0 。</p>
<p>为了确定最不常使用的键,可以为缓存中的每个键维护一个 <strong>使用计数器</strong> 。使用计数最小的键是最久未使用的键。</p>
<p>当一个键首次插入到缓存中时,它的使用计数器被设置为 <code>1</code> (由于 put 操作)。对缓存中的键执行 <code>get</code><code>put</code> 操作,使用计数器的值将会递增。</p>
<p> </p>
<p><strong>示例:</strong></p>
<pre>
<strong>输入:</strong>
["LFUCache", "put", "put", "get", "put", "get", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [3], [4, 4], [1], [3], [4]]
<strong>输出:</strong>
[null, null, null, 1, null, -1, 3, null, -1, 3, 4]
<strong>解释:</strong>
// cnt(x) = 键 x 的使用计数
// cache=[] 将显示最后一次使用的顺序(最左边的元素是最近的)
LFUCache lFUCache = new LFUCache(2);
lFUCache.put(1, 1); // cache=[1,_], cnt(1)=1
lFUCache.put(2, 2); // cache=[2,1], cnt(2)=1, cnt(1)=1
lFUCache.get(1); // 返回 1
// cache=[1,2], cnt(2)=1, cnt(1)=2
lFUCache.put(3, 3); // 去除键 2 ,因为 cnt(2)=1 ,使用计数最小
// cache=[3,1], cnt(3)=1, cnt(1)=2
lFUCache.get(2); // 返回 -1(未找到)
lFUCache.get(3); // 返回 3
// cache=[3,1], cnt(3)=2, cnt(1)=2
lFUCache.put(4, 4); // 去除键 1 ,1 和 3 的 cnt 相同,但 1 最久未使用
// cache=[4,3], cnt(4)=1, cnt(3)=2
lFUCache.get(1); // 返回 -1(未找到)
lFUCache.get(3); // 返回 3
// cache=[3,4], cnt(4)=1, cnt(3)=3
lFUCache.get(4); // 返回 4
// cache=[3,4], cnt(4)=2, cnt(3)=3</pre>
<p> </p>
<p><strong>提示:</strong></p>
<ul>
<li><code>0 <capacity, key, value <= 10<sup>4</sup></code></li>
<li>最多调用 <code>10<sup>5</sup></code><code>get</code><code>put</code> 方法</li>
</ul>
<p> </p>
<p><strong>进阶:</strong>你可以为这两种操作设计时间复杂度为 <code>O(1)</code> 的实现吗?</p>
#include <bits/stdc++.h>
using namespace std;
struct Value
{
Value(int count_, int time_, int key_, int value_)
: count(count_),
key(key_),
value(value_),
time(time_) {}
bool operator<(const Value &a) const
{
return count == a.count ? time < a.time : count < a.count;
}
int key;
int value;
int count;
int time;
};
class LFUCache
{
public:
LFUCache(int capacity_)
: capacity(capacity_),
time(0) {}
int get(int key)
{
if (capacity == 0)
return -1;
auto it = table.find(key);
if (it == table.end())
return -1;
Value cache = it->second;
judge.erase(cache);
cache.count++;
cache.time = ++time;
judge.insert(cache);
it->second = cache;
return cache.value;
}
void put(int key, int value)
{
if (capacity == 0)
return;
auto it = table.find(key);
if (it == table.end())
{
if (table.size() == capacity)
{
table.erase(judge.begin()->key);
judge.erase(judge.begin());
}
Value put_(0, ++time, key, value);
table.insert({key, put_});
judge.insert(put_);
}
else
{
Value temp = it->second;
judge.erase(temp);
Value put_(++temp.count, ++time, key, value);
it->second = put_;
judge.insert(put_);
}
}
private:
const int capacity;
int time;
unordered_map<int, Value> table;
set<Value> judge;
};
{
"type": "code_options",
"author": "CSDN.net",
"source": "solution.md",
"exercise_id": "4ff0bf6da5ea408a8791d86fbd62c206"
}
\ No newline at end of file
# LFU 缓存
<p>请你为 <a href="https://baike.baidu.com/item/%E7%BC%93%E5%AD%98%E7%AE%97%E6%B3%95">最不经常使用(LFU)</a>缓存算法设计并实现数据结构。</p>
<p>实现 <code>LFUCache</code> 类:</p>
<ul>
<li><code>LFUCache(int capacity)</code> - 用数据结构的容量 <code>capacity</code> 初始化对象</li>
<li><code>int get(int key)</code> - 如果键存在于缓存中,则获取键的值,否则返回 -1。</li>
<li><code>void put(int key, int value)</code> - 如果键已存在,则变更其值;如果键不存在,请插入键值对。当缓存达到其容量时,则应该在插入新项之前,使最不经常使用的项无效。在此问题中,当存在平局(即两个或更多个键具有相同使用频率)时,应该去除 <strong>最近最久未使用</strong> 的键。</li>
</ul>
<p><strong>注意</strong>「项的使用次数」就是自插入该项以来对其调用 <code>get</code><code>put</code> 函数的次数之和。使用次数会在对应项被移除后置为 0 。</p>
<p>为了确定最不常使用的键,可以为缓存中的每个键维护一个 <strong>使用计数器</strong> 。使用计数最小的键是最久未使用的键。</p>
<p>当一个键首次插入到缓存中时,它的使用计数器被设置为 <code>1</code> (由于 put 操作)。对缓存中的键执行 <code>get</code><code>put</code> 操作,使用计数器的值将会递增。</p>
<p> </p>
<p><strong>示例:</strong></p>
<pre>
<strong>输入:</strong>
["LFUCache", "put", "put", "get", "put", "get", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [3], [4, 4], [1], [3], [4]]
<strong>输出:</strong>
[null, null, null, 1, null, -1, 3, null, -1, 3, 4]
<strong>解释:</strong>
// cnt(x) = 键 x 的使用计数
// cache=[] 将显示最后一次使用的顺序(最左边的元素是最近的)
LFUCache lFUCache = new LFUCache(2);
lFUCache.put(1, 1); // cache=[1,_], cnt(1)=1
lFUCache.put(2, 2); // cache=[2,1], cnt(2)=1, cnt(1)=1
lFUCache.get(1); // 返回 1
// cache=[1,2], cnt(2)=1, cnt(1)=2
lFUCache.put(3, 3); // 去除键 2 ,因为 cnt(2)=1 ,使用计数最小
// cache=[3,1], cnt(3)=1, cnt(1)=2
lFUCache.get(2); // 返回 -1(未找到)
lFUCache.get(3); // 返回 3
// cache=[3,1], cnt(3)=2, cnt(1)=2
lFUCache.put(4, 4); // 去除键 1 ,1 和 3 的 cnt 相同,但 1 最久未使用
// cache=[4,3], cnt(4)=1, cnt(3)=2
lFUCache.get(1); // 返回 -1(未找到)
lFUCache.get(3); // 返回 3
// cache=[3,4], cnt(4)=1, cnt(3)=3
lFUCache.get(4); // 返回 4
// cache=[3,4], cnt(4)=2, cnt(3)=3</pre>
<p> </p>
<p><strong>提示:</strong></p>
<ul>
<li><code>0 <capacity, key, value <= 10<sup>4</sup></code></li>
<li>最多调用 <code>10<sup>5</sup></code><code>get</code><code>put</code> 方法</li>
</ul>
<p> </p>
<p><strong>进阶:</strong>你可以为这两种操作设计时间复杂度为 <code>O(1)</code> 的实现吗?</p>
<p>以下错误的选项是?</p>
## aop
### before
```cpp
#include <bits/stdc++.h>
using namespace std;
```
### after
```cpp
```
## 答案
```cpp
class LFUCache
{
private:
int cap;
int size;
int minfre;
unordered_map<int, pair<int, int>> m;
unordered_map<int, list<int>> hash_fre;
unordered_map<int, list<int>::iterator> hash_node;
public:
LFUCache(int capacity) : cap(capacity), size(0) {}
int get(int key)
{
if (m.count(key) == 0)
return -1;
hash_fre[m[key].second].erase(hash_node[key]);
m[key].second++;
hash_fre[m[key].second].push_back(key);
hash_node[key] = --hash_fre[m[key].second].end();
if (hash_fre[minfre].size() == 0)
{
minfre++;
}
return m[key].first;
}
void put(int key, int value)
{
if (cap <= 0)
return;
if (get(key) != -1)
{
m[key].first = value;
return;
}
if (size >= cap)
{
m.erase(hash_fre[minfre].front());
hash_node.erase(hash_fre[minfre].front());
hash_fre[minfre].pop_front();
}
m[key] = {value, 1};
hash_fre[1].push_back(key);
hash_node[key] = hash_fre[1].end();
minfre = 1;
if (size < cap)
size++;
}
};
```
## 选项
### A
```cpp
class Node
{
public:
int cnt;
int time;
int key;
int val;
Node(int cnt, int time, int key, int val)
{
this->cnt = cnt;
this->time = time;
this->key = key;
this->val = val;
}
bool operator<(const Node &n) const
{
if (n.cnt == cnt)
return time < n.time;
return cnt < n.cnt;
}
};
class LFUCache
{
public:
int size;
int time;
unordered_map<int, Node> LFU;
set<Node> tree;
LFUCache(int capacity)
{
time = 0;
size = capacity;
}
int get(int key)
{
if (LFU.count(key) == 0)
return -1;
unordered_map<int, Node>::iterator iter = LFU.find(key);
Node now = (*iter).second;
tree.erase(now);
now.cnt++;
now.time = time++;
tree.insert(now);
(*iter).second = now;
return now.val;
}
void put(int key, int value)
{
if (LFU.count(key) == 0)
{
Node newNode = Node(1, time++, key, value);
if (size == 0)
{
if (tree.empty())
return;
LFU.erase((*(tree.begin())).key);
tree.erase(tree.begin());
}
else
{
size--;
}
LFU.insert(make_pair(key, newNode));
tree.insert(newNode);
}
else
{
unordered_map<int, Node>::iterator iter = LFU.find(key);
Node now = (*iter).second;
tree.erase(now);
now.cnt++;
now.time = time++;
now.val = value;
tree.insert(now);
(*iter).second = now;
}
}
};
```
### B
```cpp
class LFUCache
{
public:
LFUCache(int capacity_)
: capacity(capacity_),
minfreq(0)
{
iter_table.clear();
freq_table.clear();
}
int get(int key)
{
if (capacity == 0)
return -1;
auto it = iter_table.find(key);
if (it == iter_table.end())
return -1;
list<Value>::iterator iter = it->second;
int value = iter->value;
int freq = iter->freq;
Value new_node(key, value, freq + 1);
freq_table[freq].erase(iter);
if (freq_table[freq].size() == 0)
{
freq_table.erase(freq);
if (minfreq == freq)
minfreq += 1;
}
freq_table[freq + 1].push_front(new_node);
iter_table[key] = freq_table[freq + 1].begin();
return new_node.value;
}
void put(int key, int value)
{
if (capacity == 0)
return;
auto it = iter_table.find(key);
if (it == iter_table.end())
{
if (iter_table.size() == capacity)
{
auto it2 = freq_table[minfreq].back();
iter_table.erase(it2.key);
freq_table[minfreq].pop_back();
if (freq_table[minfreq].size() == 0)
{
freq_table.erase(minfreq);
}
}
freq_table[1].push_front(Value{key, value, 1});
iter_table[key] = freq_table[1].begin();
minfreq = 1;
}
else
{
list<Value>::iterator iter = it->second;
int freq = iter->freq;
Value new_node(iter->key, value, freq + 1);
freq_table[iter->freq].erase(iter);
if (freq_table[freq].size() == 0)
{
freq_table.erase(freq);
if (minfreq == freq)
minfreq += 1;
}
freq_table[freq + 1].push_front(new_node);
iter_table[key] = freq_table[freq + 1].begin();
}
}
private:
struct Value
{
Value(int key_, int value_, int freq_)
: key(key_),
value(value_),
freq(freq_) {}
int key;
int value;
int freq;
};
int capacity;
int minfreq;
unordered_map<int, list<Value>::iterator> iter_table;
unordered_map<int, list<Value>> freq_table;
};
```
### C
```cpp
struct Value
{
Value(int count_, int time_, int key_, int value_)
: count(count_),
key(key_),
value(value_),
time(time_) {}
bool operator<(const Value &a) const
{
return count == a.count ? time < a.time : count < a.count;
}
int key;
int value;
int count;
int time;
};
class LFUCache
{
public:
LFUCache(int capacity_)
: capacity(capacity_),
time(0) {}
int get(int key)
{
if (capacity == 0)
return -1;
auto it = table.find(key);
if (it == table.end())
return -1;
Value cache = it->second;
judge.erase(cache);
cache.count++;
cache.time = ++time;
judge.insert(cache);
it->second = cache;
return cache.value;
}
void put(int key, int value)
{
if (capacity == 0)
return;
auto it = table.find(key);
if (it == table.end())
{
if (table.size() == capacity)
{
table.erase(judge.begin()->key);
judge.erase(judge.begin());
}
Value put_(0, ++time, key, value);
table.insert({key, put_});
judge.insert(put_);
}
else
{
Value temp = it->second;
judge.erase(temp);
Value put_(++temp.count, ++time, key, value);
it->second = put_;
judge.insert(put_);
}
}
private:
const int capacity;
int time;
unordered_map<int, Value> table;
set<Value> judge;
};
```
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册