Skip to content

Latest commit

 

History

History
91 lines (84 loc) · 3.14 KB

148. 排序链表-Medium.md

File metadata and controls

91 lines (84 loc) · 3.14 KB

给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。

进阶:

你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?  

示例 1: Pasted image 20201123221022.png

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

示例 2: Pasted image 20201123221033.png

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

示例 3:

输入head = []
输出:[]

提示:

  • 链表中节点的数目在范围 [0, 5 * 104] 内
  • -105 <= Node.val <= 105

Solution

  • 考虑O(n log n) 时间复杂度O(1)空间复杂度,因此可使用的排序方法为快速排序、堆排序和合并排序;其中合并排序最适合链表。其次,由于递归会开辟额外的栈空间,所以只能使用迭代。
  • 采用自底向上的策略,先将链表分成split=1长度的子链表,并两两进行归并排序;在此基础上逐渐增大split(split *= 2),直至split>=length(链表长度)
  • 注意:
    • 归并时,对于用于归并的两段子链表,若第二段没有,则表明已到链表末尾,可以跳出循环
    • 归并时,第一次遍历用于找这次用于归并的两段子链表,可用split控制遍历长度;第二次遍历用于合并两个有序链表,需要计算两段子链表的长度(因为在末尾时,第二段子链表长度不等于split),用这个长度控制遍历长度。
class Solution:
    def sortList(self, head: ListNode) -> ListNode:
        h = head
        length = 0
        intv = 1
        while h:
            h = h.next
            length += 1
        res = ListNode(None)
        res.next = head
        # merge the list in different intv.
        while intv < length:
            pre = res
            h = res.next
            while h:
                # get the two merge head `h1`, `h2`
                h1 = h
                i = intv
                while i and h:
                    h= h.next
                    i -= 1
                # no need to merge because the `h2` is None.
                if i:
                    break 
                h2 = h
                i = intv
                while i and h:
                    h = h.next
                    i -= 1
                # the `c2`: length of `h2` can be small than the `intv`.
                c1 = intv
                c2 = intv - i
                # merge the `h1` and `h2`.
                while c1 and c2:
                    if h1.val < h2.val:
                        pre.next = h1
                        h1 = h1.next
                        c1 -= 1
                    else:
                        pre.next = h2
                        h2 = h2.next
                        c2 -= 1
                    pre = pre.next
                pre.next = h1 if c1 else h2
                while c1 > 0 or c2 > 0:
                    pre = pre.next
                    c1 -= 1
                    c2 -= 1
                pre.next = h 
            intv *= 2
        return res.next