一、解题思路
- 涉及链表的特殊位置,考虑快慢指针
- 要删除链表的节点,先找到它的前驱
二、删除链表的倒数第n个节点
删除链表倒数第n个节点
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
@@@@两种解题思路:
-
推荐
通过快慢指针找到要删除节点的前驱节点,然后删除 -
不推荐
通过坐标:先得到链表的总长度,然后计算得到要删除元素的前驱节点的坐标,最后删除,
注意区分
链表数据结构的特点和数组数据结构的特点,数组偏向于用坐标,链表倾向于用指针
1、 (推荐)快慢指针解题思路:
- 初始时fast和slow 均指向头节点
- 让fast比slow超前 n 个节点
- 然后同时让fast和slow向后移动。当fast移动到链表的末尾(即 fast.next为null)时,slow 恰好指向倒数第 n 个节点的前驱节点
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @param {number} n
* @return {ListNode}
*/
var removeNthFromEnd = function(head, n) {
if(n<=0){return false}
let fast = head
let slow = head
let i = 0
//初始化快慢指针的位置,中间相隔n
while(i<n){
fast = fast.next
i++
}
//结束时fast已到最后一个
//slow此时是倒数第n个节点的前驱节点
while(fast.next){
fast = fast.next
slow = slow.next
}
slow.next = slow.next.next
return head
};
2、坐标法解题思路:
- 循环得到链表的长度(或者将链表转为数组拿到数组长度)
- 计算要删除元素前驱节点的坐标,拿到前驱节点
- 删除
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @param {number} n
* @return {ListNode}
*/
var removeNthFromEnd = function(head, n) {
// 循环得到链表的总长度
let len = getLen(head);
//前驱节点的下标 4-2=2
let preNum = len-n;
let k = 0
let pre = head
//拿到前驱节点
while(k<preNum){
//0-1
pre = pre.next
k++
}
//删除元素
pre.next=pre.next.next
return head
};
//循环得到链表长度
function getLen(head){
let i = 0
while(head.next){
head = head.next
i+=1
}
return i
}
//把链表转为数组拿到链表长度
function getArrLen(head){
let arr = []
while(head){
arr.push(head.val)
head = head.next
}
return arr.length
}