-
Notifications
You must be signed in to change notification settings - Fork 0
/
code148SortList.py
128 lines (109 loc) · 3.89 KB
/
code148SortList.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
from ListNode import *
"""
148 Sort List
Sort a linked list in O(n log n) time using constant space complexity.
"""
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
# similar to merge sort, starting from sorting every two nodes, then every four node, then every 8 nodes... until 2^m >= n
class Solution:
def mergeSortedList(self, head, n):
"""
divide and merge sorted lists
return the head and tail of the merged sorted list
|----left half-----|----right half----|----following----|
"""
# get the tail of the left half list
node = head
for i in range(1, n//2):
if node.next is not None:
node = node.next
else:
return (head, node)
# get the head of the right half list
head1 = node.next
if head1 is None: # bug fixed: missed this corner case: the head of the right half list is empty
return (head, node)
node.next = None # disconnect left half list and right half list
# get the head of the following list after this merged list
node = head1
for i in range(1, n//2):
if node.next is not None:
node = node.next
next_head = node.next
node.next = None # disconnect right half list with the following list
# aux head node
zero = ListNode(0)
node = zero
# merge the two sorted lists
while head or head1:
if head is None:
node.next = head1
head1 = head1.next
elif head1 is None:
node.next = head
head = head.next
else:
if head.val < head1.val:
node.next = head
head = head.next
else:
node.next = head1
head1 = head1.next
node = node.next
node.next = next_head
return (zero.next, node)
def sortList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if head is None:
return None
period = 2
while True:
(head, tail) = self.mergeSortedList(head, period)
if tail.next is None:
break
while tail.next is not None:
(new_head, new_tail) = self.mergeSortedList(tail.next, period)
tail.next = new_head # bug fixed: we need to connect the previous tail with the new head
tail = new_tail
period *= 2
return head
# recursive merge sort
def sortList(self, head: ListNode) -> ListNode:
if not head or not head.next:
return head
pseudoHead = ListNode(0)
pseudoHead.next = head
# find the mid node
fast, mid = pseudoHead, pseudoHead
while fast and fast.next:
fast = fast.next.next
mid = mid.next
right, mid.next = mid.next, None
# recursively sort left and right part
left, right = self.sortList(head), self.sortList(right)
pre = pseudoHead
# merge two lists
while left or right:
lVal = 2**31 if not left else left.val
rVal = 2**31 if not right else right.val
if lVal < rVal:
pre.next = left
left = left.next
else:
pre.next = right
right = right.next
pre = pre.next
return pseudoHead.next
obj = Solution()
l1 = ListNode(0)
l1.fromList([8,1,3])
PrintLinkedList(l1)
l2 = obj.sortList(l1)
PrintLinkedList(l2)