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);
运行结果
图片说明
解题思路
创建user类和tweet类
user类拥有关注者列表,推特链表头,用户id,可以实现关注,取关,和发推特
tweet类拥有推特id,时间,和后指针
主类中拥有静态时间撮和这两个静态辅助类
需要一个userId到user的map映射---需要由id得到user
取关:如果操作者存在,则直接取关
关注:如果双方不存在则创建,最后关注
发推特:如果用户不存在则创建,最后由该用户发推特
获取推特列表:利用大顶堆实现推特的按时间排序(便于多个链表合并)
先将关注者们的推特头存入列表-取出最新的放入结果集中-如果存在次新,则次新入堆

java代码

class Twitter {

    private static int timestamp=0;
    private static class User{
        private int userId;
        public Set<Integer> follows;//关注者列表
        // 用户发表的推文链表头结点
        public Tweet head; 

        public User(int id){
            this.userId=id;
            follows=new HashSet<>();
            head=null;
            //关注自己
            follow(id);
        }

        public void follow(int userId){
            follows.add(userId);
        }

        public void unfollow(int userId){
            //不可以取关自己
            if(userId != this.userId){
                follows.remove(userId);
            }

        }

        public void put(int tweetId){
            //添加在链表头
            Tweet twt=new Tweet(tweetId,timestamp);
            timestamp++;
            twt.next=head;
            head=twt;
        }


    }
    private static class Tweet{
        private int id;
        private int time;
        private Tweet next;

        public Tweet(int id,int time){
            this.id=id;
            this.time=time;
            this.next=null;
        }
    }

    // 我们需要一个映射将 userId 和 User 对象对应起来
    private HashMap<Integer, User> userMap = new HashMap<>();

    /** Initialize your data structure here. */
    public Twitter() {

    }

    /** Compose a new tweet. */
    public void postTweet(int userId, int tweetId) {
        if(!userMap.containsKey(userId)){
            User u=new User(userId);
            userMap.put(userId,u);
        }
        User user=userMap.get(userId);
        user.put(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. */
    public List<Integer> getNewsFeed(int userId) {
        List<Integer> res=new LinkedList<>();
        //不存在则创建
        if(!userMap.containsKey(userId)){
            User u=new User(userId);
            userMap.put(userId,u);
        }
        //取到该用户的关注者列表
        User u=userMap.get(userId);
        Set<Integer> followees=u.follows;

        //创建一个优先级队列来存储推特,使按时间排序:降序
        PriorityQueue<Tweet> pq=new PriorityQueue<>((a,b)->(b.time-a.time));
        //先将个被关注者的head存入堆中
        for(int id:followees){
            Tweet twt=userMap.get(id).head;
            if(twt==null) continue;
            pq.offer(twt);
        }

        while(!pq.isEmpty()){
            //最多十条
            if(res.size()==10) break;
            //取出最新的加入结果队列
            Tweet twt=pq.poll();
            res.add(twt.id);
            //如果后续还有,则将次新的加入堆
            if(twt.next != null){
                pq.offer(twt.next);
            }
        }
        return res;
    }

    /** Follower follows a followee. If the operation is invalid, it should be a no-op. */
    public void follow(int followerId, int followeeId) {
        //关注者和被关注者不存在则创建
        if(!userMap.containsKey(followerId)){
            User follower=new User(followerId);
            userMap.put(followerId,follower);
        }
        if(!userMap.containsKey(followeeId)){
            User followee=new User(followeeId);
            userMap.put(followeeId,followee);
        }
        //关注
        userMap.get(followerId).follow(followeeId);
    }

    /** Follower unfollows a followee. If the operation is invalid, it should be a no-op. */
    public void unfollow(int followerId, int followeeId) {
        //取关者存在则取关
        if(userMap.containsKey(followerId)){
            User follower=userMap.get(followerId);
            follower.unfollow(followeeId);
        }
    }
}

/**
 * Your Twitter object will be instantiated and called as such:
 * Twitter obj = new Twitter();
 * obj.postTweet(userId,tweetId);
 * List<Integer> param_2 = obj.getNewsFeed(userId);
 * obj.follow(followerId,followeeId);
 * obj.unfollow(followerId,followeeId);
 */