Description
Design a text editor with a cursor that can do the following:
- Add text to where the cursor is.
- Delete text from where the cursor is (simulating the backspace key).
- Move the cursor either left or right.
When deleting text, only characters to the left of the cursor will be deleted. The cursor will also remain within the actual text and cannot be moved beyond it. More formally, we have that 0 <= cursor.position <= currentText.length always holds.
Implement the TextEditor class:
TextEditor()Initializes the object with empty text.void addText(string text)Appendstextto where the cursor is. The cursor ends to the right oftext.int deleteText(int k)Deleteskcharacters to the left of the cursor. Returns the number of characters actually deleted.string cursorLeft(int k)Moves the cursor to the leftktimes. Returns the lastmin(10, len)characters to the left of the cursor, wherelenis the number of characters to the left of the cursor.string cursorRight(int k)Moves the cursor to the rightktimes. Returns the lastmin(10, len)characters to the left of the cursor, wherelenis the number of characters to the left of the cursor.
Example 1:
Input
["TextEditor", "addText", "deleteText", "addText", "cursorRight", "cursorLeft", "deleteText", "cursorLeft", "cursorRight"]
[[], ["leetcode"], [4], ["practice"], [3], [8], [10], [2], [6]]
Output
[null, null, 4, null, "etpractice", "leet", 4, "", "practi"]
Explanation
TextEditor textEditor = new TextEditor(); // The current text is "|". (The '|' character represents the cursor)
textEditor.addText("leetcode"); // The current text is "leetcode|".
textEditor.deleteText(4); // return 4
// The current text is "leet|".
// 4 characters were deleted.
textEditor.addText("practice"); // The current text is "leetpractice|".
textEditor.cursorRight(3); // return "etpractice"
// The current text is "leetpractice|".
// The cursor cannot be moved beyond the actual text and thus did not move.
// "etpractice" is the last 10 characters to the left of the cursor.
textEditor.cursorLeft(8); // return "leet"
// The current text is "leet|practice".
// "leet" is the last min(10, 4) = 4 characters to the left of the cursor.
textEditor.deleteText(10); // return 4
// The current text is "|practice".
// Only 4 characters were deleted.
textEditor.cursorLeft(2); // return ""
// The current text is "|practice".
// The cursor cannot be moved beyond the actual text and thus did not move.
// "" is the last min(10, 0) = 0 characters to the left of the cursor.
textEditor.cursorRight(6); // return "practi"
// The current text is "practi|ce".
// "practi" is the last min(10, 6) = 6 characters to the left of the cursor.
Constraints:
1 <= text.length, k <= 40textconsists of lowercase English letters.- At most
2 * 104calls in total will be made toaddText,deleteText,cursorLeftandcursorRight.
Follow-up: Could you find a solution with time complexity of O(k) per call?
Solutions
Solution 1: Left and Right Stacks
We can use two stacks, left and right, where the stack left stores the characters to the left of the cursor, and the stack right stores the characters to the right of the cursor.
- When calling the addText method, we push the characters in text onto the left stack one by one. The time complexity is O(|text|).
- When calling the deleteText method, we pop characters from the left stack up to k times. The time complexity is O(k).
- When calling the cursorLeft method, we pop characters from the left stack up to k times, then push the popped characters onto the right stack one by one, and finally return up to 10 characters from the left stack. The time complexity is O(k).
- When calling the cursorRight method, we pop characters from the right stack up to k times, then push the popped characters onto the left stack one by one, and finally return up to 10 characters from the left stack. The time complexity is O(k).
PythonJavaC++GoTypeScriptRust
class TextEditor: def __init__(self): self.left = [] self.right = [] def addText(self, text: str) -> None: self.left.extend(list(text)) def deleteText(self, k: int) -> int: k = min(k, len(self.left)) for _ in range(k): self.left.pop() return k def cursorLeft(self, k: int) -> str: k = min(k, len(self.left)) for _ in range(k): self.right.append(self.left.pop()) return ''.join(self.left[-10:]) def cursorRight(self, k: int) -> str: k = min(k, len(self.right)) for _ in range(k): self.left.append(self.right.pop()) return ''.join(self.left[-10:]) # Your TextEditor object will be instantiated and called as such: # obj = TextEditor() # obj.addText(text) # param_2 = obj.deleteText(k) # param_3 = obj.cursorLeft(k) # param_4 = obj.cursorRight(k)(code-box)
