diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 3ff7807d..6bc88b9e 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -338,6 +338,7 @@ export default { { text: '977-有序数组的平方', link: '/algorithm/LeetCode刷题/977-有序数组的平方' }, { text: '209-长度最小的子数组', link: '/algorithm/LeetCode刷题/209-长度最小的子数组' }, { text: '203-移除链表元素', link: '/algorithm/LeetCode刷题/203-移除链表元素' }, + { text: '707-设计链表', link: '/algorithm/LeetCode刷题/707-设计链表' }, ] } ], diff --git "a/docs/algorithm/LeetCode\345\210\267\351\242\230/707-\350\256\276\350\256\241\351\223\276\350\241\250.md" "b/docs/algorithm/LeetCode\345\210\267\351\242\230/707-\350\256\276\350\256\241\351\223\276\350\241\250.md" new file mode 100644 index 00000000..f9a2de3c --- /dev/null +++ "b/docs/algorithm/LeetCode\345\210\267\351\242\230/707-\350\256\276\350\256\241\351\223\276\350\241\250.md" @@ -0,0 +1,183 @@ +--- +layout: doc +--- + +# 707-设计链表 + +标签: + +## 题目信息 + +**题目地址**: [707. 设计链表](https://leetcode.cn/problems/design-linked-list/description/) + +**题目内容:** + +```javascript +你可以选择使用单链表或者双链表,设计并实现自己的链表。 + +单链表中的节点应该具备两个属性:val和next。val是当前节点的值,next是指向下一个节点的指针/引用。 + +如果是双向链表,则还需要属性prev以指示链表中的上一个节点。假设链表中的所有节点下标从0开始。 + +实现MyLinkedList类: + +MyLinkedList() 初始化MyLinkedList对象。 +int get(int index) 获取链表中下标为 index 的节点的值。如果下标无效,则返回 -1 。 +void addAtHead(int val) 将一个值为 val 的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。 +void addAtTail(int val) 将一个值为 val 的节点追加到链表中作为链表的最后一个元素。 +void addAtIndex(int index, int val) 将一个值为 val 的节点插入到链表中下标为 index 的节点之前。如果 index 等于链表的长度,那么该节点会被追加到链表的末尾。如果 index 比长度更大,该节点将 不会插入 到链表中。 +void deleteAtIndex(int index) 如果下标有效,则删除链表中下标为 index 的节点。 + +示例: + 输入 + ["MyLinkedList", "addAtHead", "addAtTail", "addAtIndex", "get", "deleteAtIndex", "get"] + [[], [1], [3], [1, 2], [1], [1], [1]] + 输出 + [null, null, null, null, 2, null, 3] + +解释 + MyLinkedList myLinkedList = new MyLinkedList(); + myLinkedList.addAtHead(1); + myLinkedList.addAtTail(3); + myLinkedList.addAtIndex(1, 2); // 链表变为 1->2->3 + myLinkedList.get(1); // 返回 2 + myLinkedList.deleteAtIndex(1); // 现在,链表变为 1->3 + myLinkedList.get(1); // 返回 3 + +提示: + 0 <= index, val <= 1000 + 请不要使用内置的LinkedList库。 + 调用get、addAtHead、addAtTail、addAtIndex 和 deleteAtIndex的次数不超过2000。 +``` + +## 题解 + +### 解法一 + +**思路:** + +> 主要注意的是边界处理,在遍历的时候如何取值 +> +> 实现中全部使用了`虚拟头节点dummyHead`,确保逻辑统一 + +**代码实现:** + +```javascript + +function ListNode(val, next) { + this.val = (val === undefined ? 0 : val) + this.next = (next === undefined ? null : next) +} + +var MyLinkedList = function() { + this.size = 0 + this.head = new ListNode(0, null) +}; + +/** + * @param {number} index + * @return {number} + */ +MyLinkedList.prototype.get = function(index) { + // 检索index的合法性 + if(index < 0 || index >= this.size) return -1 + // 使用虚拟头节点 保证找的到index值是cur.next + const dummyHead = new ListNode(0, this.head) + let curNode = dummyHead + while(index--) { + curNode = curNode.next + } + return curNode.next.val +}; + +/** + * @param {number} val + * @return {void} + */ +MyLinkedList.prototype.addAtHead = function(val) { + const newNode = new ListNode(val, null) + newNode.next = this.head + this.head = newNode + this.size++ + // 如果头部也是尾部元素的话 需要额外处理下 + if(this.size === 1) { + this.head.next = null + } +}; + +/** + * @param {number} val + * @return {void} + */ +MyLinkedList.prototype.addAtTail = function(val) { + const dummyHead = new ListNode(0, this.head) + let curNode = dummyHead + // 找到最后一个元素:while循环截止后,curNode此时就指向最后一个元素,curNode.next就是要插入的位置 + while(curNode.next !== null) { + curNode = curNode.next + } + const newNode = new ListNode(val, null) + curNode.next = newNode + this.size++ + // 如果头部也是尾部元素的话 需要额外处理下 + if(this.size === 1) { + this.head = newNode + } +}; + +/** + * @param {number} index + * @param {number} val + * @return {void} + */ +MyLinkedList.prototype.addAtIndex = function(index, val) { + // 检索index的合法性 + if(index > this.size) return + if(index === 0) { + this.addAtHead(val) + return + } + if(index === this.size) { + this.addAtTail(val) + return + } + // 要插入索引为index的位置 就要先找到index位置前面的节点 + // 使用虚拟头节点保证index位置是curNode.next 指向的位置 + const dummyHead = new ListNode(0, this.head) + let curNode = dummyHead + while(index--) { + curNode = curNode.next + } + const newNode = new ListNode(val, null) + newNode.next = curNode.next + curNode.next = newNode + this.size++ +}; + +/** + * @param {number} index + * @return {void} + */ +MyLinkedList.prototype.deleteAtIndex = function(index) { + if(index < 0 || index >= this.size) return + const dummyHead = new ListNode(0, this.head) + // 使用虚拟头节点保证index位置是curNode.next指向的位置 + let curNode = dummyHead + while(index--) { + curNode = curNode.next + } + curNode.next = curNode.next.next + this.head = dummyHead.next + this.size-- +}; + +/** + * Your MyLinkedList object will be instantiated and called as such: + * var obj = new MyLinkedList() + * var param_1 = obj.get(index) + * obj.addAtHead(val) + * obj.addAtTail(val) + * obj.addAtIndex(index,val) + * obj.deleteAtIndex(index) + */ +``` \ No newline at end of file