LeetCode 热题 HOT 100 Java题解
19. 删除链表的倒数第N个节点
题目:
给定一个链表,删除链表的倒数第
n
n
n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
双指针,一遍遍历
最简单可以想到的方法肯定是遍历一遍记住长度,之后第二次遍历删除倒数第
n
n
n个,但是题目要求如何一次遍历实现,因此使用双指针的办法:让两个指针都指向头部,第一个指针先走
n
n
n步,然后两个指针一起走,当第一个指针到尾部时,第二个指针刚好指向倒数第
n
n
n个。具体实施时,需要第二个指针再慢走一步,指向倒数第
n
n
n个的上一个,这样执行删除操作的时候就可以通过p1.next = p1.next.next;
进行删除了
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode p1 = head, p2 = head;
for (int i = 0; i < n; i++) {
p2 = p2.next;
}
if(p2 == null) return head.next;
while(p2.next != null) {
p1 = p1.next;
p2 = p2.next;
}
p1.next = p1.next.next;
return head;
}
}
这里存在的一个问题是,如果删除的是头节点,需要进行特殊处理,还有一个巧妙的做法是构建一个 d u m m y dummy dummy节点,让它的下一个指向 h e a d head head,这样就不需要进行特殊处理了。
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode p1 = dummy, p2 = dummy;
for (int i = 0; i < n; i++) {
p2 = p2.next;
}
while(p2.next != null) {
p1 = p1.next;
p2 = p2.next;
}
p1.next = p1.next.next;
return dummy.next;
}
}
复杂度分析
-
时间复杂度: O ( n ) O(n) O(n)
一遍遍历复杂度为链表长度 n n n。
-
空间复杂度: O ( 1 ) O(1) O(1)
需要额外常数个变量空间。