Bird
Raised Fist0
Interview Prepcustom-data-structuresmediumAmazonGoogle

Design Twitter (Top K Recent Tweets)

Choose your preparation mode4 modes available
📋
Problem

Imagine building a mini Twitter where users can post tweets and see the most recent tweets from people they follow. How do you efficiently retrieve the top K recent tweets?

Design a simplified version of Twitter where users can post tweets, follow/unfollow other users, and retrieve the 10 most recent tweets in their news feed. Each tweet has a unique ID and a timestamp. Implement the following methods: - postTweet(userId, tweetId): Compose a new tweet. - getNewsFeed(userId): Retrieve the 10 most recent tweet IDs in the user's news feed. Tweets must be ordered from most recent to least recent. - follow(followerId, followeeId): Follower follows a followee. - unfollow(followerId, followeeId): Follower unfollows a followee. Assume all tweets are timestamped in the order they are posted.

1 ≤ userId, followerId, followeeId ≤ 10^5Tweet IDs are unique integersAt most 10^5 calls will be made to all methodsEach user can follow at most 10^4 usersgetNewsFeed returns up to 10 tweets
Edge cases: User follows no one and has no tweets → getNewsFeed returns empty listUser follows themselves only → getNewsFeed returns their own tweetsUser unfollows someone they do not follow → no effect
</>
IDE
class Twitter: def __init__(self): pass def postTweet(self, userId: int, tweetId: int) -> None: pass def getNewsFeed(self, userId: int) -> list: pass def follow(self, followerId: int, followeeId: int) -> None: pass def unfollow(self, followerId: int, followeeId: int) -> None: passpublic class Twitter { public Twitter() { // constructor } public void postTweet(int userId, int tweetId) { // method } public List<Integer> getNewsFeed(int userId) { return new ArrayList<>(); } public void follow(int followerId, int followeeId) { // method } public void unfollow(int followerId, int followeeId) { // method } }class Twitter { public: Twitter() { // constructor } void postTweet(int userId, int tweetId) { // method } vector<int> getNewsFeed(int userId) { return {}; } void follow(int followerId, int followeeId) { // method } void unfollow(int followerId, int followeeId) { // method } };class Twitter { constructor() { // constructor } postTweet(userId, tweetId) { // method } getNewsFeed(userId) { return []; } follow(followerId, followeeId) { // method } unfollow(followerId, followeeId) { // method } }
class Twitter:
    def __init__(self):
        # Write your solution here
        pass
    def postTweet(self, userId: int, tweetId: int) -> None:
        pass
    def getNewsFeed(self, userId: int) -> list:
        pass
    def follow(self, followerId: int, followeeId: int) -> None:
        pass
    def unfollow(self, followerId: int, followeeId: int) -> None:
        pass
public class Twitter {
    public Twitter() {
        // Write your solution here
    }
    public void postTweet(int userId, int tweetId) {
    }
    public List<Integer> getNewsFeed(int userId) {
        return new ArrayList<>();
    }
    public void follow(int followerId, int followeeId) {
    }
    public void unfollow(int followerId, int followeeId) {
    }
}
class Twitter {
public:
    Twitter() {
        // Write your solution here
    }
    void postTweet(int userId, int tweetId) {
    }
    vector<int> getNewsFeed(int userId) {
        return {};
    }
    void follow(int followerId, int followeeId) {
    }
    void unfollow(int followerId, int followeeId) {
    }
};
class Twitter {
    constructor() {
        // Write your solution here
    }
    postTweet(userId, tweetId) {
    }
    getNewsFeed(userId) {
        return [];
    }
    follow(followerId, followeeId) {
    }
    unfollow(followerId, followeeId) {
    }
}
Coming soon
0/9
Common Bugs to Avoid
Wrong: News feed missing followee tweetsNot including followees' tweets in getNewsFeed or not updating follow relationships.✅ In getNewsFeed, collect tweets from user and all followees before sorting and slicing.
Wrong: News feed includes duplicate tweetsCounting tweets multiple times due to incorrect data structure or logic.✅ Ensure each tweet is stored once and included once in news feed; avoid duplicates in merging.
Wrong: News feed returns more than 10 tweetsNot limiting output size to 10 in getNewsFeed.✅ After sorting tweets by timestamp descending, slice the list to first 10 elements.
Wrong: Unfollow causes error or removes wrong followeesNot checking if follower actually follows followee before unfollowing.✅ Check if followee exists in follower's followees set before removing.
Wrong: Solution times out on large inputsUsing brute force scanning of all tweets instead of heap-based merge.✅ Implement max heap to merge tweets from followees efficiently in O(k log F) time.
✓
Test Cases
t1_01basic
Input[["postTweet",1,5],["getNewsFeed",1]]
Expected[[5]]

User 1 posts a tweet with ID 5. Their news feed returns this tweet.

t1_02basic
Input[["postTweet",2,6],["postTweet",2,7],["follow",1,2],["getNewsFeed",1]]
Expected[[7,6]]

User 2 posts tweets 6 and 7. User 1 follows user 2, so their news feed returns tweets 7 and 6 in order.

t2_01edge
Input[["getNewsFeed",10]]
Expected[[]]

User 10 has no tweets and follows no one, so news feed is empty.

t2_02edge
Input[["postTweet",3,10],["follow",3,3],["getNewsFeed",3]]
Expected[[10]]

User 3 follows themselves only and has one tweet, so news feed returns their own tweet.

t2_03edge
Input[["unfollow",4,5],["postTweet",4,20],["getNewsFeed",4]]
Expected[[20]]

User 4 unfollows user 5 whom they do not follow; no effect. User 4's own tweet appears in news feed.

t3_01corner
Input[["postTweet",1,100],["postTweet",2,101],["postTweet",3,102],["follow",4,1],["follow",4,2],["follow",4,3],["getNewsFeed",4]]
Expected[[102,101,100]]

User 4 follows users 1,2,3 each with one tweet; news feed merges tweets ordered by recency.

t3_02corner
Input[["postTweet",1,200],["postTweet",1,201],["postTweet",1,202],["follow",2,1],["getNewsFeed",2]]
Expected[[202,201,200]]

User 2 follows user 1 who posted multiple tweets; news feed returns most recent 10 tweets correctly.

t3_03corner
Input[["postTweet",1,300],["postTweet",1,301],["postTweet",1,302],["postTweet",1,303],["postTweet",1,304],["postTweet",1,305],["postTweet",1,306],["postTweet",1,307],["postTweet",1,308],["postTweet",1,309],["postTweet",1,310],["getNewsFeed",1]]
Expected[[310,309,308,307,306,305,304,303,302,301]]

User 1 posts 11 tweets; news feed returns only the 10 most recent tweets.

t4_01performance
Input[["postTweet",1,1],["postTweet",2,2],["postTweet",3,3],["postTweet",4,4],["postTweet",5,5],["postTweet",6,6],["postTweet",7,7],["postTweet",8,8],["postTweet",9,9],["postTweet",10,10],["follow",100000,1],["follow",100000,2],["follow",100000,3],["follow",100000,4],["follow",100000,5],["follow",100000,6],["follow",100000,7],["follow",100000,8],["follow",100000,9],["follow",100000,10],["getNewsFeed",100000]]
⏱ Performance - must finish in 2000ms

Test with 10^5 users and 10 followees for user 100000; must complete getNewsFeed in O(k log F) time within 2s.

Practice

(1/5)
1. You need to design a system that tracks passengers checking in and out of stations, and efficiently calculates average travel times between stations. Which approach best balances time and space efficiency for frequent queries?
easy
A. Use hash maps to store running totals of travel times and counts per route.
B. Store all trips explicitly and scan them to compute averages on demand.
C. Use dynamic programming to precompute all possible route averages.
D. Use a priority queue to keep track of the shortest travel times per route.

Solution

  1. Step 1: Understand the problem requirements

    The system must support frequent check-ins, check-outs, and quick average time queries between stations.
  2. Step 2: Evaluate approaches

    Storing all trips (B) leads to slow queries. Dynamic programming (C) is not applicable as routes are dynamic and not fixed. Priority queues (D) do not help compute averages efficiently. Hash maps with running totals (A) allow O(1) updates and queries.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Hash maps maintain running sums and counts for O(1) average time queries [OK]
Hint: Running totals enable O(1) average queries [OK]
Common Mistakes:
  • Thinking storing all trips is efficient for queries
2. What is the time complexity of adding a number and then finding the median using the balanced two heaps approach with lazy deletion for a data stream of size n?
medium
A. O(log n) per addNum and O(log n) per findMedian
B. O(n) per addNum and O(1) per findMedian
C. O(log n) per addNum and O(1) per findMedian
D. O(1) per addNum and O(n) per findMedian

Solution

  1. Step 1: Analyze addNum complexity

    Adding a number involves pushing to a heap and balancing heaps, each O(log n) operations.
  2. Step 2: Analyze findMedian complexity

    Median is retrieved from the top of heaps without modification, O(1) time.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Insertion is O(log n), median retrieval O(1) [OK]
Hint: Heap push/pop are O(log n), median peek is O(1) [OK]
Common Mistakes:
  • Assuming sorting each query is O(log n)
  • Confusing addNum with findMedian complexity
3. What is the average time complexity of the remove operation in the optimized Insert Delete GetRandom O(1) with duplicates data structure that uses a hash map of element to linked list nodes and a list of elements?
medium
A. O(n) because we need to find the element's index in the list before removal.
B. O(log n) due to maintaining the linked list structure during removals.
C. O(1) worst-case because linked list removals and hash map lookups are constant time.
D. O(1) average because the hash map provides direct access to an element's node for removal.

Solution

  1. Step 1: Identify data structure operations

    Removal uses hash map to get a node reference in O(1) average time, then removes node from doubly linked list in O(1).
  2. Step 2: Clarify average vs worst-case

    Hash map lookups are average O(1), but worst-case can degrade. Linked list removal is always O(1). So overall average is O(1).
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Hash map + linked list enables average O(1) removals [OK]
Hint: Hash map + linked list enables average O(1) removals [OK]
Common Mistakes:
  • Confusing average and worst-case complexities
  • Assuming linked list removal is O(log n)
  • Thinking index search is needed
4. Suppose you want to extend the LRU Cache to support a "reuse" operation that marks an existing key as recently used without retrieving its value. Which modification to the optimal LRU Cache implementation is correct to support this efficiently?
hard
A. On reuse, remove the key from the cache and re-insert it with the same value.
B. Do nothing; reuse is equivalent to get, so no code change is needed.
C. Use a queue instead of a doubly linked list to track usage order for easier reuse.
D. Add a new method that calls _remove and _add on the node corresponding to the key.

Solution

  1. Step 1: Understand reuse operation

    Reuse means marking a key as recently used without returning its value, so usage order must be updated.
  2. Step 2: Efficiently update usage order

    Calling _remove and _add on the node moves it to the front in O(1) time, correctly updating usage.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Reuse requires usage update without value retrieval, done by repositioning node [OK]
Hint: Reuse updates usage order like get but without returning value [OK]
Common Mistakes:
  • Re-inserting wastes time
  • Queue can't reorder efficiently
  • Assuming reuse needs no code change
5. Suppose the skyline problem is extended so that buildings can overlap and have negative heights (e.g., representing underground structures). Which modification to the divide and conquer approach is necessary to correctly handle this variant?
hard
A. Modify the merge step to consider absolute values of heights when computing max height
B. Adjust the merge logic to track both max and min heights at each x-coordinate and merge accordingly
C. No modification needed; the existing merge logic works for negative heights
D. Replace divide and conquer with a brute force height map simulation to handle negative heights

Solution

  1. Step 1: Understand impact of negative heights

    Negative heights mean skyline can go below ground, so max height alone is insufficient to represent shape.
  2. Step 2: Modify merge logic accordingly

    Need to track both max and min heights at each x to correctly merge skylines with negative and positive heights.
  3. Step 3: Evaluate other options

    Using absolute values loses sign info; brute force is inefficient; no modification fails correctness.
  4. Final Answer:

    Option B -> Option B
  5. Quick Check:

    Tracking both max and min heights handles negative overlaps correctly [OK]
Hint: Negative heights require tracking min and max heights, not just max [OK]
Common Mistakes:
  • Ignoring negative heights
  • Using absolute values incorrectly
  • Assuming no change needed
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard