題目難度: Medium
原題描述:
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.
題目大意:
給你一條鏈表,要你刪除倒數第n個結點,儘量只遍歷一次鏈表。
解題思路:
這道題是面試的經典題,一般是要你返回這個結點,只不過這題要你刪除而已。解題的思路是設置三個指針,讓第一個指針先走到第n個結點,然後第二個指針和第一個指針一起走,第三個指針指向第二個指針的前一個結點,直到第一個指針走到最後一個結點爲止,此時第二個指針指向的結點爲倒數第n個結點。
雖然題目說了給出的n保證有效,但是我還是加了n小於整條鏈表的長度時的情況的判斷,這點很重要,能保證程序的魯棒性。另外如果鏈表的長度剛好是n時,此時刪除的是頭結點,不能使用第三個指針,並且頭指針要移到下一個結點中。
時間複雜度分析:
掃描一遍鏈表的時間複雜度爲O(n),n爲鏈表的長度,刪除結點操作爲常數時間,可以忽略。因此總的時間複雜度爲O(n)。
以下是代碼:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeNthFromEnd(struct ListNode* head, int n)
{
struct ListNode* p1;
struct ListNode* p2;
struct ListNode* p3;
p1 = p2 = head;
p3 = NULL;
for(int i=1 ; i<=n-1 && p1 ; ++i){
p1 = p1->next;
}
if(!p1){
return head;
}
while(p1->next){
p1 = p1->next;
p3 = p2;
p2 = p2->next;
}
if(!p3){
head = p2->next;
free(p2);
}else if(p3 && p2){
p3->next = p2->next;
free(p2);
}
return head;
}