1、解题思路
- 双指针法:使用两个指针,快指针和慢指针,初始时都指向链表的头节点。快指针先移动 n 步,然后快慢指针同时移动,直到快指针到达链表末尾。此时慢指针指向倒数第 n 个节点的前一个节点,删除倒数第 n 个节点即可。
- 特殊情况处理:如果链表长度为 n,即删除头节点,直接返回头节点的下一个节点。
2、代码实现
C++
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* ListNode(int x) : val(x), next(nullptr) {}
* };
*/
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param head ListNode类
* @param n int整型
* @return ListNode类
*/
ListNode* removeNthFromEnd(ListNode* head, int n) {
// write code here
ListNode dummy(0), *fast = &dummy, *slow = &dummy;
dummy.next = head;
// 快指针先移动n步
for (int i = 0; i < n; ++i) {
fast = fast->next;
}
// 快慢指针同时移动,直到快指针到达末尾
while (fast->next != nullptr) {
fast = fast->next;
slow = slow->next;
}
// 删除倒数第n个节点
ListNode* tmp = slow->next;
slow->next = slow->next->next;
delete tmp;
return dummy.next;
}
};
Java
import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* public ListNode(int val) {
* this.val = val;
* }
* }
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param head ListNode类
* @param n int整型
* @return ListNode类
*/
public ListNode removeNthFromEnd (ListNode head, int n) {
// write code here
ListNode dummy = new ListNode(0); // 创建虚拟头节点
dummy.next = head; // 虚拟头节点指向原链表头
ListNode fast = dummy, slow = dummy;
// 快指针先移动n步
for (int i = 0; i < n; ++i) {
fast = fast.next;
}
// 快慢指针同时移动,直到快指针到达末尾
while (fast.next != null) {
fast = fast.next;
slow = slow.next;
}
// 删除倒数第n个节点
slow.next = slow.next.next;
return dummy.next;
}
}
Python
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param head ListNode类
# @param n int整型
# @return ListNode类
#
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
# write code here
dummy = ListNode(0) # 创建虚拟头节点
dummy.next = head # 虚拟头节点指向原链表头
fast = slow = dummy
# 快指针先移动n步
for _ in range(n):
fast = fast.next
# 快慢指针同时移动,直到快指针到达末尾
while fast.next:
fast = fast.next
slow = slow.next
# 删除倒数第n个节点
slow.next = slow.next.next
return dummy.next
3、复杂度分析
- 时间复杂度:O(n),只需遍历链表一次。
- 空间复杂度:O(1),仅使用两个指针。