题目
给你一个链表,删除链表的倒数第 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
**进阶:**你能尝试使用一趟扫描实现吗?
解题
方法一:反转链表
思路
把链表反转,然后删除第 N 个节点,然后再反转回去就行了。
代码
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode reversed = reverse(head);
int count = 1;
ListNode dummy = new ListNode(-1, reversed), prev = dummy;
while (prev != null) {
if (count == n && prev.next != null) {
prev.next = prev.next.next;
break;
}
count++;
prev = prev.next;
}
return reverse(dummy.next);
}
private ListNode reverse(ListNode head) {
ListNode curr = head, newPrev, newNext = null;
while (curr != null) {
newPrev = curr.next;
curr.next = newNext;
newNext = curr;
curr = newPrev;
}
return newNext;
}
}
方法二:双指针 一次扫描
思路
利用 【链表, 优先队列】链表中倒数第k个节点 先找到倒数第 n+1
个节点然后删除它的后继节点即可。
注意:可能要求删除倒数 list.length()
个节点(也就是第一个),所以要维护一个哨兵节点(dummy
)。
代码
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(-1, head);
ListNode fst = dummy, sec = dummy;
while (fst != null) {
fst = fst.next;
if (n > -1) --n;
else sec = sec.next;
}
sec.next = sec.next.next;
return dummy.next;
}
}
class Solution {
ListNode* getFromEnd(ListNode* head, int n) {
ListNode* fst = head, * sec = head;
int cnt = 0;
while (fst) {
fst = fst->next;
if (cnt < n) ++cnt;
else sec = sec->next;
}
return sec;
}
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummy = new ListNode(-1, head);
ListNode* prev = getFromEnd(dummy, n + 1);
prev->next = prev->next->next;
return dummy->next;
}
};
评论区