方法1 遍历长度
1 先单独遍历一遍链表获取长度
2 算出从头开始第几个节点需要删除
3 删除节点
var removeNthFromEnd = function(head, n) {
let len = 0
// pre始终保持着对head的引用
let pre = new ListNode(null,head)
// cur用来改变链表顺序达到删除的目的
let cur = pre
// 遍历长度,过后head指向null,已经不能再用了
while(head){
head = head.next
len++
}
let pot = len - n
for(let i = 0 ; i < pot ; i++){
cur = cur.next
}
cur.next = cur.next.next
// 注意:由于cur是由pre引用赋值所以他们指向同一内存空间,当cur改变链表顺序的时候
// pre后面的链表顺序也跟着改变,但由于pre的next一直没动,所以pre的位置还是指向开头
return pre.next
};
方法2 快慢指针
其实就是a + b = b + a 的道理
var removeNthFromEnd = function (head, n) {
let x = 0
let pre = new ListNode(null, head)
// 先将head位置指向n
while (x < n) {
head = head.next
x++
}
while(head){
head = head.next
cur = cur.next
}
cur.next = cur.next.next
return pre.next
};
方法3 先进后出栈
先将链表节点依次入栈,出栈的时候就相当于从尾部开始计数
var removeNthFromEnd = function (head, n) {
let pre = new ListNode(null,head)
let stark = []
// 全部入栈
while(cur){
stark.push(cur)
cur = cur.next
}
// 从尾部开始出栈
for(let i = 0 ; i < n ; i++){
stark.pop()
}
let temp = stark[stark.length - 1]
temp.next = temp.next.next
return pre.next
};
方法4 递归
这个递归跟遍历二叉树类似,先递归到底 再从后依次计算位数,到指定位数改变链表位置达到删除的目的
var removeNthFromEnd = function (head, n) {
// 外部变量用于计数
let count = 0
let handle = function(node){
if(!node)return null;
node.next = handle(node.next)
count++;
if(count == n)return node.next
return node
}
return handle(head)
};