美文网首页
148. 排序链表

148. 排序链表

作者: justonemoretry | 来源:发表于2021-08-31 20:59 被阅读0次
image.png

解法

自顶向下的归并,递归,会有O(logN)的空间复杂度

/**
 * 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 sort(head, null);
    }

    /**
     * 进行排序,但是尾部不取
     */
    public ListNode sort(ListNode head, ListNode tail) {
        if (head == null) {
            return head;
        }
        if (head.next == tail) {
            head.next = null;
            return head;
        }
        // 快慢指针找中间点
        ListNode fast = head;
        ListNode slow = head;
        while (fast != tail) {
            fast = fast.next;
            slow = slow.next;
            if (fast != tail) {
                fast = fast.next;
            }
        }
        // 对两边的链表进行分别排序
        ListNode left = sort(head, slow);
        ListNode right = sort(slow, tail);
        // 进行merge操作
        ListNode dummyHead = new ListNode();
        ListNode temp = dummyHead;
        while (left != null && right != null) {
            if (left.val <= right.val) {
                temp.next = left;
                left = left.next;
            } else {
                temp.next = right;
                right = right.next;
            }
            temp = temp.next;
        }
        if (left != null) {
            temp.next = left;
        }
        if (right != null) {
            temp.next = right;
        }
        return dummyHead.next;
    }
}

自底向上,迭代解法,空间复杂度O(1)

/**
 * 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) {
        if (head == null) {
            return head;
        }
        int len = 0;
        ListNode temp = head;
        while (temp != null) {
            len++;
            temp = temp.next;
        }

        ListNode dummyHead = new ListNode();
        dummyHead.next = head;
        // 每次扩大一倍步长,从下向上merge
        for (int subLen = 1; subLen < len; subLen = subLen * 2) {
            // pre后续过程后移。但dummyHead不移动,每次指向排好的头结点
            ListNode pre = dummyHead;
            ListNode cur = dummyHead.next;
            // 遍历整条链表,直到为null
            while (cur != null) {
                ListNode head1 = cur;
                for (int i = 1; i < subLen && cur != null && cur.next != null; i++) {
                    cur = cur.next;
                }

                ListNode head2 = cur.next;
                // 切断和head1之间的联系
                cur.next = null;
                cur = head2;
                for (int i = 1; i < subLen && cur != null && cur.next != null; i++) {
                    cur = cur.next;
                }

                // 保存head2的下一位元素,并切断联系
                ListNode next = null;
                if (cur != null) {
                    next = cur.next;
                    cur.next = null;
                }

                // 合并
                pre.next = merge(head1, head2);
                // 取合并链表的末尾
                while (pre.next != null) {
                    pre = pre.next;
                }
                // 接着合并
                cur = next;
            }
        }
        return dummyHead.next;
    }

    public ListNode merge(ListNode left, ListNode right) {
        ListNode dummyHead = new ListNode();
        ListNode temp = dummyHead;
        while (left != null && right != null) {
            if (left.val <= right.val) {
                temp.next = left;
                left = left.next;
            } else {
                temp.next = right;
                right = right.next;
            }
            temp = temp.next;
        }
        if (left != null) {
            temp.next = left;
        }
        if (right != null) {
            temp.next = right;
        }
        return dummyHead.next;
    }
}

相关文章

  • 链表续

    148. 排序链表

  • 148. 排序链表

    148. 排序链表

  • LeetCode-148-排序链表

    LeetCode-148-排序链表 148. 排序链表[https://leetcode-cn.com/probl...

  • 148 排序链表

    148. 排序链表要求:时间复杂度 O(NlogN), 空间O(1)采用归并排序我们使用快慢指针 来定位单链表中间的位置

  • 链表排序问题

    148. Sort List(链表归并排序)Sort a linked list in O(n log n) ti...

  • [LeetCode] 148. 排序链表

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

  • python实现leetcode之148. 排序链表

    解题思路 计算长度找到中点一分为二,分开排序然后归并 148. 排序链表[https://leetcode-cn....

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

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

  • 148. 排序链表

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

  • 148. 排序链表

    先使用快慢指针将找到链表的中点,然后将链表切分成左右两部分,然后对左右指针递归进行排序,最后归并两个已经排序的链表...

网友评论

      本文标题:148. 排序链表

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