天天看點

LeetCode 第 206 題 反轉連結清單

LeetCode 是著名的練習資料結構與算法的網站,很多學習程式設計的人都在刷上面的題來鞏固和提高自己的資料結構以及算法的能力。同時,該網站的很多資料結構及算法題都是面試中的真題。

我刷過的題目不算多,我準備把我做過的題目再逐漸的整理一下。雖然之前也有整理過,但是基本上是把題目和答案粘貼上就算完事了。這樣做其實并沒有把解題的過程留下,那麼也就既起不到總結的作用,也算不上是分享了。是以,我還是打算認真的整理一下。

我的整理不會按照題目的順序去整理,我隻能是按照我已經完成的題目去整理。今天整理的是第 206 題 “反轉連結清單”。

題目描述

題目直接從 LeetCode 拿來,題目如下:

LeetCode 第 206 題 反轉連結清單

上面的題就是 反轉連結清單 題目的截圖,同時 LeetCode 給出了一個函數的定義,然後要求實作反轉連結清單的函數體。函數定義如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* reverseList(struct ListNode* head){


}           

從函數定義可以看出,它是一個單連結清單,單連結清單的特點是目前結點通過其指針域可以找到下一個結點,而無法通過目前結點找到它的上一個結點。

問題分析

反轉單連結清單的思路還是比較簡單的,關鍵是代碼的實作,我們來簡單的分析一下代碼要完成的功能。

把問題的規模縮小到 3 個結點,情況如下:

1 -> 2 -> 3 -> NULL

反轉連結清單,後的情況如下:

3 -> 2 -> 1 -> NULL

reverseList 的參數 head 指向了連結清單的 1 結點,隻要我們循環周遊整個連結清單,并且讓目前結點的指針指向前一個結點即可。但是單連結清單隻能沿着一個方向進行周遊,無法找到上一個結點。是以,在進行周遊的時候,必須要有兩個指針,一個指針用來指向目前元素、另一個指針用來指向目前元素的上一個元素,兩個指針同時移動,這樣讓目前元素的指針就可以指向上一個元素了。

但是,這樣就會有另外一個問題,目前元素的指針是指向下一個元素的,如果将目前元素的指針指向了上一個元素,那麼目前元素和下一個元素就斷鍊了,也就是無法找到目前元素的下一個元素了。那麼,隻要在目前元素的指針指向上一個元素之前,就先讓另外一個指針指向目前元素的下一個元素,那麼就可以了。

比如,目前元素是 2 結點,指向 2 結點的指針為 cur。指向上一個結點的指針為 per,也就是說 per 指針指向 1 結點。2 結點的下一個結點是 3 結點,在 2 結點的指針指向 1 結點之前,讓 tmp 指向下一個結點。

當然了,思路是這樣的,三個指針的關系也是這樣的,但是實作代碼的時候隻要能維持 3 個指針之間的關系就可以了。

代碼實作

代碼還是比較簡單的,代碼如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */




struct ListNode* reverseList(struct ListNode* head){
    /* 指向第一個結點 */
    struct ListNode *cur = head;
    struct ListNode *per = NULL;
    struct ListNode *tmp = NULL;


    /* 判斷目前結點是否為NULL */
    while (cur) {
        /* 将目前結點儲存到tmp中 */
        tmp = cur;
        /* 目前結點移動到下一個結點 */
        cur = cur->next;
        /* 目前結點的指針指向上一個結點 */
        tmp->next = per;
        /* 上一個結點指向目前結點 */
        per = tmp;
    }


    return per;
}           

送出結果

在寫完 reverseList 函數體後,點選右下角的 “執行代碼”,然後觀察 “輸出” 和 “預期結果” 是否一緻,一緻的話就點選 “送出” 按鈕。點選 “送出” 按鈕後,系統會使用更多的測試用例來測試我們寫的函數體,如果所有的測試用例都通過了,那麼就會給出 “通過” 的字樣,如果沒有通過,會給出失敗的那一組測試用例,我們繼續修改代碼。我們以上代碼 “送出” 以後的截圖如下:

LeetCode 第 206 題 反轉連結清單

我的代碼是否最優,我并不清楚,我也沒有去閱讀别人的代碼和解題思路。如果有不懂的,歡迎給我留言,我們一起讨論。

繼續閱讀