「这是我参与11月更文挑战的第 14 天,活动详情查看:2021最后一次更文挑战」
刷算法题,从来不是为了记题,而是练习把实际的问题抽象成具体的数据结构或算法模型,然后利用对应的数据结构或算法模型来进行解题。个人觉得,带着这种思维刷题,不仅能解决面试问题,也能更多的学会在日常工作中思考,如何将实际的场景抽象成相应的算法模型,从而提高代码的质量和性能
单链表的排序
题目来源:LeetCode-148. 排序链表
题目描述
给你链表的头结点 head
,请将其按 升序 排列并返回 排序后的链表
进阶:
你可以在 O(n log n)
时间复杂度和常数级空间复杂度下,对链表进行排序吗?
示例
示例 1
1 | ini复制代码输入:head = [4,2,1,3] |
示例 2
1 | ini复制代码输入:head = [-1,5,3,4,0] |
示例 3
1 | ini复制代码输入:head = [] |
提示:
解题
解法一:暴力解法
思路
首先看到是排序,我们肯定就想到那八大排序算法,但是因为要排序的是链表,就很难用那八大排序算法了,因为链表不支持根据下标随机访问
不能使用就想办法使用,把链表遍历一遍,把值取出来放到一个数组中,然后对数组中的元素进行排序。之后再按顺序将排序后的数组元素,连接成一个链表
暴力解法思路很简单,如果用快排,它的时间复杂度是O(nlog),因为需要一个新的链表,所以需要额外的空间,空间复杂度是链表元素的个数,也就是o(n)
这里就不放代码了,主要看下边这种排序方法
解法二:归并排序
思路
有人一看到归并排序,可能就想到它的空间复杂度并不是O(1),但是我们要排的元素是存在链表里的,不是数组,我们可以在O(1)的空间复杂度,实现两个链表的合并
归并排序本质上是一种分治思想,本题就是将链表不断的一分为二,当链表分到一定程度的时候,就只剩一个结点的时候,那它就是有序的,那再将有序链表合并,最后这个链表不就是有序的了吗?
归并排序主要是找中间位置,链表找中间位置很简单,用快慢指针。慢指针,一次移动一个结点,快指针一次移动两个节点,当快指针到达链表的尾部的时候,慢指针的位置就是链表的中点位置
不清楚归并排序过程的,可以看这里(有图)
代码
1 | ini复制代码//链表排序 |
本文转载自: 掘金