![Go程序员面试算法宝典](https://wfqqreader-1252317822.image.myqcloud.com/cover/262/26268262/b_26268262.jpg)
上QQ阅读APP看书,第一时间看更新
1.4 如何对链表进行重新排序
难度系数:★★★☆☆
被考查系数:★★★★☆
题目描述:
给定链表L0->L1->L2…Ln-1->Ln,把链表重新排序为L0->Ln->L1->Ln-1->L2->Ln-2…。要求:①在原来链表的基础上进行排序,即不能申请新的结点;②只能修改结点的next域,不能修改数据域。
分析与解答:
主要思路为:①首先找到链表的中间结点;②对链表的后半部分子链表进行逆序;③把链表的前半部分子链表与逆序后的后半部分子链表进行合并,合并的思路为:分别从两个链表各取一个结点进行合并。实现方法如下图所示:
![](https://epubservercos.yuewen.com/C814A1/14700476404565706/epubprivate/OEBPS/Images/44_01.jpg?sign=1739260461-NJGvSovuHMs3WP9cDJXkZCKIlFyo1p01-0-110d4e750542c38bf5789c131b9d1ba1)
实现代码如下:
![](https://epubservercos.yuewen.com/C814A1/14700476404565706/epubprivate/OEBPS/Images/44_02.jpg?sign=1739260461-HQV2jAYRZxpU4kJL8zNQwkDBNH4nUHf4-0-010d80d7e51f162405865b14310d0d71)
![](https://epubservercos.yuewen.com/C814A1/14700476404565706/epubprivate/OEBPS/Images/45_01.jpg?sign=1739260461-eiGVhx1A6hdXH2TTISaOiz3pkjULSVGP-0-61fb82d691bc1ca98834e2a8fbc9fbdc)
![](https://epubservercos.yuewen.com/C814A1/14700476404565706/epubprivate/OEBPS/Images/46_01.jpg?sign=1739260461-OKZSZjog1qXaBL5FpaQEpjmDLV8tMWrv-0-8d17b60aff6fa05853ea8a68376b8008)
程序的运行结果为
![](https://epubservercos.yuewen.com/C814A1/14700476404565706/epubprivate/OEBPS/Images/46_02.jpg?sign=1739260461-mxQK4eCP00rI4em9EQnsj0Id9LaT3c30-0-d3ba125d8bc44c26bbf66072bb4d8206)
算法性能分析:
查找链表中间结点的方法的时间复杂度为O(n),逆序子链表的时间复杂度也为O(n),合并两个子链表的时间复杂度也为O(n),因此,整个方法的时间复杂度为O(n),其中,n表示的是链表的长度。由于这种方法只用了常数个额外指针变量,因此,空间复杂度为O(1)。
引申:如何查找链表的中间结点。
分析与解答:
主要思路:用两个指针从链表的第一个结点开始同时遍历结点,一个快指针每次走2步,另外一个慢指针每次走1步;当快指针先到链表尾部时,慢指针则恰好到达链表中部。(快指针到链表尾部时,当链表长度为奇数时,慢指针指向的即是链表中间指针,当链表长度为偶数时,慢指针指向的结点和慢指针指向的结点的下一个结点都是链表的中间结点),上面的代码FindMiddleNode就是用来求链表的中间结点的。