链表5:删除链表的倒数第N个结点(19)

本题如下:(链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list/)

题目:给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

 

 

 

思路:

 

这道题是双指针的经典应用,如果要删除倒数第n个节点,让fast移动n步,然后让fast和slow同时移动,直到fast指向链表末尾。删掉slow所指向的节点就可以了。过程虽然不复杂,但要注意一些细节。

主要分为如下几步:

(1)首先这里推荐使用虚拟头结点,这样方便处理删除实际头结点的逻辑。

(2)定义fast指针和slow指针,初始值为虚拟头结点,如下图所示:

 

(3)fast首先走n + 1步 ,为什么是n+1呢,因为只有这样同时移动的时候slow才能指向删除节点的上一个节点(方便做删除操作),如下图所示:

 

 

(4)fast和slow同时移动,直到fast指向末尾,如下图所示:

 

 (5)删除slow指向的下一个节点,如下图所示:

 

 

 

这样就可以比较清晰地写出如下的C++代码:

 1 class Solution {
 2 public:
 3     ListNode* removeNthFromEnd(ListNode* head, int n) {
 4         ListNode* dummyHead = new ListNode(0);
 5         dummyHead->next = head;
 6         ListNode* slow = dummyHead;
 7         ListNode* fast = dummyHead;
 8         while(n-- && fast != NULL) {
 9             fast = fast->next;
10         }
11         fast = fast->next; // fast再提前走一步,因为需要让slow指向删除节点的上一个节点
12         while (fast != NULL) {
13             fast = fast->next;
14             slow = slow->next;
15         }
16         slow->next = slow->next->next;
17         return dummyHead->next;
18     }
19 };

 

同时给出相应的Java版本:

 1 class Solution {
 2     public ListNode removeNthFromEnd(ListNode head, int n) {
 3         ListNode dummy = new ListNode(-1);
 4         dummy.next = head;
 5 
 6         ListNode slow = dummy;
 7         ListNode fast = dummy;
 8         while (n-- > 0) {
 9             fast = fast.next;
10         }
11         // 记住 待删除节点slow 的上一节点
12         ListNode prev = null;
13         while (fast != null) {
14             prev = slow;
15             slow = slow.next;
16             fast = fast.next;
17         }
18         // 上一节点的next指针绕过 待删除节点slow 直接指向slow的下一节点
19         prev.next = slow.next;
20         // 释放 待删除节点slow 的next指针, 这句删掉也能AC
21         slow.next = null;
22 
23         return dummy.next;
24     }
25 }

 

posted @ 2022-08-11 14:43  Ricentch  阅读(41)  评论(0)    收藏  举报