PracHub
QuestionsPremiumCoachesLearningGuidesInterview Prep

Quick Overview

This question evaluates a candidate's understanding of data structure design, time-series aggregation, and algorithmic complexity for in-memory accounting of per-driver earnings.

  • medium
  • Rippling
  • Coding & Algorithms
  • Software Engineer

Design a Driver Payroll System

Company: Rippling

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: medium

Interview Round: Technical Screen

Design an in-memory payroll system for a food delivery company. Each driver has a unique `driver_id` and a fixed `hourly_rate` set when the driver is registered. Implement a data structure that supports the following operations efficiently: 1. `register_driver(driver_id, hourly_rate)` - Add a new driver to the system. 2. `record_shift(driver_id, start_ts, end_ts)` - Record one completed shift for the driver. - `start_ts` and `end_ts` are Unix timestamps in seconds, and `end_ts > start_ts`. - The pay for the shift is `hourly_rate * (end_ts - start_ts) / 3600`. 3. `get_total_earned(driver_id)` - Return the total earnings accumulated by that driver across all recorded shifts. Follow-up: 4. `settle_up_to(cutoff_ts)` - Pay out all earnings from shifts that ended at or before `cutoff_ts`. 5. `get_unpaid_balance(driver_id)` - After one or more settlements, return how much money is still unpaid for that driver. Discuss what data structures you would use, how each operation works, and the time and space complexity of your design. If a driver has many historical shifts, explain how to support the settlement operation efficiently.

Quick Answer: This question evaluates a candidate's understanding of data structure design, time-series aggregation, and algorithmic complexity for in-memory accounting of per-driver earnings.

Part 1: Basic Driver Payroll Tracker

Implement a basic in-memory payroll tracker for delivery drivers. Each driver has a unique string `driver_id` and a fixed `hourly_rate` set at registration time. You are given a list of operations to process in order. Supported operations: - `('register_driver', driver_id, hourly_rate)` — add a new driver. - `('record_shift', driver_id, start_ts, end_ts)` — record one completed shift. The pay for the shift is `hourly_rate * (end_ts - start_ts) / 3600`. - `('get_total_earned', driver_id)` — query the total amount earned by that driver across all recorded shifts so far. Return the results of all `get_total_earned` operations in the order they appear. All operations are valid: - a driver is registered before any shift/query for that driver, - each `driver_id` is registered once, - `end_ts > start_ts`.

Constraints

  • 0 <= len(operations) <= 2 * 10^5
  • 1 <= hourly_rate <= 10^6
  • 0 <= start_ts < end_ts <= 10^9
  • Each driver_id is a non-empty string and is registered exactly once
  • All query and shift operations refer to already-registered drivers

Examples

Input: [('register_driver', 'd1', 20), ('record_shift', 'd1', 0, 7200), ('get_total_earned', 'd1'), ('register_driver', 'd2', 15), ('record_shift', 'd2', 0, 3600), ('record_shift', 'd1', 7200, 10800), ('get_total_earned', 'd1'), ('get_total_earned', 'd2')]

Expected Output: [40.0, 60.0, 15.0]

Explanation: Driver d1 earns 40 for the first 2-hour shift and 20 for the next 1-hour shift, for a total of 60. Driver d2 earns 15.

Input: [('register_driver', 'solo', 30), ('get_total_earned', 'solo')]

Expected Output: [0.0]

Explanation: Edge case: a registered driver with no recorded shifts has earned 0.

Input: [('register_driver', 'p1', 12), ('record_shift', 'p1', 0, 1800), ('get_total_earned', 'p1')]

Expected Output: [6.0]

Explanation: A 30-minute shift at 12 per hour pays 6.

Input: [('register_driver', 'a', 25), ('record_shift', 'a', 0, 3600), ('get_total_earned', 'a'), ('get_total_earned', 'a')]

Expected Output: [25.0, 25.0]

Explanation: Repeated queries should return the same accumulated total when no new shifts are added.

Hints

  1. Use one hash map for each driver's hourly rate and another for each driver's running total earned.
  2. You do not need to store every historical shift in Part 1; when a shift is recorded, its pay can be added immediately.

Part 2: Driver Payroll with Settlement Cutoffs

Extend the payroll system to support settlements. Each driver has a unique string `driver_id` and a fixed `hourly_rate`. You are given a list of operations to process in order. Supported operations: - `('register_driver', driver_id, hourly_rate)` — add a new driver. - `('record_shift', driver_id, start_ts, end_ts)` — record one completed shift. The shift's pay is `hourly_rate * (end_ts - start_ts) / 3600`. - `('settle_up_to', cutoff_ts)` — mark as paid every shift whose `end_ts <= cutoff_ts`. - `('get_unpaid_balance', driver_id)` — return how much money is still unpaid for that driver. Return the results of all `get_unpaid_balance` operations in the order they appear. Your implementation should support settlement efficiently even when there are many historical shifts. Avoid scanning all recorded shifts on every settlement. All operations are valid: - a driver is registered before any shift/query for that driver, - each `driver_id` is registered once, - `end_ts > start_ts`.

Constraints

  • 0 <= len(operations) <= 2 * 10^5
  • 1 <= hourly_rate <= 10^6
  • 0 <= start_ts < end_ts <= 10^9
  • Each driver_id is a non-empty string and is registered exactly once
  • All query and shift operations refer to already-registered drivers

Examples

Input: [('register_driver', 'd1', 20), ('record_shift', 'd1', 0, 3600), ('record_shift', 'd1', 3600, 10800), ('get_unpaid_balance', 'd1'), ('settle_up_to', 4000), ('get_unpaid_balance', 'd1'), ('settle_up_to', 20000), ('get_unpaid_balance', 'd1')]

Expected Output: [60.0, 40.0, 0.0]

Explanation: Before any settlement, both shifts are unpaid for a total of 60. After settling up to 4000, only the first shift is paid. After settling up to 20000, both are paid.

Input: [('register_driver', 'd1', 10), ('register_driver', 'd2', 30), ('record_shift', 'd1', 0, 7200), ('record_shift', 'd2', 0, 3600), ('settle_up_to', 5000), ('get_unpaid_balance', 'd1'), ('get_unpaid_balance', 'd2'), ('record_shift', 'd2', 3600, 7200), ('get_unpaid_balance', 'd2'), ('settle_up_to', 8000), ('get_unpaid_balance', 'd1'), ('get_unpaid_balance', 'd2')]

Expected Output: [20.0, 0.0, 30.0, 0.0, 0.0]

Explanation: The first settlement pays only d2's first shift. Later, after another d2 shift is recorded and settlement reaches 8000, all remaining unpaid shifts are paid.

Input: [('register_driver', 'empty', 25), ('settle_up_to', 100000), ('get_unpaid_balance', 'empty')]

Expected Output: [0.0]

Explanation: Edge case: a driver with no shifts has unpaid balance 0, even after settlement.

Input: [('register_driver', 'x', 10), ('record_shift', 'x', 0, 3600), ('settle_up_to', 5000), ('get_unpaid_balance', 'x'), ('settle_up_to', 1000), ('get_unpaid_balance', 'x')]

Expected Output: [0.0, 0.0]

Explanation: A shift should not be paid twice. A later settlement with a smaller cutoff changes nothing.

Hints

  1. When a shift is recorded, compute its pay immediately and keep track of it as unpaid for that driver.
  2. A min-heap ordered by shift end time lets `settle_up_to` remove only the shifts that became payable, instead of scanning every stored shift.
Last updated: Apr 19, 2026

Loading coding console...

PracHub

Master your tech interviews with 8,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

  • Compare Complete and Partial Poker Hands - Rippling (medium)
  • Implement Courier Delivery Cost Tracking - Rippling (medium)
  • Implement Article Vote Tracking - Rippling (medium)
  • Implement logger and card ranking - Rippling (medium)
  • Compare Complete or Partial Hands - Rippling (medium)