Problem
You run an e-commerce website and want to record the last N
order
ids in a log. Implement a data structure to accomplish this, with the following API:
record(order_id)
: adds the order_id to the logget_last(i)
: gets the ith last element from the log. i is guaranteed to be smaller than or equal to N.
You should be as efficient with time and space as possible.
Examples
Example 1:
Input
["OrderLog(3)", "record", "record", "record", "get_last", "get_last"]
[[3], [10], [20], [30], [1], [2]]
Output
[null, null, null, 1, null, -1, null, -1, 3, 4]
Explanation
OrderLog orderLog = new orderLog(3); // log = []
orderLog.record(10); // log = [10]
orderLog.record(20); // log = [10, 20]
orderLog.record(30); // log = [10, 20, 30]
orderLog.get_last(1); // Retrieves the most recent order ID (30).
orderLog.get_last(2); // Retrieves the second-most recent order ID (20).
Solution
Method 1 - Using Circular Array
We can first define following:
OrderLog
: The class representing the log.N
: The maximum number of order IDs to store.orders
: A circular array to store the order IDs.head
: Index pointing to the oldest order ID in the array.
Record method
First we implement record method.
record(order_id)
: Adds the new order ID to the log.- It updates the
head
index using modulo (%
) to achieve circular behavior within the array. - This ensures that the latest order ID is always stored at the most recently accessed position.
- It updates the
get_last(i)
: Retrieves thei
th last order ID from the log.- It checks for invalid index values.
- It calculates the actual index in the array by considering the
head
position and the requested position (i
). - The modulo operation is used again to handle cases where the requested position might be beyond the beginning of the array (due to the circular nature).
Code
Java
class OrderLog {
private final int N;
private final int[] orders;
private int head; // Index of the oldest order ID
public OrderLog(int N) {
this.N = N;
this.orders = new int[N];
this.head = 0;
}
public void record(int orderId) {
orders[head] = orderId;
head = (head + 1) % N; // Update head using modulo to handle circular behavior
}
public int getLast(int i) {
if (i < 0 || i >= N) {
throw new IllegalArgumentException("Index out of bounds");
}
// Calculate the actual index based on head and requested position
int actualIndex = (head - i - 1 + N) % N;
return orders[actualIndex];
}
}
Python
class OrderLog:
def __init__(self, n):
self.n = n
self.orders = [None] * n # Initialize array with None values
self.head = 0 # Index of the oldest order ID
def record(self, order_id):
self.orders[self.head] = order_id
self.head = (self.head + 1) % self.n # Update head using modulo
def get_last(self, i):
if 0 <= i < self.n:
# Calculate actual index based on head and requested position
actual_index = (self.head - i - 1 + self.n) % self.n
return self.orders[actual_index]
else:
raise IndexError("Index out of bounds")
Complexity
record()
- ⏰ Time complexity:
O(1)
, due to the constant-time array access and update. - 🧺 Space complexity:
O(n)
, as we are storing the elements in array
getLast()
- ⏰ Time complexity:
O(1)
, Runs in constant time (O(1)) as well, because the calculation of the actual index using modulo is also a constant-time operation. - 🧺 Space complexity:
O(n)
, as we are storing the elements in array