19. 删除链表的倒数第 N 个结点
题目
给你一个链表,删除链表的倒数第 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
解题思路
计算链表长度
一种容易想到的方法是,我们首先从头节点开始对链表进行一次遍历,得到链表的长度 L。随后我们再从头节点开始对链表进行一次遍历,当遍历到第 L−n+1 个节点时,它就是我们需要删除的节点。
为了与题目中的 n 保持一致,节点的编号从 1 开始,头节点为编号 1 的节点。
为了方便删除操作,我们可以从哑节点开始遍历 L−n+1 个节点。当遍历到第 L−n+1 个节点时,它的下一个节点就是我们需要删除的节点,这样我们只需要修改一次指针,就能完成删除操作。
该方式比较传统,下方的第二个方法 比较好。
双指针遍历
采取双重遍历肯定是可以解决问题的,但题目要求我们一次遍历解决问题,那我们的思路得发散一下。
我们可以设想假设设定了双指针 p 和 q 的话,当 q 指向末尾的 NULL,p 与 q 之间相隔的元素个数为 n 时,那么删除掉 p 的下一个指针就完成了要求。
- 设置虚拟节点 dummyHead 指向 head
- 设定双指针 p 和 q,初始都指向虚拟节点 dummyHead
- 移动 q,直到 p 与q 之间相隔的元素个数为 n
- 同时移动 p 与 q,直到 q 指向的为 NULL
- 将 p 的下一个节
点指向下下个节点
代码
双指针遍历 代码
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode preNode = new ListNode(-1);
preNode.next = head;
ListNode firstNode = preNode;
ListNode secondNode = firstNode;
for (int i = 0; i < n; i++) {
secondNode = secondNode.next;
}
while (secondNode.next != null) {
firstNode = firstNode.next;
secondNode = secondNode.next;
}
firstNode.next = firstNode.next.next;
return preNode.next;
}
}
原文地址:https://blog.csdn.net/liyunxiangrxm/article/details/140183227
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!