总的来说,203 206比较简单。707,注意一些边界情况的处理。
203.移除链表元素
给你一个链表的头节点 head
和一个整数 val
,请你删除链表中所有满足 Node.val == val
的节点,并返回 新的头节点 。
代码:可能会操作头结点,所以设置一个dummy。
// 链表的定义
function ListNode(val,next){
this.val=(val===undefined ? 0 : val);
this.next=(next===undefined ? null : next);
}
var removeElements = function (head, val) {
let dummy = new ListNode(0,head);
let cur = dummy;
while(cur.next){
if(cur.next.val == val){
cur.next = cur.next.next;
}else{
cur=cur.next;
}
}
return dummy.next;
};
707.设计链表
设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性: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
个节点。
思路:添加一个根据索引返回相应结点的方法,实现类似于数组根据下标直接返回值的操作,还蛮方便的。一些操作可能会引起head结点和tail结点的改变,要重点关注。
function ListNode(val, next) {
this.val = (val === undefined ? 0 : val);
this.next = (next === undefined ? null : next);
}
var MyLinkedList = function () {
this.size = 0;
this.head = null;
this.tail = null;
};
MyLinkedList.prototype.get = function (index) {
if (index >= this.size) return -1;
let cur = this.head;
while (index--) {
cur = cur.next;
}
return cur.val;
}
MyLinkedList.prototype.addAtHead = function (val) {
let node = new ListNode(val);
// 空
if(!this.size){
this.head = node;
this.tail = node;
}else{
node.next = this.head;
this.head = node;
}
this.size++;
};
MyLinkedList.prototype.addAtTail = function (val) {
let node = new ListNode(val);
// 空
if (!this.size) {
this.head = node;
this.tail = node;
} else {
this.tail.next = node;
this.tail = node;
}
this.size++;
};
// 根据索引,返回索引处的节点。
MyLinkedList.prototype.getNode = function(index){
// 已经保证了这个index是有意义的
let cur = this.head;
while(index--){
cur = cur.next;
}
return cur;
}
MyLinkedList.prototype.addAtIndex = function (index, val) {
let node = new ListNode(val);
if(index==this.size) {
this.addAtTail(val);
}else if(index <= 0){
this.addAtHead(val);
}else if(index<this.size){
// 在中间位置插入一个元素.不用进行首尾节点的处理
// 第一步,根据索引找到目标位置(前一个)处的节点
let prev = this.getNode(index-1);
let tmp = prev.next;
prev.next = node;
node.next = tmp;
this.size++;
}
};
MyLinkedList.prototype.deleteAtIndex = function (index) {
if(index<0 || index>=this.size) return;
if(this.size==1){
// 删除的一定是这唯一一个节点
this.head = null;
this.tail = null;
}else if(index>0){
let prev = this.getNode(index-1);
prev.next = prev.next.next;
if(index==this.size-1){
this.tail = prev;
}
}else{
this.head = this.head.next;
}
this.size--;
};
206.反转链表
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
画图模拟操作,辅助做题。
var reverseList = function (head) {
let prev = null;
let cur = head;
while(cur){
let next = cur.next;
cur.next = prev;
prev = cur;
cur = next;
}
return prev;
};