0148-leetcode算法实现之排序链表-sortLinkedList-python&golang实现

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

进阶:

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

示例 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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sort-list

思路:
-1.断链
-2.合并
-3.循环

python

# 0148.排序链表
"""
知识点1:归并排序的整体思想
知识点2:找到一个链表的中间节点的方法
知识点3:合并两个已排好序的链表为一个新的有序链表
"""
# 参考:https://leetcode-cn.com/problems/sort-list/solution/pai-xu-lian-biao-di-gui-die-dai-xiang-jie-by-cherr/

class ListNode:
    def __init__(self, val):
        self.val = val
        self.next = None

class Solution:
    def sortList1(self, head: ListNode) -> ListNode:
        """
        迭代,时间O(nlogn), 空间O(1)
        :param head:
        :return:
        """
        length = self.getLength(head)
        dummy = ListNode(-1)
        dummy.next = head

        step = 1
        while step < length:
            # 每次变换步长, pre和cur指针初始化在表头
            pre, cur = dummy, dummy.next
            while cur:
                h1 = cur # 第一部分头,第二次循环之后,cur为剩余部分头,不断往后把链表按照步长step分成一块一块...
                h2 = self.split(h1, step) # 第二部分头
                cur = self.split(h2, step) # 剩余部分头
                temp = self.merge(h1, h2) # 一二部分合并
                pre.next = temp # 前面部分与排序好的连接
                while pre.next:
                    pre = pre.next # pre移动到排序好部分的末尾
            step = step * 2

        return dummy.next

    def sortList(self, head: ListNode) -> ListNode:
        """
        递归法,时间O(nlogn), 空间O(logn)
        :param head:
        :return:
        """
        if head is None or head.next is None:
            return head
        slow, fast = head, head.next

        # 断链
        while fast != None and fast.next != None:
            slow = slow.next
            fast = fast.next.next
        rightHead = slow.next
        slow.next = None
        # 递归
        left = self.sortList(head)
        right = self.sortList(rightHead)
        # 合并
        return self.merge(left, right)

    def merge(self, h1, h2: ListNode) -> ListNode:
        dummy = ListNode(-1)
        p = dummy

        while h1 != None and h2 != None:
            if h1.val < h2.val:
                p.next = h1
                h1 = h1.next
            else:
                p.next = h2
                h2 = h2.next
            p = p.next
        p.next = h1 or h2

        return dummy.next

    def getLength(self, head: ListNode) -> int:
        cnt = 0
        while head:
            cnt += 1
            head = head.next
        return cnt

    def split(self, head: ListNode, step: int) -> ListNode :
        # 断链操作
        if head == None:
            return head
        cur = head
        for i in range(1, step):
            if cur.next != None:
                cur = cur.next
        right = cur.next
        cur.next = None # 以cur为界断开原链
        # 返回右链链头
        return right

golang

// 迭代
func sortList1(head *ListNode) *ListNode {
	length := getLength(head)
	dummy := &ListNode{}
	dummy.Next = head

	for step := 1; step < length; step = step * 2 {
		pre, cur := dummy, dummy.Next
		for cur != nil {
			h1 := cur
			h2 := split(h1, step)
			cur = split(h2, step)
			temp := merge(h1, h2)
			pre.Next = temp
			for pre.Next != nil {
				pre = pre.Next
			}
		}
	}
	return dummy.Next
}

func getLength(head *ListNode) int {
	cnt := 0
	cur := head
	for cur != nil {
		cnt++
		cur = cur.Next
	}
	return cnt
}

func split(head *ListNode, step int) *ListNode {
	if head == nil {
		return head
	}
	cur := head
	for i := 1; i < step; i++ {
		if cur.Next != nil {
			cur = cur.Next
		}
	}
	right := cur.Next
	cur.Next = nil
	return right
}

// 递归 leetcode提示初始时间限制
func sortList(head *ListNode) *ListNode {
	if head == nil || head.Next == nil {
		return head
	}
	// 断链
	slow, fast := head, head.Next
	for fast != nil && fast.Next != nil {
		slow = slow.Next
		fast = fast.Next
	}
	rightHead := slow.Next
	slow.Next = nil
	// 递归
	left := sortList(head)
	right := sortList(rightHead)

	return merge(left, right)
}

func merge(h1, h2 *ListNode) *ListNode {
	dummy := &ListNode{}
	p := dummy
	for h1 != nil && h2 != nil {
		if h1.Val < h2.Val {
			p.Next = h1
			h1 = h1.Next
		} else {
			p.Next = h2
			h2 = h2.Next
		}
		p = p.Next
	}
	if h1 != nil {
		p.Next = h1
	} else {
		p.Next = h2
	}
	return dummy.Next
}

原文地址:https://www.cnblogs.com/davis12/p/15506571.html