链表算法面试题---链表的归并排序

题目描述

给定一个链表,请用归并排序的方法,对链表完成排序。

之前一道题中:链表的插入排序,我们完成了通过插入排序的方式对链表进行了排序,我们知道插入排序的时间复杂度是O(n^2),那么我们当然可以想到使用更快速的排序方式,所以本题尝试使用归并排序的方式来实现。

归并排序分析

归并的核心思想就是把一个大集合拆分为两个小集合,再分别对两个小集合进行拆分,直到不能拆分为止,然后对拆分后的小集合进行排序,排序完成后再向上合并,最终合并为一个有序的集合。

那么在之前的基础题中,我们也遇到过如何对两个有序链表进行合并:合并有序链表,所以最终归并的方式只需要对链表进行拆分即可,那么又可以通过快慢指针的方式找到中间节点进行拆分:返回链表的中间节点,所以实际上只要有了前面练习的基础,那么实现归并排序并不困难。

代码实现

public class MergeSortList {
    public static void main(String[] args) {
        ListNode n = new ListNode(1);
        ListNode head = n;
        for (int i = 2; i < 6; i++) {
            n.next = new ListNode(i);
            n = n.next;
        }

        for (int i = 6; i > 0; i--) {
            n.next = new ListNode(i);
            n = n.next;
        }

        System.out.println(new MergeSortList().sortList(head));
    }

    public ListNode sortList(ListNode head) {
        //类似数组归并一样,从头尾开始
        return sortList(head, null);
    }

    private ListNode sortList(ListNode head, ListNode tail) {
        //无法继续拆分的情况
        if (head == null) {
            return null;
        }
        //无法继续拆分的情况
        if (head.next == tail) {
            head.next = null;
            return head;
        }

        //快慢指针找到中间节点
        ListNode slow = head, fast = head;
        while (fast != tail && fast.next != tail) {
            slow = slow.next;
            fast = fast.next.next;
        }

        ListNode mid = slow;
        //左边继续拆分
        ListNode left = sortList(head, mid);
        //右边继续拆分
        ListNode right = sortList(mid, tail);
        //有序链表合并
        return merge(left, right);
    }

    private ListNode merge(ListNode left, ListNode right) {
        ListNode mergeNode = new ListNode();
        ListNode help = mergeNode;
        //比较两个链表当前的值,值小的链表就把引用赋给mergeNode,并向后移动一位重新赋值给自己,同时help指向值小的那个节点
        while (left != null && right != null) {
            if (left.val < right.val) {
                help.next = left;
                left = left.next;
            } else {
                help.next = right;
                right = right.next;
            }
            help = help.next;
        }
        //最后如果有剩余的节点,就一次性链上去
        help.next = left == null ? right : left;
        return mergeNode.next;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码拉松

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值