这是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战
题目
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
示例1
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
示例2
输入:head = [1], n = 1
输出:[]
思路
在链表的数据结构中,想要删除第n个位置上的节点,需分几种情况
-
删除的为头节点,只需将头节点的引用指向头节点的字节点,即
head = head.next -
删除的为中间节点,需要将第
n - 1的位置上节点的子节点引用,指向第n个节点的子节点,即Node(n-1).next = Node(n).next -
删除的为尾节点,需要将第
n - 1的位置上节点的子节点引用指向null
但是需要注意的是,题目要删除的是倒数第 n 个节点,也就是要删除第 len - n 个节点,按照这个思路,可以先遍历一遍计算链表的长度 len,然后遍历链表一次,当达到 len - 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) {
let h = head;
let len = 0;
// 计算链表长度
while(h) {
h = h.next;
len++;
}
// 删除的是头节点
if(len == n) {
head = head.next;
return head;
}
h = head;
// 找到要删除的节点前一个节点
for(let i = 0; i < len - n - 1; i++) {
h = h.next;
}
h.next = h.next.next;
return head;
};
思考
上面的解法,为了计算链表的长度,完整的遍历了一次链表,在找删除节点的前一个节点时,又遍历了一次链表。有没有一种方法只遍历一次,就找到删除节点的前一个节点呢?
双指针: 可以定义两个指针left, right,初始时,两个指针都是指向头节点;但是先让 right 指针走 n 步,然后再让两个指针同时走,当 right 走到链表的最后时,left 指针指向的就是 len - n 个位置上的节点
但是从上述两次遍历的解法中,我们真正需要找到的是第 len - n - 1 个位置上的节点。此时我们可以在头节点之前在加一个空节点,这样双指针拿到的就是 len - n - 1 个位置上的节点,此时进行删除操作,最后再删除头节点,即为题目所求
代码如下
/**
* 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 h = new ListNode(null, head);
// 定义两个指针
let left = h, right = h;
// 右边指针先走
for(let i = 0; i < n; i++) {
right = right.next;
}
// 当right走到最尾
while(right.next) {
right = right.next;
left = left.next;
}
// 删除节点
left.next = left.next.next;
// 删除头节点
h = h.next;
return h;
};
小结
上述双指针的算法,也称为快慢指针,比较适用于链表查找倒数第几个节点的问题
LeetCode 👉 HOT 100 👉 删除链表的倒数第 N 个结点 - 中等题
LeetCode 👉 HOT 100 👉 电话号码的字母组合 - 中等题 ✅
LeetCode 👉 HOT 100 👉 三数之和 - 中等题 ✅
LeetCode 👉 HOT 100 👉 盛最多水的容器 - 中等题 ✅
LeetCode 👉 HOT 100 👉 最长回文子串 - 中等题 ✅
LeetCode 👉 HOT 100 👉 无重复字符的最长子串 - 中等题 ✅