题意:
在链表类中实现这些功能:
- get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。
- addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
- addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
- addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
- deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。
示例:
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
思路:
- 我们在设计上面的方法中,常常要通过索引获取节点,所以我们可以创建一个getNode()的函数
- getNode(): 因为我们在后面需要删除节点,删除节点就涉及到删除头节点,而链表的删除都是通过当前节点的上一个节点的next来删除的,我们就需要写一段独立的逻辑来删除头节点。设置虚拟头节点就可以规避这个问题。
MyLinkedList.prototype.getNode = function(index){
if(index<0 || index>=this._size) return null
let cur = new LinkNode(0,this._head)
while(index-- >= 0){//先判断index是否大于等于0,再--
cur = cur.next//遍历到index
}
return cur
}
- get(index): 通过获取节点的val值即可
MyLinkedList.prototype.get = function(index) {
if(index<0 || index>=this._size) return -1
return this.getNode(index).val
};
- addAtHead: 分两种情况,一种是为空链表,则头节点和尾节点都指向新加入的node,另一种不为空链表,则创建一个新节点node,让node的next指向原来的头节点,并将node赋值给头节点
MyLinkedList.prototype.addAtHead = function(val) {
const node = new LinkNode(val,this._head)
this._head = node
this._size++
if(!this._tail){
this._tail = node
}
};
- addAtTail: 同样也分两种情况,一种是为空链表,则头节点和尾节点都指向新加入的node,另一种不为空链表,则创建一个新节点node,让this._tail.next指向node节点,再将node节点赋值给this._tail
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: 题目给了三种情况,分别进行实现。可以直接调用前面写过的函数
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: 分为三种情况:删除头节点,删除尾节点,删除链表中某个节点。删除指定索引值的节点,首先就是通过索引值找到这个节点,即调用getNode(index)函数,然后通过node.next = node.next.next删除此节点
MyLinkedList.prototype.deleteAtIndex = function(index) {
if(index<0 || index>=this._size) return
//删除头节点
if(index === 0){
this._head = this._head.next
this._size--
return
}
//删除链表中某一元素节点
const node = this.getNode(index-1)
node.next = node.next.next
//处理尾节点
if(index === this._size-1){
this._tail = node
}
this._size--
};