Leetcode 148 Sort List 單鏈表排序

原題鏈接

https://leetcode.com/problems/sort-list/

題目描述

Sort a linked list in O(nlogn) time using constant space complexity.
在O(nlogn)時間複雜度和常數空間複雜度內對單鏈表進行排序。

解題思路

在對數組的排序中,具有O(nlogn)時間複雜度的排序方式是歸併排序快速排序,這裏也嘗試使用此兩種方式。在快速排序時,需要有兩個指針分別從數據首尾向中間結點移動,這對單鏈表來說不很方便。因此這裏首要考慮使用歸併排序的方法。

在歸併排序時,有一個比較關鍵的步驟是找到中間結點,在數組中找中間元素是很容易的,但是鏈表不具有隨機訪問的特性,爲了找到中間結點不得不遍歷整個鏈表,這裏我們使用快慢指針的方法來獲取中間結點,並把鏈表分爲左右均等的兩部分。

算法描述

  1. 找到單鏈表的中間結點,將鏈表分爲兩部分listA/listB
  2. 對listA和listB分別調用歸併排序
  3. 對排序之後的listA和listB進行歸併

代碼 c

/**
 * 單鏈表歸併排序
 */
struct ListNode* sortList(struct ListNode* head) {
    struct ListNode* merge(struct ListNode*, struct ListNode*);

    if (head == NULL || head->next == NULL) return head;

    /* 將鏈表平分爲兩個鏈表 */
    struct ListNode first, *fast = &first, *slow = &first;
    first.next = head;
    while (fast->next && fast->next->next) {
        fast = fast->next->next;
        slow = slow->next;
    }
    struct ListNode* next = slow->next;
    slow->next = NULL;

    /* 對兩個子鏈表分別調用歸併排序 */
    struct ListNode* partOne = sortList(head);
    struct ListNode* partTwo = sortList(next);

    /* 對排好序的子鏈表進行歸併 */
    return merge(partOne, partTwo);
}

/* 歸併 */
struct ListNode* merge(struct ListNode* partOne, struct ListNode* partTwo) {
    struct ListNode *curOne = partOne, *curTwo = partTwo;
    struct ListNode head, *cur = &head;

    while (curOne && curTwo) {
        if (curOne->val < curTwo->val) {
            cur->next = curOne;
            cur = curOne;
            curOne = curOne->next;
        } else {
            cur->next = curTwo;
            cur = curTwo;
            curTwo = curTwo->next;
        }
    }
    while (curOne) {
        cur->next = curOne;
        cur = curOne;
        curOne = curOne->next;
    }
    while (curTwo) {
        cur->next = curTwo;
        cur = curTwo;
        curTwo = curTwo->next;
    }
    cur->next = NULL;

    return head.next;
}

完整代碼https://github.com/Orange1991/leetcode/blob/master/148/c/main.c

運行情況

Language Status Time
c Accept 24ms

2015/8/1

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章