355. Design Twitter!

class Twitter {
    // global count
    private int countId;
    private Map<Integer, User> users;
    
    /** Initialize your data structure here. */
    public Twitter() {
        users = new HashMap<>();
    }
    
    /** Compose a new tweet. */
    public void postTweet(int userId, int tweetId) {
        if(!users.containsKey(userId)){
            users.put(userId, new User(userId));
        }
        users.get(userId).postTweet(tweetId, countId++);
    }
    
    public List<Integer> getNewsFeed(int userId) {
        List<Integer> result = new ArrayList<>();
        if(!users.containsKey(userId)) return result;
        Set<Integer> followees = users.get(userId).followed;
        
        // important: for merge the k ordered list, 
        // use PriorityQueue
        PriorityQueue<Tweet> priorityQueue = new PriorityQueue<>((a, b)->b.countId-a.countId);
        for(int followee: followees){
            Tweet tweet = users.get(followee).tweets;
            if(tweet!=null){
                priorityQueue.offer(users.get(followee).tweets); 
            }
        }
        
        // total tweed might be less than 10
        while(result.size()<10 && !priorityQueue.isEmpty()){
            Tweet tweet = priorityQueue.poll();
            if(tweet.next!=null){
                priorityQueue.offer(tweet.next);
            }
            result.add(tweet.tweetId);
        }
        return result;
    }
    
    /** Follower follows a followee. If the operation is invalid, it should be a no-op. */
    public void follow(int followerId, int followeeId) {
        if(!users.containsKey(followerId))
            users.put(followerId, new User(followerId));
        if(!users.containsKey(followeeId))
            users.put(followeeId, new User(followeeId));
        users.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) {
        users.get(followerId).unfollow(followeeId);
    }
    
    class User{
        public int userId;
        public Tweet tweets;
        // userId who the user is following
        public Set<Integer> followed;
        
        public User(int userId){
            this.userId = userId;
            followed = new HashSet<>();
            // a user is a follower of himself
            followed.add(userId);
        }
        
        public void postTweet(int tweetId, int countId){
            //always add new tweet to the head of the tweets
            Tweet tweet = new Tweet(tweetId, countId);
            tweet.next=tweets;
            tweets=tweet;
        }
        
        public void follow (int userId){
            followed.add(userId);
        }
        
        public void unfollow(int userId){
            followed.remove(userId);
        }
    }
    
    class Tweet{
        private int tweetId;
        private int countId;
        private Tweet next;
        
        public Tweet(int tweetId, int countId){
            this.tweetId = tweetId;
            this.countId = countId;
        }
    }
}

/**
 * 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);
 */

Last updated