Design Twitter
MEDIUMDescription
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 IDtweetIdby the useruserId. Each call to this function will be made with a uniquetweetId.List<Integer> getNewsFeed(int userId)Retrieves the10most 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 IDfollowerIdstarted following the user with IDfolloweeId.void unfollow(int followerId, int followeeId)The user with IDfollowerIdstarted unfollowing the user with IDfolloweeId.
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 <= 5000 <= tweetId <= 104- All the tweets have unique IDs.
- At most
3 * 104calls will be made topostTweet,getNewsFeed,follow, andunfollow. - A user cannot follow himself.
Approaches
Checkout 3 different approaches to solve Design Twitter. Click on different approaches to view the approach and algorithm in detail.
Brute-force Sorting
This is a straightforward approach where we simulate the process directly. For getNewsFeed, we gather all tweets from the user and the users they follow into a single list, sort this list by time, and then take the 10 most recent ones.
Algorithm
- Maintain a map
userFollowsfor follow/unfollow relationships (Map<Integer, Set<Integer>>). - Maintain a map
userTweetsto store a list ofTweetobjects for each user (Map<Integer, List<Tweet>>). ATweetobject contains its ID and a timestamp. - Use a global, static, incrementing
timestampfor each new tweet to ensure chronological order. - For
getNewsFeed(userId):- Create an empty list
candidateTweets. - Add all of
userId's own tweets tocandidateTweets. - For each
followeeIdthatuserIdfollows, add all of their tweets tocandidateTweets. - Sort
candidateTweetsbased on timestamp in descending order. - Return the IDs of the first 10 tweets in the sorted list.
- Create an empty list
We use a Map to store follow relationships (userId -> Set<followeeId>) and another Map to store each user's tweets (userId -> List<Tweet>). A global timestamp is used to record the post time of each tweet, ensuring chronological order. postTweet adds a new tweet with the current timestamp to the user's tweet list. follow and unfollow simply update the follow-relationship map. The main logic is in getNewsFeed. It first identifies all relevant users (the user themselves and their followees). It then iterates through these users, collecting all their tweets into a temporary list. This list is then sorted in descending order based on the tweet's timestamp. Finally, the IDs of the first 10 tweets from the sorted list are returned.
class Twitter {
private static int timestamp = 0;
private Map<Integer, Set<Integer>> userFollows;
private Map<Integer, List<Tweet>> userTweets;
private class Tweet {
int id;
int time;
public Tweet(int id, int time) {
this.id = id;
this.time = time;
}
}
public Twitter() {
userFollows = new HashMap<>();
userTweets = new HashMap<>();
}
public void postTweet(int userId, int tweetId) {
userTweets.computeIfAbsent(userId, k -> new ArrayList<>()).add(new Tweet(tweetId, timestamp++));
}
public List<Integer> getNewsFeed(int userId) {
List<Tweet> allTweets = new ArrayList<>();
// Add user's own tweets
if (userTweets.containsKey(userId)) {
allTweets.addAll(userTweets.get(userId));
}
// Add followees' tweets
Set<Integer> followees = userFollows.get(userId);
if (followees != null) {
for (int followeeId : followees) {
if (userTweets.containsKey(followeeId)) {
allTweets.addAll(userTweets.get(followeeId));
}
}
}
// Sort all collected tweets by time descending
allTweets.sort((a, b) -> b.time - a.time);
List<Integer> newsFeed = new ArrayList<>();
for (int i = 0; i < Math.min(10, allTweets.size()); i++) {
newsFeed.add(allTweets.get(i).id);
}
return newsFeed;
}
public void follow(int followerId, int followeeId) {
userFollows.computeIfAbsent(followerId, k -> new HashSet<>()).add(followeeId);
}
public void unfollow(int followerId, int followeeId) {
if (userFollows.containsKey(followerId) && followerId != followeeId) {
userFollows.get(followerId).remove(followeeId);
}
}
}
Complexity Analysis
Pros and Cons
- Simple to understand and implement.
postTweet,follow, andunfollowoperations are very fast, typically O(1).
getNewsFeedis very inefficient. Its performance degrades significantly as the total number of tweets (N) from the user and their followees increases.
Code Solutions
Checking out 3 solutions in different languages for Design Twitter. Click on different languages to view the code.
Video Solution
Watch the video walkthrough for Design Twitter
Similar Questions
5 related questions you might find useful
Patterns:
Data Structures:
Subscribe to Scale Engineer newsletter
Learn about System Design, Software Engineering, and interview experiences every week.
No spam, unsubscribe at any time.