PracHub
QuestionsPremiumLearningGuidesInterview PrepNEWCoaches

Quick Overview

This question evaluates a candidate's ability to design efficient stateful data structures and algorithms for tracking user votes, including correct handling of idempotent repeated votes, vote changes, deduplication, and retrieval of the most recent events.

  • easy
  • Rippling
  • Coding & Algorithms
  • Software Engineer

Implement an article voting tracker

Company: Rippling

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: easy

Interview Round: Technical Screen

## Coding: Article Voting Tracker Design and implement a data structure to track users’ votes (upvote/downvote) on articles. ### Operations Implement functions/methods with the following behavior: 1. `vote(userId, articleId, voteType)` where `voteType ∈ {UP, DOWN}` - Track the user’s vote on the article. - **If the user repeats the same vote on the same article** (e.g., UP then UP again), it should be **counted only once** (i.e., do not record a new vote event). - **If the user changes their vote** on the same article (e.g., UP then DOWN, or DOWN then UP), it **should be counted as a new vote event**. 2. `getLastVotes(userId)` - Return (or print) the user’s **last 3 vote events**, most recent first. - Each returned event should include at least: `(articleId, voteType, timestamp-or-order)`. ### Notes / constraints - Assume many users and articles. - The focus is on correct behavior and efficient operations. - Define and handle edge cases (e.g., user has < 3 vote events; unknown user).

Quick Answer: This question evaluates a candidate's ability to design efficient stateful data structures and algorithms for tracking user votes, including correct handling of idempotent repeated votes, vote changes, deduplication, and retrieval of the most recent events.

You are given a sequence of operations for an article voting system. Build a tracker that records users' votes on articles and answers history queries. Rules: - A vote operation has the form ('vote', userId, articleId, voteType), where voteType is 'UP' or 'DOWN'. - If the same user repeats the same vote on the same article, it should be ignored and must not create a new vote event. - If the user changes their vote on the same article, it must create a new vote event. - A query operation has the form ('getLastVotes', userId). For each query, return that user's last 3 counted vote events, most recent first. Represent each returned event as a tuple: (articleId, voteType, eventOrder). The eventOrder is a 1-based global counter that increases only when a new vote event is actually counted.

Constraints

  • 0 <= len(operations) <= 200000
  • voteType is always 'UP' or 'DOWN'
  • Each operation should be handled efficiently, ideally in O(1) average time

Examples

Input: [('vote', 'u1', 'a1', 'UP'), ('vote', 'u1', 'a1', 'UP'), ('vote', 'u1', 'a2', 'DOWN'), ('vote', 'u1', 'a1', 'DOWN'), ('getLastVotes', 'u1')]

Expected Output: [[('a1', 'DOWN', 3), ('a2', 'DOWN', 2), ('a1', 'UP', 1)]]

Explanation: The second vote is a duplicate and is ignored. The change from UP to DOWN on a1 creates a new event.

Input: [('vote', 'u1', 'a1', 'UP'), ('vote', 'u2', 'a2', 'DOWN'), ('getLastVotes', 'u3'), ('getLastVotes', 'u2'), ('getLastVotes', 'u1')]

Expected Output: [[], [('a2', 'DOWN', 2)], [('a1', 'UP', 1)]]

Explanation: u3 has no history, so the result is empty. u2 and u1 each have only one counted vote event.

Input: [('vote', 'u1', 'a1', 'UP'), ('vote', 'u1', 'a2', 'UP'), ('vote', 'u1', 'a3', 'DOWN'), ('vote', 'u1', 'a4', 'UP'), ('vote', 'u1', 'a2', 'UP'), ('getLastVotes', 'u1')]

Expected Output: [[('a4', 'UP', 4), ('a3', 'DOWN', 3), ('a2', 'UP', 2)]]

Explanation: Only the last 3 counted events are returned. The repeated UP vote on a2 is ignored.

Input: [('vote', 'u1', 'a1', 'UP'), ('vote', 'u1', 'a1', 'DOWN'), ('vote', 'u1', 'a1', 'UP'), ('getLastVotes', 'u1')]

Expected Output: [[('a1', 'UP', 3), ('a1', 'DOWN', 2), ('a1', 'UP', 1)]]

Explanation: Each change of vote on the same article creates a new counted event.

Input: []

Expected Output: []

Explanation: With no operations, there are no query results.

Solution

from collections import defaultdict, deque

def solution(operations):
    current_votes = defaultdict(dict)
    recent_events = defaultdict(lambda: deque(maxlen=3))
    event_order = 0
    results = []

    for op in operations:
        if op[0] == 'vote':
            _, user_id, article_id, vote_type = op
            previous = current_votes[user_id].get(article_id)

            if previous == vote_type:
                continue

            event_order += 1
            current_votes[user_id][article_id] = vote_type
            recent_events[user_id].append((article_id, vote_type, event_order))

        elif op[0] == 'getLastVotes':
            _, user_id = op
            results.append(list(reversed(recent_events.get(user_id, []))))

        else:
            raise ValueError(f'Unknown operation: {op[0]}')

    return results

Time complexity: O(m) total for m operations, with O(1) average time per operation. Space complexity: O(p + u), where p is the number of distinct (userId, articleId) pairs that have a stored current vote and u is the number of users with recent history.

Hints

  1. Keep the current vote for each (userId, articleId) pair so you can detect whether a new vote is a duplicate or a change.
  2. Since each query only needs the last 3 events, you only need to keep a small recent history per user.
Last updated: May 4, 2026

Loading coding console...

PracHub

Master your tech interviews with 7,500+ real questions from top companies.

Product

  • Questions
  • Learning Tracks
  • Interview Guides
  • Resources
  • Premium
  • For Universities
  • Student Access

Browse

  • By Company
  • By Role
  • By Category
  • Topic Hubs
  • SQL Questions
  • Compare Platforms
  • Discord Community

Support

  • support@prachub.com
  • (916) 541-4762

Legal

  • Privacy Policy
  • Terms of Service
  • About Us

© 2026 PracHub. All rights reserved.

Related Coding Questions

  • Implement logger and card ranking - Rippling (medium)
  • Design a Driver Payroll System - Rippling (medium)
  • Compare Complete or Partial Hands - Rippling (medium)
  • Implement Food Delivery Billing - Rippling (medium)
  • Implement a balance tracker and interval merger - Rippling (medium)