LeetCode Design Twitter โ OOP design with heap-based feed merge. User follow/unfollow, post tweet, and getNewsFeed in O(k log k). Java and Python solutions.
LeetCode ยท #355
Design Twitter Solution
Design a simplified Twitter where users can post tweets, follow/unfollow other users, and retrieve their 10 most recent tweets in their news feed.
Implement the Twitter class with four methods: postTweet(userId, tweetId), getNewsFeed(userId) (returns most recent 10 tweets from the user and their followees), follow(followerId, followeeId), and unfollow(followerId, followeeId).
Example
Twitter twitter = new Twitter();
twitter.postTweet(1, 5); // User 1 posts tweet 5
twitter.getNewsFeed(1); // โ [5]
twitter.follow(1, 2); // User 1 follows user 2
twitter.postTweet(2, 6); // User 2 posts tweet 6
twitter.getNewsFeed(1); // โ [6, 5] (most recent first)
twitter.unfollow(1, 2); // User 1 unfollows user 2
twitter.getNewsFeed(1); // โ [5] (user 2's tweets gone)
Constraints
โข 1 โค userId, followerId, followeeId โค 500โข 0 โค tweetId โค 10โดโข At most 3 ร 10โด calls total
02
Section Two ยท Approach 1
Brute Force โ Collect & Sort
On getNewsFeed, collect all tweets from the user and their followees into one list, sort by timestamp, and return the top 10. Simple but expensive when users have many tweets.
Why it works
Sorting by timestamp guarantees recency. Taking the first 10 gives the correct feed.
Why we can do better
Problem: Collecting all tweets means iterating over potentially thousands of tweets just to pick 10. Since each user's tweets are already in chronological order, this is a merge k sorted lists problem โ a min-heap of size k (where k = number of followed users) merges them in O(10 ยท log k) instead of sorting everything.
Java โ Collect & Sort
// Pseudocode โ full brute forcepublicList<Integer> getNewsFeed(int userId) {
List<int[]> all = newArrayList<>();
// add all tweets from user + followees with timestamps// sort all by timestamp descending// return first 10 tweet IDs
}
Python โ Collect & Sort
defgetNewsFeed(self, userId: int) -> list[int]:
all_tweets = []
# collect tweets from user + followees with timestamps
all_tweets.sort(key=lambda t: -t[0]) # sort by time descreturn [t[1] for t in all_tweets[:10]]
Metric
Value
Time (getNewsFeed)
O(T log T) โ T = total tweets from user + followees
Space
O(T)
03
Section Three ยท Approach 2
Heap Merge โ O(10 ยท log k)
Each user's tweet list is already sorted by time (newest first). To build a feed, treat each user's list as a sorted stream and merge them with a max-heap keyed by timestamp. Pop 10 times to get the 10 most recent across all followed users.
๐ก Mental model: Imagine k newspaper stands, each with papers stacked newest-on-top. You want today's top 10 headlines across all stands. Instead of collecting every paper and sorting, you peek at the top paper from each stand (put them in a heap). Pick the newest headline, then reveal the next paper from that stand. After 10 picks, you have your top-10 headlines without touching most papers.
Data Structures
userTweets:HashMap<userId, List<(time, tweetId)>> โ each user's tweets in chronological order.
followees:HashMap<userId, HashSet<followeeId>> โ who each user follows.
Global timestamp: Counter incremented with each tweet for ordering.
Algorithm โ getNewsFeed
Step 1: Collect the user's own ID + all followee IDs.
Step 2: For each person, if they have tweets, push their most recent tweet into a max-heap (keyed by timestamp).
Step 3: Pop from the heap up to 10 times. After each pop, push the next tweet from that same user (if any).
Step 4: Return the collected tweet IDs.
๐ฏ When to recognize this pattern:
Merging multiple sorted streams into one โ this is the exact same pattern as LC 23 (Merge k Sorted Lists).
The heap holds one element per stream and always yields the global best.
It appears in Twitter feeds, calendar event merging, and multi-way external sort.
Why only 10 pops?:
The problem caps the feed at 10 tweets. We never need to merge the full lists โ just pop 10 times from the heap.
This makes getNewsFeed O(10 ยท log k) = O(log k) regardless of how many tweets exist.
O(U + T + F) where U = users, T = total tweets, F = total follow relationships.
Each tweet is stored once; the heap is transient (created per getNewsFeed call).
07
Section Seven ยท Edge Cases
Edge Cases & Pitfalls
Case
Scenario
Why It Matters
No tweets
getNewsFeed for new user
Heap is empty โ return empty list.
Self-follow
follow(1, 1)
User's own tweets should already appear. follow(self) should be harmless (idempotent).
Unfollow not followed
unfollow(1, 99)
Should not throw. Use discard or null-check.
More than 10 tweets
User posts 20 tweets
Feed should return exactly 10 most recent.
Multiple users' tweets interleaved
Users post alternately
Heap merge correctly interleaves by timestamp.
Follow then unfollow
Feed should reflect current follow state
getNewsFeed rebuilds sources on each call โ no stale data.
โ Common Mistake: Forgetting to include the user's own tweets in the feed. The user always sees their own tweets โ add userId to the set of sources before merging. Don't require self-follow; handle it implicitly.