Leetcode 148. 排序链表

【中等】力扣算法题解析LeetCode148:排序链表 本文介绍了一种高效排序链表的算法,采用自底向上的归并排序实现O(n log n)时间复杂度和O(1)空间复杂度。关键步骤包括:计算链表长度、逐步倍增子链表长度、精确截取子链表进行归并,并使用迭代法合并有序链表。算法通过哑结点和指针操作优化空间,避免了递归带来的额外消耗。文章提供了完整的Java实现代码,并分析了时间复杂度为O(n log n)和空间复杂度O(1)的性能特点,适合处理大规模链表排序问题。 阅读详情

题目

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

示例 1:

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

示例 2:

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

解答

解法一:归并排序

思路:

  1. 使用快慢指针确定中点的位置。
  2. 分别对左部分和右部分递归。
  3. merge 两部分链表。

要点:

  • fast 指针的初始化:fast = head.next 这样可以保证取到中点的左边界。
  • 归并过程分割次数:1,2,,,logn 次,可以看出分割次数是 O(logn) 级别。
  • 快慢指针搜索次数:n / 2 * 1,n / 4 * 2 ,,,,n / (2^n) * (2^(n-1) )。可以看出是 O(n) 级别。
  • merge 过程不多说了,不管使用递归还是非递归方式实现,时间复杂度都是 O(n) 级别 。
  • merge 过程只使用到了几个指针(改变了一些指针的指向),空间复杂度是 O(1) 级别。

所以整体复杂度:

  • O(nlogn) 的时间:【 分割次数 O(logn) x (快慢指针搜索次数 O(n) + merge 过程 O(n) ) 】= O(nlogn)
  • O(1) 的空间:几个指针的交换 O(1)。(然而如果严格上来讲栈帧也是需要空间的 :)
代码
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    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 right = sortList(slow.next);
        slow.next = null;
        ListNode left = sortList(head);
        
        return merge(left, right);
    }
    
    private ListNode merge(ListNode l1, ListNode l2) {
        if(l1 == null) return l2;
        if(l2 == null) return l1;
        
        if(l1.val < l2.val) {
            l1.next = merge(l1.next, l2);
            return l1;
        } else {
            l2.next = merge(l1, l2.next);
            return l2;
        }
    }
}
结果

在这里插入图片描述

解法二:快速排序

根据 pivot 将将链表分成两部分,分别进行快速排序。

复杂度:O(nlogn) 的时间,O(1) 的空间。

但能明显看出:链表还是适用于归并排序,并不适合用于快速排序。

代码
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode sortList(ListNode head) {
        quickSort(head, null);
        return head;
    }
    
    private void quickSort(ListNode head, ListNode tail) {
        if(head == tail || head.next == tail) return;
        
        int pivot = head.val;
        ListNode left = head;
        ListNode cur = head.next;
        while(cur != tail) {
            if(cur.val < pivot) {
                left = left.next;
                swapVal(left, cur);
            }
            
            cur = cur.next;
        }
        
        swapVal(head, left);
        
        quickSort(head, left);
        quickSort(left.next, tail);
    }
    
    private void swapVal(ListNode n1, ListNode n2) {
        int t = n1.val;
        n1.val = n2.val;
        n2.val = t;
    }
}
结果

在这里插入图片描述

YOLO11创新改进系列:卷积,主干 注意力,C3k2融合,检测头等创新机制(已更新110+) 本专栏提供详细的 YOLO11 教程,包括基础知识、源码解析、入门实践、算法改进和项目实战,适合发表YOLO11 学习者订阅。内容包含 100+多篇独家改进机制,适合发表论文,评分高达 96 分。订阅者将获得一键运行的改进文件及答疑交流群支持。 使用服务器的同学还可以私聊获取搭建好的运行环境。 阅读详情

相关推荐

ansys workbench 静力结构分析 高阶教程

ansys workbench 静力结构分析 高阶教程 目录ansys workbench 静力结构分析 高阶教程新建工程模型导入设置材料模型简化: 主要内容: 材料设置、模型简化、网格细化、约束分析、接触设置、求解设置、报错处理、结果分析 基础教程: ansys workbench 静力结构分析 基础操作流程(入门) ansys版本: 19.0(16.0及以上均可) 参考资料: 推荐教学视频《有限元分析 张晔》(超详细 ???? )、ansys workbench 超级学习手册(查阅用) 说明:一些基

weixin_43434624的博客 5万+

leetcode:148. 排序链表

题目来源 148. 排序链表 题目描述 题目解析 归并排序 时间复杂度O(nlogn),不考虑递归栈空间的话空间复杂度是O(1) 数组实现 核心: 21. 合并两个有序链表 归并排序的核心是一个merge()函数,其主要功能是实现两个有序链表的合并。 算法: 将链表从中间断开【快慢指针取中】,分成连部分,左右两边在分别分开。。。一直到只剩下一个节点【这个时候旧没有方法在拆分了】,然后就可以merge了 /** * Definition for singly-linked list. * public

OceanStar的博客 990

Shader Graph入门

Shader Graph 简介

zaizai1007的博客 1万+

【LeetCode】148. 排序链表

给你链表的头结点head,请将其按排列并返回。[1,2,3,4]head = [][]你可以在O(n log n)时间复杂度和常数级空间复杂度下,对链表进行排序吗?

m0_74197695的博客 1396

Dev C++调试程序方法详解

Dev C++调试程序方法详解

weixin_70641798的博客 1万+

Unity多渠道APK打包:同一工程稳定输出不冲突安装包

Android应用多渠道分发是移动开发的基础场景,其核心在于解决包名唯一性、渠道可识别性与构建可重复性三大问题。原理上,Unity安卓打包本质是三阶段流程:生成Android工程、Gradle编译、APK签名,而包名冲突根源在生成阶段对PlayerSettings的强依赖。技术价值体现在规避人工配置失误、支撑CI/CD自动化、满足华为/小米等商店合规要求。典型应用场景包括应用宝、TapTap、B站等渠道独立包管理,以及AB测试、灰度发布等运营需求。本文聚焦Unity原生方案,通过BuildPlayerOpt

weixin_33736048的博客 794

LeetCode 148.排序链表的五种解法

LeetCode 148.排序链表的五种解法 快速排序递归非递归 归并排序递归非递归 调用STL排序

CS_boy的博客 1417

保姆级教程:用Java和HslCommunication库搞定三菱PLC数据读写(附完整代码)

本文提供了一份详细的Java与三菱PLC通信教程,通过HslCommunication库实现高效数据读写。内容涵盖环境配置、通信模式选择、数据类型操作、异常处理及性能优化,并附有完整代码示例,帮助开发者快速掌握工业自动化中的PLC数据交互技术。

weixin_28731223的博客 227

LeetCode 排序链表

给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。 1、暴力方法,先将链表的值存放到一个数组中,然后对这个数组进行快速排序,然后只需要遍历这个数组,将对应的数组的值赋值给链表的节点即可。但是这样做的话需要开辟空间给数组。 对应的代码: class Solution { public ListNode sortList(ListNode head) { ListNode cur = head; List<Integer> list =

奋斗的龙猫的博客 676

使用protege推理小例子---关系链

使用protege推理小例子---关系链关系链推理 SubPropertityChain在Protege中使用关系链推理1、创建Person类2、创建对象关系3、添加实例4、进行推理5、推理结果 关系链推理 SubPropertityChain 关系链简单的说就是将多个关系表达式串联起来,如下图 1-1 图1-1 小明的父亲是大明,大明的父亲是老明。这就是一个由两组关系连接的关系链,根据关系链可以推理出,小明和老明之间的关系是爷孙关系。 在Protege中使用关系链推理 1、创建Person类 在Entit

weixin_45237780的博客 4457

【深度学习新浪潮】Nano Banana(Gemini 2.5 Flash Image)技术解析与开发者实操指南

重新定义了 AI 图像生成的产业标准。它不仅是“平民化的视觉工厂”,更是推动内容生产从“创意试错”转向“精准制造”的关键工具。未来,随着视频生成能力的加入(谷歌计划支持“文字指令 - 动态场景 - 多平台适配”全流程),Nano Banana 有望进一步颠覆影视、广告等领域的创作范式。:批量生成多场景图,模特姿态自然,服装褶皱和材质细节高度一致,节省 90% 拍摄成本。模型的非正式代号,是一款革命性的 AI 图像生成与编辑工具,主打。:生成细节丰富的厨师特写,光影自然,皮肤纹理和刀具反光逼真。

专注:太空算力、AI infra、异构调度、大模型成本工程 886

LeetCode 148——排序链表

1. 题目 2. 解答 2.1 快速排序 可参考 快速排序和归并排序 中的第一种快速排序思想,与在数组中排序有两点不同。 第一,我们需要取最后一个元素作为主元,在数组中可以直接访问到最后一个元素,但在单链表中,我们需要先遍历一遍链表才能访问到最后一个元素。 第二,在数组中,利用主元将数组划分为左右两个部分后,我们可以用下标来递归调用,但在链表中,我们改用头指针和尾指针来标识左右两个部分。如下图所...

seniusen的博客 2622

MCU-内部flash模拟成EepRom(重新梳理)

通过fee写数据Data的过程中,数据会mapping一个虚拟地址,这个虚拟地址就是你的身份,在向flash写数据的过程中会写入很多相同虚拟地址的不同数据,在读取或切页的过程中,遍历数据只会认为最下面第一个的虚拟地址所持有的数据是有效数据,其他的都是老数据,可以丢弃。模拟成eeprom的两个eep_page写数据逻辑就是,先在eep_page0写数据,eep_page0写满后,将eep_page0的有效数据copy到eep_page1,之后擦eep_page0;

xiandang8023的博客 711

148. 排序链表 - 力扣(LeetCode)

给你链表的头结点head,请将其按排列并返回。输入:head = [4,2,1,3]输出:[1,2,3,4输入:head = [-1,5,3,4,0]输出:[-1,0,3,4,5输入:head = []输出:[]你可以在O(n log n)时间复杂度和常数级空间复杂度下,对链表进行排序吗?

Dubhehug的博客 404

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

LeetCode 148:排序链表

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 解题思...

香农三定律的博客 217

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

LeetCode148——排序链表

我的LeetCode代码仓:https://github.com/617076674/LeetCode 原题链接:https://leetcode-cn.com/problems/sort-list/description/ 题目描述: 知识点:归并排序、链表 思路:自顶向下的归并排序 本题和LeetCode147——对链表进行插入排序其实是同一个问题——对链表进行排序操作,但是本题...

清风阁 1558

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

golang力扣leetcode 148.排序链表

148.排序链表148.排序链表题解代码 148.排序链表 148.排序链表 题解 时间复杂度是 O(nlogn) 的排序算法包括归并排序、堆排序和快速排序(快速排序的最差时间复杂度是 On2次,其中最适合链表的排序算法是归并排序。 坑点:链表中节点的数目在范围 [0, 5 * 104] 内,没注意节点可能为0,没写head == nil,排错排了好久 思路:归并排序,找中点和合并操作 代码 package main type ListNode struct { Val int Next *List

清风 869

Leetcode 148. 排序链表 C++

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 题解 归并排序的思想 用快慢指针找到中间的节点,归并排序的思想进行排序,详细过程见代码 代码 ListNode* sortList(

weixin_43750513的博客 109

Java实现 LeetCode 148 排序链表

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 PS: 参考:Sort List——经典(链表中的归并排序)...

南 墙 1万+

【力扣】148.排序链表

力扣 148题排序链表 c++解法

Father_Of_Soft的博客 377

Leetcode148. 排序链表

Leetcode148. 排序链表 题目: 在 O(nlogn)O(n log n)O(nlogn) 时间复杂度和常数级空间复杂度下,对链表进行排序。 示例 1: 输入: 4->2->1->3 输出: 1->2->3->4 示例 2: 输入: -1->5->3->4->0 输出: -1->0->3->4->5 题解: 归并排序+递归 java代码: /** * @param head * @ret

会流泪de鱼的博客 299

Leetcode148(力扣148):排序链表

class Solution { public: ListNode* sortList(ListNode* head) { ListNode dummyHead(0); dummyHead.next = head; auto p = head; int length = 0; while (p) { ++length; p = p->next; } .

weixin_44537258的博客 224

leetcode 148.排序链表

因为题目进阶要求我们使用常数级空间复杂度,此时不能用递归,采用迭代方式,直接进行归并。在这里我们主要使用快慢指针进行链表的分解,快指针一次走两步,慢指针一次走一步。设置dummynode哨兵节点,pre前序指针,h遍历指针来进行操作,归并思路,从长度为1开始,当归并长度大于等于链表长度说明归并完成。需要注意的点是,要注意当前归并序列是否满足归并长度,进行对应设置。其中Left指针指向左归并序列,right指向右归并序列。时间复杂度和常数级空间复杂度下,对链表进行排序吗?

qq_60461973的博客 839

力扣 148. 排序链表

步骤核心操作目的分快慢指针找中点 + 断开链表把原链表拆成两个独立子链表,降低问题规模治递归排序子链表解决最小子问题(空/单节点链表天然有序)合双指针合并有序链表把有序子结果合并成最终有序链表。

qq_52318674的博客 539
上一篇: Leetcode 147. 对链表进行插入排序
下一篇: Leetcode 160. 相交链表
一纸浮萍
博客等级 码龄9年 11粉丝 103原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值