Swift实现高效链表排序:一步步解读

在这里插入图片描述
在这里插入图片描述

文章目录

    • 前言
    • 摘要
    • 问题描述
    • 题解
      • 解题思路
      • Swift 实现代码
      • 代码分析
      • 示例测试与结果
    • 时间复杂度
    • 空间复杂度
    • 总结
    • 关于我们

前言

本题由于没有合适答案为以往遗留问题,最近有时间将以往遗留问题一一完善。

148. 排序链表

不积跬步,无以至千里;不积小流,无以成江海,Swift社区 伴你前行。如果大家有建议和意见欢迎在文末留言,我们会尽力满足大家的需求。

难度水平:中等

摘要

如何高效地对链表进行升序排序一直是算法中的经典问题之一。本文将深入解析如何使用Swift语言实现基于归并排序的链表排序算法,满足O(n log n)的时间复杂度和常数级空间复杂度的需求。同时,提供一段可运行的代码模块,帮助读者快速理解和实战。

问题描述

给定一个单链表的头结点head,要求对链表节点按升序排序并返回排序后的链表。

示例输入与输出

在这里插入图片描述

  • 示例 1:
    输入:head = [4, 2, 1, 3]
    输出:[1, 2, 3, 4]

在这里插入图片描述

  • 示例 2:
    输入:head = [-1, 5, 3, 4, 0]
    输出:[-1, 0, 3, 4, 5]

  • 示例 3:
    输入:head = []
    输出:[]

约束条件

  • 链表中的节点数范围:[0, 5 * 10^4]
  • 节点值范围:[-10^5, 10^5]

进阶要求

O(n log n)时间复杂度和常数级空间复杂度下完成链表排序。

题解

解题思路

归并排序是链表排序的理想选择,因其适合链表的顺序特性,并能够在O(n log n)时间复杂度内完成排序:

  1. 分割链表:递归地将链表从中间分为两个子链表,直到每个子链表只有一个节点。
  2. 合并有序链表:将两个已排序的链表按照升序合并成一个新的有序链表。

Swift 实现代码

class ListNode {var val: Intvar next: ListNode?init(_ val: Int) {self.val = valself.next = nil}
}func sortList(_ head: ListNode?) -> ListNode? {// 基本情况:空链表或只有一个节点guard let head = head, head.next != nil else {return head}// 使用快慢指针找到链表中点let mid = findMiddle(head)let rightHead = mid.nextmid.next = nil// 递归对两部分排序let left = sortList(head)let right = sortList(rightHead)// 合并排序后的两部分return merge(left, right)
}func findMiddle(_ head: ListNode) -> ListNode {var slow = headvar fast = headwhile fast.next != nil, fast.next?.next != nil {slow = slow.next!fast = fast.next!.next!}return slow
}func merge(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? {let dummy = ListNode(0)var current = dummyvar l1 = l1var l2 = l2while let node1 = l1, let node2 = l2 {if node1.val < node2.val {current.next = node1l1 = node1.next} else {current.next = node2l2 = node2.next}current = current.next!}current.next = l1 ?? l2return dummy.next
}

代码分析

  1. 查找链表中点

    • 使用快慢指针找到链表的中间节点并将链表分成两部分。
    • 时间复杂度:O(n)
    • 空间复杂度:O(1)
  2. 递归排序

    • 不断分割链表直到只有一个节点时停止递归,然后逐步合并已排序的链表。
  3. 合并有序链表

    • 使用双指针遍历两个已排序链表,按值大小将节点逐个合并。
    • 时间复杂度:O(n)
    • 空间复杂度:O(1)

示例测试与结果

测试代码

func printList(_ head: ListNode?) {var current = headvar result: [Int] = []while let node = current {result.append(node.val)current = node.next}print(result)
}// 创建示例链表:[4, 2, 1, 3]
let head = ListNode(4)
head.next = ListNode(2)
head.next?.next = ListNode(1)
head.next?.next?.next = ListNode(3)// 调用排序函数
let sortedHead = sortList(head)// 打印结果
printList(sortedHead) // 输出:[1, 2, 3, 4]

测试结果

  • 输入:[4, 2, 1, 3]
    输出:[1, 2, 3, 4]
  • 输入:[-1, 5, 3, 4, 0]
    输出:[-1, 0, 3, 4, 5]
  • 输入:[]
    输出:[]

时间复杂度

  • 分割链表:每次递归调用的时间为O(n),最多递归log n次,总复杂度为O(n log n)
  • 合并链表:每层递归的合并操作处理所有节点,总复杂度为O(n)

总时间复杂度:O(n log n)

空间复杂度

  • 除递归调用外无需额外的存储空间,递归栈空间为O(log n)

总空间复杂度:O(log n)

总结

本文展示了如何在Swift中使用归并排序对链表进行高效排序,从分割链表到合并排序,算法步骤清晰,代码简洁。无论是处理小型链表还是大型数据集,该方法都能够在O(n log n)的时间内完成排序,是面试和实际开发中的理想解决方案。

关于我们

我们是由 Swift 爱好者共同维护,我们会分享以 Swift 实战、SwiftUI、Swift 基础为核心的技术内容,也整理收集优秀的学习资料。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/482276.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开源 - Ideal库 - Excel帮助类,TableHelper实现(三)

书接上回&#xff0c;我们今天继续讲解实现对象集合与DataTable的相互转换。 01、把表格转换为对象集合 该方法是将表格的列名称作为类的属性名&#xff0c;将表格的行数据转为类的对象。从而实现表格转换为对象集合。同时我们约定如果类的属性设置了DescriptionAttribute特性…

基于DHCP,ACL的通信

该问题为华为的学习资料 1.首先把所有的PC机全部设置为DHCP 2.配置地址 3.ospf 4.dhcp 5.acl AR1 dhcp en interface GigabitEthernet0/0/0ip address 192.168.1.254 255.255.255.0 dhcp select global interface GigabitEthernet0/0/1ip address 10.1.12.1 255.255.255.…

基于深度学习的卷积神经网络十二生肖图像识别系统(PyQt5界面+数据集+训练代码)

本研究提出了一种基于深度学习的十二生肖图像识别系统&#xff0c;旨在利用卷积神经网络&#xff08;CNN&#xff09;进行图像分类&#xff0c;特别是十二生肖图像的自动识别。系统的核心采用了两种经典的深度学习模型&#xff1a;ResNet50和VGG16&#xff0c;进行图像的特征提…

探索温度计的数字化设计:一个可视化温度数据的Web图表案例

随着科技的发展&#xff0c;数据可视化在各个领域中的应用越来越广泛。在温度监控和展示方面&#xff0c;传统的温度计已逐渐被数字化温度计所取代。本文将介绍一个使用Echarts库创建的温度计Web图表&#xff0c;该图表通过动态数据可视化展示了温度值&#xff0c;并通过渐变色…

Attention显存统计与分析

Attention显存估计 简单的Attention函数 import torch import torch.nn as nn import einops class Attention(nn.Module):def __init__(self, dim, num_heads8, qkv_biasFalse, qk_scaleNone, attn_drop0., proj_drop0.):super().__init__()self.num_heads num_headshead_d…

[MacOS] [kubernetes] MacOS玩转虚拟化最佳实践

❓ 为什么不在MacOS本机安装呢&#xff1f;因为M系列芯片是Arm架构&#xff0c;与生产环境或者在本地调试时候&#xff0c;安装虚拟镜像和X86不同&#xff0c;造成不必要的切换环境的额外成本&#xff0c;所以在虚拟化的x86调试 步骤 & 详情 一: 安装OrbStack & 并配置…

Unity世界坐标转屏幕坐标报错解决办法。

问题描述&#xff0c;如果你在脚本中尝试使用Camera.转换世界坐标的时候发现点不出来&#xff0c;可以点到你的Camera这个方法看能否跳转&#xff0c;如果能够跳转&#xff0c;并且这个脚本是你自己写的&#xff0c;那么恭喜你&#xff0c;下面就是解决办法&#xff0c;直接将C…

系统监控——分布式链路追踪系统

摘要 本文深入探讨了分布式链路追踪系统的必要性与实施细节。随着软件架构的复杂化&#xff0c;传统的日志分析方法已不足以应对问题定位的需求。文章首先解释了链路追踪的基本概念&#xff0c;如Trace和Span&#xff0c;并讨论了其基本原理。接着&#xff0c;文章介绍了SkyWa…

IAR中编译下载未下载问题

第一张图片是正常下载&#xff0c;第二张未正常下载。经过查看download选项发现 启用了 suppress download &#xff08;禁用下载)

【UE5 C++】判断两点连线是否穿过球体

目录 前言 原理 代码 测试 结果 前言 通过数学原理判断空间中任意两点的连线是否穿过球体&#xff0c;再通过射线检测检验算法的正确性。 原理 &#xff08;1&#xff09;设球体球心的坐标为 &#xff0c;半径为r&#xff1b; &#xff08;2&#xff09;设线段中A点的坐…

网络安全之IP伪造

眼下非常多站点的涉及存在一些安全漏洞&#xff0c;黑客easy使用ip伪造、session劫持、xss攻击、session注入等手段危害站点安全。在纪录片《互联网之子》&#xff08;建议搞IT的都要看下&#xff09;中。亚伦斯沃茨&#xff08;真实人物&#xff0c;神一般的存在&#xff09;涉…

《运放秘籍》第二部:仪表放大器专项知识点总结

一、差分放大器与仪表放大器的讨论 1.1. 仪放的前世今生——差分放大器原理&#xff1f; 1.2. 差分放大的原理 1.3. 差分放大器检测电流 1.4. 差分放大器端一&#xff1a;输入阻抗 1.5. 差分放大器端二&#xff1a;共模抑制比 1.6. 为什么关注输入阻抗&#xff1f;共模抑…

AJAX一、axios使用,url组成(协议,域名,资源路径)查询参数和化简,错误处理,请求/响应报文,状态码,接口文档,

一、AJAX是什么 概念 &#xff1a; AJAX是一种与服务器&#xff08;后端&#xff09;通信的技术 二、请求库axios的基本用法 1导包 2使用 // 1. 发请求 axios({ url: 请求地址 }).then(res > { // 2.接收并使用数据 }) <body><p class"province"…

关于ConstarintLayout有关的点

目录 一、概述 二、过程。 1、介绍 主要特点 关键概念 使用示例 总结 2、我遇到的问题 问题&#xff1a; 可能的原因&#xff1a; 结论 一、概述 在学习过程中&#xff0c;发现对ConstarintLayout理解不够到位&#xff0c;下面是发现并解决问题过程。 二、过程。 1…

【UE5 C++课程系列笔记】06——定时器的基本使用

目标 使用定时器每秒调用函数打印一句日志信息&#xff0c;并在调用一定次数后停止定时器。 步骤 1. 新建一个Actor类&#xff0c;这里命名为 2. 先在“TimerActor.cpp”中获取定时器管理器 使用定时器管理器来设置定时器&#xff0c;该定时器在2s后启动&#xff0c;然后每…

用c语言完成俄罗斯方块小游戏

用c语言完成俄罗斯方块小游戏 这估计是你在编程学习过程中的第一个小游戏开发&#xff0c;怎么说呢&#xff0c;在这里只针对刚学程序设计的学生&#xff0c;就是说刚接触C语言没多久&#xff0c;有一点功底的学生看看&#xff0c;简陋的代码&#xff0c;简陋的实现&#xff0…

iQOO Neo10系列携三大蓝科技亮相,性能与续航全面升级

11月29日&#xff0c;iQOO Neo10系列正式登场。作为iQOO Neo系列的最新力作&#xff0c;Neo10系列不仅延续了该系列一贯的“双芯”特色&#xff0c;更在性能、续航、屏幕、影像等多个方面实现了全面升级&#xff0c;为用户带来前所未有的使用体验。此次发布的Neo10系列共有两款…

springboot信息化在线教学平台的设计与实现(代码+数据库+LW)

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了信息化在线教学平台的开发全过程。通过分析信息化在线教学平台管理的不足&#xff0c;创建了一个计算机管理信息化在线教学平台的方案。文章介绍了信息化在线教…

DataX实战|使用Python 构建简易的DataX数据血缘工具(一)

导读&#xff1a; 在这篇文章中&#xff0c;我介绍了如何使用 Python 构建简易的 DataX 数据血缘工具&#xff0c;以便解决 DataXWeb 在查询表上下游关系时的不足。 选择 Flask 作为框架&#xff0c;利用 DataXWeb 的元数据 job_info 表和 job_json&#xff0c;通过 JSON 解析…

Android 14之HIDL转AIDL通信

Android 14之HIDL转AIDL通信 1、interface接口1.1 接口变更1.2 生成hidl2aidl工具1.3 执行hidl2aidl指令1.4 修改aidl的Android.bp文件1.5 创建路径1.6 拷贝生成的aidl到1和current1.7 更新与冻结版本1.8 编译模块接口 2、服务端代码适配hal代码修改2.1 修改Android.bp的hidl依…