IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> LeetCode-归并排序链表 -> 正文阅读

[数据结构与算法]LeetCode-归并排序链表

题目描述

?

示例分析

题目要求

?

一看见时间复杂度为O(N*logN),而处于这个时间复杂度的排序只有三个:堆排、快排、归并排序,快排最坏情况下,是O(N^2),而堆排不适合链表的排序,所以只剩下归并排序了。?


??方法一:自顶而下(递归)

自顶而下的方式,就是将链表在递出去的过程中不断拆分成两半,直到只剩下最后两个结点的时候才开始归回来合并,在归回来的时候,左右两个序列段都已经分别有序了,所以合并过程就是将两个有序序列段合并。但是这样做还是达不到完成这个题的要求,这里只是提供一种递归的思路,后面会给出迭代的思路。

代码实现

    public ListNode sortList(ListNode head) {
        if(head == null || head.next == null) return head;
        ListNode slow = head;
        ListNode fast = head.next;
        //快慢指针来分割链表
        while(fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        ListNode midR = slow.next;
        slow.next = null;//将中间结点置空是下次递归 return 的必要条件
        ListNode left = sortList(head);
        ListNode right = sortList(midR);
        //合并
        ListNode newHead = new ListNode(0);
        ListNode prev = newHead;;
        while(left != null && right != null) {
            if(left.val <= right.val) {
                prev.next = left;
                left = left.next;
            } else {
                prev.next = right;
                right = right.next;
            }
            prev = prev.next;
        }
        //走到这里,两个有序序列,一个为空,一个不为空,把不为空的接在prev的后面
        prev.next = (left != null ? left : right);
        return newHead.next;
    }

画图分析

上图分析了左半部分递出去的过程,2和5合并完之后成为一个有序序列段,而 midR 这一边是一个单独的只有一个结点的有序序列段,所以就印证了前面的解释。

复杂度分析

  • 时间复杂度:O(N*logN) ,就是归并排序的时间复杂度。
  • 空间复杂度:O(logN),每一层的合并都用到了辅助结点,所以空间复杂度就是树的高度。

?方法二:自底而上(迭代)

自顶而下为什么做不到常数个空间的空间复杂度呢,因为每递归一次,就要开辟一个辅助的栈空间,并且先执行一个函数的左,右边还没执行,所以栈空间就没有被回收,就必然导致空间复杂度较迭代来说要高。迭代的方式不像递归那样先操作整条链表,再不断细分,而是先两两有序,再四个四个有序...,最后当subLen = 链表长度的一半时,执行完本次循环,就全部有序。

代码实现

    public ListNode sortList(ListNode head) {
        if (head == null) {
            return head;
        }
        int len = 0;
        ListNode node = head;
        while (node != null) {
            len++;
            node = node.next;
        }
        ListNode newHead = new ListNode(0, head);
        //每次循环不断让左右序列扩大两倍
        for (int subLen = 1; subLen < len; subLen <<= 1) {
            ListNode prev = newHead;
            ListNode cur = newHead.next;
            while (cur != null) {
                ListNode head1 = cur;
                //移动到左子序列的尾巴
                for (int i = 1; i < subLen && cur.next != null; i++) {
                    cur = cur.next;
                }
                ListNode head2 = cur.next;
                //分割
                cur.next = null;
                cur = head2;
                //移动到右子序列的尾巴
                for (int i = 1; i < subLen && cur != null && cur.next != null; i++) {
                    cur = cur.next;
                }
                //用next记录下一次待合并的两序列中左序列的头
                ListNode next = null;
                if (cur != null && cur.next != null) {
                    next = cur.next;
                    cur.next = null;
                }
                ListNode merged = merge(head1, head2);
                //将合并的序列串在辅助结点之后
                prev.next = merged;
                while (prev.next != null) {
                    prev = prev.next;
                }
                cur = next;
            }

画图分析

从图中可以明显看出迭代与递归的区别,也印证了前面说的先两两有序,再四个四个有序,当subLen = 1/2 len 的时候,执行完本次循环就全部有序。且迭代真正做到了开辟常数个栈空间。

复杂度分析

  • 时间复杂度: O(N*logN)
  • 空间复杂度: O(1)

本篇完!!!

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-07-04 23:13:18  更:2022-07-04 23:13:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 23:38:33-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码