[LeetCode] 355. Design Twitter 设计推特

 

Design a simplified version of Twitter where users can post tweets, follow/unfollow another user, and is able to see the 10 most recent tweets in the user's news feed.

Implement the Twitter class:

  • Twitter() Initializes your twitter object.
  • void postTweet(int userId, int tweetId) Composes a new tweet with ID tweetId by the user userId. Each call to this function will be made with a unique tweetId.
  • List<Integer> getNewsFeed(int userId) Retrieves 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 themself. Tweets must be ordered from most recent to least recent.
  • void follow(int followerId, int followeeId) The user with ID followerId started following the user with ID followeeId.
  • void unfollow(int followerId, int followeeId) The user with ID followerId started unfollowing the user with ID followeeId.

 

Example 1:

Input
["Twitter", "postTweet", "getNewsFeed", "follow", "postTweet", "getNewsFeed", "unfollow", "getNewsFeed"]
[[], [1, 5], [1], [1, 2], [2, 6], [1], [1, 2], [1]]
Output
[null, null, [5], null, null, [6, 5], null, [5]]

Explanation
Twitter twitter = new Twitter();
twitter.postTweet(1, 5); // User 1 posts a new tweet (id = 5).
twitter.getNewsFeed(1);  // User 1's news feed should return a list with 1 tweet id -> [5]. return [5]
twitter.follow(1, 2);    // User 1 follows user 2.
twitter.postTweet(2, 6); // User 2 posts a new tweet (id = 6).
twitter.getNewsFeed(1);  // User 1's news feed should return a list with 2 tweet ids -> [6, 5]. Tweet id 6 should precede tweet id 5 because it is posted after tweet id 5.
twitter.unfollow(1, 2);  // User 1 unfollows user 2.
twitter.getNewsFeed(1);  // User 1's news feed should return a list with 1 tweet id -> [5], since user 1 is no longer following user 2.

 

Constraints:

  • 1 <= userId, followerId, followeeId <= 500
  • 0 <= tweetId <= 104
  • All the tweets have unique IDs.
  • At most 3 * 104 calls will be made to postTweetgetNewsFeedfollow, and unfollow.

 

这道题让设计个简单的推特,具有发布消息,获得新鲜事,添加关注和取消关注等功能。需要用两个 HashMap 来做,第一个是建立用户和其所有好友之间的映射,另一个是建立用户和其所有消息之间的映射。由于获得新鲜事是需要按时间顺序排列的,那么可以用一个整型变量 cnt 来模拟时间点,每发一个消息,cnt 自增1,就知道 cnt 大的是最近发的。在建立用户和其所有消息之间的映射时,还需要建立每个消息和其时间点 cnt 之间的映射。这道题的主要难点在于实现 getNewsFeed() 函数,这个函数获取自己和好友的最近 10 条消息,这里的做法是用户也添加到自己的好友列表中,然后遍历该用户的所有好友,遍历每个好友的所有消息,维护一个大小为 10 的哈希表,如果新遍历到的消息比 HashMap 中最早的消息要晚,那么将这个消息加入,然后删除掉最早的那个消息,这样就可以找出最近 10 条消息了,参见代码如下:

 

解法一:

class Twitter {
public:
    Twitter() {
        time = 0;
    }
    
    void postTweet(int userId, int tweetId) {
        follow(userId, userId);
        tweets[userId].insert({time++, tweetId});
    }
    
    vector<int> getNewsFeed(int userId) {
        vector<int> res;
        map<int, int> top10;
        for (auto id : friends[userId]) {
            for (auto a : tweets[id]) {
                top10.insert({a.first, a.second});
                if (top10.size() > 10) top10.erase(top10.begin());
            }
        }
        for (auto a : top10) {
            res.insert(res.begin(), a.second);
        }
        return res;
    }
    
    void follow(int followerId, int followeeId) {
        friends[followerId].insert(followeeId);
    }
    
    void unfollow(int followerId, int followeeId) {
        if (followerId != followeeId) {
            friends[followerId].erase(followeeId);
        }
    }
    
private:
    int time;
    unordered_map<int, unordered_set<int>> friends;
    unordered_map<int, map<int, int>> tweets;
};

 

下面这种方法和上面的基本一样,就是在保存用户所有消息的时候,用的是 vector<pair<int, int>>,这样可以用 priority_queue 来帮助找出最新 10 条消息,参见代码如下:

 

解法二:

class Twitter {
public:
    Twitter() {
        time = 0;
    }
    
    void postTweet(int userId, int tweetId) {
        follow(userId, userId);
        tweets[userId].push_back({time++, tweetId});
    }
    
    vector<int> getNewsFeed(int userId) {
        vector<int> res;
        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
        for (auto id : friends[userId]) {
            for (auto a : tweets[id]) {
                if (q.size() > 0 && q.top().first > a.first && q.size() > 10) break;
                q.push(a);
                if (q.size() > 10) q.pop();
            }
        }
        while (!q.empty()) {
            res.insert(res.begin(), q.top().second);
            q.pop();
        }
        return res;
    }
    
    void follow(int followerId, int followeeId) {
        friends[followerId].insert(followeeId);
    }
    
    void unfollow(int followerId, int followeeId) {
        if (followerId != followeeId) {
            friends[followerId].erase(followeeId);
        }
    }
    
private:
    int time;
    unordered_map<int, unordered_set<int>> friends;
    unordered_map<int, vector<pair<int, int>>> tweets;
};

 

Github 同步地址:

https://github.com/grandyang/leetcode/issues/355

 

参考资料:

https://leetcode.com/problems/design-twitter/

https://leetcode.com/problems/design-twitter/discuss/82849/Short-c%2B%2B-solution

https://leetcode.com/problems/design-twitter/discuss/82916/C%2B%2B-solution-with-max-heap

 

LeetCode All in One 题目讲解汇总(持续更新中...)

posted @ 2016-06-12 11:39  Grandyang  阅读(11119)  评论(7编辑  收藏  举报
Fork me on GitHub