题目描述
给定一个链表,删除链表的倒数第 n 个节点并返回链表的头指针。
示例
输入:1 -> 2 -> 3 -> 4 -> 5,n = 2
输出:1 -> 2 -> 3 -> 5
解法一:双指针法
思路:
使用双指针法,第一个指针先走 n 步,然后第二个指针和第一个指针一起走,直到第一个指针走到链表尾部,此时第二个指针指向的就是要删除的节点。
具体过程如下:
- 双指针 p1 和 p2,同时指向链表的头部。
- 将 p1 向前移动 n 步。
- 将 p1 和 p2 一起向前移动,直到 p1 走到链表的尾部。
- 删除 p2 指向的节点即可。
时间复杂度为 O ( n ) O(n) O(n),其中 n 是链表的长度。
代码:(双指针法,时间复杂度 O ( n ) O(n) O(n))
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummyHead = new ListNode(0);
dummyHead.next = head;
ListNode p1 = dummyHead, p2 = dummyHead;
for (int i = 0; i < n; i++) {
p1 = p1.next;
}
while (p1.next != null) {
p1 = p1.next;
p2 = p2.next;
}
p2.next = p2.next.next;
return dummyHead.next;
}
}
解法二:栈
思路:
将链表中所有节点入栈,然后弹出第 n 个节点,如果节点存在前驱节点,则更新前驱节点的指向即可。
具体过程如下:
- 使用栈将链表中的所有节点入栈。
- 弹出栈顶的 n 个节点,记录第 n 个节点 node,记录其前驱节点 prev。
- 将 prev 的指向更新为 node 的下一个节点。
时间复杂度为 O ( n ) O(n) O(n),其中 n 是链表的长度。
代码:(栈,时间复杂度 O ( n ) O(n) O(n))
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummyHead = new ListNode(0);
dummyHead.next = head;
Stack<ListNode> stack = new Stack<>();
ListNode cur = dummyHead;
while (cur != null) {
stack.push(cur);
cur = cur.next;
}
for (int i = 0; i < n; i++) {
stack.pop();
}
ListNode prev = stack.peek();
prev.next = prev.next.next;
return dummyHead.next;
}
}