148.排序链表

描述

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

示例 1:

输入: 4->2->1->3
输出: 1->2->3->4
示例 2:

输入: -1->5->3->4->0
输出: -1->0->3->4->5

解析

这个复杂度,可以想到用快排和归并。但是常数级的空间复杂度,数组的话,需要一个暂存后的数组,链表的话,可以直接连,好似穿针引线。

代码

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

    public ListNode sortList(ListNode head) {
        return Optional.ofNullable(merge(head)).orElse(head);
    }

    public ListNode merge(ListNode head){
        if (head == null || head.next == null) {  //递归退出条件:即链表被划分后只剩一个结点
            return head;
        }
        ListNode pre = head;                    //这里使用快慢指针,进行链表划分
        ListNode slow = head;
        ListNode fast = head;
        while (fast != null && fast.next != null) {
            pre = slow;
            slow = slow.next;
            fast = fast.next.next;
        }
        pre.next = null;              //fast为原链表尾.next, slow为划分后链表右半部分表头, pre为左半部分表尾结点,所以pre.next要为null
        ListNode left = merge(head); //左半部分递归划分
        ListNode right = merge(slow); //右半部分递归划分
        return mergeList(left, right);  //合并链表
    }

    //合并两个有序链表
    public ListNode mergeList(ListNode left, ListNode right) {
        if (left == null) return right;
        if (right == null) return left;
        ListNode head = new ListNode(-1);
        ListNode temp = head;
        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 head.next;
    }
}

 

posted on 2019-08-16 14:23  反光的小鱼儿  阅读(378)  评论(0编辑  收藏  举报