The task is to simulate browser navigation: maintain a history of visited pages and move backward and forward through it. The defining behavior is what happens when you visit a new page from the middle of the history: all forward history is discarded.
Visit pages A, B, C, D, then go back twice to B. Visiting E from there discards C and D for good. The history becomes A, B, E, with nothing to move forward to. This clear-forward-on-visit rule is the core design challenge.
The question becomes: what data structure supports appending, truncating forward entries, and moving a pointer back and forth?
1 <= steps <= 100 -> Steps are small, so a loop that moves the pointer one position at a time is fast enough.5000 calls to visit, back, and forward -> With so few operations, even O(n) work per call is acceptable.Browser history maps directly onto a doubly linked list. Each node stores a URL, and you keep a pointer to the current node. Going back follows the prev pointer, going forward follows the next pointer, and visiting a new page creates a node after the current one and severs everything that came after.
The structure matches the problem one-to-one, but it carries overhead: a node allocation on every visit, pointer bookkeeping, and node-by-node traversal during back and forward.
url, prev, and next fields.current to this node.visit(url), create a new node, set current.next to the new node and the new node's prev to current. Move current to the new node. This automatically discards all forward history because nothing points to the old next chain anymore.back(steps), move current backward by following prev pointers up to steps times, stopping if prev is null.forward(steps), move current forward by following next pointers up to steps times, stopping if next is null.back and forward, O(1) for visit. Back and forward traverse the linked list one node at a time, up to steps nodes. Visit creates one node and updates two pointers.The next approach stores the history in a contiguous array, which replaces node-by-node traversal with index arithmetic and removes per-visit allocations.
Store the URLs in a dynamic array in visit order, with an integer index marking the current page.
Clearing forward history does not require deleting anything. On a visit from the middle of the history, write the new URL at position current + 1 and update a boundary variable, last, that marks the last valid index. Entries beyond last are dead history that back and forward never touch.
Every operation becomes O(1): visit writes one array slot and updates two integers, while back and forward reduce to clamped index arithmetic.
A stale entry beyond last can never be read: forward clamps the index to last, back only decreases it, and visit keeps current <= last by moving them together. A stale slot is either overwritten by a later visit or stays unreachable. This is the same technique as an array-backed stack, where popping decrements a size counter instead of erasing memory.
The clamping also satisfies the "move at most steps" rule without a loop. Requesting 100 steps back from index 2 gives max(0, 2 - 100) = 0, the homepage.
current = 0 and last = 0 (the index of the last valid page).visit(url), increment current by 1. If current equals the array size, append the URL. Otherwise, overwrite the URL at current. Set last = current to invalidate all forward history.back(steps), set current = max(0, current - steps). Return the URL at the new current.forward(steps), set current = min(last, current + steps). Return the URL at the new current.visit, which occasionally triggers an array resize). Visit writes to one array position and updates two integers. Back and forward each do a single subtraction or addition plus a max/min comparison, with no loops or traversals.last, but its size never exceeds the number of visits plus one.