面試題——單鏈錶快速排序

AcWing 1451 單鏈錶快速排序

題目

給定一個單鏈表,請使用快速排序算法對其排序

要求:期望平均時間複雜度爲O(nlogn),期望額外空間複雜度爲O(logn)

思考題: 如果只能改變鏈表結構,不能修改每個節點的val值該如何做呢

數據範圍

鏈表中的所有數大小均在int範圍內,鏈表長度在[0, 10000]

輸入樣例:

[5, 3, 2]

輸出樣例:

[2, 3, 5]

思路

​ 首先我們要思考快排的思想

​ 快排就是選定一個目標值,將比目標值小的都放在左邊,比目標值大的都放在右邊,然後遞歸處理左邊和右邊,最後將三者(還有等於目標值的可能)合併,那在鏈表中如何實現快排呢

​ 很簡單,我們要定義三個鏈表,分別代表left、mid、right,我們設定一個目標值,假設爲int val = head->val,通過遍歷原鏈表,我們將比val小的放在left後,將比val大的放在right後,相等的放在mid後,然後遞歸處理leftright,最後將三者連接即可

​ 這裏需要注意幾個細節,因爲三個鏈表的表頭指針我們後面會用到,所以我們需要一個變量來記錄每個鏈表尾節點的指針:ltail、mtail、rtail,通過這三個指針,我們可以實現向鏈表尾插入數據;在遍歷鏈表結束後,要將三個尾指針指空,否則系統無法判斷鏈表是否結束了,下面是代碼

代碼

class Solution {
public:
    ListNode* quickSortList(ListNode* head) {
        if (!head || !head->next) return head;
        auto left = new ListNode(-1), mid = new ListNode(-1), right = new ListNode(-1);
        auto ltail = left, mtail = mid, rtail = right;
        int val = head->val;
        for (auto p = head; p; p = p->next) {
            if (p->val < val) ltail = ltail->next = p;
            else if (p->val == val) mtail = mtail->next = p;
            else rtail = rtail->next = p;
        }
        ltail->next = rtail->next = mtail->next = NULL;
        left->next = quickSortList(left->next);
        right->next = quickSortList(right->next);
        auto lh = left;
        while (lh->next) lh = lh->next;
        lh->next = mid->next;
        while (lh->next) lh = lh->next;
        lh->next = right->next;
        return left->next;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章