1. 程式人生 > 其它 >LeetCode 148 排序連結串列

LeetCode 148 排序連結串列

技術標籤:資料結構與演算法連結串列指標演算法leetcode資料結構

給你連結串列的頭結點head,請將其按 升序 排列並返回 排序後的連結串列 。

進階:

你可以在O(nlogn) 時間複雜度和常數級空間複雜度下,對連結串列進行排序嗎?

示例 1:


輸入:head = [4,2,1,3]
輸出:[1,2,3,4]

示例 2:


輸入:head = [-1,5,3,4,0]
輸出:[-1,0,3,4,5]

示例 3:

輸入:head = []
輸出:[]

提示:

連結串列中節點的數目在範圍[0, 5 * 104]內
-105<= Node.val <= 105

解題思路:

自頂向下歸併排序。

對連結串列自頂向下歸併排序的過程如下。

找到連結串列的中點,以中點為分界,將連結串列拆分成兩個子連結串列。尋找連結串列的中點可以使用快慢指標的做法,快指標每次移動 2步,慢指標每次移動 1步,當快指標到達連結串列末尾時,慢指標指向的連結串列節點即為連結串列的中點。

對兩個子連結串列分別排序。

將兩個排序後的子連結串列合併,得到完整的排序後的連結串列。可以使用「21. 合併兩個有序連結串列」的做法,將兩個有序的子連結串列進行合併。

上述過程可以通過遞迴實現。遞迴的終止條件是連結串列的節點個數小於或等於 1,即當連結串列為空或者連結串列只包含 1個節點時,不需要對連結串列進行拆分和排序。

Python程式碼:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def sortList(self, head: ListNode) -> ListNode:
        if not head or not head.next:
            return head
        fast = head.next
        slow = head
        while fast and fast.next:
            fast = fast.next.next
            slow = slow.next
        mid = slow.next
        slow.next = None
        return self.mergeTwoLists(self.sortList(head), self.sortList(mid))

    def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
        dummy = ListNode(-1)
        pre = dummy
        while l1 and l2:
            if l1.val <= l2.val:
                pre.next = l1
                l1 = l1.next
            else:
                pre.next = l2
                l2 = l2.next
            pre = pre.next
        if l1:
            pre.next = l1
        else:
            pre.next = l2
        return dummy.next