Design Auction System solution and explanation
5 more videos on this problem
Leetcode 3815 | Design Auction System | Leetcode Weekly contest 485CodeWithMeGuys · 11:22 · 424 views
Design Auction System 🔥 LeetCode 3815 | Weekly Contest 485 | Design + Heaps Study Placement · 18:53 · 352 views
3815. Design Auction System (Leetcode Medium)Programming Live with Larry · 9:59 · 226 views
Design Auction System | LeetCode 3815 | Design | MapscodeTips · 13:52 · 169 views
LeetCode 3815. Design Auction System | Map | Set | 2D Map | Medium | Easiest solution ideaLeet's Code · 24:10 · 147 views
Design Auction System | leetcode 3815 | leetcode weekly contest 485 | must do dsa | Max HeapCode Thoughts · 24:11 · 100 views
The problem
You are asked to design an auction system that manages bids from multiple users in real time.
Each bid is associated with a userId, an itemId, and a bidAmount.
Implement the AuctionSystem class:
AuctionSystem(): Initializes theAuctionSystemobject.void addBid(int userId, int itemId, int bidAmount): Adds a new bid foritemIdbyuserIdwithbidAmount. If the sameuserIdalready has a bid onitemId, replace it with the newbidAmount.void updateBid(int userId, int itemId, int newAmount): Updates the existing bid ofuserIdforitemIdtonewAmount. It is guaranteed that this bid exists.void removeBid(int userId, int itemId): Removes the bid ofuserIdforitemId. It is guaranteed that this bid exists.int getHighestBidder(int itemId): Returns theuserIdof the highest bidder foritemId. If multiple users have the same highestbidAmount, return the user with the highestuserId. If no bids exist for the item, return -1.
Example 1:
Input:
["AuctionSystem", "addBid", "addBid", "getHighestBidder", "updateBid", "getHighestBidder", "removeBid", "getHighestBidder", "getHighestBidder"]
[[], [1, 7, 5], [2, 7, 6], [7], [1, 7, 8], [7], [2, 7], [7], [3]]
Output:
[null, null, null, 2, null, 1, null, 1, -1]
Explanation
AuctionSystem auctionSystem = new AuctionSystem(); // Initialize the Auction systemauctionSystem.addBid(1, 7, 5); // User 1 bids 5 on item 7
auctionSystem.addBid(2, 7, 6); // User 2 bids 6 on item 7
auctionSystem.getHighestBidder(7); // return 2 as User 2 has the highest bid
auctionSystem.updateBid(1, 7, 8); // User 1 updates bid to 8 on item 7
auctionSystem.getHighestBidder(7); // return 1 as User 1 now has the highest bid
auctionSystem.removeBid(2, 7); // Remove User 2's bid on item 7
auctionSystem.getHighestBidder(7); // return 1 as User 1 is the current highest bidder
auctionSystem.getHighestBidder(3); // return -1 as no bids exist for item 3
Constraints:
1 <= userId, itemId <= 5 * 1041 <= bidAmount, newAmount <= 109- At most
5 * 104total calls toaddBid,updateBid,removeBid, andgetHighestBidder. - The input is generated such that for
updateBidandremoveBid, the bid from the givenuserIdfor the givenitemIdwill be valid.
Approach overview
Problem Overview: Design a system that manages auction bids efficiently. You need to support operations such as placing a bid, updating or removing a bid, and retrieving the highest bidder. The system must keep bids ordered by value while allowing fast updates when the same bidder changes their bid.
Approach 1: Brute Force List Scan (O(n) time per query, O(n) space)
The simplest design stores all bids in a list or array. Each new bid is appended or updated by scanning the list for the bidder. When the highest bid is required, iterate through all stored bids and track the maximum value. This approach is straightforward but inefficient because every lookup or ranking operation requires a full scan. Time complexity becomes O(n) per query with O(n) space, which does not scale when the number of bidders grows.
Approach 2: Hash Table + Heap (Priority Queue) (O(log n) updates, O(n) space)
A more practical solution uses a hash table to store the latest bid for each bidder and a heap (priority queue) to track the highest bid. The heap stores pairs like (bidAmount, bidderId). When a bidder updates their bid, push the new value to the heap and update the hash map. While retrieving the top bid, discard stale entries whose value no longer matches the hash table. This keeps insertion and update operations at O(log n), while lookups remain efficient.
Approach 3: Hash Table + Ordered Set (O(log n) per operation)
The cleanest design uses a hash table combined with an ordered set (such as TreeSet in Java or balanced BST structures). The hash table maps bidderId → bidAmount so updates can be located instantly. The ordered set stores pairs sorted by bid amount (and optionally bidder id for tie-breaking). When a bidder updates their bid, remove the old pair from the ordered set and insert the new one. Retrieving the highest bidder becomes a constant-time lookup of the last element in the ordered structure. Each modification costs O(log n) time and the total space remains O(n).
Recommended for interviews: The Hash Table + Ordered Set design is typically expected. The brute-force version shows you understand the requirements, but interviewers want to see how you maintain ordering while supporting fast updates. Combining direct lookup from a hash table with ordered retrieval from a balanced tree demonstrates solid system design and data structure selection.
Solution
We define two hash tables. items is used to store all bid information for each item, where items[itemId] stores an ordered set. Each element in the set is a tuple (bidAmount, userId), representing a user's bid amount for that item. Since we need to quickly retrieve the user with the highest bid, this ordered set needs to be sorted by bid amount in ascending order. If bid amounts are identical, they are sorted by user ID in ascending order. The other hash table users is used to store the bid information of each user for each item, where users[userId][itemId] stores the user's bid amount for that item.
For the addBid(userId, itemId, bidAmount) operation, we first check if the user has already placed a bid on the item. If they have, we call the removeBid(userId, itemId) method to remove the original bid; then we add the new bid information to users and items.
For the updateBid(userId, itemId, newAmount) operation, we first retrieve the user's original bid amount for the item from users, then remove the corresponding tuple (oldAmount, userId) from items, add the new bid information to items, and update the bid amount in users.
For the removeBid(userId, itemId) operation, we first retrieve the user's original bid amount for the item from users, then remove the corresponding tuple (oldAmount, userId) from items, and finally delete the user's bid information for that item from users.
For the getHighestBidder(itemId) operation, we first check if items[itemId] is empty. If it is, we return -1; otherwise, we return the user ID of the last element in the ordered set, which corresponds to the highest bidder.
In terms of time complexity, each operation takes O(log m) time, where m is the number of bids for the current item. The space complexity is O(n), where n is the total number of bids.
class AuctionSystem:
def __init__(self):
self.items = defaultdict(SortedList)
self.users = {}
def addBid(self, userId: int, itemId: int, bidAmount: int) -> None:
if userId not in self.users:
self.users[userId] = {}
if itemId in self.users[userId]:
self.removeBid(userId, itemId)
self.users[userId][itemId] = bidAmount
self.items[itemId].add((bidAmount, userId))
def updateBid(self, userId: int, itemId: int, newAmount: int) -> None:
oldAmount = self.users[userId][itemId]
self.items[itemId].remove((oldAmount, userId))
self.items[itemId].add((newAmount, userId))
self.users[userId][itemId] = newAmount
def removeBid(self, userId: int, itemId: int) -> None:
oldAmount = self.users[userId][itemId]
self.items[itemId].remove((oldAmount, userId))
self.users[userId].pop(itemId)
def getHighestBidder(self, itemId: int) -> int:
ls = self.items[itemId]
return -1 if not ls else ls[-1][1]
# Your AuctionSystem object will be instantiated and called as such:
# obj = AuctionSystem()
# obj.addBid(userId,itemId,bidAmount)
# obj.updateBid(userId,itemId,newAmount)
# obj.removeBid(userId,itemId)
# param_4 = obj.getHighestBidder(itemId)class AuctionSystem {
private final Map<Integer, TreeSet<int[]>> items = new HashMap<>();
private final Map<Integer, Map<Integer, Integer>> users = new HashMap<>();
public AuctionSystem() {
}
public void addBid(int userId, int itemId, int bidAmount) {
users.computeIfAbsent(userId, k -> new HashMap<>());
if (users.get(userId).containsKey(itemId)) {
removeBid(userId, itemId);
}
users.get(userId).put(itemId, bidAmount);
items.computeIfAbsent(itemId, k -> new TreeSet<>(
(a, b) -> a[0] != b[0] ? Integer.compare(a[0], b[0]) : Integer.compare(a[1], b[1])
));
items.get(itemId).add(new int[]{bidAmount, userId});
}
public void updateBid(int userId, int itemId, int newAmount) {
int oldAmount = users.get(userId).get(itemId);
TreeSet<int[]> set = items.get(itemId);
set.remove(new int[]{oldAmount, userId});
set.add(new int[]{newAmount, userId});
users.get(userId).put(itemId, newAmount);
}
public void removeBid(int userId, int itemId) {
int oldAmount = users.get(userId).get(itemId);
TreeSet<int[]> set = items.get(itemId);
set.remove(new int[]{oldAmount, userId});
users.get(userId).remove(itemId);
}
public int getHighestBidder(int itemId) {
TreeSet<int[]> set = items.get(itemId);
if (set == null || set.isEmpty()) {
return -1;
}
return set.last()[1];
}
}
/**
* Your AuctionSystem object will be instantiated and called as such:
* AuctionSystem obj = new AuctionSystem();
* obj.addBid(userId,itemId,bidAmount);
* obj.updateBid(userId,itemId,newAmount);
* obj.removeBid(userId,itemId);
* int param_4 = obj.getHighestBidder(itemId);
*/class AuctionSystem {
unordered_map<int, set<pair<int, int>>> items;
unordered_map<int, unordered_map<int, int>> users;
public:
AuctionSystem() {
}
void addBid(int userId, int itemId, int bidAmount) {
if (users[userId].count(itemId)) {
removeBid(userId, itemId);
}
users[userId][itemId] = bidAmount;
items[itemId].insert({bidAmount, userId});
}
void updateBid(int userId, int itemId, int newAmount) {
int oldAmount = users[userId][itemId];
auto& s = items[itemId];
s.erase({oldAmount, userId});
s.insert({newAmount, userId});
users[userId][itemId] = newAmount;
}
void removeBid(int userId, int itemId) {
int oldAmount = users[userId][itemId];
auto& s = items[itemId];
s.erase({oldAmount, userId});
users[userId].erase(itemId);
}
int getHighestBidder(int itemId) {
auto it = items.find(itemId);
if (it == items.end() || it->second.empty()) {
return -1;
}
return it->second.rbegin()->second;
}
};
/**
* Your AuctionSystem object will be instantiated and called as such:
* AuctionSystem* obj = new AuctionSystem();
* obj->addBid(userId,itemId,bidAmount);
* obj->updateBid(userId,itemId,newAmount);
* obj->removeBid(userId,itemId);
* int param_4 = obj->getHighestBidder(itemId);
*/Complexity analysis
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Brute Force List Scan | O(n) per query | O(n) | Small datasets or quick prototype implementation |
| Hash Table + Heap (Priority Queue) | O(log n) updates, amortized O(log n) retrieval | O(n) | When frequent highest-bid queries are needed with simple priority tracking |
| Hash Table + Ordered Set | O(log n) per operation | O(n) | Best general solution when bids must stay fully ordered with efficient updates |
Frequently asked questions
Is Design Auction System easy or hard?
Design Auction System is typically considered a medium-level problem. The main challenge is selecting the right combination of data structures to support both fast updates and ordered retrieval. Understanding hash tables, heaps, and ordered sets makes the solution straightforward.
Design Auction System Python/Java solution
In Python, the design can be implemented using a dictionary for bid storage and a sorted container or heap for ranking bids. In Java, HashMap combined with TreeSet provides a natural ordered-set implementation. Both maintain O(log n) updates and efficient retrieval of the highest bid.
How to solve Design Auction System in O(log n)?
Store bidder-to-bid mappings in a hash table for constant-time lookup. Maintain a sorted structure like TreeSet or balanced BST containing (bidAmount, bidderId). When a bid changes, remove the old pair from the ordered set and insert the updated one. Each modification costs O(log n) while keeping the highest bid instantly accessible.
What is the best approach for Design Auction System?
The most practical solution uses a hash table combined with an ordered set (balanced binary search tree). The hash table stores the current bid for each bidder, while the ordered set keeps bids sorted by value. This allows bid insertion, update, and removal in O(log n) time while retrieving the highest bidder in O(1) or O(log n) depending on the structure.
Is Design Auction System asked at Google/Amazon/Meta?
Design-style data structure problems involving heaps, ordered sets, and hash tables are common in interviews at companies like Amazon, Google, and Meta. Variants appear in system design or advanced data structure rounds where candidates must support efficient updates and ranking queries.
What data structure is used in Design Auction System?
The key structures are a hash table for fast bidder lookup and an ordered set or heap for maintaining sorted bids. The ordered set approach is often preferred because it supports deletion and reinsertion cleanly while preserving order in O(log n) time.
What is the time complexity of Design Auction System?
Using the optimal hash table plus ordered set design, each operation such as placing, updating, or removing a bid runs in O(log n) time due to tree rebalancing. Lookup of the highest bid is typically O(1) or O(log n). Space complexity is O(n) because all active bids must be stored.
