LeetCode 148. Sort List

该文章介绍了如何运用归并排序的思想解决LeetCode第148题,即对一个单向链表进行从小到大的排序。通过快慢指针找到链表中点,然后递归地对两半部分进行排序,最后合并两个已排序的链表。整个过程保证了O(nlogn)的时间复杂度和O(1)的空间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

LeetCode 148. Sort List

题目描述

一个单向链表, 依据结点的值对其进行从小到大排序, 要求时间复杂度为O(nlogn), 空间复杂度为O(1)

图例:
在这里插入图片描述

思路

  1. 采用归并排序的思想, 将链表分成两部分, 分别对两部分进行排序, 然后将两部分合并
  2. 首先, 采用快慢指针的方法, 找到链表的中间结点
  3. 然后, 递归的对两部分进行排序, 第一部分是头结点到中间结点的前一个结点, 第二部分是中间结点到尾结点
  4. 最后, 将两部分合并, 合并的方法是, 依次比较两部分的结点值, 将较小的结点插入到新链表中, 直到其中一部分的结点全部插入到新链表中, 然后将另一部分的结点全部插入到新链表中
  5. 递归的终止条件是, 当链表为空或者链表只有一个结点时, 不需要排序, 直接返回链表即可

代码

type ListNode struct {
	Val  int
	Next *ListNode
}

func sortList(head *ListNode) *ListNode {
	if head == nil || head.Next == nil { // 递归的终止条件
		return head
	}

	slow, fast := head, head
	var mid *ListNode
	for fast != nil && fast.Next != nil { // 找到链表的中间结点
		mid = slow
		slow = slow.Next
		fast = fast.Next.Next
	}
	mid.Next = nil // 将第一个链表断开

	list1 := sortList(head) // 递归的对两部分进行排序
	list2 := sortList(slow)

	return merge(list1, list2) // 合并两个有序链表
}

func merge(list1, list2 *ListNode) *ListNode {
	if list1 == nil { // 合并两个有序链表
		return list2
	}
	if list2 == nil { // 合并两个有序链表
		return list1
	}

	head := &ListNode{} // 新链表的头结点
	rear := head        // 新链表的尾结点
	p1, p2 := list1, list2

	for ; p1 != nil && p2 != nil; rear = rear.Next {
		if p1.Val < p2.Val { // 依次比较两部分的结点值, 将较小的结点插入到新链表中
			rear.Next = p1
			p1 = p1.Next
		} else if p1.Val >= p2.Val {
			rear.Next = p2
			p2 = p2.Next
		}
	}

	if p1 != nil { // 将剩余的结点插入到新链表中
		rear.Next = p1
	}
	if p2 != nil {
		rear.Next = p2
	}

	return head.Next // 返回新链表的头结点的下一个结点
}

nil {
		rear.Next = p2
	}

	return head.Next // 返回新链表的头结点的下一个结点
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值