2296. Design a Text Editor

2296. Design A Text Editor #

题目 #

请设计一个带光标的文本编辑器,它可以实现以下功能:

  • 添加:在光标处添加文本。
  • 删除:在光标处删除文本。
  • 移动:将光标往左或往右移动。

当删除文本时,只有光标左边的字符会被删除。光标会留在文本内,即任何时候 0 <= cursor.position <= currentText.length 都成立。

请实现 TextEditor 类:

  • TextEditor() 用空文本初始化对象。
  • void addText(String text)text 添加到光标所在位置。添加完后光标在 text 的右边。
  • int deleteText(int k) 删除光标左边 k 个字符。返回实际删除的字符数目。
  • String cursorLeft(int k) 将光标向左移动 k 次。返回移动后光标左边 min(10, len) 个字符,其中 len 是光标左边的字符数目。
  • String cursorRight(int k) 将光标向右移动 k 次。返回移动后光标左边 min(10, len) 个字符,其中 len 是光标左边的字符数目。

思路 #

代码 #

class TextEditor {
    private class ListNode {
        public char character;
        public ListNode prev;
        public ListNode next;
        
        ListNode (char character, ListNode prev, ListNode next) {
            this.character = character;
            this.prev = prev;
            this.next = next;
        }
    }
    
    private ListNode sentinel;
    /** cursor 是光标指针,(ptr, cursor] 指示 cursor 在内的左侧字符,长度不大于 threshold */
    private ListNode ptr;
    private ListNode cursor;
    private int windowSize;
    private int threshold;
    
    public TextEditor() {
        this.windowSize = 0;
        this.threshold = 10;
        
        this.sentinel = new ListNode('s', null, null);
        this.sentinel.prev = this.sentinel.next = this.sentinel;
        this.ptr = this.sentinel;
        this.cursor = this.sentinel;
    }
    
    public void addText(String text) {
        for (int i=0; i<text.length(); i++) {
            this.cursor.next = new ListNode(text.charAt(i), this.cursor, this.cursor.next);
            this.cursor.next.next.prev = this.cursor.next;
            this.cursor = this.cursor.next;
            
            if (this.windowSize == this.threshold) this.ptr = this.ptr.next;
            else this.windowSize += 1;
        }
    }
    
    public int deleteText(int k) {
        int result = 0;
        
        for (int i=0; i<k & this.windowSize > 0; i++) {
            this.cursor = this.cursor.prev;
            this.cursor.next = this.cursor.next.next;
            this.cursor.next.prev = this.cursor;
            
            if (this.ptr == this.sentinel) this.windowSize -= 1;
            else this.ptr = this.ptr.prev;
            
            result += 1;
        }
        
        return result;
    }
    
    public String cursorLeft(int k) {
        String result = "";
        
        for (int i=0; i<k && this.windowSize > 0; i++) {
            this.cursor = this.cursor.prev;
            
            if (this.ptr == this.sentinel) this.windowSize -= 1;
            else this.ptr = this.ptr.prev;
        }
        
        ListNode node = this.ptr;
        while (node != this.cursor) {
            node = node.next;
            result += String.valueOf(node.character);
        }
        
        return result;
    }
    
    public String cursorRight(int k) {
        String result = "";
        
        for (int i=0; i<k && this.cursor.next != this.sentinel; i++) {
            this.cursor = this.cursor.next;
            
            if (this.windowSize == this.threshold) this.ptr = this.ptr.next;
            else this.windowSize += 1;
        }
        
        ListNode node = this.ptr;
        while (node != this.cursor) {
            node = node.next;
            result += String.valueOf(node.character);
        }
        
        return result;
    }
}