給定一個鏈表,刪除鏈表的倒數第n個節點,並且返回鏈表的頭結點。
示例:
給定一個鏈表: 1->2->3->4->5, 和 n = 2.
當刪除了倒數第二個節點後,鏈表變爲 1->2->3->5.
說明:
給定的n保證是有效的
解題思路:
- 因爲是鏈表不能像數組一樣直接定位,所有必須得遍歷。整體思路是讓前面的指針先移動n步,之後前後指針共同移動直到前面的指針到尾部爲止;
- 首先設立預先指針pre,預先指針是一個小技巧,這個套路在鏈表操作中很常見,在第2題中也碰到了;
- 設預先指針pre的下一個節點指向head,設前指針爲start,後指針爲end,二者都等於pre;
- start先向前移動n步;
- 之後start和end共同向前移動,此時二者的距離爲n,當start到尾部時,end的位置恰好爲倒數第n個節點;
- 因爲要刪除該節點,所以要移動到該節點的前一個才能刪除,所以循環結束條件爲start.next != null;
- 刪除後返回pre.next;
- 時間複雜度:O(n)。
代碼實現:
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode pre = new ListNode(0);
pre.next = head;
ListNode start = pre;
ListNode end = pre;
// start節點先後移n爲
while (n != 0) {
start = start.next;
n--;
}
// start end節點同時後移
while (start.next != null) {
start = start.next;
end = end.next;
}
// 最後倒數第N個節點在end節點後一個節點
end.next = end.next.next;
return pre.next;
}
注意:這裏最後返回是pre.next,爲什麼不直接返回head呢,這是因爲head有可能是被刪掉的結點。而pre.next指向的一定是新鏈表的頭指針。
有問題歡迎留言哦
參考:
https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/solution/
https://draw.mdnice.com/algorithm/19.html