本文为Python算法题集之一的代码示例
给你链表的头结点 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 * 104]
内-105 <= Node.val <= 105
**进阶:**你可以在 O(n log n)
时间复杂度和常数级空间复杂度下,对链表进行排序吗?
通常优化:减少循环层次
通常优化:增加分支,减少计算集
通常优化:采用内置算法来提升计算速度
分析题目特点,分析最优解
链表的排序算法极为耗时
可以采用归并法对链表进行拆分然后合并
可以用列表排序法进行简单排序
CheckFuncPerf
(本地化函数用时和内存占用测试模块)已上传到CSDN,地址:Python算法题集_检测函数用时和内存占用的模块链表双层,每次循环将一个最大值移到尾部,毫无意外的超时
import CheckFuncPerf as cfp
class Solution:
@staticmethod
def sortList_base(head):
if not head:
return head
if not head.next:
return head
bexchange = True
tmphead = ListNode(-1)
tmphead.next = head
tmpNode = tmphead
while bexchange and tmpNode:
bexchange = False
startNode = tmpNode
while startNode:
if startNode.next:
nextnode = startNode.next
if startNode.next.next:
nextnode2 = nextnode.next
if nextnode.val > nextnode2.val:
tmpNext = nextnode2.next
startNode.next = nextnode2
nextnode2.next = nextnode
nextnode.next = tmpNext
bexchange = True
startNode = startNode.next
return tmphead.next
result = cfp.getTimeMemoryStr(Solution.sortList_base, ahead)
print(result['msg'], '执行结果 = {}'.format(result['result'].val))
# 运行结果【链表长度1W】
函数 sortList_base 的运行时间为 20534.61 ms;内存使用量为 4.00 KB 执行结果 = 1
将链表存入列表结构,通过列表排序,最后再连接起来,性能优异,内存O(n)
import CheckFuncPerf as cfp
class Solution:
@staticmethod
def sortList_ext1(head):
if not head:
return head
if not head.next:
return head
list_node = []
while head:
list_node.append([head.val, head])
head = head.next
sort_list = sorted(list_node, key=lambda x: x[0])
for iIdx in range(len(sort_list)-1):
sort_list[iIdx][1].next = sort_list[iIdx+1][1]
sort_list[-1][1].next = None
return sort_list[0][1]
result = cfp.getTimeMemoryStr(Solution.sortList_ext1, ahead)
print(result['msg'], '执行结果 = {}'.format(result['result'].val))
# 运行结果【链表长度1W】
函数 sortList_ext1 的运行时间为 2.99 ms;内存使用量为 16.00 KB 执行结果 = 1
使用递归设计,用值定位将链表拆分排序;递归的最大层次为990,因此链表长度在2^990次方内都不会溢出
import CheckFuncPerf as cfp
class Solution:
@staticmethod
def sortList_ext2(head):
if not head:
return head
min_val = max_val = head.val
curnode = head
while curnode:
min_val = min(min_val, curnode.val)
max_val = max(max_val, curnode.val)
curnode = curnode.next
if min_val == max_val:
return head
mid_val = (min_val + max_val) // 2
head1 = ListNode(0)
last1 = head1
head2 = ListNode(0)
last2 = head2
curnode = head
while curnode:
if curnode.val <= mid_val:
last1.next = curnode
last1 = last1.next
else:
last2.next = curnode
last2 = last2.next
curnode = curnode.next
last1.next = None
last2.next = None
head1 = Solution.sortList_ext2(head1.next)
head2 = Solution.sortList_ext2(head2.next)
curnode = head1
while curnode.next:
curnode = curnode.next
curnode.next = head2
return head1
result = cfp.getTimeMemoryStr(Solution.sortList_ext2, ahead)
print(result['msg'], '执行结果 = {}'.format(result['result'].val))
# 运行结果
函数 sortList_ext2 的运行时间为 71.03 ms;内存使用量为 0.00 KB 执行结果 = 1
使用递归设计,用快慢指针将链表拆分排序;递归的最大层次为990,因此链表长度在2^990次方内都不会溢出
import CheckFuncPerf as cfp
class Solution:
@staticmethod
def sortList_ext3(head):
if not head or not head.next:
return head
slownode, fastnode = head, head.next
while fastnode and fastnode.next:
fastnode, slownode = fastnode.next.next, slownode.next
midnode, slownode.next = slownode.next, None
leftlink, rightlink = Solution.sortList_ext3(head), Solution.sortList_ext3(midnode)
tmpnode = headnode = ListNode(0)
while leftlink and rightlink:
if leftlink.val < rightlink.val:
tmpnode.next, leftlink = leftlink, leftlink.next
else:
tmpnode.next, rightlink = rightlink, rightlink.next
tmpnode = tmpnode.next
tmpnode.next = leftlink if leftlink else rightlink
return headnode.next
result = cfp.getTimeMemoryStr(Solution.sortList_ext3, ahead)
print(result['msg'], '执行结果 = {}'.format(result['result'].val))
# 运行结果
函数 sortList_ext3 的运行时间为 19.02 ms;内存使用量为 0.00 KB 执行结果 = 1
根据本地日志分析,最优算法为第2种sortList_ext1
,如果内存要O(1)的话,则最优算法为第4种sortList_ext3
iLen = 10000
nums = [iLen - x for x in range(iLen)]
def generateOneLinkedList(data):
head = ListNode()
current_node = head
for num in data:
new_node = ListNode(num)
current_node.next = new_node
current_node = new_node
return head.next
ahead = generateOneLinkedList(nums)
result = cfp.getTimeMemoryStr(Solution.sortList_base, ahead)
print(result['msg'], '执行结果 = {}'.format(result['result'].val))
# 算法本地速度实测比较
函数 sortList_base 的运行时间为 20534.61 ms;内存使用量为 4.00 KB 执行结果 = 1
函数 sortList_ext1 的运行时间为 2.99 ms;内存使用量为 16.00 KB 执行结果 = 1
函数 sortList_ext2 的运行时间为 71.03 ms;内存使用量为 0.00 KB 执行结果 = 1
函数 sortList_ext3 的运行时间为 19.02 ms;内存使用量为 0.00 KB 执行结果 = 1
一日练,一日功,一日不练十日空
may the odds be ever in your favor ~