Loading

【力扣】148. 排序链表

 

给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。

进阶:

你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?
 

示例 1:


输入:head = [4,2,1,3]
输出:[1,2,3,4]
示例 2:


输入:head = [-1,5,3,4,0]
输出:[-1,0,3,4,5]
示例 3:

输入:head = []
输出:[]
 

提示:

链表中节点的数目在范围 [0, 5 * 104] 内
-105 <= Node.val <= 105

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sort-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

 

简单做法:

public ListNode sortList(ListNode head) {
        if(head == null || head.next == null){
            return head;
        }
        List<ListNode> list = new ArrayList<ListNode>();
        while(head != null){
            list.add(head);
            head = head.next;
        }
        Collections.sort(list,(item1,item2) -> (item1.val - item2.val));
        for(int i = 1; i < list.size(); i++){
            list.get(i-1).next = list.get(i);
        }
        list.get(list.size() -1 ).next = null;
        return list.get(0);
    }

 

 

//首先先用昨天的题目的排序方式写一遍、发现时间超限
    public ListNode sortList(ListNode head) {

        if(head == null || head.next == null){
            return head;
        }
        //我们使用 fast,slow 快慢双指针法,奇数个节点找到中点,偶数个节点找到中心左边的节点。
        ListNode fast = head.next;
        ListNode slow = head;
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
        }
        //将链表分割,分为左边和右边
        ListNode temp = slow.next;
        slow.next = null;//分割需要设置为null

        ListNode left = sortList(head);
        ListNode right = sortList(temp);

        //进行左边和右边链表的整和
        ListNode h = new ListNode();
        ListNode result = h;

        //这个循环没有问题
        while(left != null && right != null){
            if(left.val < right.val){
                h.next = left;
                left = left.next;
            }else {
                h.next = right;
                right = right.next;
            }
            h = h.next;
        }
        //这里有一些疑问: h.next = left  || h.next = right  为什么要这么设置,这两种设置效果是一样的
        //因为在循环结束时,有可能因为right为空了,或者left为空了,导致没有给h.next 赋值,所以,再这里复制。
        h.next = right != null ? right : left;

        return result.next;
    }

时间复杂度:O(logn)

空间复杂度:O(logn)

以上算法的整体思想是:找到中心点,将链表分割,将分割后的链表排序,最后合并.

 

posted @ 2020-11-22 20:14  冯廷鑫  阅读(161)  评论(0编辑  收藏  举报