diff --git a/problems/0707.设计链表.md b/problems/0707.设计链表.md index ed1726d9..5c72b05a 100644 --- a/problems/0707.设计链表.md +++ b/problems/0707.设计链表.md @@ -1191,6 +1191,160 @@ MyLinkedList.prototype.deleteAtIndex = function(index) { */ ``` +```js +/** + 定义双头节点的结构:同时包含前指针`prev`和后指针next` +*/ +class Node { + constructor(val, prev, next) { + this.val = val + this.prev = prev + this.next = next + } +} + +/** + 双链表:维护 `head` 和 `tail` 两个哨兵节点,这样可以简化对于中间节点的操作 + 并且维护 `size`,使得能够以O(1)时间判断操作是否合法 +*/ +var MyLinkedList = function () { + this.tail = new Node(-1) + this.head = new Node(-1) + this.tail.prev = this.head + this.head.next = this.tail + this.size = 0 +}; + +/** + * 获取在index处节点的值 + * + * @param {number} index + * @return {number} + * + * 时间复杂度: O(n) + * 空间复杂度: O(1) + */ +MyLinkedList.prototype.get = function (index) { + // 当索引超出范围时,返回-1 + if (index > this.size) { + return -1 + } + + let cur = this.head + for (let i = 0; i <= index; i++) { + cur = cur.next + } + + return cur.val +}; + +/** + * 在链表头部添加一个新节点 + * + * @param {number} val + * @return {void} + * + * 时间复杂度: O(1) + * 空间复杂度: O(1) + */ +MyLinkedList.prototype.addAtHead = function (val) { + /** + head <-> [newNode] <-> originNode + */ + this.size++ + const originNode = this.head.next + // 创建新节点,并建立连接 + const newNode = new Node(val, this.head, originNode) + + // 取消原前后结点的连接 + this.head.next = newNode + originNode.prev = newNode +}; + +/** + * 在链表尾部添加一个新节点 + * + * @param {number} val + * @return {void} + * + * 时间复杂度: O(1) + * 空间复杂度: O(1) + */ +MyLinkedList.prototype.addAtTail = function (val) { + /** + originNode <-> [newNode] <-> tail + */ + this.size++ + const originNode = this.tail.prev + + // 创建新节点,并建立连接 + const newNode = new Node(val, originNode, this.tail) + + // 取消原前后结点的连接 + this.tail.prev = newNode + originNode.next = newNode +}; + +/** + * 在指定索引位置前添加一个新节点 + * + * @param {number} index + * @param {number} val + * @return {void} + * + * 时间复杂度: O(n) + * 空间复杂度: O(1) + */ +MyLinkedList.prototype.addAtIndex = function (index, val) { + // 当索引超出范围时,直接返回 + if (index > this.size) { + return + } + this.size++ + + let cur = this.head + for (let i = 0; i < index; i++) { + cur = cur.next + } + + const new_next = cur.next + + // 创建新节点,并建立连接 + const node = new Node(val, cur, new_next) + + // 取消原前后结点的连接 + cur.next = node + new_next.prev = node +}; + +/** + * 删除指定索引位置的节点 + * + * @param {number} index + * @return {void} + * + * 时间复杂度: O(n) + * 空间复杂度: O(1) + */ +MyLinkedList.prototype.deleteAtIndex = function (index) { + // 当索引超出范围时,直接返回 + if (index >= this.size) { + return + } + + this.size-- + let cur = this.head + for (let i = 0; i < index; i++) { + cur = cur.next + } + + const new_next = cur.next.next + // 取消原前后结点的连接 + new_next.prev = cur + cur.next = new_next +}; +``` + ### TypeScript: ```TypeScript