本文已参与「新人创作礼」活动,一起开启掘金创作之路。
题目
给你一个链表,删除链表的倒数第
n**个结点,并且返回链表的头结点。
输入: head = [1,2,3,4,5], n = 2
输出: [1,2,3,5]
解题思路
思路一
我们使用双指针的方式进行解决,首先进行处理一下边界的情况,在定义双指针,左侧指针和右侧指针间隔n,左侧的指针下个元素就是我们所要删除的,在定义一个
index变量,用户记录rightPointer走的次数,便于赋值左侧指针
var removeNthFromEnd = function (head, n) {
if(!head){return head}
if(!head.next && n ===1){return null}
let rightPointer = head
let leftPointer = null
let index = 0
while (rightPointer) {
//右侧指针走到了末尾
if (!rightPointer.next) {
//左侧指针再循环一次就是要删除的元素了,因此要删除的元素是head节点
if((n - index) === 1 ){
if(!leftPointer){
return head.next
}
}else {
//左侧指针的下一个就是要删除的元素,并删除
leftPointer.next = leftPointer.next.next
}
}
//右侧指针不断向右移动
rightPointer = rightPointer.next
//记住移动次数
index++
//移动n次后左侧指针开始指向头指针
if (index === n) {
leftPointer = head
}else {
//随着右侧指针移动,左侧指针也不断移动
if (leftPointer) {
leftPointer = leftPointer.next
}
}
}
//如果循环中没有返回,那么头指针就没有变,就返回原来的头指针
return head
}
思路二
加个虚拟头结点,以防止溢出,比如只有5个节点,要求找到倒数第5个,即第一个,那么应该找到倒数第6个。 主程序中,先走的指针是从dummy开始的,找到倒数第N+1个节点
let findFromEnd = (head, n) => {
let p1 = new ListNode;
let p2 = new ListNode;
p1 = head;
for(let i = 0; i < n; i++) {
p1 = p1.next; // 倒数第几个就先走几步
}
p2 = head;
while(p1 !== null) {
p2 = p2.next;
p1 = p1.next;
}
return p2;
}
var removeNthFromEnd = function(head, n) {
let dummy = new ListNode(-1);
dummy.next = head;
let delP = findFromEnd(dummy, n+1); // 从dummy开始
delP.next = delP.next.next;
return dummy.next;
};