【leetcode】刪除連結串列的倒數第N個節點(C語言解答)
阿新 • • 發佈:2018-12-19
題目:
給定一個連結串列,刪除連結串列的倒數第 n 個節點,並且返回連結串列的頭結點。
示例:
給定一個連結串列: 1->2->3->4->5, 和 n = 2. 當刪除了倒數第二個節點後,連結串列變為 1->2->3->5.
說明:
給定的 n 保證是有效的。
進階:
你能嘗試使用一趟掃描實現嗎?
解題思路:
開始的時候,我的想法是:先計算連結串列的長度length,然後通過length和n計算出要刪除的結點是第幾個節點!這是一種解法,但在寫程式時,需要考慮多種特殊情況:1.要刪除的節點如果是頭節點怎麼辦?2.要刪除的節點是尾節點怎麼辦?3.要刪除的節點如果既是頭節點也是尾節點怎麼辦?(連結串列中只有一個節點)
在諸多特殊情況的處理過程中,程式碼逐漸變得複雜、繁瑣、不堪入目:
/** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */ struct ListNode* removeNthFromEnd(struct ListNode* head, int n) { struct ListNode* p; struct ListNode* q; int length=0; int i,j; if(head->next==NULL) return head; p=head->next; while(p){ length++;//計算連結串列長度 p=p->next; } i=length-n;//計算倒數第n個節點是第幾個節點 3 p=head->next; j=0; if(i==-1&&length==0) { head=NULL; return head; } if(i==-1)//如果要刪除的是連結串列的第一個節點 { head->next=p->next; return head; } while(p->next&&j<i-1) { p=p->next;//查詢第i-1個節點 j++; } q=p->next;//q指向第i個節點 if(n==1)//要刪除的是連結串列的最後一個節點 { p->next=NULL; } else { p->next=q->next;//修改連結關係 } free(q); return head; }
一番折騰之後,我明白了雙指標的用法,改進了解題思路:
首先讓指標first指向頭節點,然後讓其向後移動n步,接著讓指標sec指向頭結點,並和first一起向後移動。當first的next指標為NULL時,sec即指向了要刪除節點的前一個節點,接著讓first指向的next指標指向要刪除節點的下一個節點即可。注意如果要刪除的節點是首節點,那麼first向後移動結束時會為NULL,這樣加一個判斷其是否為NULL的條件,若為NULL則返回頭結點的next指標。
用一張圖解釋就是:
C語言解答:
/** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */ struct ListNode* removeNthFromEnd(struct ListNode* head, int n) { struct ListNode* first=head; while(n--!=0) first=first->next; if(!first) return head->next; struct ListNode* sec=head; while(first->next!=NULL){ sec=sec->next; first=first->next; } sec->next=sec->next->next; return head; }