题目
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例 :
给定一个链表: 1->2->3->4->5, 和 *n* = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
标签
链表;哑节点;栈
解题思路
方法一:普通遍历
在对链表进行操作时,先统计它的节点个数,再将指针指向待删除的前一个节点,然后进行删除。但同时,我们还需要对头节点进行特殊的判断了。
方法二:哑节点
在对链表进行操作时,一种常用的技巧是添加一个哑节点(dummy node),它的next 指针指向链表的头节点。这样一来,我们就不需要对头节点进行特殊的判断了。
方法三:栈
我们也可以在遍历链表的同时将所有节点依次入栈。根据栈「先进后出」的原则,我们弹出栈的第 n 个节点就是需要删除的节点,并且目前栈顶的节点就是待删除节点的前驱节点。
代码
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
public class Leetcode19_RemoveNthNodeFromEndofList {
public static void main(String[] args) {
ListNode head = new ListNode(1);
head.add(2);
// head.add(3);
// head.add(4);
// head.add(5);
head.print();
Leetcode19_RemoveNthNodeFromEndofList.removeNthFromEnd2(head, 1);
System.out.println();
head.print();
}
//方法一:普通遍历
public static ListNode removeNthFromEnd(ListNode head, int n) {
ListNode node = head;
int size = 0;
//统计节点的个数
while (node != null) {
size++;
node = node.next;
}
if (n <= 0 || n > size) {
return null;
}
ListNode result = head;
//指向要删除的前一个节点
for (int i = 1; i < size - n; i++) {
result = result.next;
}
//result当前指向head,要删除首元素
if (n == size) {
return head.next;
}
// //如果要删除最后一个节点,需特殊考虑边界
// if (n == 1) {
// result.next = result.next.next;
// return head;
// }
else {
//result.next.val = result.next.next.val;
result.next = result.next.next;
}
return head;
}
//方法二:设置哑节点
public static ListNode removeNthFromEnd2(ListNode head, int n) {
ListNode dummy = new ListNode(0, head);
//统计head长度
int size = 0;
ListNode node = head;
while (node != null) {
size++;
node = node.next;
}
ListNode cur = dummy;
//指向要删除的前一个节点
for (int i = 1; i < size - n + 1; i++) {
cur = cur.next;
}
cur.next = cur.next.next;
ListNode ans = dummy.next;
return ans;
}
//方法三:栈
public static ListNode removeNthFromEnd3(ListNode head, int n) {
ListNode dummy = new ListNode(0, head);
Deque<ListNode> stack = new LinkedList<ListNode>();
ListNode cur = dummy;
//压入栈内
while (cur != null) {
stack.push(cur);
cur = cur.next;
}
for (int i = 0; i < n; i++) {
stack.pop();
}
//获取待删除的前驱结点
ListNode prev = stack.peek();
prev.next = prev.next.next;
return dummy.next;
}
}
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/