题目链接
题解
// 双向链表
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)
*/