刪除從鏈結末端第N個節點 | Medium | LeetCode#19. Remove Nth Node From End of List
題目敘述
題目難度:
Medium
題目敘述: 給定一個 Linked List 的
head
,移除從尾端數來第n
個節點,並返回list
解法
一開始的想法
最直覺的做法就是,先取得 list 長度,再用長度扣掉 n
得到的數字假設是 m
,就要被刪除的就是從首端往後數的第 m
個節點。 刪除節點這部分也很基本,那就是透過一個 pointer 指向要被刪除節點指向的下一個節點位址,在讓待刪除節點的前一個節點指向這個 pointer,最後返回 head
我的解法
1 | /** |
那實際寫code,還是有少考慮到一些 edge case,像是如果要刪除的節點本身就是 head
,這樣就需要將最終回傳的 head
指定為當前 head
的下一個節點,另外就是若只是一個節點的List,那就直接回傳 NULL
即可。其他部分做法就跟剛剛提的一樣。首先讓 ptr
指標走完整個 list,並記錄長度。之後再將 ptr指回 head
。另外這裡也透過一個變數 m
來看從 head
到底要走多少步。
1 | while(ptr!=nullptr && count<m){ |
這段代表讓指標移動到我們要刪除的位置,迴圈跑完後 prev
會移動到刪除節點的前一個節點位置,ptr
會待向帶刪除節點,這裡其實可以將 prev->next
直接指向 ptr->next
就不需要額外的 temp
接著將 ptr
指向 nullptr
並且刪除指標。最後回傳 head
執行結果
其他做法
其他做法處理 edge case 的方式我覺得很值得參考:
1 | ListNode *dummy = new ListNode(0); |
透過一個新的節點,可以保證都會指導鏈結頭部,最後只要回傳 dummy node 的 next
就好
1 | /** |
執行結果
複雜度
時間複雜度
我原本的程式
$O(L)$: 計算長度時需要遍歷 $L$ 個節點,找到待刪除節點最壞狀況也會遍歷 $N$ 個節點,因此會是 $O(N)+O(N) = O(N)$
新的做法
$O(L)$: 前半迴圈走了 $N+1$ 步,後半迴圈執行了 $L-N$ 次,因此執行時間複雜度為 $O(L)$, $L$ 為鏈結長度
空間複雜度
我原本的程式
$O(1)$: 宣告指標,常數級別儲存
新的做法
$O(1)$: 宣告指標跟空節點,常數級別儲存