355. 设计推特

题目:

设计一个简化版的推特(Twitter),可以让用户实现发送推文,关注/取消关注其他用户,能够看见关注人(包括自己)的最近十条推文。你的设计需要支持以下的几个功能:

postTweet(userId, tweetId): 创建一条新的推文
getNewsFeed(userId): 检索最近的十条推文。每个推文都必须是由此用户关注的人或者是用户自己发出的。推文必须按照时间顺序由最近的开始排序。
follow(followerId, followeeId): 关注一个用户
unfollow(followerId, followeeId): 取消关注一个用户
示例:

Twitter twitter = new Twitter();

// 用户1发送了一条新推文 (用户id = 1, 推文id = 5).
twitter.postTweet(1, 5);

// 用户1的获取推文应当返回一个列表,其中包含一个id为5的推文.
twitter.getNewsFeed(1);

// 用户1关注了用户2.
twitter.follow(1, 2);

// 用户2发送了一个新推文 (推文id = 6).
twitter.postTweet(2, 6);

// 用户1的获取推文应当返回一个列表,其中包含两个推文,id分别为 -> [6, 5].
// 推文id6应当在推文id5之前,因为它是在5之后发送的.
twitter.getNewsFeed(1);

// 用户1取消关注了用户2.
twitter.unfollow(1, 2);

// 用户1的获取推文应当返回一个列表,其中包含一个id为5的推文.
// 因为用户1已经不再关注用户2.
twitter.getNewsFeed(1);

 

解答:

我之前以为tweetid就是越大越新呢,题目没说清楚。

一共用两个哈希表。

哈希表1:key为userid。value为该user关注的所有人id,是一个集合。

哈希表2:key为userid。value为该user发的所有推特,是一个链表,用来维持该用户的所有推特的时间有序性,链表头部为最新的,尾部为最老的(代码中每个链表尾部插入一个dummy节点,保证它比所有推文的时间都更早)(因为要从头部动态插入数据,所以用链表)。

class Twitter {
public:
    struct data{
        static int seq; //静态变量,每生产一个data对象,就++
        int tweetID;    //推文id
        int time;       //该推文的时间戳
        data(int id,int tim):tweetID(id),time(tim){}
        data(int id):tweetID(id),time(seq++){}
    };
    unordered_map<int,unordered_set<int> > mp1;//mp1[x]:used_id为x的用户关注了谁
    unordered_map<int,list<data> >mp2;   //mp2[x]:user_id为x的用户发的所有推文
    Twitter() {
        
    }
    
    void postTweet(int userId, int tweetId) {
        //cout<<"postTweet"<<endl;
        if(mp2[userId].empty()){
            mp2[userId].push_back(data(0,-1)); //每个链表尾部都是一个时间为-1的推文
        }
        mp2[userId].push_front(tweetId);
    }
    
    vector<int> getNewsFeed(int userId) {
        mp1[userId].insert(userId);
        //cout<<"getNewsFeed"<<endl;
        //按照data对象中的time从大到小进行排序,time越大越新,越小越老
        auto cmp=[](list<data>::iterator a,list<data>::iterator b){return (*a).time<(*b).time;};
        priority_queue<list<data>::iterator,vector<list<data>::iterator>,decltype(cmp)> p(cmp);
        vector<int> res;
        for(int followeeId:mp1[userId]){
            if(mp2[followeeId].empty()){
                mp2[followeeId].push_back(data(0,-1));
            }
            p.push(mp2[followeeId].begin());//把userId所有关注的人的链表头部放入最小堆p中
        }
        for(int i=0;i<10;++i){
            auto iter=p.top();
            if(iter->time==-1){ //没有更新的推文了,break
                break;
            }
            res.push_back(iter->tweetID);//把当前最新的推文放入结果数组
            p.pop();
            p.push(++iter); //把前面放入结果数组的推文的下一篇推文push进优先队列
        }
        return res;
    }
    
    void follow(int followerId, int followeeId) {
        mp1[followerId].insert(followeeId);
    }
    
    void unfollow(int followerId, int followeeId) {
        mp1[followerId].erase(followeeId);
    }
};
int Twitter::data::seq=0;   //初始化静态变量

 

posted @ 2020-04-21 18:27  NeoZy  阅读(143)  评论(0)    收藏  举报