描述
给定一个链表,删除链表的倒数第 nn 个节点并返回链表的头指针
例如,
给出的链表为: 1→2→3→4→5, n= 2n=2.
删除了链表的倒数第 n 个节点之后,链表变为1→2→3→5.
备注:
题目保证 nn 一定是有效的
请给出时间复杂度为 O(n) 的算法
解法一:
将链表存入Map中,通过索引快速找到要删除的结点,要注意头尾结点的删除的特殊性
public ListNode removeNthFromEnd (ListNode head, int n) {
// write code here
Map<Integer,ListNode> nodes = new HashMap<>();
ListNode tmp = head;
int idx = 0;
while(tmp != null) {
nodes.put(idx++, tmp);
tmp = tmp.next;
}
// 删除头节点,注意只有一个节点的链表
int idx2Del = idx - n;
if (idx2Del == 0 && idx > 1) {
return nodes.get(1);
} else if (idx2Del == 0) {
return null;
}
ListNode nodePre = nodes.get(idx2Del-1);
// 如果删除的是尾节点
ListNode nodeNext = null;
// 如果不是尾节点
if (n > 1) {
nodeNext = nodes.get(idx2Del+1);
}
nodePre.next = nodeNext;
return nodes.get(0);
}
解法二:
- 1,双指针,先移动fast指针,使其与slow指针相差
n
个结点 - 2,slow最终指向要删除的结点的前一个结点,fast指向尾结点
- 3,临界点的考虑非常重要:只有一个结点,只有两个结点,如果删除的是头结点,如果删除的是尾结点
ListNode slow = head;
ListNode fast = head;
int idx = 0;
while(fast.next != null) {
if (idx++ < n) {
fast = fast.next;
} else {
slow = slow.next;
fast = fast.next;
}
}
// 如果是删除头节点
if (idx + 1 == n) {
return slow.next;
}
// 如果是删除其他节点
slow.next = slow.next.next;
return head;