1. 程式人生 > >【資料結構】連結串列相關練習題:刪除連結串列中重複的節點

【資料結構】連結串列相關練習題:刪除連結串列中重複的節點

  • 題目描述

在一個排序的連結串列中,存在重複的結點,請刪除該連結串列中重複的結點,重複的結點不保留,返回連結串列頭指標。 例如,連結串列1->2->3->3->4->4->5 處理後為 1->2->5。

  • 思路分析

我們可以給定兩個一前一後的指標n1,n2,當兩個指標的val不一樣時,不需要處理,直到一樣時,n1不動,讓第二個指標n2往後走,走到跟n2不相同的地方,把n1和n2之間的數字刪掉,再想辦法把n1和n2連結起來,只要遇到相同的,就又重複前面的邏輯,這裡還有一個問題要注意,就是刪除時,得有它的前一個指標,所以還得有一個指標永遠記錄n1的前一個。

(補充一個簡單的連結串列的去重:如果是有n個3,但是要保留一個時,當兩個指標一樣時,刪掉一個,然後前面的指標繼續指向下一個,一直這樣,兩個指標相同時,刪掉一個,直到連結串列結束)

注意:如果連結串列只有一個節點或者沒有節點的時候,要單獨處理,這裡有一個原則,就是一般情況下,如果你寫的程式碼能正常處理一個節點都沒有的情況就不用判斷,如果不行,就要判斷;還有一個就是,如果你一開始就要動兩個或兩個指標以上的指標,就要單獨處理一下,剩下的不用處理

具體實現程式碼如下:

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead)
    {
        if(pHead==NULL||pHead->next==NULL)
            return pHead;
        struct ListNode* prev=NULL;
        struct ListNode* n1=pHead;
        struct ListNode* n2=n1->next;
        while(n2!=NULL)
        {
            if(n1->val!=n2->val)
            {
                prev=n1;
                n1=n2;
                n2=n2->next;
            }
            else
            {
               while(n2&&n1->val==n2->val) 
               {
                   n2=n2->next;
               }
                if(prev!=NULL)
                {
                    prev->next=n2;
                }
                else
                {
                    pHead=n2;
                }
                //刪除掉重複的節點
                while(n1!=n2)
                {
                    struct ListNode* next=n1->next;
                    free(n1);
                    n1=next;
                }
                n1=n2;
                if(n2)
                    n2=n2->next;
            }
        }
        return pHead;
    }
};