LeetCode 355 Design Twitter
概述
https://leetcode.com/problems/design-twitter/
需要我们存储的信息:
- 用户之间的关注关系,显然这是一个图;
- 用户发的 tweet,我们需要记录前后顺序和发送者。
设用户个数为 m,tweet 个数为 n。
基于全局数组的解法
所有 tweet 存到一个向量里,需要获取 feed 的时候,就从末尾处按个遍历,直到凑够 10 个合适的或者到达末尾为之。
时间复杂度:getNewsFeed 操作最坏情况 O(n) 最好情况 O(1),postTweet 操作 O(1) 空间复杂度:max(O(n), O(m^2))
const int MAX_USER_NUM = 501;
class Twitter {
public:
vector<pair<int, int>> tweets;
bool graph[MAX_USER_NUM][MAX_USER_NUM] = {0};
Twitter() {
for (int i = 0; i < MAX_USER_NUM; i ++) {
graph[i][i] = true;
}
}
void postTweet(int userId, int tweetId) {
tweets.push_back({userId, tweetId});
}
vector<int> getNewsFeed(int userId) {
vector<int> res;
for (int i = tweets.size() - 1; i >= 0; i --) {
if (graph[userId][tweets[i].first]) {
res.push_back(tweets[i].second);
if (res.size() == 10) break;
}
}
return res;
}
void follow(int followerId, int followeeId) {
graph[followerId][followeeId] = true;
}
void unfollow(int followerId, int followeeId) {
graph[followerId][followeeId] = false;
}
};
拉式(为每个用户维护发帖列表)
每个用户维护一个其发帖记录,于是我们的任务就是合并 f 个有序列表,且满 10 个就停,f 为其关注者数量。
getNewsFeed 时当场合并 feed。
- 时间复杂度:getNewsFeed 操作最坏情况 O(f),postTweet 操作 O(1)
- 空间复杂度:max(O(n), O(m^2))
推式(为每个用户维护收贴列表)
每个用户额外维护一个大小为 10 的 queue,postTweet 直接遍历其所有关注者(记为 f)更新其 queue,
另外这种情况下连用户关注关系图都不用了,但是为了取关时方便还是用吧,直接用 set 不就好了。
- 时间复杂度:getNewsFeed 操作 O(1),postTweet 操作 O(f)
- 空间复杂度:O(n)
实际应用中我感觉是选 2,因为 2 的 getNewsFeed 操作是 O(1),用户体验好, 缺点是 feed 有一定延时,不过这种场景下还 okay。
这里我们实现后者。
这个思路虽然高效但确是错误的,因为这样的话用户没办法看关注前的帖子,也没办法在取关后从 feed 里剔除掉帖子。
后者还好说,但是前者难搞。
class Twitter {
public:
vector<pair<int, int>> tweets;
unordered_map<int, set<int>> user2followers;
unordered_map<int, list<int>> user2feeds;
Twitter() {
}
void postTweet(int userId, int tweetId) {
tweets.push_back({userId, tweetId});
if (user2followers.count(userId)) {
user2followers[userId].insert(userId);
}
for (auto i : user2followers[userId]) {
user2feeds[i].push_front(tweetId);
if (user2feeds[i].size() > 10) user2feeds[i].pop_back();
}
}
vector<int> getNewsFeed(int userId) {
vector<int> res(user2feeds[userId].begin(), user2feeds[userId].end());
return res;
}
void follow(int followerId, int followeeId) {
user2followers[followeeId].insert(followerId);
}
void unfollow(int followerId, int followeeId) {
user2followers[followeeId].erase(followerId);
}
};
Links: leetcode-355-design-twitter