I recently took Airbnb's software engineering online assessment. I hope this question format helps people who take it later.
One of the online assessment questions was a banking system or filesystem with unit tests. It was similar to CodeSignal's progressive-level problems. It was not a set of independent LeetCode questions; instead, new requirements kept being added to the same codebase.
The overall format:
At the beginning, I received an interface and starter code and had to complete the implementation. There were four levels in total. I had to pass the tests for the current level before the next one unlocked, and later levels could access all data from earlier levels, so it was best not to make the initial data structure too rigid.
Level 1: Basic Banking Operations
The system needed to support:
create_account(timestamp, account_id)
deposit(timestamp, account_id, amount)
transfer(timestamp, source_account_id, target_account_id, amount)
The main job was maintaining account balances. This level itself was not difficult, but it had many edge cases: an account might not exist; source and target might be the same account; the balance might be insufficient; an account might be duplicated; and a successful transfer had to return the correct balance.
Level 2: Top Spenders
The requirement was to rank accounts by the total value of outgoing transactions. It added an operation similar to:
top_spenders(timestamp, n)
I needed to track each account's total outgoing amount. For example, if A transfers 100 to B, A's outgoing total increases by 100 while B's does not. Sorting used both total spending and a tie-breaker, so it was not enough to throw the numbers into a heap; account ID ordering also mattered.
Level 3: Scheduled Payments
The system now had to support scheduling a payment, executing it at a specified timestamp, canceling it, and checking or otherwise handling its state.
The biggest trap here was timestamp execution order. It was not enough to record data when schedule_payment was called. Whenever a later operation occurred, the system might first need to process scheduled payments that should already have executed by that timestamp.
I felt that the real test was a state machine plus event ordering. A natural approach was to consider a min-heap containing entries such as:
(execute_time, payment_id, ...)
I would also keep a payment-status dictionary mapping each payment ID to its metadata and process due payments before every API operation. A successful payment also affected Level 2's outgoing-transaction totals, so if the earlier data model was scattered, this level became painful.
Level 4: Merge Accounts
The final level was account merging. The broad requirement was to merge accounts while retaining the balances and transaction histories of both. That included the balance, transaction history, spending history, and scheduled-payment or payment information.
The hardest part was not the merge itself, but deciding what to do with the old account IDs. If everything from the earlier levels had been stored under raw account_id values spread across a dozen dictionaries, Level 4 was difficult to retrofit. A better idea was to centralize account state from the beginning, or at least think in terms of account aliases and a canonical account.
My overall impression:
I did not think this was like a typical LeetCode Hard problem. The algorithms themselves were not especially difficult, but the question tested careful reading of requirements, data-structure design, edge cases, state consistency, timestamp ordering, and the ability to add new features quickly to existing code. It felt like a small object-oriented design or machine-coding exercise combined with LeetCode-style implementation. That was quite different from simply solving one LeetCode Medium problem.
Good luck with the online assessment.
Discussion
Loading comments…