Skip to main content

2296. Text Editor

Design a Text Editor

Think of this cursor as a dividing line:

the left side uses a LIFO stack,

the right side uses a deque that supports insertion and removal at front.

This way, no matter where the cursor moves or how far it slides, characters can be transferred between stack and deque with ease.

Methods to Implement

addText(string text)

Push the entire text onto the left stack.

Time complexity: O(text)O(|\text{text}|)

deleteText(int k)

Delete min(k, len(stack)) characters from the top of left stack.

Actual deletion count to return is min(k, len(stack)).

Time complexity: O(k)O(k)

cursorLeft(int k)

Moving the cursor left by kk positions means our dividing line cuts off some left side characters, so characters near the top of left stack now are characters near the front of right deque.

Pop min(k, len(stack)) characters from the top of left stack one by one, and push each into the front of right deque.

After these pops, go to the top of left stack to slice substring consisting of min(10, len(stack)) characters going leftward from there.

Time complexity: O(k)O(k)

cursorRight(int k)

Moving the cursor right by kk positions means our dividing line cuts off some right side characters, characters near the front of right deque now become characters near the top of left stack.

Pop min(k, len(Deque)) characters from the front of right deque one by one, and push each onto the top of left stack.

After these pops, go to the top of left stack to slice substring consisting of min(10, len(stack)) characters going leftward from there.

Time complexity: O(k)O(k)

Stack Deque_Efficiency

Space complexity: O(n)O(n), where nn is total number of characters on both sides of the cursor.

#include <deque>
#include <string>
#include <vector>
using namespace std;

class TextEditor // LeetCode Q.2296.
{
private:
deque<char> cursorLeftSide, cursorRightSide;

string sliceCursorLeftTail() {
string text = "";

int startIdx = 0;
if (cursorLeftSide.size() > 10)
startIdx += cursorLeftSide.size() - 10;

for (int idx = startIdx; idx < cursorLeftSide.size(); idx++)
text += cursorLeftSide[idx];

return text;
}

public:
TextEditor() {}

void addText(string text) {
for (const auto& letter : text)
cursorLeftSide.push_back(letter);
}

int deleteText(int k) {
int deletionsCount = cursorLeftSide.size();
if (k < deletionsCount)
deletionsCount = k;

while (k > 0 && !cursorLeftSide.empty()) {
cursorLeftSide.pop_back();
k--;
}

return deletionsCount;
}

string cursorLeft(int k) {
while (k > 0 && !cursorLeftSide.empty()) {
char letter = cursorLeftSide.back();
cursorRightSide.push_front(letter);
cursorLeftSide.pop_back();
k--;
}

return sliceCursorLeftTail();
}

string cursorRight(int k) {
while (k > 0 && !cursorRightSide.empty()) {
char letter = cursorRightSide.front();
cursorLeftSide.push_back(letter);
cursorRightSide.pop_front();
k--;
}

return sliceCursorLeftTail();
}
};