PracHub
QuestionsPremiumCoachesLearningGuidesInterview Prep

Quick Overview

This question evaluates the ability to design and implement an in-memory, time-ordered stateful system handling event scheduling, transactional updates, historical queries, merging state, and ranked aggregations using appropriate data structures and algorithms, and it belongs to the Coding & Algorithms domain.

  • hard
  • Meta
  • Coding & Algorithms
  • Software Engineer

Implement a Timestamped Banking System

Company: Meta

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: hard

Interview Round: Take-home Project

Implement an in-memory banking system that processes API calls in nondecreasing `timestamp` order. Support the following operations: - `create_account(timestamp, account_id) -> bool` - Create a new account with balance `0`. - Return `false` if the account already exists; otherwise return `true`. - `deposit(timestamp, account_id, amount) -> int | None` - Add `amount` to the account balance. - Return the updated balance. - Return `None` if the account does not exist. - `transfer(timestamp, source, target, amount) -> int | None` - Move `amount` from `source` to `target`. - Return the updated balance of `source`. - Return `None` if either account does not exist, `source == target`, or `source` has insufficient funds. - `top_spenders(timestamp, n) -> list[str]` - Return up to `n` accounts with the largest total outgoing amount. - Format each result as `"account_id(total_outgoing)"`. - Sort by total outgoing amount in descending order; break ties by `account_id` in ascending lexicographic order. - Outgoing amount includes money successfully sent out of an account. - `schedule_payment(timestamp, account_id, amount, delay) -> str | None` - Schedule a withdrawal of `amount` from `account_id` at time `timestamp + delay`. - Return a globally unique payment ID such as `"payment1"`, `"payment2"`, and so on. - Return `None` if the account does not exist. - `cancel_payment(timestamp, account_id, payment_id) -> bool` - Cancel a pending scheduled payment. - Return `true` only if the payment exists, belongs to `account_id`, and has not already executed or been canceled. - `merge_accounts(timestamp, account_id_1, account_id_2) -> bool` - Merge `account_id_2` into `account_id_1`. - The surviving account keeps `account_id_1`. - Its balance becomes the sum of both balances. - Its outgoing total becomes the sum of both outgoing totals. - Any pending scheduled payments owned by `account_id_2` are transferred to `account_id_1`. - `account_id_2` is then deleted. - Return `false` if either account does not exist or the two IDs are the same. - `get_balance(timestamp, account_id, time_at) -> int | None` - Return the balance of `account_id` at historical time `time_at`. - Return `None` if the account does not exist at query time or if `time_at` is earlier than the account's creation time. Additional assumptions to make the problem self-contained: - All amounts are nonnegative integers. - Whenever an operation is called at time `t`, all scheduled payments due at or before `t` must be processed before the operation itself. - If multiple scheduled payments are due at the same time, process them in payment creation order. - A scheduled payment executes only if the owning account has sufficient funds at execution time; otherwise it is skipped.

Quick Answer: This question evaluates the ability to design and implement an in-memory, time-ordered stateful system handling event scheduling, transactional updates, historical queries, merging state, and ranked aggregations using appropriate data structures and algorithms, and it belongs to the Coding & Algorithms domain.

Part 1: Basic Timestamped Account Operations

Given a list of banking commands, process CREATE, DEPOSIT, and TRANSFER operations in order. Return the result of every command. A CREATE succeeds only if the account does not already exist. A DEPOSIT returns the new balance or None if the account does not exist. A TRANSFER returns the source account's new balance, or None if either account does not exist, the two accounts are the same, or the source lacks enough money.

Constraints

  • 0 <= len(queries) <= 20000
  • 1 <= amount <= 10^9
  • account_id is a non-empty string
  • Timestamps are integers and queries should be processed in the given order

Examples

Input: ([['CREATE', 1, 'alice'], ['DEPOSIT', 2, 'alice', 100], ['CREATE', 3, 'bob'], ['TRANSFER', 4, 'alice', 'bob', 30], ['DEPOSIT', 5, 'bob', 10]],)

Expected Output: [True, 100, True, 70, 40]

Explanation: Alice is created and funded. After transferring 30 to Bob, Alice has 70. Bob then deposits 10 and reaches 40.

Input: ([['CREATE', 1, 'a'], ['CREATE', 2, 'a'], ['DEPOSIT', 3, 'missing', 50], ['TRANSFER', 4, 'a', 'missing', 10]],)

Expected Output: [True, False, None, None]

Explanation: Duplicate creation fails, depositing into a missing account fails, and transferring to a missing account also fails.

Input: ([['CREATE', 1, 'x'], ['CREATE', 2, 'y'], ['DEPOSIT', 3, 'x', 20], ['TRANSFER', 4, 'x', 'x', 5], ['TRANSFER', 5, 'x', 'y', 25], ['TRANSFER', 6, 'x', 'y', 20]],)

Expected Output: [True, True, 20, None, None, 0]

Explanation: A self-transfer is invalid, an overdraft transfer is invalid, and the final valid transfer leaves x with balance 0.

Input: ([],)

Expected Output: []

Explanation: Edge case: no queries means no outputs.

Hints

  1. A hash map from account_id to current balance is enough for this level.
  2. For TRANSFER, check every failure condition before changing either balance.

Part 2: Rank the Top Spenders

Extend the banking system with a TOP query. Every successful TRANSFER adds its amount to the source account's total outgoing money. DEPOSIT does not affect outgoing totals. For a TOP query, return up to n current accounts sorted by highest outgoing total, breaking ties by lexicographically smaller account_id. Include accounts with zero outgoing if needed to fill the answer.

Constraints

  • 0 <= len(queries) <= 20000
  • 1 <= amount <= 10^9
  • 1 <= n <= 20000
  • account_id is a non-empty string
  • Only successful TRANSFER operations contribute to outgoing totals

Examples

Input: [('CREATE', 'alice'), ('CREATE', 'bob'), ('DEPOSIT', 'alice', 100), ('DEPOSIT', 'bob', 20), ('TRANSFER', 'alice', 'bob', 30), ('TRANSFER', 'bob', 'alice', 20)]

Expected Output: [True, True, 100, 20, 70, 30]

Explanation: After the first transfer, alice has 70. After the second transfer, bob has 30, and TRANSFER returns the source account's balance.

Input: [('DEPOSIT', 'ghost', 10), ('CREATE', 'a'), ('CREATE', 'a'), ('TRANSFER', 'a', 'a', 5), ('DEPOSIT', 'a', 0)]

Expected Output: [None, True, False, None, None]

Explanation: Depositing to a missing account fails, duplicate creation returns False, self-transfer is invalid, and non-positive deposits are invalid.

Input: [('CREATE', 'a'), ('CREATE', 'b'), ('DEPOSIT', 'a', 20), ('TRANSFER', 'a', 'b', 25), ('TRANSFER', 'a', 'b', 20)]

Expected Output: [True, True, 20, None, 0]

Explanation: The first transfer fails because account a only has 20. The second succeeds and leaves a with 0.

Input: []

Expected Output: []

Explanation: No queries means no results.

Hints

  1. Store two values per account: current balance and total outgoing amount.
  2. For TOP, sort accounts using the key `(-outgoing, account_id)`.

Part 3: Scheduled Payments in a Banking System

Build a banking system that supports delayed withdrawals. A SCHEDULE query creates a payment id like `payment1`, `payment2`, and so on, and schedules a withdrawal to happen at `timestamp + delay`. Before processing any query at time t, first execute every pending payment whose execution time is less than or equal to t. If multiple payments are due at the same time, execute them in creation order. If a due payment does not have enough funds, it is skipped and removed. A CANCEL succeeds only if the payment is still pending and belongs to that account.

Constraints

  • 0 <= len(queries) <= 20000
  • Queries are given in nondecreasing timestamp order
  • 1 <= amount <= 10^9
  • 1 <= delay <= 10^9
  • account_id is a non-empty string

Examples

Input: ([['CREATE', 1, 'a'], ['DEPOSIT', 2, 'a', 100], ['SCHEDULE', 3, 'a', 30, 5], ['BALANCE', 7, 'a'], ['BALANCE', 8, 'a'], ['CANCEL', 9, 'a', 'payment1']],)

Expected Output: [True, 100, 'payment1', 100, 70, False]

Explanation: The payment is scheduled for time 8. The balance is still 100 at time 7, becomes 70 at time 8, and can no longer be canceled afterward.

Input: ([['CREATE', 1, 'a'], ['DEPOSIT', 2, 'a', 50], ['SCHEDULE', 3, 'a', 40, 4], ['SCHEDULE', 4, 'a', 20, 3], ['BALANCE', 7, 'a']],)

Expected Output: [True, 50, 'payment1', 'payment2', 10]

Explanation: Both payments are due at time 7. `payment1` executes first and leaves balance 10, so `payment2` fails due to insufficient funds.

Input: ([['CREATE', 1, 'x'], ['DEPOSIT', 2, 'x', 25], ['SCHEDULE', 3, 'x', 10, 2], ['CANCEL', 4, 'x', 'payment1'], ['BALANCE', 5, 'x'], ['CANCEL', 6, 'x', 'payment1']],)

Expected Output: [True, 25, 'payment1', True, 25, False]

Explanation: The payment is canceled before it is due, so the balance remains unchanged. Canceling the same payment again fails.

Input: ([],)

Expected Output: []

Explanation: Edge case: no queries.

Hints

  1. A min-heap ordered by `(execution_time, creation_order)` lets you run due payments efficiently.
  2. Be careful with query order: due payments at time t happen before processing a CANCEL or BALANCE query at time t.

Part 4: Merge Accounts and Query Historical Balances

Build a banking system with CREATE, DEPOSIT, TRANSFER, MERGE, and GET_BALANCE operations. A MERGE at time t combines account_id_2 into account_id_1: account_id_1 keeps existing and gains all of account_id_2's current money, while account_id_2 stops existing from time t onward. A GET_BALANCE query asks for the balance that a specific account had at an earlier time `time_at`. Return None if the account had not been created yet at `time_at`, or if it had already been merged away by `time_at`.

Constraints

  • 0 <= len(queries) <= 20000
  • Queries are given in strictly increasing timestamp order
  • Each account_id is created at most once in the entire input
  • 1 <= amount <= 10^9
  • For every GET_BALANCE query, `time_at` is an integer with `time_at <= timestamp`

Examples

Input: ([['CREATE', 1, 'a'], ['CREATE', 2, 'b'], ['DEPOSIT', 3, 'a', 50], ['DEPOSIT', 4, 'b', 30], ['MERGE', 5, 'a', 'b'], ['GET_BALANCE', 6, 'a', 4], ['GET_BALANCE', 7, 'a', 5], ['GET_BALANCE', 8, 'b', 4], ['GET_BALANCE', 9, 'b', 5]],)

Expected Output: [True, True, 50, 30, True, 50, 80, 30, None]

Explanation: Before the merge, a had 50 and b had 30. At time 5, a becomes 80 and b stops existing.

Input: ([['CREATE', 1, 'x'], ['CREATE', 2, 'y'], ['DEPOSIT', 3, 'x', 100], ['TRANSFER', 4, 'x', 'y', 40], ['GET_BALANCE', 5, 'x', 3], ['GET_BALANCE', 6, 'y', 4], ['MERGE', 7, 'y', 'x'], ['GET_BALANCE', 8, 'y', 7], ['GET_BALANCE', 9, 'x', 6], ['GET_BALANCE', 10, 'x', 7]],)

Expected Output: [True, True, 100, 60, 100, 40, True, 100, 60, None]

Explanation: After the transfer, x has 60 and y has 40. Merging x into y at time 7 makes y equal 100 and removes x from that time on.

Input: ([['CREATE', 1, 'a'], ['MERGE', 2, 'a', 'a'], ['GET_BALANCE', 3, 'a', 0], ['GET_BALANCE', 4, 'missing', 1], ['DEPOSIT', 5, 'missing', 10]],)

Expected Output: [True, False, None, None, None]

Explanation: Merging an account with itself is invalid. Historical queries before creation or for unknown accounts return None.

Input: ([],)

Expected Output: []

Explanation: Edge case: no queries.

Hints

  1. Store only balance changes: for each account, keep a list of `(timestamp, balance)` entries.
  2. To answer GET_BALANCE fast, binary search for the last history entry whose timestamp is `<= time_at`, and also check creation and deletion times.
Last updated: Apr 19, 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
  • 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

  • Find Shortest Unique Prefixes - Meta (medium)
  • Compute Exclusive Execution Times - Meta (medium)
  • Solve Tree Columns And Maze Variants - Meta (medium)
  • Solve Tree Diameter and Palindromic Counts - Meta (medium)
  • Simulate Monster Team Battles - Meta (hard)