返回
:链表中的小妙招:删除倒数第N个节点
前端
2023-09-04 13:27:19
双指针法
双指针法是一种广泛用于链表操作的技巧。它涉及使用两个指针同时遍历链表,一个指针比另一个指针提前N个节点。当后一个指针到达链表的末尾时,前一个指针将位于倒数第N个节点之前。然后,我们可以轻松地删除该节点。
public ListNode removeNthFromEnd(ListNode head, int n) {
// 创建两个指针,一个指向头结点,另一个指向头结点的下一个节点
ListNode slow = head;
ListNode fast = head.next;
// 移动快速指针,使其领先慢指针N个节点
for (int i = 0; i < n; i++) {
fast = fast.next;
}
// 如果快速指针已经到达链表的末尾,则说明要删除的是头结点
if (fast == null) {
return head.next;
}
// 同时移动慢指针和快速指针,直到快速指针到达链表的末尾
while (fast.next != null) {
slow = slow.next;
fast = fast.next;
}
// 删除慢指针指向的节点
slow.next = slow.next.next;
// 返回头结点
return head;
}
递归法
递归法是一种使用函数调用自身来解决问题的技术。它可以用于解决许多不同类型的问题,包括链表操作。在删除链表的倒数第N个节点的问题中,我们可以使用递归函数来遍历链表并找到要删除的节点。
public ListNode removeNthFromEnd(ListNode head, int n) {
// 如果链表为空,则返回空
if (head == null) {
return null;
}
// 计算链表的长度
int length = 0;
ListNode current = head;
while (current != null) {
length++;
current = current.next;
}
// 计算要删除的节点的位置
int index = length - n;
// 使用递归函数删除链表的第index个节点
return removeNthFromEnd(head, index, 0);
}
private ListNode removeNthFromEnd(ListNode head, int index, int currentIndex) {
// 如果当前节点是我们要删除的节点,则返回下一个节点
if (currentIndex == index) {
return head.next;
}
// 继续遍历链表,并递增当前节点的索引
head.next = removeNthFromEnd(head.next, index, currentIndex + 1);
// 返回头结点
return head;
}
时间和空间复杂度
双指针法和递归法的时间复杂度都是O(n),其中n是链表的长度。这是因为这两种方法都需要遍历整个链表一次。空间复杂度都是O(1),因为这两种方法都不需要额外的空间。
结论
在本文中,我们探讨了如何从链表中删除倒数第N个节点。我们介绍了两种解决方案:一种使用双指针,另一种使用递归。我们还详细分析了每种方法,并讨论了其时间和空间复杂度。最后,我们提供了一些额外的技巧和建议,帮助您更好地理解和解决此类问题。