美文网首页
归并排序链表

归并排序链表

作者: 眼若繁星丶 | 来源:发表于2020-11-22 12:40 被阅读0次

归并排序链表

LeetCode 148

原题链接

归并排序

分治思想,链表对半分,一直对半分,直到分成两两的链表节点,然后两两排序,再归并回去,最终结果就是有序的链表。

这里存在几个问题:

  1. 怎么找到链表的中点
  2. 怎么一直对半分下去,直到分成两两节点
  3. 怎么合并两个链表

回答:

  1. 找链表中点有一个思想,利用快慢指针,快指针走两步,慢指针走一步,这样快指针走到链表最末尾时,慢指针就正好在链表中间,接下来,应该把链表从中间切断,只需要将中间节点的next = null即可。然后开始归并排序。
  2. 一直对半分下去,可以用递归的思想,实现。
  3. merge函数来合并,可以参考21. 合并两个有序链表对已经排序好的链表进行连接,其中,排序的过程应该放到merge函数里,在连接之前就进行排序,然后再连接返回。

代码如下

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */

class Solution {
    public ListNode sortList(ListNode head) {
        return head == null ? null : mergeSort(head);
    }
    
    private ListNode mergeSort(ListNode head) {
        if (head.next == null) {
            return head;
        }
        // p,q分别为慢指针,快指针,pre指针是来保存最后慢指针指向的中间节点,便于后面断链
        ListNode p = head, q = head, pre = null;
        while (q != null && q.next != null) {
            pre = p;
            p = p.next;
            q = q.next.next;
        }
        // 这里将中间节点断链
        pre.next = null;
        // 这里利用递归,让等分的两个链表
        ListNode l = mergeSort(head);
        ListNode r = mergeSort(p);
        return merge(l, r);
    }
    // 先进行排序,再进行合并
    ListNode merge(ListNode l, ListNode r) {
        // dummy头结点,作为待返回节点的哨兵头结点,便于后面的返回
        ListNode dummyHead = new ListNode(0);
        ListNode cur = dummyHead;
        while (l != null && r != null) {
            // 这里进行值的判断,然后进行排序,就是把符合的节点插入到待返回链表中
            if (l.val <= r.val) {
                cur.next = l;
                cur = cur.next;
                l = l.next;
            } else {
                cur.next = r;
                cur = cur.next;
                r = r.next;
            }
        }
        // 有一个链表为空,则将另一个链表继续接在返回链表上
        if (l != null) {
            cur.next = l;
        }
        if (r != null) {
            cur.next = r;
        }
        return dummyHead.next;
    }
}

相关文章

  • LeetCode 专题 :分治算法

    LeetCode 第 23 题:归并多个有序链表 传送门:23. 合并K个排序链表。 合并 k 个排序链表,返回合...

  • python链表归并排序

    利用归并排序的思想,使用o(nlogn)时间复杂度,排序链表

  • 148. Sort List

    链表排序,使用归并排序 Runtime: 268 ms, faster than 17.27% Memory Us...

  • 23. Merge k Sorted Lists

    题目描述:将k个已排序的链表合并为一条排好序的链表。分析复杂度。分析:k个链表的归并可以利用归并排序的思想,每次取...

  • 归并的思想解决链表排序、多个链表合并问题

    1. 23.合并多个有序链表 与归并排序思想一致,两两合并。 2. 148. 排序链表 思路:与归并思想一致 快慢...

  • 【leetCode】148. Sort List 解题报告

    -- 关键字:链表、归并排序-- 难度:Medium-- 题目大意:对一个链表排序,时间复杂度:O(NlogN) ...

  • 排序链表 归并

    https://leetcode-cn.com/explore/interview/card/bytedance/...

  • 面试算法:单链表的归并排序

    链表适合插入和删除,不适合检索,尤其是单向链表中寻找节点的父节点。 归并排序:归并排序对于数组来说,空间复杂度为N...

  • 常见算法

    单链表反转 冒泡排序 选择排序 插入排序 希尔排序 快速排序 归并排序 堆排序 二分查找 重建二叉树

  • 结构|链表

    学习笔记,可能有些谬误,请批判性阅读。 先给出链表的定义。 链表排序 归并排序用起来 删除链表倒数第n个节点 双指...

网友评论

      本文标题:归并排序链表

      本文链接:https://www.haomeiwen.com/subject/fcjuiktx.html