leetcode19.删除链表的倒数第N个节点
- 1 题目
- 2 思路
- 3 代码
- 3.1 C++版本
- 3.2 C版本
- 3.3 Java版本
- 3.4 JavaScript版本
- 4 总结
1 题目
题源链接
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
示例 1:
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
示例 2:
输入:head = [1], n = 1
输出:[]
示例 3:
输入:head = [1,2], n = 1
输出:[1]
提示:
链表中结点的数目为 sz
1 <= sz <= 30
0 <= Node.val <= 100
1 <= n <= sz
2 思路
双指针的经典应用,如果要删除倒数第n个节点,让fast移动n步,然后让fast和slow同时移动,直到fast指向链表末尾。删掉slow所指向的节点就可以了。
快慢指针法:
定义fast指针和slow指针,还是和以前一样,添加虚拟头结点,链表:听说添加虚拟头结点会更方便噢
接下来举一个例子,删除倒数第n个结点,n举例为3:
3 代码
3.1 C++版本
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode* slow = dummyHead;
ListNode* fast = dummyHead;
while(n-- && fast != NULL) {
fast = fast->next;
}
fast = fast->next; // fast再提前走一步,因为需要让slow指向删除节点的上一个节点
while (fast != NULL) {
fast = fast->next;
slow = slow->next;
}
slow->next = slow->next->next;
// ListNode *tmp = slow->next; C++释放内存的逻辑
// slow->next = tmp->next;
// delete nth;
return dummyHead->next;
}
};
3.2 C版本
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
//快慢指针法
//定义虚拟头结点
struct ListNode *fakeHead = (struct ListNode*)malloc(sizeof(struct ListNode));
fakeHead->next = head;
struct ListNode *fast = head, *slow = fakeHead; //定义快慢指针
while (n--) fast = fast->next;
while (fast) {
fast = fast->next;
slow = slow->next;//遍历到fast为空时,slow实际是指向待删结点前一个结点
}
struct ListNode * temp = slow->next; //temp指向待删结点
slow->next = temp->next;
free(temp);
return fakeHead->next;
}
3.3 Java版本
public ListNode removeNthFromEnd(ListNode head, int n){
ListNode dummyNode = new ListNode(0);
dummyNode.next = head;
ListNode fastIndex = dummyNode;
ListNode slowIndex = dummyNode;
//只要快慢指针相差 n 个结点即可
for (int i = 0; i < n ; i++){
fastIndex = fastIndex.next;
}
while (fastIndex.next != null){
fastIndex = fastIndex.next;
slowIndex = slowIndex.next;
}
//此时 slowIndex 的位置就是待删除元素的前一个位置。
//具体情况可自己画一个链表长度为 3 的图来模拟代码来理解
slowIndex.next = slowIndex.next.next;
return dummyNode.next;
}
3.4 JavaScript版本
/**
* @param {ListNode} head
* @param {number} n
* @return {ListNode}
*/
var removeNthFromEnd = function(head, n) {
let ret = new ListNode(0, head),
slow = fast = ret;
while(n--) fast = fast.next;
while (fast.next !== null) {
fast = fast.next;
slow = slow.next
};
slow.next = slow.next.next;
return ret.next;
};
4 总结
双指针的经典应用,如果要删除倒数第n个节点,让fast移动n步,然后让fast和slow同时移动,直到fast指向链表末尾。删掉slow所指向的节点就可以了。
这类的题,做会一道之后要学会类比运用,真正掌握这个思想。
By–Suki 2023/1/12