1. 删除链表中的倒数第N个节点
public class RemoveNthFromEnd19 {
//定义一个单链表
public class ListNode {
int val; //当前节点值
ListNode next; //下一个节点值
//构造方法 初始化当前节点值
ListNode(int x) { val = x; }
}
/**删除链表中倒数第N个节点 方法1:单指针(两次循环)
*时间复杂度 O(n) n:链表长度
* @param head 给定的初始链表
* @param n 要删除的倒数第几个节点
* @return dummy的哑元节点的下一个节点开始的链表
*
* 例:head链表是 1->2->3->4->5(要操作的链表) 删除倒数第2个节点4
* dummy 链表是 0->1->2->3->4->5(在head的基础上加了一个哑元节点0)
* 第一个while循环算出 length=3
* 第二个while循环 first = first.next; 链表指针定位到节点3
* first.next = first.next.next; 将3节点的下一个节点指向改为节点5,相当于删除了节点4
* 返回dummy哑元节点的下一个节点的链表
*/
public ListNode removeNthFromEnd01(ListNode head, int n) {
ListNode dummy = new ListNode(0);
//head和dummmy是同一个链表
dummy.next = head;
//第一个循环:算出正序要更改的节点序号 first链表是中间要操作的链表
int length = 0;
ListNode first = head;
while (first != null) {
length++;
first = first.next;
}
length -= n; //删除倒数第n个节点 等价于删除正序 (lenght - n + 1)个节点
//第二个循环:定位到要删除的节点的前一个节点
//注意:dummy链表的头结点是0,是哑元节点
first = dummy;
while (length > 0) {
length--;
first = first.next;
}
first.next = first.next.next;
return dummy.next;
}
/**删除链表中倒数第N个节点 方法2:双指针(一次循环)
*时间复杂度 O(n) n:链表长度
* @param head 给定的初始链表
* @param n 要删除的倒数第几个节点
* @return dummy的哑元节点的下一个节点开始的链表
*/
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode first = dummy;
ListNode second = dummy;
// 将第一个指针移动到第 (n + 1)节点 使第一个指针和第二个指针间距保持为 n
for (int i = 1; i <= n + 1; i++) {
first = first.next;
}
// 同时移动两个指针 直到第一个指针指向链表结尾null,第二个指针此时要被删除节点的前一个节点处
while (first != null) {
first = first.next;
second = second.next;
}
second.next = second.next.next;
return dummy.next;
}
}
方法1图解 :
方法2图解: