AlgoInsight

DSA problem

Design a Text Editor

HardData Structure DesignPattern: Data Structure Designtop600GoogleAmazonMicrosoftMetaBloomberg

Design a text editor with a cursor that supports four operations: addText(text) inserts text at the current cursor position and shifts the cursor right by text.length. deleteText(k) deletes up to k characters immediately to the left of the cursor and returns the number actually deleted. cursorLeft(k) moves the cursor up to k positions left and returns the last (up to) 10 characters that now lie to the left of the cursor. cursorRight(k) is the mirror, moving the cursor up to k positions right.

A naive implementation using a single string is too slow: every insert and delete in the middle of a string is O(n), which is unacceptable for 2 * 10^5 operations on a string that can grow to 4 * 10^4 characters. The classic trick for "edit at the cursor" is the two-stack model — represent the document as two stacks: left is everything to the left of the cursor (top = nearest to cursor), and right is everything to the right of the cursor (top = nearest to cursor).

In this model, addText(s) is simply pushing the characters of s onto left — O(|s|). deleteText(k) is popping up to k characters off left — O(k) amortized. cursorLeft(k) transfers up to k characters from left to right one at a time, which physically moves the cursor to the left. cursorRight(k) is the mirror — pop from right, push onto left. Each character is moved at most twice between the stacks across the lifetime of a query, so the amortized cost is O(1) per character of motion.

After every cursorLeft / cursorRight we need to return the last (up to) 10 characters left of the cursor. Because left is a stack with the most-recent character at the top, those 10 characters are simply the top 10 of left in their stored order — easy to read in O(10). Both stack-based operations are trivially O(k) per call, but the editor as a whole is O(total operations) — exactly the bound the problem requires.

Examples

Example 1
Input: addText("leetcode"); deleteText(4); addText("practice"); cursorRight(3); cursorLeft(8); deleteText(10); cursorLeft(2); cursorRight(6)
Output: 4, "etpractice", "leet", "", "practi"
Explanation: After addText("leetcode") the document is "leetcode|". deleteText(4) removes 4 chars and returns 4 ("leet|"). addText("practice") -> "leetpractice|". cursorRight(3) hits the end and returns last 10 of left = "etpractice". cursorLeft(8) -> cursor in middle, last 10 left = "leet". deleteText(10) deletes up to 10 to the left, returns 4 (only "leet" was there). cursorLeft(2) returns "" (no chars left of cursor). cursorRight(6) returns "practi".
Example 2
Input: addText("hello"); cursorLeft(3); addText("xy")
Output: — state only
Explanation: After addText("hello"): left=h,e,l,l,o; right=[]. cursorLeft(3): move 3 chars from left to right; left=h,e; right=o,l,l. addText("xy"): left=h,e,x,y; right=o,l,l. Document = "hexy" + "llo" = "hexyllo".
Example 3
Input: deleteText(5) on an empty editor
Output: 0
Explanation: left is empty so nothing is deleted and 0 is returned.

Constraints

4 hints and a full solution walkthrough with step-by-step visualizations are available in the practice editor.

designstackstringdoubly-linked-listsimulation

Browse all DSA problems