You have been tasked with writing a program for a popular bank that will automate all its incoming transactions (transfer, deposit, and withdraw). The bank has n accounts numbered from 1 to n. The initial balance of each account is stored in a 0-indexed integer array balance, with the (i + 1)th account having an initial balance of balance[i].
Execute all the valid transactions. A transaction is valid if:
1 and n, andImplement the Bank class:
Bank(long[] balance) Initializes the object with the 0-indexed integer array balance.boolean transfer(int account1, int account2, long money) Transfers money dollars from the account numbered account1 to the account numbered account2. Return true if the transaction was successful, false otherwise.boolean deposit(int account, long money) Deposit money dollars into the account numbered account. Return true if the transaction was successful, false otherwise.boolean withdraw(int account, long money) Withdraw money dollars from the account numbered account. Return true if the transaction was successful, false otherwise.
Example 1:
Input
["Bank", "withdraw", "transfer", "deposit", "transfer", "withdraw"]
[[[10, 100, 20, 50, 30]], [3, 10], [5, 1, 20], [5, 20], [3, 4, 15], [10, 50]]
Output
[null, true, true, true, false, false]
Explanation
Bank bank = new Bank([10, 100, 20, 50, 30]);
bank.withdraw(3, 10); // return true, account 3 has a balance of $20, so it is valid to withdraw $10.
// Account 3 has $20 - $10 = $10.
bank.transfer(5, 1, 20); // return true, account 5 has a balance of $30, so it is valid to transfer $20.
// Account 5 has $30 - $20 = $10, and account 1 has $10 + $20 = $30.
bank.deposit(5, 20); // return true, it is valid to deposit $20 to account 5.
// Account 5 has $10 + $20 = $30.
bank.transfer(3, 4, 15); // return false, the current balance of account 3 is $10,
// so it is invalid to transfer $15 from it.
bank.withdraw(10, 50); // return false, it is invalid because account 10 does not exist.
Constraints:
n == balance.length1 <= n, account, account1, account2 <= 1050 <= balance[i], money <= 1012104 calls will be made to each function transfer, deposit, withdraw.Problem Overview: You need to design a simple banking system that stores balances for n accounts and supports three operations: transfer, deposit, and withdraw. Each operation must validate account numbers and ensure sufficient balance before modifying the stored amounts.
Approach 1: Direct Array Manipulation (O(1) per operation, O(n) space)
The most straightforward design stores account balances in an array where the index represents the account number. Every operation performs constant-time access using direct indexing. For example, a transfer checks if both accounts exist, verifies that the source account has enough funds, then subtracts from one index and adds to the other.
This approach works because arrays provide O(1) random access. Validation simply checks if the account index falls within the valid range. Deposits increment the balance at the target index, while withdrawals subtract after confirming sufficient funds. The implementation stays clean and efficient since each operation touches only a few array positions.
This design aligns well with problems involving fixed-size collections and predictable identifiers. When account IDs map directly to indices, arrays are faster and simpler than extra data structures. Concepts here closely relate to array operations and straightforward simulation of system behavior.
Approach 2: HashMap for Account Balances (O(1) average per operation, O(n) space)
A more flexible design stores balances in a HashMap where the key is the account number and the value is the balance. Each operation performs constant-time average lookups using a hash table. Before modifying balances, the system checks whether the relevant keys exist in the map.
Transfers involve two hash lookups followed by updates to both accounts. Deposits update the value for the target account, while withdrawals check the stored balance before subtracting. HashMap-based storage removes reliance on contiguous indices and works even if account numbers are sparse or dynamically created.
This design demonstrates common system design patterns where entities are mapped to values using a hash table. It becomes useful when identifiers are not guaranteed to align with array indices or when the system might expand dynamically.
Recommended for interviews: The array-based implementation is typically expected because the problem provides account balances in order and account numbers map directly to positions. It shows you recognize the simplest constant-time design. The HashMap approach still demonstrates good understanding of scalable system modeling and hash-based lookups.
This approach uses a simple array to store the balance of each account starting from account 1 at index 0. All operations check for validity by ensuring accounts fit within valid range and ensuring sufficient funds for transactions before modifying the array accordingly.
This implementation provides a simple C structure to represent the bank. It uses a pointer to manage the balance array and account size. Each transaction checks if accounts are in range and if balance conditions are met, updating the balances accordingly. Memory is freed to avoid leaks.
Time Complexity: O(1) for each transaction since operations are basic arithmetic and index checks.
Space Complexity: O(1), as no extra space is used other than input and output.
In this approach, we can use a hashmap (or dictionary for Python, Map for Java, etc.) where keys are account numbers and values are their respective balance amounts. It allows for a more dynamic setup, even though it's less efficient than direct array access due to its average constant time complexity for reads and writes.
This Java implementation uses a HashMap to manage accounts and balances. Using a map allows dynamic addition or removal of accounts, but for this fixed scenario it's less efficient than array manipulation. This approach ensures that each transaction first checks the key's existence and balance sufficiency before applying changes.
Time Complexity: O(1) on average for each transaction due to efficient map operations.
Space Complexity: O(n) to store balance data for each account, which could also adjust dynamically if needed.
We can use an array balance to store the balance of each account. For each operation, we simply perform the required checks and updates according to the problem statement.
For the transfer operation, we need to check whether the account numbers are valid and whether the balance is sufficient. If the conditions are met, we perform the transfer.
For the deposit operation, we only need to check whether the account number is valid, and then perform the deposit.
For the withdraw operation, we need to check whether the account number is valid and whether the balance is sufficient. If the conditions are met, we perform the withdrawal.
Each operation has a time complexity of O(1), so the overall time complexity is O(q), where q is the number of operations. The space complexity is O(1).
| Approach | Complexity |
|---|---|
| Direct Array Manipulation | Time Complexity: O(1) for each transaction since operations are basic arithmetic and index checks. |
| HashMap for Account Balances | Time Complexity: O(1) on average for each transaction due to efficient map operations. |
| Simulation | — |
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Direct Array Manipulation | O(1) per operation | O(n) | When account numbers map directly to indices and the total number of accounts is fixed |
| HashMap for Account Balances | O(1) average per operation | O(n) | When account identifiers may be sparse, dynamic, or not aligned with array indices |
Simple Bank System | Easy Simulation| Leetcode 2043 | codestorywithMIK • codestorywithMIK • 5,329 views views
Watch 9 more video solutions →Practice Simple Bank System with our built-in code editor and test cases.
Practice on FleetCodePractice this problem
Open in Editor