[19].刪除鏈表的倒數第 N 個節點

 


題目

給定一個鏈表,刪除鏈表的倒數第 nn 個節點,並且返回鏈表的頭結點。

示例:

給定一個鏈表: 1->2->3->4->5, 和 n = 2.

當刪除了倒數第二個節點後,鏈表變爲 1->2->3->5.

 


函數原型

C 的函數原型:

struct ListNode* removeNthFromEnd(struct ListNode* head, int n){

}

 


邊界判斷

struct ListNode* removeNthFromEnd(struct ListNode* head, int n){

}

 


算法設計:從前掃一遍,從後掃一遍

思路:先計算鏈表長度(從前掃一遍),再刪除倒數第 n 個結點(從後掃一遍)。

typedef struct ListNode Node;
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
    // 設置一個虛擬頭節點(哨兵)
    Node* H = malloc(sizeof(Node));
    H->next = head;
    
    // 兩個指針跟隨用於刪除
    Node*p = H->next, *pre = H;
    int cnt = 1;
    int i = 1;

    while(p){
        p = p->next;
        cnt++;      // 計算length
    }

    p = H->next;    // 把p拉回去

    while(i<(cnt-n) ){
        pre = p;
        p  = p->next;
        i++;
    }      

    // 循環結束,pre位於要刪除節點的前驅,p在刪除位置
    pre->next = p->next;
    free(p);

    // 釋放哨兵
    Node *ans = H->next;
    free(H), H = NULL;

    return ans;
}
  • 時間複雜度:Θ(n)\Theta(n)
  • 空間複雜度:Θ(1)\Theta(1)
     

算法設計:雙指針

思路:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/solution/chao-jian-ji-shuang-zhi-zhen-fu-tu-jie-by-newpp/

配套編碼:

struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
    struct ListNode *p = head, *q = head;
    
    while(p){
        if(n < 0){ 
        	q = q -> next; 
        }       
        n--;
        p = p -> next;
    }
    
    if(n == 0){ 
    	return head -> next; 
    }
    
    q -> next = q -> next -> next;
    return head;
}
  • 時間複雜度:Θ(n)\Theta(n)
  • 空間複雜度:Θ(1)\Theta(1)
     

算法設計:遞歸

思路:m從後開始統計元素個數,如果等於n,即到達倒數第n個,將當前下一節點指向返回個當前上一節點連接,否則返回當前節點連接 遞歸回溯,來回一次。

int m;
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
     if( head == NULL ){
        m = 0;
        return head;
     }

    head->next = removeNthFromEnd(head->next, n);
    return ++m==n ? head->next : head;
}
  • 時間複雜度:Θ(n)\Theta(n)
  • 空間複雜度:Θ(n)\Theta(n)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章