zoukankan      html  css  js  c++  java
  • [LeetCode] 148. Sort List(单链表排序)

    Description

    Given the head of a linked list, return the list after sorting it in ascending order.
    给定单链表的头节点 head,对其升序排序,然后返回该链表。

    Follow up

    Can you sort the linked list in O(n logn) time and O(1) memory (i.e. constant space)?
    你能以 (O(Nlog{N})) 的时间复杂度和 (O(1)) 的空间复杂度解决它吗?

    Examples

    Example 1

    Input: head = [4,2,1,3]
    Output: [1,2,3,4]
    

    Example 2

    Input: head = [-1,5,3,4,0]
    Output: [-1,0,3,4,5]
    

    Example 3

    Input: head = []
    Output: []
    

    Constraints

    • The number of nodes in the list is in the range [0, 5 * 104].
    • -105 <= Node.val <= 105

    Solution

    对于单链表来说最合适的排序算法,(O(N^2)) 算法里比较适合的是插入排序,(O(Nlog{N})) 算法里比较适合的是归并排序,本题将他们各自实现一遍,详细的步骤附在代码的注释里。

    插入排序版本:

    /**
     * Example:
     * var li = ListNode(5)
     * var v = li.`val`
     * Definition for singly-linked list.
     * class ListNode(var `val`: Int) {
     *     var next: ListNode? = null
     * }
     */
    class Solution {
        fun sortList(head: ListNode?): ListNode? {
            // 链表为空或只有一个元素,就不管它了,直接返回
            if (head?.next == null) {
                return head
            }
            // 在这里,交换是交换节点本身,所以加入 dummy 节点
            val dummy = ListNode(-1)
            dummy.next = head
            // end 初始为 head,在排序过程中,dummy(不包括,仅为了方便交换) 到 head(包括)之间的所有节点都是有序的
            // 我们要做的,就是把 head 后面的节点不断插入这个有序的区间里。
            var end = head
            // cur -> 当前要处理的节点
            var cur = head.next
            while (cur != null) {
                var p = dummy.next
                var pre: ListNode? = dummy
                // 找到合适的插入位置
                while (p != cur && cur.`val` >= p!!.`val`) {
                    p = p.next
                    pre = pre?.next
                }
    
                if (cur === p) {
                    // 当前节点是已排序区间内最大的,直接把区间后移
                    end = cur
                } else {
                    // 插入进合适的位置
                    end?.next = cur.next
                    cur.next = p
                    pre?.next = cur
                }
    
                // 处理下一个节点
                cur = end?.next
            }
    
            return dummy.next
        }
    }
    

    归并排序版:

    /**
     * Example:
     * var li = ListNode(5)
     * var v = li.`val`
     * Definition for singly-linked list.
     * class ListNode(var `val`: Int) {
     *     var next: ListNode? = null
     * }
     */
    class Solution {
        fun sortList(head: ListNode?): ListNode? {
            // 如果链表为空或者只有一个节点,不管它了,直接返回
            if (head?.next == null) {
                return head
            }
    
            // 双指针法找出中间节点
            var fast = head
            var slow = head
            while (fast?.next?.next != null) {
                fast = fast.next?.next
                slow = slow?.next
            }
    
            // 将链表的前后两部分断开
            fast = slow
            slow = slow?.next
            fast?.next = null
    
            // 分别对前后两段进行排序
            fast = sortList(head)
            slow = sortList(slow)
    
            return merge(fast, slow)
        }
    
        private fun merge(left: ListNode?, right: ListNode?): ListNode? {
            // 特殊情况处理,一边为空就返回另一边
            if (left == null) {
                return right
            }
            if (right == null) {
                return left
            }
    
            var p = left
            var q = right
    
            val dummy = ListNode(-1)
            var result: ListNode? = dummy
            while (p != null && q != null) {
                if (p.`val` < q.`val`) {
                    result?.next = p
                    p = p.next
                } else {
                    result?.next = q
                    q = q.next
                }
                result = result?.next
            }
    
            result?.next = p?:q
            return dummy.next
        }
    }
    
  • 相关阅读:
    python_levenshtein 的安装和使用
    接口测试困难
    pycharm修改windows的IP
    Excel读取,修改,新建
    appium混合应用的处理
    冒泡排序
    选择排序
    插入排序
    python中两种退出方式os._exit(),sys.exit()
    二分查找
  • 原文地址:https://www.cnblogs.com/zhongju/p/14028831.html
Copyright © 2011-2022 走看看