PracHub
QuestionsCoachesLearningGuidesInterview Prep

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.

Implement a tracker for an article voting system that records users' votes and answers history queries. You are given a list `operations`, processed **in order**. Each operation is a tuple (or list) whose first element is the operation name. Implement: ```python def solution(operations): ``` Return a list containing one result for each `getLastVotes` query, in the order the queries appear. ## Operations **Vote** — `('vote', userId, articleId, voteType)`, where `voteType` is either `'UP'` or `'DOWN'`. - Compare the incoming vote to the user's **current** (most recent) vote on that same article: - If it is **the same** as the user's current vote on that article, it is a duplicate — **ignore it**. No vote event is created and the global counter does not change. - If it **differs** from the user's current vote on that article (a first-ever vote on the article, or a change such as `UP → DOWN`), a **new vote event is counted**. - Only the **latest** vote on an article matters when deciding "same vs. different." So voting back to an earlier value still counts as a change — e.g. `UP → DOWN → UP` on one article produces **three** events. **Query** — `('getLastVotes', userId)`. - Append to the output the user's **last 3 counted vote events**, ordered **most recent first**. - If the user has fewer than 3 counted events, return all of them (still most recent first). - If the user has no counted events (or has never appeared), return an empty list `[]`. ## Event representation Each counted event is a tuple `(articleId, voteType, eventOrder)`: - **`eventOrder`** is a **1-based global counter shared across all users**. It increments by 1 **only** when a new vote event is actually counted (duplicates do not increment it). The first counted event across the whole sequence has `eventOrder = 1`, the next `2`, and so on, regardless of which user produced it. ## Notes - `getLastVotes` reports each event with the `eventOrder` it had **when it was counted**; values are never renumbered. - An empty `operations` list produces an empty result list `[]`. ## Constraints - `0 <= len(operations) <= 200000` - `voteType` is always `'UP'` or `'DOWN'`. - Each operation should be handled efficiently, ideally in **O(1)** average time.

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)]]

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

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

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)]]

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)]]

Input: []

Expected Output: []

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 8,000+ 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
  • AI Coding 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 a Searchable Logger Pipeline - Rippling (hard)
  • Implement an In-Memory File System - Rippling
  • Compare Complete and Partial Poker Hands - Rippling (medium)
  • Implement Courier Delivery Cost Tracking - Rippling (medium)
  • Implement Article Vote Tracking - Rippling (medium)