Problem · Design

Banking System with Historical Snapshots

Learn this problem
HardCoinbase logoCoinbaseFULLTIMEOA

Problem statement

Process operations in input order and return one string result for every operation.

Every row starts with an operation name and a unique timestamp. Timestamps are strictly increasing.

  • ["CREATE_ACCOUNT", timestamp, account]: create account with balance 0. Return true.
  • ["DEPOSIT", timestamp, account, amount]: add the positive integer amount and return the account's new decimal balance.
  • ["MERGE_ACCOUNTS", timestamp, survivor, absorbed]: add the absorbed account's balance to the survivor, then retire the absorbed account. Return true.
  • ["SNAPSHOT", timestamp]: capture every active account and balance after all earlier operations. Return the next ID: snapshot0, snapshot1, and so on.
  • ["GET_BALANCE_AT_SNAPSHOT", timestamp, account, snapshotId]: return the account's decimal balance in that exact snapshot, or null if the account did not exist in it.

Snapshots are immutable. A merge never changes an earlier snapshot: before the merge, both account IDs retain their separate saved balances. Later snapshots contain the combined balance only under the survivor's ID, so the absorbed ID returns null there.

Function

processBankingSnapshots(operations: String[][]) → String[]

Examples

Example 1

operations = [["CREATE_ACCOUNT","1","alice"],["CREATE_ACCOUNT","2","bob"],["DEPOSIT","3","alice","100"],["DEPOSIT","4","bob","60"],["SNAPSHOT","5"],["MERGE_ACCOUNTS","6","alice","bob"],["SNAPSHOT","7"],["GET_BALANCE_AT_SNAPSHOT","8","alice","snapshot0"],["GET_BALANCE_AT_SNAPSHOT","9","bob","snapshot0"],["GET_BALANCE_AT_SNAPSHOT","10","bob","snapshot1"],["GET_BALANCE_AT_SNAPSHOT","11","alice","snapshot1"]]return = ["true","true","100","60","snapshot0","true","snapshot1","100","60","null","160"]

snapshot0 keeps Alice's 100 and Bob's 60. The merge then combines them under Alice. In snapshot1, Bob is absent and Alice has 160.

Example 2

operations = [["CREATE_ACCOUNT","1","main"],["DEPOSIT","2","main","40"],["SNAPSHOT","3"],["CREATE_ACCOUNT","4","aux"],["DEPOSIT","5","aux","25"],["MERGE_ACCOUNTS","6","main","aux"],["DEPOSIT","7","main","10"],["SNAPSHOT","8"],["GET_BALANCE_AT_SNAPSHOT","9","main","snapshot0"],["GET_BALANCE_AT_SNAPSHOT","10","aux","snapshot0"],["GET_BALANCE_AT_SNAPSHOT","11","main","snapshot1"],["GET_BALANCE_AT_SNAPSHOT","12","aux","snapshot1"]]return = ["true","40","snapshot0","true","25","true","75","snapshot1","40","null","75","null"]

The auxiliary account was not yet created in snapshot0. After it is merged and another deposit reaches the survivor, snapshot1 contains only main with balance 75.

Example 3

operations = [["CREATE_ACCOUNT","1","cash"],["SNAPSHOT","2"],["DEPOSIT","3","cash","5"],["SNAPSHOT","4"],["DEPOSIT","5","cash","7"],["SNAPSHOT","6"],["GET_BALANCE_AT_SNAPSHOT","7","cash","snapshot0"],["GET_BALANCE_AT_SNAPSHOT","8","cash","snapshot1"],["GET_BALANCE_AT_SNAPSHOT","9","cash","snapshot2"]]return = ["true","snapshot0","5","snapshot1","12","snapshot2","0","5","12"]

The three snapshots preserve the account's balances 0, 5, and 12 even though the queries occur after all deposits.

Constraints

  • 1 <= operations.length <= 100000
  • 1 <= timestamp <= 1000000000, and operation timestamps are unique and strictly increasing.
  • Account IDs are non-empty, are created at most once, and contain only letters, digits, and underscores.
  • Every DEPOSIT names an active account and has 1 <= amount <= 1000000000.
  • Every MERGE_ACCOUNTS names two distinct active accounts.
  • Every historical query names an existing snapshot ID.
  • Every balance fits in a signed 64-bit integer.
  • Every operation has exactly the arguments shown above.

More Coinbase problems

drafts saved locally
public String[] processBankingSnapshots(String[][] operations) {
  // write your code here
}
operations[["CREATE_ACCOUNT","1","alice"],["CREATE_ACCOUNT","2","bob"],["DEPOSIT","3","alice","100"],["DEPOSIT","4","bob","60"],["SNAPSHOT","5"],["MERGE_ACCOUNTS","6","alice","bob"],["SNAPSHOT","7"],["GET_BALANCE_AT_SNAPSHOT","8","alice","snapshot0"],["GET_BALANCE_AT_SNAPSHOT","9","bob","snapshot0"],["GET_BALANCE_AT_SNAPSHOT","10","bob","snapshot1"],["GET_BALANCE_AT_SNAPSHOT","11","alice","snapshot1"]]
expected["true", "true", "100", "60", "snapshot0", "true", "snapshot1", "100", "60", "null", "160"]
checking account