Design Twitter

MediumDesign · Heap (K-way Merge) · Hash Map🧩 Data Structure DesignLeetCode #355 ↗Updated

Problem

Build a tiny social feed. postTweet(userId, tweetId) publishes a tweet with a unique id; follow(a, b) / unfollow(a, b) make user a start or stop following b; getNewsFeed(userId) returns the ids of the 10 most recent tweets written by the user or anyone they follow, newest first.
InputpostTweet(1,5) getNewsFeed(1)Output[5]
Inputfollow(1,2) postTweet(2,6) getNewsFeed(1)Output[6,5]
Inputunfollow(1,2) getNewsFeed(1)Output[5]

1 ≤ userId ≤ 500  ·  0 ≤ tweetId ≤ 104, all unique  ·  ≤ 3·104 calls in total

Try it yourself

Java
class Twitter {
    public Twitter() {
        
    }

    public void postTweet(int userId, int tweetId) {
        
    }

    public List<Integer> getNewsFeed(int userId) {
        
    }

    public void follow(int followerId, int followeeId) {
        
    }

    public void unfollow(int followerId, int followeeId) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
Each user's tweets are already in time order, so a feed is a merge of sorted lists — but only the top 10 are needed. A max-heap holding one cursor per followed user pops the newest tweet 10 times and stops.
PatternData Structure Design

Instinct Implement a class whose methods must all hit a time bound (often O(1)) - write each method's target cost, then glue a hash map to a structure that keeps order.

Memory hack Finder plus keeper - a hash map finds it fast, a list/heap/array keeps the order, and every method updates both.

Open the Data Structure Design guide →

Approaches

Brute ForceGlobal Timeline Scan

Time feed O(T), others O(1)Space O(T + F)

Append every tweet {author, id} to one global list. For a feed, scan that list from newest to oldest and keep tweets whose author is the user or someone they follow, stopping after 10 hits.

Java
class Twitter {
    private final List<int[]> timeline = new ArrayList<>(); // {authorId, tweetId}
    private final Map<Integer, Set<Integer>> following = new HashMap<>();
    public Twitter() { }
    public void postTweet(int userId, int tweetId) {
        timeline.add(new int[]{userId, tweetId});
    }
    public List<Integer> getNewsFeed(int userId) {
        Set<Integer> follows = following.getOrDefault(userId, Collections.emptySet());
        List<Integer> feed = new ArrayList<>();
        for (int i = timeline.size() - 1; i >= 0 && feed.size() < 10; i--) {
            int author = timeline.get(i)[0];
            if (author == userId || follows.contains(author)) feed.add(timeline.get(i)[1]);
        }
        return feed;
    }
    public void follow(int followerId, int followeeId) {
        following.computeIfAbsent(followerId, k -> new HashSet<>()).add(followeeId);
    }
    public void unfollow(int followerId, int followeeId) {
        Set<Integer> s = following.get(followerId);
        if (s != null) s.remove(followeeId);
    }
}

Tiny code, but a feed may scan every tweet ever posted (T = total tweets).

At a glance

LevelApproachTimeSpace
Brute ForceGlobal Timeline Scanfeed O(T), others O(1)O(T + F)
BetterPer-User Tweets, Collect Last 10 Each & Sortfeed O(F log F)O(T + F)
OptimalK-way Merge with a Max-Heapfeed O(F + 10 log F)O(T + F)
Common pitfalls
  • Sorting by tweet id instead of posting time — ids are not chronological.
  • Leaving out the user's own tweets, or listing them twice after a self-follow.
  • unfollow on a user who follows nobody — guard the null set.
Interview tips
  • Ask about ordering (global clock) and duplicate follows before coding.
  • Connect the feed to “Merge k Sorted Lists” — it signals the heap.
  • Mention push vs pull: precomputing feeds on post trades write cost for read speed.
Pattern
K-way merge with a heap → top-k newest/smallest items across many individually sorted lists.
My notes saved in this browser