删除链表的倒数第N个节点(java、python)
1、问题描述
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
进阶:
你能尝试使用一趟扫描实现吗?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list
2、问题分析
首先双重遍历肯定能解决问题,我们来找一下解题规律,设链表长度为m,则要删除的节点位置为m-n+1
当m=5,n=2时,删除第4个节点。
既然这样不妨设置两个指针p,q,且指针的位置距离一直保持相差n个节点,设p的位置为x,则q的位置为x+n+1,显然当p,q指针一直向右移动时,当q指向null(链表尾结点后的空节点)时(x+n+1=m+1),p的位置为m-n,而删除的节点位置为m-n+1,所以要删除的节点为p指针位置的下一个节点,这样一次遍历就能完成。
最好在链表开头加一个虚拟节点,否则删除第一个节点时会有问题,因为删除的是p的下一个节点,这个时候p刚好在虚拟节点位置。
3、代码
java
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode p = new ListNode(0);//虚拟节点
p.next = head;
ListNode q = p;
ListNode first = p; //临时存储虚拟头节点
for(int i=1;i<=n+1;i++){ //循环n+1次使q指针和p指针位置差n个节点
q = q.next;
}
while(q!=null){ //循环遍历整个链表
p = p.next;
q = q.next;
}
ListNode temp = p.next; //要删除的节点
p.next = temp.next; //p的节点指向要删除的节点的下一个节点,达到目的
return first.next; //返回头节点
}
}
python
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
p = ListNode(0)
p.next = head
q = p
first = p
for i in range(n+1):
q = q .next
while(q!=None):
p = p.next
q = q.next
temp = p.next
p.next = temp.next
return first.next