Problem Statement (Asked By Twitter)
You manage an e-commerce website and need to keep track of the last N
order IDs in a log. Design a data structure that supports the following operations efficiently:
record(order_id)
– Adds the given order_id
to the log.get_last(i)
– Retrieves the i
-th most recent order ID from the log. It is guaranteed that i ≤ N
.Your implementation should optimize both time and space usage.
Problem link: https://leetcode.com/problems/reorder-data-in-log-files/description/
Disclaimer: Try solving the problem on your own first! Use this solution only as a reference to learn and improve.
An array is an ideal data structure for this problem since it allows constant-time indexing.
We can initialize an array of size N and maintain a log of recent orders. When recording new orders:
This ensures that both recording and retrieving orders take O(1) time.
record()
):import java.util.ArrayList; import java.util.List; class Log { private final int capacity; private final List<Integer> log; public Log(int n) { this.capacity = n; this.log = new ArrayList<>(); } public void record(int orderId) { if (log.size() >= capacity) { log.remove(0); // Remove the oldest order (slow operation) } log.add(orderId); } public int getLast(int i) { return log.get(log.size() - i); } public static void main(String[] args) { Log orderLog = new Log(5); orderLog.record(101); orderLog.record(102); orderLog.record(103); orderLog.record(104); orderLog.record(105); orderLog.record(106); // Oldest (101) is removed System.out.println(orderLog.getLast(1)); // Output: 106 System.out.println(orderLog.getLast(3)); // Output: 104 } }
This approach works but record()
takes O(N) time due to shifting elements in ArrayList.remove(0)
.
record()
):class CircularLog { private final int[] log; private final int capacity; private int curIndex; public CircularLog(int n) { this.capacity = n; this.log = new int[n]; this.curIndex = 0; } public void record(int orderId) { log[curIndex] = orderId; // Overwrite the oldest order curIndex = (curIndex + 1) % capacity; // Move index in circular fashion } public int getLast(int i) { int index = (curIndex - i + capacity) % capacity; // Handle negative indices return log[index]; } public static void main(String[] args) { CircularLog orderLog = new CircularLog(5); orderLog.record(101); orderLog.record(102); orderLog.record(103); orderLog.record(104); orderLog.record(105); orderLog.record(106); // Overwrites 101 System.out.println(orderLog.getLast(1)); // Output: 106 System.out.println(orderLog.getLast(3)); // Output: 104 } }
curIndex
, overwriting old values instead of shifting elements.curIndex = (curIndex + 1) % capacity
ensures that we wrap around when reaching the array’s end.index=(curIndex−i+capacity) mod capacity
This prevents negative indices whencurIndex < i
.
Operation | Naïve Approach | Circular Buffer |
---|---|---|
record() | O(N) (due to shifting) | O(1) (direct overwrite) |
getLast(i) | O(1) | O(1) |
Circular Buffer is much more efficient for large N, ensuring constant-time performance.
Did this solution help you understand the concept better? Let me know your thoughts in the comments below! Don’t forget to follow us on Instagram @coderz.py for more DSA tips and solutions to ace your coding interviews.
You are given a stream of elements that is too large to fit into memory.…
The formula for the area of a circle is given by πr². Use the Monte…
Given an integer k and a string s, write a function to determine the length…
There is a staircase with N steps, and you can ascend either 1 step or…
Build an autocomplete system that, given a query string s and a set of possible…
Design a job scheduler that accepts a function f and an integer n. The scheduler…