题目 点击前往
设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。
在链表类中实现这些功能: * get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。 * addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。 * addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。 * addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。 * deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。
示例 1:
1 2 3 4 5 6 7 MyLinkedList linkedList = new MyLinkedList(); linkedList.addAtHead(1); linkedList.addAtTail(3); linkedList.addAtIndex(1,2); //链表变为1-> 2-> 3 linkedList.get(1); //返回2 linkedList.deleteAtIndex(1); //现在链表是1-> 3 linkedList.get(1); //返回3
解题思路
通过阅读题目可以发现经常出现以下几点:链表长度、首部、尾部。所以需要在在MyLinkedList中定义以下变量:
1 2 3 4 5 var MyLinkedList = function ( ) { this ._size = 0 ; this ._head = null ; this ._tail = null ; };
getNode(index)
该方法用于获取指定下标的节点,属于一个通用函数,后续方法中会重复调用这个函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 MyLinkedList .prototype .getNode = function (index ){ if (index < 0 || index >= this ._size ) return null ; let cul = new LinkNode (0 ,this ._head ); while (index-- >=0 ){ cul = cul.next ; } return cul; }
get(index)
根据要求:
获取链表中第 index 个节点的值。
如果索引无效,则返回-1。
1 2 3 4 5 6 MyLinkedList .prototype .get = function (index ) { if (index < 0 || index >= this ._size ) return -1 ; return this .getNode (index).val ; };
addAtHead(val)
在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
同样,需要设置一个虚拟头节点进行操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 MyLinkedList .prototype .addAtHead = function (val ) { const node = new LinkNode (val,this ._head ); this ._head = node; this ._size ++; if (!this ._tail ){ this ._tail = node; } };
addAtTail(val)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 MyLinkedList .prototype .addAtTail = function (val ) { const node = new LinkNode (val,null ); this ._size ++; if (this ._tail ){ this ._tail .next = node; this ._tail = node; return } this ._tail = node; this ._head = node; };
addAtIndex(index,val)
在链表中的第 index 个节点之前添加值为 val 的节点。
如果 index 等于链表的长度,则该节点将附加到链表的末尾。
如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 MyLinkedList .prototype .addAtIndex = function (index, val ) { if (index > this ._size ) return if (index <= 0 ){ this .addAtHead (val); return } if (index == this ._size ){ this .addAtTail (val); return } const node = this .getNode (index-1 ); node.next = new LinkNode (val,node.next ); this ._size ++; };
deleteAtIndex(index)
如果索引 index 有效,则删除链表中的第 index 个节点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 MyLinkedList .prototype .deleteAtIndex = function (index ) { if (index < 0 || index >= this ._size ) return if (index===0 ){ this ._head = this ._head .next ; if (index == this ._size -1 ){ this ._tail = this ._head ; } this ._size --; return ; } const node = this .getNode (index-1 ); node.next = node.next .next ; if (index === this ._size - 1 ){ this ._tail = node } this ._size --; };