题目描述
你可以选择使用单链表或者双链表,设计并实现自己的链表。
单链表中的节点应该具备两个属性: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 的节点。
思路(采用虚拟头结点)
获取链表中的下标为index的节点的值
- 先找到index-1的节点
- 返回第index个节点的值
伪代码
cur=virtualNode;
while(index){
cur=cur.next;
index--;
}
return cur.next.val;
链表头插入节点
- 将新节点的next指向head
- 虚拟头结点的next指向newNode
伪代码
newNode.next=virtualNode.next;
virtualNode.next=newNode;
链表尾插入节点
- 找到尾部节点
- 尾部结点的next指向newNode
- newNode的next 指向null
伪代码
while(cur.next!=null){
cur=cur.next;
}
cur.next=newNode;
第n个节点前插入节点
- 找到尾第n-1个节点
- n-1个节点的next指向newNode,newNode的next指向第n个节点
伪代码
cur=virtualNode;
while(n){
curcur.next;
n--;
}
newNode.next=cur.next;
cur.next=newNode;
删除第n个节点
- 找到第n-1个节点
- n-1个节点的next指向n-1个节点的next的next
伪代码
cur=virtualNode;
while(n){
curcur.next;
n--;
}
cur.next=cur.next.next;
完整代码
var MyLinkedList = function() {
this.size=0;
this.head=null;
};
/**
* @param {number} index
* @return {number}
*/
MyLinkedList.prototype.get = function(index) {
if(index<0||index>=this.size){
return -1;
}
var virtualNode=new ListNode("");
virtualNode.next=this.head;
var cur=virtualNode;
while(index){
cur=cur.next;
index--;
}
return cur.next.val;
};
/**
* @param {number} val
* @return {void}
*/
MyLinkedList.prototype.addAtHead = function(val) {
var virtualNode=new ListNode("");
virtualNode.next=this.head;
var newNode=new ListNode(val);
newNode.next=virtualNode.next;
virtualNode.next=newNode;
this.head=newNode;
this.size+=1;
};
/**
* @param {number} val
* @return {void}
*/
MyLinkedList.prototype.addAtTail = function(val) {
if(this.size==0){
this.addAtHead(val);
return;
}
var virtualNode=new ListNode("");
virtualNode.next=this.head;
var cur=virtualNode;
while(cur.next!=null){
cur=cur.next;
}
var newNode=new ListNode(val);
cur.next=newNode;
newNode.next=null;
this.size+=1;
};
/**
* @param {number} index
* @param {number} val
* @return {void}
*/
MyLinkedList.prototype.addAtIndex = function(index, val) {
var virtualNode=new ListNode("");
virtualNode.next=this.head;
var cur=virtualNode;
var newNode=new ListNode(val)
if(index==0){
this.addAtHead(val);
return;
}
if(index<0){
this.addAtHead(val);
return;
}
if(index==this.size){
this.addAtTail(val);
return;
}
if(index>this.size){
return;
}
while(index){
cur=cur.next;
index--;
}
newNode.next=cur.next;
cur.next=newNode;
this.size+=1;
};
/**
* @param {number} index
* @return {void}
*/
MyLinkedList.prototype.deleteAtIndex = function(index) {
var virtualNode=new ListNode("");
virtualNode.next=this.head;
var cur=virtualNode;
if(index<0||index>=this.size){
return;
}
if(index==0){
this.head=this.head.next;
}
while(index){
cur=cur.next;
index--;
}
cur.next=cur.next.next;
this.size-=1;
};