删除链表的倒数第N个节点
1.问题描述
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
进阶:
你能尝试使用一趟扫描实现吗?
2.求解
两次遍历
对于本题,我们并不知道列表的节点数目,我们可以先遍历一遍,拿到节点数length,然后第二次再遍历至length - n的位置,这个位置就是倒数第n个的前一个位置,此时我们让它的next=next.next即可完成目标。
代码如下
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0);
dummy.next = head;
int length = 0;
ListNode first = head;
while (first != null) {
first = first.next;
length++;
}
length = length - n;
first = dummy;
while (length > 0) {
length--;
first = first.next;
}
first.next = first.next.next;
return dummy.next;
}
- 时间复杂度O(n),n为数组长度。
- 空间复杂度O(1),只使用了常数级的额外空间
ps: 一开始的时候设置头指针时候直接使用dummy指向head,然后发现遇到需要删除头部指针时或者只有一个节点时,处理比较麻烦,这里需要注意的是,如果遍历输出带头节点的单链表,带头结点的判断条件是while(head->next!=NULL)。
双指针一次遍历
- 在本题中可以使用双指针,先设置哑节点,定义指针p,和哨兵指针q,通过让哨兵指针先行n+1步(有哑节点存在),让两指针之间保持不变的距离。
- 遍历哨兵指针,同时移动指针p,这样当哨兵指针移动至链表结尾时,指针q所指向的节点即时倒数第n+1个节点,此时令该节点的next指向next.next即可完成目标
代码如下
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode l1 = dummy;
ListNode l2 = dummy;
while (n >= 0){
n--;
l2 = l2.next;
}
while(l2 != null){
l1 = l1.next;
l2 = l2.next;
}
l1.next = l1.next.next;
return dummy.next;
}
- 时间复杂度、空间复杂度不变
ps:这里需要注意的是,虽然使用两个指针只进行了一次遍历,但性能却不会提升,也可以使用哈希结构把整个节点存储下来,然后进行删除操作,但是我试了下,速度并没有很快。
递归
本题中的递归比较容易理解,递、归的脉络比较清晰。
- 首先是递的过程,定义递归函数,每次将当前节点的下个节点传入,判断当前节点是否为
null,若为null即到达临界条件。 - 到达临界条件即,节点遍历完成,开始归来的过程,归来时每次令计数器加一,判断计数器是否等于n,若等于n,则说明咋已经找到第n的节点的前一个节点(计数器从0开始),此时可令该节点的next指向next.next。
- 需要注意的一点是,如果删除的是头节点时,此时会在调用递归函数最后返回的值是n,我们还需要最后判断下返回值是否等于n,若等于,则将头节点的next指针置空
代码如下
/*
执行用时:0 ms, 在所有 Java 提交中击败了100.00% 的用户
内存消耗:36.2 MB, 在所有 Java 提交中击败了79.58% 的用户
*/
public ListNode removeNthFromEnd(ListNode head, int n) {
int index = access(head, n);
if(index == n - 1){
head = head.next;
}
return head;
}
int access(ListNode listNode, int n){
if(listNode.next == null){
return 0;
}
int index = access(listNode.next, n);
if(index == n - 1){
listNode.next = listNode.next.next;
}
return ++index;
}

给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
浙公网安备 33010602011771号