Implement single-tab browser history navigation
Company: Chime
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Technical Screen
Quick Answer: This question evaluates understanding of data structures, stateful API behavior, amortized time complexity, set membership tracking, and edge-case handling for implementing browser-like history navigation in the coding & algorithms domain.
Constraints
- The first operation is always BrowserSession(homepage).
- Urls are non-empty strings; the current page always exists.
- steps may be 0 or negative; non-positive steps must not move the cursor.
- back/forward clamp at the oldest/newest page rather than erroring.
- haveVisited is true for any url ever visited (and the homepage), even after a later visit() drops it from the live forward history.
- Target O(1) amortized time per operation and O(n) space for n total visits.
Examples
Input: (['BrowserSession', 'visit', 'visit', 'visit', 'back', 'back', 'forward', 'visit', 'forward', 'back', 'back'], [['leetcode.com'], ['google.com'], ['facebook.com'], ['youtube.com'], [1], [1], [1], ['linkedin.com'], [2], [2], [7]])
Expected Output: [None, None, None, None, 'facebook.com', 'google.com', 'facebook.com', None, 'linkedin.com', 'google.com', 'leetcode.com']
Explanation: Canonical LeetCode-1472 sequence. After visiting google/facebook/youtube the cursor is at youtube; back(1)->facebook, back(1)->google, forward(1)->facebook, then visit(linkedin) clears the forward history (youtube is gone) and lands on linkedin. forward(2) is clamped to linkedin (newest), back(2)->google, back(7) clamps to the homepage leetcode.com.
Input: (['BrowserSession', 'visit', 'visit', 'haveVisited', 'haveVisited', 'back', 'haveVisited'], [['home.com'], ['a.com'], ['b.com'], ['a.com'], ['z.com'], [1], ['b.com']])
Expected Output: [None, None, None, True, False, 'a.com', True]
Explanation: haveVisited bonus: a.com was visited so it is true; z.com never was so it is false. After back(1) lands on a.com, b.com is still considered visited because the visited set is never shrunk.
Hints
- A dynamic array of urls plus an integer cursor gives O(1) back/forward by just clamping the index — no node rewiring needed. A doubly linked list + cursor is the classic alternative but costs more pointers and worse cache locality for the same asymptotics.
- visit must drop the forward history first: truncate the array to cursor+1, then append. That truncation is what makes 'visit after going back' branch correctly.
- haveVisited can't read the live history (a page can be truncated away), so track every visited url in a separate hash set that you never shrink.
- Clamp steps before moving: back -> max(0, cur - steps), forward -> min(len-1, cur + steps), and treat steps <= 0 as a no-op so the cursor stays put.