2296. 设计一个文本编辑器【划水刷题】

题目链接

2296. 设计一个文本编辑器

题解

// 双向链表
class DoubleLinkedList {
    val: string;
    next: DoubleLinkedList | null;
    pre: DoubleLinkedList | null;
    constructor(val?: string, next?: DoubleLinkedList | null, pre?: DoubleLinkedList | null) {
        this.val = val || '';
        this.next = next || null;
        this.pre = pre || null;
    }
}

class TextEditor {
    /**
        首先定一个空的头结点,dummyHead,和一个光标cursoe,其中真正的光标的位置应该在cursor 的右边

        addText可以分解成addChar,然后执行多次,每次addChar实际上是在cursor右边插入了一个字符,注意的是,插入的结点的pre和next指针

        deleteText就是删除从cursor往前数的k个字符,可以分解成deleteChar,每次删除一个,执行k次

        cursorLeft和cursoeRight执行的是类似操作,就是光标指向prev还是next;最后,统计光标左边的10个字符生成一个新的字符串返回

     */
    dummyHead: DoubleLinkedList // 头结点
    cursor: DoubleLinkedList    // 光标
    constructor() {
        // 初始化头结点和光标
        this.dummyHead = new DoubleLinkedList()
        this.cursor = this.dummyHead
    }
    /** 在光标所在处添加文本
     * @params text: 添加的文本
     */
    addText(text: string): void {
        // 记录光标下一个结点
        let cursorNext = this.cursor.next
        // 记录光标位置结点
        let now = this.cursor
        // 将每个字符插入到光标位置结点的右边
        for (let i = 0; text[i]; ++i) {
            //  新建一个结点放在光标位置结点的右边
            now.next = new DoubleLinkedList(text[i])
            //  将新建的结点的pre指向光标位置结点
            now.next.pre = now
            //  将光标位置结点的next指向新建的结点
            now = now.next
        }
        // 将光标位置结点的next指向cursorNext
        now.next = cursorNext
        // 如果cursorNext存在,则将cursorNext的pre指向新建的结点
        if (cursorNext) cursorNext.pre = now
        // 将光标位置结点指向新建的结点
        this.cursor = now
    }

    /** 删除光标所在处的文本
     * @params k: 删除的字符串长度
     */
    deleteText(k: number): number {
        // 记录索引用
        let cnt = 0
        // 如果光标位置结点不等于头结点 且k不为0则进入循环
        while (this.cursor != this.dummyHead && k--) {
            // cnt后移
            ++cnt
            // 将光标位置结点的pre指向光标位置结点的next
            this.cursor.pre.next = this.cursor.next
            // 如果光标位置结点的next存在,则将光标位置结点的next的pre指向光标位置结点的pre
            if (this.cursor.next) {
                this.cursor.next.pre = this.cursor.pre
            }
            // 光标前移
            this.cursor = this.cursor.pre
        }
        // 返回删除的字符数
        return cnt
    }

    /**
     * 获取光标左边的字符串
     * @params n: 字符串长度
     */
    getCursorLeftString(n: number): string {
        // 记录字符串
        let ret = ''
        // 记录光标位置结点
        let now: DoubleLinkedList = this.cursor
        // 如果光标位置结点不等于头结点且n不为0则进入循环
        while (now != this.dummyHead && n--) {
            // 字符串拼接
            ret += now.val
            // 光标前移
            now = now.pre
        }
        // 字符串反转
        return ret.split('').reverse().join('')
    }

    /** 
     * 光标左移
     * @params k: 光标移动的字符串长度
     */
    cursorLeft(k: number): string {
        // 如果光标位置结点不等于头结点且k不为0则进入循环
        while (this.cursor != this.dummyHead && k--) {
            // 光标前移
            this.cursor = this.cursor.pre
        }
        // 返回左面的字符 根据题意最多只要10个
        return this.getCursorLeftString(10)
    }

    /** 光标右移
     * @params k: 光标移动的字符串长度
     */
    cursorRight(k: number): string {
        // 如果光标位置结点不等于头结点且k不为0则进入循环
        while (this.cursor.next && k--) {
            // 光标后移
            this.cursor = this.cursor.next
        }
        // 返回左面的字符 根据题意最多只要10个
        return this.getCursorLeftString(10)
    }
}

/**
 * Your TextEditor object will be instantiated and called as such:
 * var obj = new TextEditor()
 * obj.addText(text)
 * var param_2 = obj.deleteText(k)
 * var param_3 = obj.cursorLeft(k)
 * var param_4 = obj.cursorRight(k)
 */
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值