Design Twitter
應用面向對象設計(OO)模擬Twitter的幾個功能,分別是:
- 發推postTweet(userId, tweetId): Compose a new tweet.
- 獲取最近的十條推文getNewsFeed(userId): 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.
- 關注follow(followerId, followeeId): Follower follows a follow.
- 取關unfollow(followerId, followeeId): Follower unfollows a followee.
跟微博一樣??
首先要考慮的是,這里應該有用戶、推文,用戶很簡單,一個整形就可以表示。推文需要有,userId,tweetId,timestamp(我們這里并不需要詳細的時間,只要有每條推文的先后順數就可以了),對此我們使用struct tweet
接下來分析功能,每一個用戶都應該有一個數組來記錄他的關注對象,另外一個數組紀錄他的推文,這里可以選擇建一個structure記錄這些數據,但是在這道題里我們只用到了兩個unordered_maps存放對應數據,在map中每個整形(userId)都有對應的followees和tweets
有了這樣的數據結構呢,postTweet, follow, unfollow都很好實現了,只需要對map進行相應操作即可。
有些難得是getNewsFeed這個函數,返回用戶關注的最近十條推文,包括他自己的。對于這種有順序的東西很容易想到priority_queue, 下面這個solution用一個priority-queue存儲該用戶關注的每個用戶的推文的begin iterator, end iterator. begin iterator用于從每個follow發的最新的推文中選出最新的。
class Twitter {
private:
struct tweet {
int userId;
int tweetId;
int timesStamp;
tweet(int x, int y, int z): userId(x), tweetId(y), timesStamp(z){};
};
struct mycompare {
bool operator()(pair<list<tweet>::iterator, list<tweet>::iterator> p1,
pair<list<tweet>::iterator, list<tweet>::iterator> p2) {
return p1.first->timesStamp < p2.first->timesStamp;
}
};
int timeLabel = 0;
unordered_map<int, unordered_set<int>> followees;
unordered_map<int, list<tweet>> tweets;
public:
/** Initialize your data structure here. */
Twitter() {}
/** Compose a new tweet. */
void postTweet(int userId, int tweetId) {
followees[userId].insert(userId);
tweets[userId].push_front(tweet(userId, tweetId, timeLabel));
timeLabel++;
}
/** 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> res;
if (followees.find(userId) == followees.end()) return res;
priority_queue<pair<tweet, tweet>,
vector<pair<tweet, tweet>>,
mycompare> pq;
for (auto it = followees[userId].begin(); it != followees[userId].end(); it++)
if (tweets[*it].begin() != tweets[*it].end())
pq.push(make_pair(* tweets[*it].begin(), * tweets[*it].end()));
int index = 0;
while(!pq.empty() && index < 10) {
auto tmp = pq.top();
pq.pop();
res.push_back(tmp.first.tweetId);
if (++tmp.first != tmp.second)
pq.push(tmp);
index++;
}
return res;
}
/** Follower follows a followee. If the operation is invalid, it should be a no-op. */
void follow(int followerId, int followeeId) {
followees[followerId].insert(followerId);
followees[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 (followees.find(followerId) != followees.end() && followerId != followeeId) {
followees[followerId].erase(followeeId);
}
}
};
/**
* 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);
*/