PracHub
QuestionsPremiumLearningGuidesCheatsheetNEW

Quick Overview

This question evaluates a candidate's ability to design efficient stateful systems and algorithmic data structures for tracking per-tenant resource balances, including handling idempotency, negative balance policies, concurrency, and persistence.

  • Medium
  • OpenAI
  • Coding & Algorithms
  • Software Engineer

Implement GPU credit ledger

Company: OpenAI

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: Medium

Interview Round: Technical Screen

You manage a GPU pool with per-tenant credits. Given a list/stream of events where each event adjusts a tenant’s credit balance by a signed integer (positive = add credit, negative = deduct credit), implement three functions: ( 1) init(events): initialize internal state by applying the given ordered events; ( 2) getBalance(tenantId): return the current credit balance for the specified tenant; ( 3) applyEvent(event): process a new single event and update state. Define the event schema (tenantId, delta, optional timestamp/id), decide whether to reject events that would drive balances below zero or allow negatives, and handle idempotency if event ids repeat. Aim for O( 1) average time per operation after O(n) initialization, and discuss data structures, concurrency considerations, and how you would persist state for crash recovery.

Quick Answer: This question evaluates a candidate's ability to design efficient stateful systems and algorithmic data structures for tracking per-tenant resource balances, including handling idempotency, negative balance policies, concurrency, and persistence.

You are implementing an in-memory credit ledger for a shared GPU pool. Each event changes one tenant's credit balance. Use the event schema: (eventId, tenantId, delta) - eventId: unique identifier for idempotency - tenantId: tenant whose balance changes - delta: signed integer; positive adds credits, negative deducts credits Business rules: 1. A tenant's balance may never go below 0. If applying an event would make the balance negative, reject that event. 2. Idempotency is required. If the same eventId is seen again, it must not change state a second time. Instead, return the same success/failure result that was produced the first time that eventId was processed. 3. During initialization, apply the initial events in order using the same rules. 4. getBalance for an unknown tenant should return 0. For the online judge, implement a single function: solution(init_events, operations) - init_events is the ordered list passed to init(events) - operations is a list of later actions, each of which is either: - ('get', tenantId) - ('apply', (eventId, tenantId, delta)) Return a list of outputs for the operations, in order: - For ('get', tenantId), append the current integer balance. - For ('apply', event), append True if that event is accepted, or False if it is rejected. If it is a duplicate eventId, append the same boolean result as the first time it was processed. Follow-up discussion (not required in code): be ready to explain your O(1)-average data structures, how you would make updates thread-safe, and how you would persist the ledger for crash recovery using techniques such as a write-ahead log plus snapshots.

Constraints

  • 0 <= len(init_events), len(operations) <= 2 * 10^5
  • -10^9 <= delta <= 10^9
  • Average-case O(1) time is expected for each get/apply after O(n) initialization
  • If an eventId repeats, it represents the same logical event; replays must be idempotent

Examples

Input: ([('e1', 'tenantA', 10), ('e2', 'tenantA', -3), ('e3', 'tenantB', 5)], [('get', 'tenantA'), ('get', 'tenantB'), ('apply', ('e4', 'tenantA', 2)), ('apply', ('e5', 'tenantB', -6)), ('get', 'tenantB'), ('apply', ('e6', 'tenantA', -4)), ('get', 'tenantB')])

Expected Output: [7, 5, True, False, 5, True, 5]

Explanation: After initialization, tenantA has 7 and tenantB has 5. Adding 2 to tenantA succeeds. Deducting 6 from tenantB fails because it would make the balance negative. Deducting 4 from tenantA later succeeds.

Input: ([], [('get', 'ghost'), ('apply', ('x1', 'ghost', -3)), ('get', 'ghost'), ('apply', ('x1', 'ghost', -3)), ('apply', ('x2', 'ghost', 4)), ('get', 'ghost')])

Expected Output: [0, False, 0, False, True, 4]

Explanation: Unknown tenants start at 0. The first deduction is rejected, and repeating the same eventId returns the same False result. A later positive event succeeds, leaving balance 4.

Input: ([('i1', 'gpu', 5), ('i1', 'gpu', 5), ('i2', 'gpu', -7), ('i3', 'gpu', -2)], [('get', 'gpu'), ('apply', ('i2', 'gpu', -7)), ('apply', ('i1', 'gpu', 5)), ('apply', ('i4', 'gpu2', 1)), ('get', 'gpu2'), ('apply', ('i5', 'gpu', -3)), ('get', 'gpu')])

Expected Output: [3, False, True, True, 1, True, 0]

Explanation: During initialization, i1 is applied once, its duplicate does nothing, i2 is rejected, and i3 succeeds. Later duplicates of i2 and i1 return their original results. A new tenant gpu2 can be credited from 0.

Solution

def solution(init_events, operations):
    balances = {}
    event_result = {}

    def process_event(event):
        event_id, tenant_id, delta = event

        if event_id in event_result:
            return event_result[event_id]

        new_balance = balances.get(tenant_id, 0) + delta
        accepted = new_balance >= 0

        if accepted:
            balances[tenant_id] = new_balance

        event_result[event_id] = accepted
        return accepted

    for event in init_events:
        process_event(event)

    result = []
    for op in operations:
        if op[0] == 'get':
            tenant_id = op[1]
            result.append(balances.get(tenant_id, 0))
        elif op[0] == 'apply':
            event = op[1]
            result.append(process_event(event))
        else:
            raise ValueError('Unknown operation type')

    return result

Time complexity: O(len(init_events) + len(operations)) average. Space complexity: O(T + E), where T is the number of tenants seen and E is the number of distinct eventIds seen.

Hints

  1. Use one hash map for current balances by tenantId, and another hash map for eventId -> previous result.
  2. Before mutating a balance, compute the projected new balance and reject the event if it would drop below zero.
Last updated: Apr 23, 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

  • Simulate Infection Spread on a Grid - OpenAI (hard)
  • Implement Social Follow Recommendations - OpenAI (medium)
  • Build a Compose Rating Card - OpenAI (medium)
  • Convert IPv4 Ranges to CIDR Blocks - OpenAI (medium)
  • Implement Persistent KV Store Serialization - OpenAI (hard)