一、题目描述
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
-
示例:
-
给定一个链表: 1->2->3->4->5, 和 n = 2.
-
当删除了倒数第二个节点后,链表变为 1->2->3->5.
-
-
说明:
给定的 n 保证是有效的。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
}
}
- 进阶:
你能尝试使用一趟扫描实现吗?
二、解题
- 这里首先要明确:
-
单链表的头节点不是以前写过的空节点,里面有元素的存储;
-
题目中规定了n有效,此处可以不再对n进行合法性校验;
-
题目中给的入参是链表的头节点和n,只有这两个参数我们无法判断删除节点是否是头节点,所以还需要拿到链表的长度;
-
链表只有一个节点的情况也要特殊处理;
- 代码
- 单链表
public class TestDemo19 {
class ListNode {
int val;
ListNode next;
public ListNode() {
this.val = -1;
this.next = null;
}
public ListNode(int val) {
this.val = val;
this.next = null;
}
}
public ListNode head;
public TestDemo19() {
head = new ListNode();
}
public void insert(int val) { //头插法
if (this.head.val == -1) {
this.head.val = val;
} else {
ListNode node = new ListNode(val);
node.next = this.head;
this.head = node;
}
}
public void show() {
ListNode head = this.head;
while (head != null) {
System.out.print(head.val + " ");
head = head.next;
}
System.out.println();
}
public void show(ListNode node) { //从node节点处打印链表
ListNode head = node;
while (head != null) {
System.out.print(head.val + " ");
head = head.next;
}
System.out.println();
}
}
- 答案
public static ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(-1); //人为给一个记录位置的头节点
dummy.next = head;
ListNode first = head;
ListNode second = dummy;
int length = 0;
while(first != null) {
length++;
first = first.next;
}
length = length - n;
while (length > 0) {
second = second.next;
length--;
}
second.next = second.next.next;
return dummy.next;
}
- 还有种更简单的方法,只需要遍历链表一次,思路可以在另一篇文章中看到删除倒数第K个节点。
public static ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode cur1 = dummy;
ListNode cur2 = dummy;
while (n > 0) {
cur1 = cur1.next;
n--;
}
while (cur1.next != null) {
cur1 = cur1.next;
cur2 = cur2.next;
}
cur2.next = cur2.next.next;
return dummy.next;
}