LeetCode 連結串列操作相關(一)
連結串列操作對於我來說是一個相對薄弱的環節,需要好好練習。
一、刪除連結串列中的節點
刪除指定節點這種題目是連結串列的基本操作,本題題目如下:
請編寫一個函式,使其可以刪除某個連結串列中給定的(非末尾)節點,你將只被給定要求被刪除的節點。
現有一個連結串列 -- head = [4,5,1,9],它可以表示為:
4 -> 5 -> 1 -> 9
示例 1:
輸入: head = [4,5,1,9], node = 5 輸出: [4,1,9] 解釋: 給定你連結串列中值為 5 的第二個節點,那麼在呼叫了你的函式之後,該連結串列應變為 4 -> 1 -> 9.
示例 2:
輸入: head = [4,5,1,9], node = 1 輸出: [4,5,9] 解釋: 給定你連結串列中值為 1 的第三個節點,那麼在呼叫了你的函式之後,該連結串列應變為 4 -> 5 -> 9.
說明:
- 連結串列至少包含兩個節點。
- 連結串列中所有節點的值都是唯一的。
- 給定的節點為非末尾節點並且一定是連結串列中的一個有效節點。
- 不要從你的函式中返回任何結果。
思路:看到題目時首先需要找到該指定節點,也就是遍歷找到該節點。其次,考慮找到之後的操作,因為要求是不要返回任何結果,所以直接修改即可,程式碼如下:其中傳入的引數是需要刪除的那個節點的指標。
void deleteNode(ListNode* node) { node->val = node->next->val; node->next = node->next->next; }
二、刪除連結串列的倒數第N個節點
給定一個連結串列,刪除連結串列的倒數第 n 個節點,並且返回連結串列的頭結點。
示例:
給定一個連結串列: 1->2->3->4->5, 和 n = 2. 當刪除了倒數第二個節點後,連結串列變為 1->2->3->5.
說明:
給定的 n 保證是有效的。
進階:
你能嘗試使用一趟掃描實現嗎?
解題思路:我的最初想法是首先遍歷一遍找到連結串列中一共有多少個節點,再根據N很容易得出是哪個節點需要刪除。但是看到題目中要求是一遍掃描實現,這樣的話就需要換個思路。
我們需要兩個指標,第一個指標指向連結串列的頭部,第二個指標指向第N個節點,兩個節點同時向後遍歷,直到第二個節點指向連結串列的尾部時,第一個節點就指向了連結串列的倒數第N個節點,這就巧妙地找到了指定節點。接下來再進行刪除操作即可:
程式碼如下:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* first=head;
while(n--!=0)
first=first->next;
if(!first)
return head->next;
ListNode* sec=head;
while(first->next!=NULL){
sec=sec->next;
first=first->next;
}
sec->next=sec->next->next;
return head;
}
需要注意的是若需要刪除的節點是頭結點的話我們只需要將連結串列的頭部向後移動一位即可。
三、
反轉一個單鏈表。
示例:
輸入: 1->2->3->4->5->NULL 輸出: 5->4->3->2->1->NULL
進階: 你可以迭代或遞迴地反轉連結串列。你能否用兩種方法解決這道題?
思路:由於自己對連結串列的不熟悉,看到這個題目時並沒有想到很好的辦法。只能百度參考了其他人的答案。
假設我們對V進行反轉操作,那麼本來V指向W,則反轉之後V指向U,這時W就無法再訪問到了,也就是產生了斷鏈現象,為了避免斷鏈,我們需要在指標轉向之前先將下一個節點儲存下來。因此我們需要三個節點來進行操作,程式碼如下:
ListNode* ReverseList(ListNode* pHead)
{
ListNode* pReversedHead = NULL;
ListNode* pNode = pHead;
ListNode* pPrev = NULL;
while(pNode != NULL)
{
ListNode* pNext = pNode->m_pNext;
if(pNext == NULL)
pReversedHead = pNode;
pNode->m_pNext = pPrev;
pPrev = pNode;
pNode = pNext;
}
return pReversedHead;
}
以上程式碼都是參考其他網友的回答,還需要對連結串列認真理解和學習。