问题:
Given a linked list, remove the nth node from the end of list and return its head.
For example,
Given linked list: 1->2->3->4->5, and n = 2.
After removing the second node from the end, the linked list becomes 1->2->3->5.
Note:
Given n will always be valid.
Try to do this in one pass.
这个问题唯一需要的主要的是:要轮询链表一次,就删除指定的节点。
代码示例:
方案一:
利用Map维护节点下表和节点。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
//只能轮询一次,于是用空间换时间
Map<Integer, ListNode> map = new HashMap<>();
int len = 0;
ListNode temp = head;
while (temp != null) {
++len;
//用map按位置存储节点
map.put(len, temp);
temp = temp.next;
}
if (len >= n) {
int removeIndex = len - n + 1;
//删除头和尾,特殊处理
if (removeIndex - 1 < 1 || removeIndex + 1 > len) {
if (removeIndex - 1 < 1 && removeIndex + 1 > len) {
//单一节点的场景
head = null;
} else if (removeIndex - 1 < 1) {
//删头
head.next = null;
head = map.get(removeIndex + 1);
} else if (removeIndex + 1 > len) {
//删尾
map.get(removeIndex).next = null;
map.get(removeIndex - 1).next = null;
}
} else {
//删除中间的节点
map.get(removeIndex).next = null;
map.get(removeIndex - 1).next = map.get(removeIndex + 1);
}
}
return head;
}
}
方案二:
使用两个下标,让第一个下标领先第二个下标n跳。
然后,第一个下标和第二个下标同时移动。
于是,第一个下标到达最后一个节点时,第二个小标到达倒数第(n+1)个节点。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode first = head;
ListNode second = head;
for (int i = 1; i <= n; ++i) {
first = first.next;
}
//first等于null,说明删除的是第一个节点
if (first == null) {
return second.next;
}
while (first.next != null) {
first = first.next;
second = second.next;
}
second.next = second.next.next;
return head;
}
}