劍指offer——反轉鏈表

題目:定義一個函數,輸入鏈表的頭結點,反轉該鏈表並輸出反轉後鏈表的頭結點,鏈表結點結構定義如下:

struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
            val(x), next(NULL) {
    }
};

解決與鏈表相關的問題總是有大量的指針操作,而指針操作的代碼總是很容易出錯。很多面試官喜歡出鏈表相關的問題,就是想通過指針操作來考察應聘者的編碼功底。爲了避免出錯,我們最好先進行全面的分析,在實際軟件開發週期中,設計的時間總不會比編碼的時間短。在面試的時候我們不要急於動手寫代碼,而是一開始仔細分析和設計,這將會給面試官留下很好的印象。與其很快的寫出一段漏洞百出的代碼,倒不如仔細分析再寫出魯棒的代碼。

爲了正確的反轉一個鏈表,需要調整鏈表中指針的方向。爲了將調整指針的這個複雜過程分析清楚,我們可以藉助畫圖來直觀的分析,具體圖如下:

反轉前:所示的鏈表 H、I、J 是三個相鄰的結點。

反轉中:經過若干操作,我們已經把結點 H 之前的指針調整完畢,這些節點的next都指向前面一個結點。

我們可以看到,上圖所示的鏈表 I 結點的next指向 H ,此時的鏈表結構爲結點 I 和 J 之間發生斷裂。

不難注意到,由於結點 I 的next指向了它的前一個結點,導致我們無法在鏈表中遍歷到結點 J ,爲了避免鏈表在結點 I 處斷裂,我們需要在調整結點 I 的next之前,把結點 J 保存下來。

也就是說我們在調整結點 I 的next指針時,除了需要知道結點 I 本身,還要知道結點 I 的前一個結點 H ,因爲我們需要把結點 I 的next指向結點 H 。同時,我們還需要保存 I 的下一個節點 J ,以防止鏈表斷裂。

爲此,我們需要定義三個指針,分別指向當前遍歷的結點、它的前一個結點、它的後一個結點。

最後我們試着找到反轉鏈表的頭結點。不難分析出,反轉之後的鏈表的頭結點爲原始鏈表的尾節點。

爲此,我們給出代碼如下:

  ListNode* ReverseList(ListNode* pHead) {
        ListNode* ReversepHead = NULL;
        ListNode* pNode = pHead;
        ListNode* pPrev = NULL;
        while(pHead != NULL)
        {
            ListNode* pNext = pHead->next;
            if(pHead->next == NULL)
                ReversepHead = pHead;
            pHead->next = pPrev;
            pPrev = pHead;
            pHead = pNext;
        }
        return ReversepHead;
    }

發佈了78 篇原創文章 · 獲贊 98 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章