leetcode
leetcode 2001 ~ 2050
设计一个文本编辑器

设计一个文本编辑器

难度:

标签:

题目描述

代码结果

运行时间: 221 ms, 内存: 34.8 MB


/* 
 思路:
 使用Java Stream API来简化某些操作。
 我们将文本编辑器的功能实现为一个类TextEditor,该类有以下成员变量:
 1. StringBuilder text:存储文本内容。
 2. int cursor:表示光标的位置。
 
 构造方法初始化时创建一个空的文本,并将光标置于最开始的位置。 
 方法:
 - addText(String text):在光标处插入文本并更新光标位置。
 - int deleteText(int k):删除光标前的k个字符,返回实际删除的字符数。
 - String cursorLeft(int k):将光标左移k次,并返回光标左侧的10个字符。
 - String cursorRight(int k):将光标右移k次,并返回光标左侧的10个字符。
 */

import java.util.stream.Collectors;

class TextEditor {
    private StringBuilder text;
    private int cursor;

    public TextEditor() {
        text = new StringBuilder();
        cursor = 0;
    }

    public void addText(String textToAdd) {
        text.insert(cursor, textToAdd);
        cursor += textToAdd.length();
    }

    public int deleteText(int k) {
        int deleteCount = Math.min(k, cursor);
        text.delete(cursor - deleteCount, cursor);
        cursor -= deleteCount;
        return deleteCount;
    }

    public String cursorLeft(int k) {
        cursor = Math.max(0, cursor - k);
        return text.substring(Math.max(0, cursor - 10), cursor)
                    .chars()
                    .mapToObj(c -> String.valueOf((char)c))
                    .collect(Collectors.joining());
    }

    public String cursorRight(int k) {
        cursor = Math.min(text.length(), cursor + k);
        return text.substring(Math.max(0, cursor - 10), cursor)
                    .chars()
                    .mapToObj(c -> String.valueOf((char)c))
                    .collect(Collectors.joining());
    }
}

解释

方法:

这个题解使用了两个栈,left和right,来模拟文本编辑器中的光标位置。left栈存储光标左边的所有字符,而right栈存储光标右边的所有字符。当添加文本时,文本被添加到left栈的顶部。当删除文本时,从left栈的顶部移除指定数量的字符。移动光标时,字符会在两个栈之间移动,模拟光标的左右移动。每次操作后,可以通过连接left栈的顶部字符来获取光标左侧的文本。

时间复杂度:

O(k)

空间复杂度:

O(n)

代码细节讲解

🦆
为什么在设计这个文本编辑器时选择使用两个栈来模拟光标的位置而不是使用其他数据结构如链表或数组?
使用两个栈来模拟光标位置的主要原因是操作的简便性和效率。在文本编辑器中,光标操作(如移动光标和删除字符)通常涉及到对光标位置前后的字符进行频繁的添加和删除。使用两个栈,一个存储光标左边的字符,另一个存储光标右边的字符,可以非常方便地实现这些操作。例如,移动光标时只需将字符从一个栈移至另一个栈。如果使用链表,则虽然可以实现相似操作,但在特定位置插入和删除字符可能需要更复杂的指针操作和更高的时间成本。使用数组时,插入和删除操作可能需要大量的元素移动,尤其是在数组中间的操作,效率较低。因此,两个栈的使用在此类应用中提供了既简单又高效的解决方案。
🦆
在实现deleteText方法时,如果删除字符数量k大于left栈的长度,这种情况如何处理?题解中是否考虑了这种边界情况?
题解中已经考虑了这种边界情况。在deleteText方法的实现中,有一个循环会持续从left栈中删除字符,直到删除的字符数达到请求的k个或left栈为空。如果k的值大于left栈的长度,循环会在栈为空时结束。因此,这种情况下会删除left栈中的所有字符,而实际删除的字符数目等于原left栈的长度,这个值会在方法的最后被返回。
🦆
在实现cursorLeft和cursorRight方法时,光标移动的步数k如果大于当前栈的深度,是否有处理机制来确保光标不会移动到无效位置?
是的,题解中已经考虑了这种情况。无论是cursorLeft还是cursorRight方法,都包含一个循环,该循环会持续执行直到移动的步数k为0或相应的栈(left栈或right栈)为空。这意味着如果k的值大于栈的深度,循环会在栈为空时结束,此时不会再有更多的字符可以移动。由此,光标的移动不会超过有效的位置范围。
🦆
在deleteText操作中,返回的是实际删除的字符数目,这一设计有什么特别的意义或用途吗?
返回实际删除的字符数目可以为调用者提供重要的反馈信息。在多种情况下,如编程或编辑应用中,知道实际删除了多少字符可能对于进一步的操作决策或错误处理非常有用。例如,在一个自动化的编辑任务中,程序可能需要确认确切删除了多少字符来决定是否需要进行额外的修改或更新其他相关的数据结构。此外,这也可以帮助调试和验证程序的正确性。

相关问题