leetcode刷题笔记一百四十八题 排序列表

leetcode刷题笔记一百四十八题 排序列表

源地址: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

//最初的想法与很多人一致,使用快慢指针分割进行归并排序
//但是由于使用了递归,时间复杂度为O(nlogn), 空间复杂度为O(logn)
/**
 * Definition for singly-linked list.
 * class ListNode(var _x: Int = 0) {
 *   var next: ListNode = null
 *   var x: Int = _x
 * }
 */
object Solution {
    def sortList(head: ListNode): ListNode = {
        if (head == null || head.next == null) return head
        var slow = head
        var fast = head.next

        while (fast != null && fast.next != null){
            fast = fast.next.next
            slow = slow.next
        }

        var mid = slow.next
        var start = head
        slow.next = null

        var left = sortList(head) 
        var right = sortList(mid)

        var h = ListNode(0)
        val res = h
        while (left != null && right != null){
            if (left.x < right.x){
                h.next = left
                left = left.next
            }
            else{
                h.next = right
                right = right.next
            }
            h = h.next
        }
        if (left != null) h.next = left
        else h.next = right
        return res.next
    }
}

//若要实现空间复杂度O(1),需要将递归改为迭代处理,使用intv标记当前当前作用范围,逐渐扩大,直至与链表长度一致
import util.control.Breaks._ 
object Solution {
    def sortList(head: ListNode): ListNode = {
        var h = head
        var length = 0
        var intv = 1

        //测量链表长度
        while (h != null){
            h = h.next
            length += 1
        }

        //构建辅助头结点
        val res = ListNode(0)
        res.next = head

        while (intv < length){
            breakable{
                var pre = res
                var cur = res.next
                //基于intv 对链表进行归并
            //breakable{
                while (cur != null){
                    //intln("yes")
                    var cur1 = cur
                    var i = intv
                    while (i > 0 && cur != null){
                        i -= 1
                        cur = cur.next
                    }
                    //第一段intv未满,第二段为空
                    if (i > 0) break()
                    
                    var cur2 = cur
                    i = intv
                    while (i > 0 && cur != null){
                        cur = cur.next
                        i -= 1
                    }
                    
                    var length1 = intv
                    var length2 = intv - i
                    while (length1 > 0 && length2 > 0){
                        if (cur1.x < cur2.x){
                            pre.next = cur1
                            cur1 = cur1.next
                            length1 -= 1
                        }
                        else{
                            pre.next = cur2
                            cur2 = cur2.next
                            length2 -= 1 
                        }
                        pre = pre.next
                    }
                    if (length1 > 0){
                        pre.next = cur1
                    }
                    else{
                        pre.next = cur2
                    }
                    //更新pre指针,连接同层链表
                    while (length1 > 0){
                        pre = pre.next
                        length1 -= 1 
                    }                    
                    while (length2 > 0){
                        pre = pre.next
                        length2 -= 1
                    }                    
                    pre.next = cur
                }
                
            } 
            intv *= 2
        }
        return res.next 
    }
}
posted @ 2020-08-29 18:16  ganshuoos  阅读(124)  评论(0编辑  收藏  举报