【LeetCode148】链表排序

本文介绍了一种在O(nlogn)时间复杂度和常数级空间复杂度下对链表进行排序的方法——归并排序。利用快慢指针法找到中间节点,递归地对左右两部分进行排序,最后合并两个有序链表。适用于链表排序问题。

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

题目描述:

在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
示例 1:
输入: 4->2->1->3
输出: 1->2->3->4
示例 2:
输入: -1->5->3->4->0
输出: -1->0->3->4->5

提交结果

在这里插入图片描述

归并排序(最简单的)

虽然归并排序在对数组排序的时候空间复杂度为O(n),因为在merge的过程中会开辟一个长度为n的临时数组。但对两个有序链表的合并空间复杂度是O(1)的,只需将两条链表按照次序挂在一起即可,不需要辅助空间。

核心思想

和对数组的归并排序一样,分为三个过程

  • 将链表划分为两部分(二路归并)
  • 然后对分成的两部分采取同递归处理,直至不能再分(即只有一个结点,或者没有结点),因为此时每部分只有一个结点或者没有结点,所以每一部分都是有序的。
  • 进行有序链表的合并

注: 整个链表的排序过程以null,作为划分,而不再像数组那样有边界元素的索引作为界限。

具体操作
1.快慢指针法找中点

排序对象是链表,没有下标索引,因此需要通过遍历找中间结点,而快慢指针法只需一趟遍历即可找到中间结点。之前写得找中间结点的博客,也是LeetCode上的题目。快慢指针法找中点

2.递归调用mergeSortList
3.有序链表的合并

对于有序链表的合并,也是LeetCode上的题目,可分为递归解法和循环解法,也比较简单,可以参照之前写得合并有序链表的博客。合并有序链表.

代码实现

主体代码:

public ListNode mergeSortList(ListNode head) {
    // 空链表和一个结点的链表无需排序
    if(head == null || head.next == null){
        return head;
    }
    // 找中间结点
    ListNode midNode = findMid(head);
    // 左部分排序
    ListNode left = mergeSortList(head);
    // 右部分排序
    ListNode right = mergeSortList(midNode);
    // 合并
    ListNode newHead = merge(left,right);
    return newHead;
}

快慢指针找中间结点

private ListNode findMid(ListNode head){
    ListNode fast = head;
    ListNode slow = head;
    ListNode prev = null;
    while(fast != null && fast.next != null){
        prev = slow;
        slow = slow.next;
        fast = fast.next.next;
    }
    prev.next = null;    //   前半部分排序的划分界限
    return slow;
}

合并两个有序链表

private ListNode merge(ListNode left,ListNode right){
    if(left == null) return right;
    if(right == null) return left;
    ListNode head = null;
    if(left.val <= right.val){
        head = left;
        head.next = merge(left.next,right);
    }else{
        head = right;
        head.next = merge(left,right.next);
    }
    return head;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值