題目描述:在 o(n log n) 時間複雜度和常數級空間複雜度下,對鍊錶進行排序。例如:輸入: 4->2->1->3
輸出: 1->2->3->4。
思路分析:因為要求在o(nlogn)的時間複雜度,所以想到使用歸併排序。下面對歸併排序做個介紹。
歸併排序
基本方法如下:
(1)把待排序序列的n個記錄看成n個有序子串行,每個子串行長度為1.
(2)把當時序列組裡的有序子串行兩兩歸併,完成一遍後序列組裡的排序序列個數減半,每個子串行長度加倍。
(3)對加長有序子串行重複(2)操作,最終得到乙個n的有序序列。
def
merge
(list_left, list_right)
:"""
入引數組都是有序的,此處將兩個有序陣列合併成乙個大的有序陣列
"""# 兩個陣列的起始下標
l, r =0,
0 new_list =
while l <
len(list_left)
and r <
len(list_right)
:if list_left[l]
< list_right[r]:)
l +=
1else:)
r +=
1 new_list += list_left[l:
] new_list += list_right[r:
]return new_list
defmerge_sort
(mylist)
:"""歸併排序
mylist: 待排序陣列
return: 新陣列list
"""iflen
(mylist)
<=1:
return mylist
mid =
len(mylist)//2
list_left = merge_sort(mylist[
:mid]
) list_right = merge_sort(mylist[mid:])
return merge(list_left, list_right)
對應這題,由於是鍊錶,我們無法直接得到鍊錶的中點,這可以通過快慢指標得到,在合併兩個有序鍊錶時需要建立乙個臨時指標,注意與陣列合併的不同,可以自己在紙上嘗試一下節點是如何轉換的。
# definition for singly-linked list.
class
listnode
:def
__init__
(self, x)
: self.val = x
self.
next
=none
class
solution
:def
sortlist
(self, head: listnode)
-> listnode:
ifnot head or
not head.
next
:return head
mid = self.getmid(head)
rhead, mid.
next
= mid.
next
,none
return self.mergesort(self.sortlist(head)
,self.sortlist(rhead)
)def
getmid
(self,head):if
not head:
return head
slow = fast = head
while fast.
next
and fast.
next
.next
: slow, fast = slow.
next
, fast.
next
.next
return slow
defmergesort
(self,lhead,rhead)
: dummy = cur = listnode(0)
#使用了額外的空間,因此時間複雜度不是常數級。
while lhead and rhead:
if lhead.val<=rhead.val:
cur.
next
, lhead = lhead,lhead.
next
else
: cur.
next
, rhead = rhead,rhead.
next
cur = cur.
next
cur.
next
= lhead or rhead
return dummy.
next
迭代的歸併排序
class
listnode
:def
__init__
(self, x)
: self.val = x
self.
next
=none
class
solution
:def
sortlist
(self, head: listnode)
-> listnode:
h, length, intv = head,0,
1while h: h, length = h.
next
, length +
1 res = listnode(0)
res.
next
= head
# merge the list in different intv.
while intv < length:
pre, h = res, res.
next
while h:
# get the two merge head `h1`, `h2`
h1, i = h, intv
while i and h: h, i = h.
next
, i -
1if i:
break
# no need to merge because the `h2` is none.
h2, i = h, intv
while i and h: h, i = h.
next
, i -
1 c1, c2 = intv, intv - i # the `c2`: length of `h2` can be small than the `intv`.
# merge the `h1` and `h2`.
while c1 and c2:
if h1.val < h2.val: pre.
next
, h1, c1 = h1, h1.
next
, c1 -
1else
: pre.
next
, h2, c2 = h2, h2.
next
, c2 -
1 pre = pre.
next
pre.
next
= h1 if c1 else h2
while c1 >
0or c2 >
0: pre, c1, c2 = pre.
next
, c1 -
1, c2 -
1 pre.
next
= h intv *=
2return res.
next
leetcode 鍊錶排序
對鍊錶排序,用歸併排序。題目要求空間時間複雜度為o nlogn 但是空間複雜度為o 1 1.自己寫的程式,時間複雜度為o nlogn 但是空間複雜度為o n 用快慢指標 分別走2步和1步 找到中間節點。但是最後排序的部分,用複製將排好序的部分貼上會原來鍊錶中,這個方法比較笨,而且增加空間複雜度,並不...
leetcode 鍊錶 排序
思路 使用歸併排序。拆分 合併均採用遞迴方式。public listnode sortlist listnode head pre.next null return merge sortlist head sortlist slow public listnode merge listnode l1...
leetcode 排序鍊錶
利用歸併排序的思想,不過這裡排序的不是列表,是乙個鍊錶。具體 如下 definition for singly linked list.class listnode object def init self,x self.val x self.next none class solution obj...