LeetCode.148 排序链表

Posted 硬盘红了

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode.148 排序链表相关的知识,希望对你有一定的参考价值。

题目描述:在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。

 

O(nlogn)的时间复杂度第一时间就是归并排序了,然后要常数级空间,那就不能用递归。

 

原地归并

public ListNode sortList(ListNode head) {
        //如果只有一个节点直接返回
        if (head == null || head.next == null) {
            return head;
        }
        //获取链表长度
        int len = ListNodeLength(head);

        //定义哨兵节点用于返回
        ListNode dummyNode = new ListNode(-1);
        dummyNode.next = head;

        //循环时间复杂度O(logn),外层控制轮次,内层进行分割
        //i控制分割步长,指数级增长 1,2,4,8...步长超过链表长度就是排序完成
        for (int i = 1; i < len; i = i <<1) {
            //设置每一轮分割的起始节点
            ListNode pre = dummyNode;
            ListNode curNode = dummyNode.next;
            //每一轮都从curNode开始,也就是每一轮排序后的头节点,那么终止条件自然就是curNode != null
            while(curNode != null){
                ListNode leftNode = curNode;
                ListNode rightNode = cut(leftNode,i);
                //寻找分割的起始节点
                curNode = cut(rightNode,i);
                //通过pre节点指向排序后的头节点,作为下一轮分割的起始节点
                pre.next = mergeTwoLinkedList(leftNode,rightNode);
                while (pre.next != null){
                    pre = pre.next;
                }
            }
        }
        return dummyNode.next;
    }

    /**
     * 分割,断链。
     * @param head      进行断链操作的节点
     * @param step      分割步长,指数级增长,1-2-4-8...
     * @return          保存断链节点的下一个节点,作为下一组节点的开始节点
     */
    private ListNode cut(ListNode head, int step) {
        if (head == null){
            return null;
        }
        //设置分割步长step
        for (int i = 1; head.next != null && i < step; i++){
            head = head.next;
        }
        ListNode rightNode = head.next;
        //断链
        head.next = null;
        return rightNode;
    }

    public int ListNodeLength(ListNode head) {
        int length = 0;
        ListNode cur = head;
        while (cur != null) {
            cur = cur.next;
            length++;
        }
        return length;
    }

    public ListNode mergeTwoLinkedList(ListNode l1, ListNode l2) {
        ListNode dummyNode = new ListNode(-1);
        ListNode cur = dummyNode;
        while (l1 != null && l2 != null) {
            if (l1.val < l2.val) {
                cur.next = l1;
                l1 = l1.next;
            } else {
                cur.next = l2;
                l2 = l2.next;
            }
            cur = cur.next;
        }
        cur.next = l1 == null ? l2 : l1;
        return dummyNode.next;
    }

 

以上是关于LeetCode.148 排序链表的主要内容,如果未能解决你的问题,请参考以下文章

[Leetcode]148. 排序链表(归并排序)

LeetCode 148. 排序链表

精选力扣500题 第43题 LeetCode 148. 排序链表c++/java详细题解

LeetCode | 148. 排序链表

LeetCode.148 排序链表

leetcode-148排序链表