zoukankan      html  css  js  c++  java
  • 【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(nlogn)和O(1)O(1),根据时间复杂度我们自然想到二分法,从而联想到归并排序;

    对数组做归并排序的空间复杂度为 O(n)O(n),分别由新开辟数组O(n)O(n)和递归函数调用O(logn)O(logn)组成,而根据链表特性:

    数组额外空间:链表可以通过修改引用来更改节点顺序,无需像数组一样开辟额外空间;
    递归额外空间:递归调用函数将带来O(logn)O(logn)的空间复杂度,因此若希望达到O(1)O(1)空间复杂度,则不能使用递归。

    通过递归实现链表归并排序,有以下两个环节:

    分割 cut 环节: 找到当前链表中点,并从中点将链表断开(以便在下次递归 cut 时,链表片段拥有正确边界);
    我们使用 fast,slow 快慢双指针法,奇数个节点找到中点,偶数个节点找到中心左边的节点。
    找到中点 slow 后,执行 slow.next = None 将链表切断。
    递归分割时,输入当前链表左端点 head 和中心节点 slow 的下一个节点 tmp(因为链表是从 slow 切断的)。
    cut 递归终止条件: 当head.next == None时,说明只有一个节点了,直接返回此节点。
    合并 merge 环节: 将两个排序链表合并,转化为一个排序链表。
    双指针法合并,建立辅助ListNode h 作为头部。
    设置两指针 left, right 分别指向两链表头部,比较两指针处节点值大小,由小到大加入合并链表头部,指针交替前进,直至添加完两个链表。
    返回辅助ListNode h 作为头部的下个节点 h.next。
    时间复杂度 O(l + r),l, r 分别代表两个链表长度。
    当题目输入的 head == None 时,直接返回None。

     分割与归并过程在一个方法中完成

    class Solution {
        public ListNode sortList(ListNode head) {
            if (head == null || head.next == null)
                return head;
            ListNode fast = head.next, slow = head;
            while (fast != null && fast.next != null) {
                slow = slow.next;
                fast = fast.next.next;
            }
            ListNode tmp = slow.next;
            slow.next = null;
            ListNode left = sortList(head);
            ListNode right = sortList(tmp);
            ListNode h = new ListNode(0);
            ListNode res = 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 != null ? left : right;
            return res.next;
        }
    }

     我的:

    class ListNode {
        int val;
        ListNode next;
        ListNode(int x) { val = x; }
     }
    
    public class Solution148 {
        public ListNode sortList(ListNode head) {
            if (head == null || head.next == null) {
                return head;
            }
            ListNode slow = head, fast = head.next;
            while (fast != null && fast.next != null) {
                slow = slow.next;
                fast = fast.next.next;
            }
            ListNode temp = slow.next;
            slow.next = null;
            ListNode left = sortList(head);
            ListNode right = sortList(temp);
            ListNode res = new ListNode(0);
            ListNode cur = res;
            while (left != null && right != null) {
                if (left.val < right.val) {
                    cur.next = left;
                    left = left.next;
                } else {
                    cur.next = right;
                    right = right.next;
                }
                cur = cur.next;
            }
            cur.next = left == null ? right : left;
            return res.next;
    
        }
    }

    https://leetcode-cn.com/problems/sort-list/solution/sort-list-gui-bing-pai-xu-lian-biao-by-jyd/

  • 相关阅读:
    如何关闭和打开oracle 10g自动收集统计信息功能
    ORA00600:internal error code,arguments
    ORA01033: ORACLE initialization or shutdown in progress
    ORA01652:unable to extend temp segment by num in tablespace name
    ORA01578:Oracle data block corrupted
    ORA03113:endoffile on communication channel
    ORA01650:unable to extend rollback segment NAME by NUM intablespace NAME
    ORA01628:max # of extents num reached for rollback segment num
    C# 项目中的 bin 目录和 obj 目录的区别,以及 Debug 版本和 Release 版本的区别
    管理 Hadoop 集群的5大工具
  • 原文地址:https://www.cnblogs.com/twoheads/p/11474025.html
Copyright © 2011-2022 走看看