PracHub
QuestionsPremiumCoachesLearningGuidesInterview Prep

Quick Overview

This question evaluates skills in designing and implementing a stateful in-memory banking system, covering account modeling, transfer lifecycle and expiration handling, balance management, and tracking aggregate outgoing amounts.

  • medium
  • Anthropic
  • Coding & Algorithms
  • Software Engineer

Implement a Banking System

Company: Anthropic

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: medium

Interview Round: Onsite

Design and implement an in-memory banking system. All operations are processed in non-decreasing timestamp order. Account identifiers are strings. Money amounts are non-negative integers. A transfer expires if it has not been accepted within `TRANSFER_EXPIRATION_MS = 86,400,000` milliseconds after it was created. Implement the following operations: 1. `create_account(timestamp, account_id) -> bool` - Create a new account with balance `0`. - Return `true` if the account was created. - Return `false` if an account with the same id already exists. 2. `deposit(timestamp, account_id, amount) -> int | null` - Before applying the deposit, expire any pending transfers that should have timed out by this timestamp. - Add `amount` to the account balance. - Return the new balance. - Return `null` if the account does not exist. 3. `top_outgoing(timestamp, n) -> list[string]` - Before computing the result, expire any pending transfers that should have timed out by this timestamp. - Return up to `n` accounts sorted by total outgoing money in descending order. - Break ties by lexicographically smaller account id. - Outgoing money includes only completed outgoing transfers. Pending or expired transfers must not count. 4. `transfer(timestamp, source_account_id, target_account_id, amount) -> string | null` - Before creating the transfer, expire any pending transfers that should have timed out by this timestamp. - Create a pending transfer from `source_account_id` to `target_account_id`. - Immediately withhold `amount` from the source account balance. - Return a unique transfer id such as `"transfer1"`, `"transfer2"`, etc. - Return `null` if either account does not exist, both accounts are the same, or the source account has insufficient available balance. 5. `accept_transfer(timestamp, account_id, transfer_id) -> bool` - Before accepting the transfer, expire any pending transfers that should have timed out by this timestamp. - Accept the pending transfer only if `account_id` is the target account. - Move the withheld money into the target account balance. - Add `amount` to the source account's total outgoing money. - Return `true` if the transfer was accepted. - Return `false` if the transfer does not exist, is already accepted, has expired, or `account_id` is not the target account. 6. `merge_accounts(timestamp, destination_account_id, source_account_id) -> bool` - Before merging, expire any pending transfers that should have timed out by this timestamp. - Merge `source_account_id` into `destination_account_id`. - Return `false` if either account does not exist or both ids are the same. - Add the source account's balance to the destination account's balance. - Add the source account's total outgoing money to the destination account's total outgoing money. - Redirect pending incoming transfers targeting the source account so that they now target the destination account. - Redirect pending outgoing transfers created by the source account so that they now originate from the destination account; the withheld balance remains withheld. - If there is a pending transfer between the destination and source accounts, cancel it and return the withheld amount to the appropriate surviving account. - Remove the source account after the merge. Your implementation should correctly handle edge cases such as expired transfers being canceled before later deposits, attempts to accept expired transfers, duplicate account creation, insufficient funds, and sorting ties in `top_outgoing`.

Quick Answer: This question evaluates skills in designing and implementing a stateful in-memory banking system, covering account modeling, transfer lifecycle and expiration handling, balance management, and tracking aggregate outgoing amounts.

Design and implement an in-memory banking system. You are given a list of operations in non-decreasing timestamp order. Process them in order and return the result of each operation. Accounts are identified by strings. Balances and money amounts are non-negative integers. Transfers are created as pending transfers: the amount is immediately withheld from the source balance, but it is not added to the target balance and does not count as outgoing money until the transfer is accepted. A transfer created at timestamp t is valid through timestamp t + TRANSFER_EXPIRATION_MS, inclusive. It expires before processing any later operation whose timestamp is greater than t + TRANSFER_EXPIRATION_MS. When a pending transfer expires, its withheld amount is returned to its current source account. Supported operations: - create_account(timestamp, account_id): create an account with balance 0. Return True if created, or False if the account already exists. - deposit(timestamp, account_id, amount): expire pending transfers first, then add amount to the account. Return the new balance, or None if the account does not exist. - top_outgoing(timestamp, n): expire pending transfers first. Return up to n account ids sorted by completed outgoing money descending, breaking ties by lexicographically smaller account id. - transfer(timestamp, source_account_id, target_account_id, amount): expire pending transfers first. Create a pending transfer, withhold amount from the source account, and return a unique id transfer1, transfer2, etc. Return None if either account does not exist, both ids are the same, or the source has insufficient available balance. - accept_transfer(timestamp, account_id, transfer_id): expire pending transfers first. Accept the transfer only if account_id is the current target. Add the amount to the target balance and add it to the source account's completed outgoing total. Return True if accepted, otherwise False. - merge_accounts(timestamp, destination_account_id, source_account_id): expire pending transfers first. Merge source into destination. Return False if either account does not exist or both ids are the same. Add the source balance and completed outgoing total to the destination. Redirect pending incoming transfers targeting the source to the destination. Redirect pending outgoing transfers from the source to originate from the destination. If a pending transfer is directly between destination and source in either direction, cancel it and return its withheld amount to the surviving merged account. Remove the source account.

Constraints

  • 1 <= len(operations) <= 2000
  • 0 <= timestamp <= 10^12, and timestamps are non-decreasing
  • Account ids are non-empty strings
  • 0 <= amount <= 10^9
  • 0 <= n <= number of operations
  • TRANSFER_EXPIRATION_MS = 86,400,000
  • A transfer created at t expires before processing operations with timestamp > t + TRANSFER_EXPIRATION_MS

Examples

Input: ([('create_account', 1, 'alice'), ('create_account', 2, 'alice'), ('deposit', 3, 'bob', 50), ('create_account', 4, 'bob'), ('deposit', 5, 'alice', 100), ('deposit', 6, 'bob', 100), ('top_outgoing', 7, 3), ('top_outgoing', 8, 0)],)

Expected Output: [True, False, None, True, 100, 100, ['alice', 'bob'], []]

Explanation: Duplicate account creation fails, depositing to a missing account returns None, and accounts with equal outgoing totals are sorted lexicographically. Requesting the top 0 accounts returns an empty list.

Input: ([('create_account', 1, 'A'), ('create_account', 2, 'B'), ('deposit', 3, 'A', 500), ('transfer', 4, 'A', 'B', 200), ('top_outgoing', 5, 2), ('accept_transfer', 6, 'A', 'transfer1'), ('accept_transfer', 7, 'B', 'transfer1'), ('top_outgoing', 8, 2), ('deposit', 9, 'B', 50), ('accept_transfer', 10, 'B', 'transfer1')],)

Expected Output: [True, True, 500, 'transfer1', ['A', 'B'], False, True, ['A', 'B'], 250, False]

Explanation: The pending transfer does not count as outgoing before acceptance. Accepting with the wrong target fails. After B accepts, B receives 200 and A's outgoing total becomes 200. Accepting the same transfer again fails.

Input: ([('create_account', 0, 'A'), ('create_account', 1, 'B'), ('deposit', 2, 'A', 1000), ('transfer', 10, 'A', 'B', 300), ('accept_transfer', 86400010, 'B', 'transfer1'), ('transfer', 86400011, 'B', 'A', 100), ('deposit', 172800012, 'B', 50), ('accept_transfer', 172800013, 'A', 'transfer2'), ('top_outgoing', 172800014, 2)],)

Expected Output: [True, True, 1000, 'transfer1', True, 'transfer2', 350, False, ['A', 'B']]

Explanation: transfer1 is accepted exactly at its expiration boundary, so it succeeds. transfer2 expires before the later deposit, so its withheld 100 is returned to B before depositing 50, producing balance 350. The expired transfer cannot be accepted and does not count as outgoing.

Input: ([('create_account', 1, 'A'), ('create_account', 2, 'C'), ('deposit', 3, 'A', 10), ('transfer', 4, 'A', 'C', 20), ('transfer', 5, 'A', 'A', 1), ('transfer', 6, 'A', 'X', 1), ('deposit', 7, 'A', 0), ('top_outgoing', 8, 5)],)

Expected Output: [True, True, 10, None, None, None, 10, ['A', 'C']]

Explanation: Transfers fail for insufficient funds, same source and target, and missing target account. Depositing 0 is allowed and leaves the balance unchanged.

Input: ([('create_account', 1, 'A'), ('create_account', 2, 'B'), ('create_account', 3, 'C'), ('deposit', 4, 'A', 1000), ('deposit', 5, 'B', 500), ('deposit', 6, 'C', 200), ('transfer', 7, 'A', 'B', 300), ('transfer', 8, 'B', 'A', 100), ('transfer', 9, 'C', 'B', 50), ('transfer', 10, 'B', 'C', 200), ('merge_accounts', 11, 'A', 'B'), ('deposit', 12, 'A', 0), ('accept_transfer', 13, 'A', 'transfer3'), ('accept_transfer', 14, 'C', 'transfer4'), ('top_outgoing', 15, 3), ('deposit', 16, 'C', 0), ('accept_transfer', 17, 'B', 'transfer1')],)

Expected Output: [True, True, True, 1000, 500, 200, 'transfer1', 'transfer2', 'transfer3', 'transfer4', True, 1300, True, True, ['A', 'C'], 350, False]

Explanation: When B merges into A, pending transfers A->B and B->A are canceled and their withheld amounts are returned. Pending transfer C->B is redirected to C->A, and pending transfer B->C is redirected to A->C. After accepting them, A has outgoing 200 and C has outgoing 50.

Input: ([('create_account', 1, 'A'), ('create_account', 2, 'B'), ('create_account', 3, 'C'), ('deposit', 4, 'B', 100), ('transfer', 5, 'B', 'C', 40), ('accept_transfer', 6, 'C', 'transfer1'), ('top_outgoing', 7, 3), ('merge_accounts', 8, 'A', 'B'), ('top_outgoing', 9, 3), ('deposit', 10, 'A', 10)],)

Expected Output: [True, True, True, 100, 'transfer1', True, ['B', 'A', 'C'], True, ['A', 'C'], 70]

Explanation: B's completed outgoing total of 40 is added to A during the merge. B's remaining balance 60 is also moved to A, so depositing 10 afterward returns 70.

Hints

  1. Use dictionaries to store account state and transfer state. For each account, track both available balance and completed outgoing total.
  2. Remember that pending transfers withhold money immediately, but they only affect outgoing totals when accepted. Expiration and merging both need to update pending transfers carefully.
Last updated: Jun 13, 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

  • Implement Persistent Memoization LRU Cache - Anthropic (hard)
  • Fix a Corrupted Bootloader Instruction - Anthropic (medium)
  • Implement a Time-Aware Task Manager - Anthropic (hard)
  • Implement a Simplified DNS Resolver - Anthropic (hard)
  • Implement Task Management and Duplicate Detection - Anthropic (medium)