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

news2025/2/7 10:37:01

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

文章目录

    • 前言
    • 摘要
    • 问题描述
    • 题解
      • 解题思路
      • 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: Int
    var next: ListNode?

    init(_ val: Int) {
        self.val = val
        self.next = nil
    }
}

func sortList(_ head: ListNode?) -> ListNode? {
    // 基本情况:空链表或只有一个节点
    guard let head = head, head.next != nil else {
        return head
    }

    // 使用快慢指针找到链表中点
    let mid = findMiddle(head)
    let rightHead = mid.next
    mid.next = nil

    // 递归对两部分排序
    let left = sortList(head)
    let right = sortList(rightHead)

    // 合并排序后的两部分
    return merge(left, right)
}

func findMiddle(_ head: ListNode) -> ListNode {
    var slow = head
    var fast = head

    while 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 = dummy
    var l1 = l1
    var l2 = l2

    while let node1 = l1, let node2 = l2 {
        if node1.val < node2.val {
            current.next = node1
            l1 = node1.next
        } else {
            current.next = node2
            l2 = node2.next
        }
        current = current.next!
    }

    current.next = l1 ?? l2
    return dummy.next
}

代码分析

  1. 查找链表中点

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

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

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

示例测试与结果

测试代码

func printList(_ head: ListNode?) {
    var current = head
    var 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.coloradmin.cn/o/2251744.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

mysql系列2—InnoDB数据存储方式

背景 本文将深入探讨InnoDB的底层存储机制&#xff0c;包括行格式、页结构、页目录以及表空间等核心概念。通过全面了解这些基础概念&#xff0c;有助于把握MySQL的存储架构&#xff0c;也为后续深入讨论MySQL的索引原理和查询优化策略奠定了基础。 1.行格式 mysql中数据以行…

vue实现echarts饼图自动轮播

echarts官网&#xff1a;Examples - Apache ECharts echartsFn.ts 把echarts函数封装成一个文件 import * as echarts from "echarts";const seriesData [{"value": 12,"name": "过流报警"},{"value": 102,"name&qu…

【Python数据分析五十个小案例】使用自然语言处理(NLP)技术分析 Twitter 情感

博客主页&#xff1a;小馒头学python 本文专栏: Python爬虫五十个小案例 专栏简介&#xff1a;分享五十个Python爬虫小案例 项目简介 什么是情感分析 情感分析&#xff08;Sentiment Analysis&#xff09;是文本分析的一部分&#xff0c;旨在识别文本中传递的情感信息&…

网络安全防护指南:筑牢网络安全防线(5/10)

一、网络安全的基本概念 &#xff08;一&#xff09;网络的定义 网络是指由计算机或者其他信息终端及相关设备组成的按照一定的规则和程序对信息收集、存储、传输、交换、处理的系统。在当今数字化时代&#xff0c;网络已经成为人们生活和工作中不可或缺的一部分。它连接了世…

宏海科技募资额有所缩减,最大销售和采购都重度依赖美的集团

《港湾商业观察》施子夫 11月29日&#xff0c;北交所上市审核委员会将召开2024年第24次上市委审议会议&#xff0c;届时将审议武汉宏海科技股份有限公司&#xff08;以下简称&#xff0c;宏海科技&#xff09;的首发上会事项。 在上会之前&#xff0c;宏海科技共收到北交所下…

算法日记 36-38day 动态规划

今天把动态规划结束掉&#xff0c;包括子序列以及编辑距离 题目&#xff1a;最长公共子序列 1143. 最长公共子序列 - 力扣&#xff08;LeetCode&#xff09; 给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 &…

Gopeed 1.6.3 | 不限速下载工具附百度网盘不限速教程

Gopeed是一款高效且易于使用的下载软件。它具有加速下载速度的功能&#xff0c;可以帮助用户更快地下载文件。此外&#xff0c;Gopeed还支持多线程下载&#xff0c;可以同时下载多个文件&#xff0c;提高下载效率。它提供了简洁的界面和简单的操作&#xff0c;方便用户操作和管…

K8S版本和istio版本的对照关系

版本对照关系 下载地址1 下载地址2

【大数据学习 | Spark-SQL】关于RDD、DataFrame、Dataset对象

1. 概念&#xff1a; RDD&#xff1a; 弹性分布式数据集&#xff1b; DataFrame&#xff1a; DataFrame是一种以RDD为基础的分布式数据集&#xff0c;类似于传统数据库中的二维表格。带有schema元信息&#xff0c;即DataFrame所表示的二维表数据集的每一列都带有名称和类型…

如何调用百度文心一言API实现智能问答

诸神缄默不语-个人CSDN博文目录 百度需要先认证个人信息才能使用LLM API。 文章目录 1. 获得 API Key2. 撰写代码并实现提问和回答2.1 用openai包实现调用2.2 用openai包实现流式调用2.3 用openai包实现工具调用2.4 构建智能体2.5 文生图2.6 图生图 3. 用gradio建立大模型问答…

python除了熟悉的pandas,openpyxl库也很方便的支持编辑Excel表

excel表格是大家经常用到的文件格式&#xff0c;各行各业都会跟它打交道。之前文章我们介绍了使用openpyxl和xlrd库读取excel表数据&#xff0c;使用xlwt库创建和编辑excel表&#xff0c;在办公自动化方面可以方便我们快速处理数据&#xff0c;帮助我们提升效率。 python之open…

JMeter 并发策略-针对准点秒杀场景的压测实现

一、场景的压测实现 1&#xff0c;创建线程组&#xff0c;10并发用户执行5次&#xff1b; 2&#xff0c;创建 Synchronizing Timer 元件,用于同步线程&#xff0c;设置同步元件 Synchronizing Timer 3&#xff0c;创建 http 请求4&#xff0c;创建 view results in table 元件…

损失函数分类

1. NLLLoss&#xff08;负对数似然损失&#xff09; 定义&#xff1a; 直接对预测的概率 p(yi) 的负对数求平均。通常配合 Softmax 使用&#xff0c;输入为对数概率。 优点&#xff1a; 对离散分类问题效果良好。更灵活&#xff0c;用户可以自行计算 Softmax。 缺点&#x…

【热门主题】000072 分布式数据库:开启数据管理新纪元

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 【热…

算法笔记:力扣148. 排序链表

思路&#xff1a; 将链表中的节点一一取出放到list集合中&#xff0c;然后通过Comparator实现排序&#xff0c;对排序好的list节点一一取出&#xff0c;组成排序好的新链表。 关键思路&#xff1a; Comparator实现对ListNode的排序&#xff1b; &#x1f4a1;注意&#xff…

Kafka知识体系

一、认识Kafka 1. kafka适用场景 消息系统&#xff1a;kafka不仅具备传统的系统解耦、流量削峰、缓冲、异步通信、可扩展性、可恢复性等功能&#xff0c;还有其他消息系统难以实现的消息顺序消费及消息回溯功能。 存储系统&#xff1a;kafka把消息持久化到磁盘上&#xff0c…

MacOS安装MySQL数据库和Java环境以及Navicat

安装MySQL 去官网下载&#xff1a;MySQL 下载好后安装&#xff0c;在设置里往下滑&#xff0c;出现了这样&#xff0c;就代表安装成功了 接下来配置环境&#xff1a; 首先在我们的设备上找到终端并打开,输入 vim ~/.bash_profile(注意vim后面的空格)&#xff0c;输入完成后点击…

Css、less和Sass(SCSS)的区别详解

文章目录 Css、less和Sass&#xff08;SCSS&#xff09;的区别详解一、引言二、CSS 简介1.1、CSS 示例 三、Less 简介2.1、Less 特性2.2、Less 示例 四、Sass&#xff08;SCSS&#xff09;简介3.1、Sass 特性3.2、SCSS 示例 五、总结 Css、less和Sass&#xff08;SCSS&#xff…

misc-好久不见17

wireshark_secret Ctrlshirtv 8、热心助人的小明同学 使用工具volatility查看镜像的信息 volatility_2.6_win64_standalone -f image.raw imageinfo 列出所有用户和密码&#xff1a; volatility_2.6_win64_standalone -f image.raw --profileWin7SP1x86_23418 hashdump Xi…

利用PyTorch Profiler实现大模型的性能分析和故障排查

本文介绍PyTorch Profiler结合TensorBoard分析模型性能&#xff0c;分别从数据加载、数据传输、GPU计算、模型编译等优化思路去提升模型训练的性能。最后总结了一些会导致CPU和GPU同步的常见的PyTorch API&#xff0c;在使用这些API时需要考虑是否会带来性能影响。 PyTorch Pr…