题目
给你一个链表,删除链表的倒数第 n
**个结点,并且返回链表的头结点。
示例 1:
输入: head = [1,2,3,4,5], n = 2
输出: [1,2,3,5]
题解
方式一:双指针 + 虚拟节点
复杂度:O(n)遍历链表
// 找到要删除的节点,链表只能遍历
public ListNode removeNthFromEnd(ListNode head, int n) {
// 虚拟节点,方便删除第一个节点
ListNode dummy = new ListNode();
dummy.next = head;
ListNode slow = dummy;
ListNode fast = dummy;
// 快指针先走n步
for (int i = 0; i < n; i++) {
fast = fast.next;
}
// 快指针走到最后一个节点
while (fast.next != null) {
slow = slow.next;
fast = fast.next;
}
// 此时,slow.next就是要删除的节点
slow.next = slow.next.next;
return dummy.next;
}
方式二:栈
复杂度:O(n),额外多了O(n)的空间——栈
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode();
dummy.next = head;
Deque<ListNode> deque = new LinkedList<>();
ListNode cur = dummy;
// 包括虚拟节点全部入栈
while (cur != null) {
deque.addLast(cur);
cur = cur.next;
}
// 出栈n个元素
for (int i = 0; i < n; i++) {
deque.pollLast();
}
// 此时,栈顶是要删除元素的前一个节点
ListNode pre = deque.getLast();
pre.next = pre.next.next;
return dummy.next;
}
总结
数据结构:栈
算法:双指针