给你一个链表,删除链表的倒数第 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
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list/
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
感谢labuladong的单链表的六大解题套路,你都见过么?,力扣官方题解的删除链表的倒数第N个节点
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
// return removeNthFromEndI(head, n);
// return removeNthFromEndII(head, n);
return removeNthFromEndIII(head, n);
}
//方法三:使用栈
//遍历链表时,同时将所有节点入栈。这样弹出的第n个节点就是需要删除的节点,并且此时栈顶元素就是待删除节点的前驱节点。
//时间复杂度O(L),空间复杂度O(L)
private ListNode removeNthFromEndIII(ListNode head, int n) {
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode p = dummy;
Stack<ListNode> stack = new Stack<>();
while (p != null) {
stack.push(p);
p = p.next;
}
for (int i = 0; i < n; i++) {
stack.pop();
}
//待删除节点的前驱节点
ListNode prev = stack.peek();
prev.next = prev.next.next;
return dummy.next;
}
//方法二:快慢指针
//首先需要找到链表倒数第k个节点,这里定义两个指针p1和p2均指向链表头部。
//先让指针p1走k步,假设链表的总长度为n,此时p1还剩n-k步走到链表末尾的空指针
//接着让p1和p2同时走,直到p1走到链表尾部,此时指针p2则指向了第n-k个节点,即倒数第k个节点
//本题只要找到第n+1个节点,然后删除第n个节点即可。
//时间复杂度O(L),空间复杂度O(1)
private ListNode removeNthFromEndII(ListNode head, int n) {
if (head == null) {
return null;
}
//因为head有可能被删,虚拟头节点才会永远指向真正的头节点
ListNode dummy = new ListNode(-1);
dummy.next = head;
//找到倒数第n+1个节点
ListNode node = findFromEnd(dummy, n + 1);
node.next = node.next.next;
return dummy.next;
}
private ListNode findFromEnd(ListNode head, int k) {
ListNode p1 = head;
//p1先走k步
for (int i = 0; i < k; i++) {
p1 = p1.next;
}
ListNode p2 = head;
//p1和p2同时走n-k步
while (p1 != null) {
p1 = p1.next;
p2 = p2.next;
}
return p2;
}
//方法一:两次遍历
//先遍历一次求出链表的长度len,然后再遍历一次求出第len-n+1的前一个节点,删除改节点的指向
//时间复杂度O(L),空间复杂度O(1)
private ListNode removeNthFromEndI(ListNode head, int n) {
if (head == null) {
return null;
}
int len = getLength(head);
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode p = dummy;
//找出倒数第n+1个节点
for (int i = 1; i < len - n + 1; i++) {
p = p.next;
}
p.next = p.next.next;
return dummy.next;
}
private int getLength(ListNode head) {
int len = 0;
while (head != null) {
len++;
head = head.next;
}
return len;
}
}