题目:
148. 排序链表
题解:
归并排序的基本思想是: 找到链表的middle节点,然后递归对前半部分和后半部分分别进行归并排序,最后对两个以排好序的链表进行Merge。
1. 题解一:归并排序(递归法)(首选)
21. 合并两个有序链表 876. 链表的中间结点
2. 题解二:归并排序(从底至顶直接合并)
current
= dummy
.next
;
tail
= dummy
;
for (step
= 1; step
< length
; step
*= 2) {
while (current
) {
left
= current
;
right
= cut(current
, step
);
current
= cut(right
, step
);
tail
.next
= merge(left
, right
);
while (tail
->next
) tail
= tail
->next
;
}
}
代码:
1. 代码一:归并排序(递归法)(首选)
public class code148_1 {
public static ListNode
sortList(ListNode head
) {
if(head
== null
|| head
.next
== null
)
{
return head
;
}
ListNode midNode
= middleNode(head
);
ListNode rightHead
= midNode
.next
;
midNode
.next
= null
;
ListNode left
= sortList(head
);
ListNode right
= sortList(rightHead
);
return mergeTwoLists(left
, right
);
}
public static ListNode
middleNode(ListNode head
) {
if(head
== null
)
{
return null
;
}
ListNode slow
= head
;
ListNode fast
= head
;
while(fast
.next
!= null
&& fast
.next
.next
!= null
)
{
slow
= slow
.next
;
fast
= fast
.next
.next
;
}
return slow
;
}
public static ListNode
mergeTwoLists(ListNode l1
, ListNode l2
) {
ListNode dummy
= new ListNode(0);
ListNode cur
= dummy
;
while(l1
!= null
&& l2
!= null
)
{
if(l1
.val
< l2
.val
)
{
cur
.next
= l1
;
cur
= cur
.next
;
l1
= l1
.next
;
}
else
{
cur
.next
= l2
;
cur
= cur
.next
;
l2
= l2
.next
;
}
}
if(l1
== null
)
{
cur
.next
= l2
;
}
else
{
cur
.next
= l1
;
}
return dummy
.next
;
}
private static ListNode
createLinkedList(int[] arr
) {
if (arr
.length
== 0) {
return null
;
}
ListNode head
= new ListNode(arr
[0]);
ListNode current
= head
;
for (int i
= 1; i
< arr
.length
; i
++) {
current
.next
= new ListNode(arr
[i
]);
current
= current
.next
;
}
return head
;
}
private static void printLinkedList(ListNode head
) {
ListNode current
= head
;
while (current
!= null
) {
System
.out
.printf("%d -> ", current
.val
);
current
= current
.next
;
}
System
.out
.println("NULL");
}
public static void main(String
[] args
) {
int[] x1
= { 4, 2, 1, 3 };
ListNode list1
= createLinkedList(x1
);
printLinkedList(list1
);
ListNode res1
= sortList(list1
);
printLinkedList(res1
);
System
.out
.println("***************************************");
int[] x2
= { -1, 5, 3, 4, 0 };
ListNode list2
= createLinkedList(x2
);
printLinkedList(list2
);
ListNode res2
= sortList(list2
);
printLinkedList(res2
);
}
}
2. 代码二:归并排序(从底至顶直接合并)
public class code148_2 {
public static ListNode
sortList(ListNode head
) {
ListNode dummyHead
= new ListNode(Integer
.MIN_VALUE
);
dummyHead
.next
= head
;
ListNode p
= dummyHead
.next
;
int length
= 0;
while (p
!= null
) {
++length
;
p
= p
.next
;
}
for (int size
= 1; size
< length
; size
<<= 1) {
ListNode cur
= dummyHead
.next
;
ListNode tail
= dummyHead
;
while (cur
!= null
) {
ListNode left
= cur
;
ListNode right
= cut(cur
, size
);
cur
= cut(right
, size
);
tail
.next
= merge(left
, right
);
while (tail
.next
!= null
) {
tail
= tail
.next
;
}
}
}
return dummyHead
.next
;
}
public static ListNode
cut(ListNode head
, int n
) {
if (n
<= 0)
return head
;
ListNode p
= head
;
while (--n
> 0 && p
!= null
) {
p
= p
.next
;
}
if (p
== null
)
return null
;
ListNode next
= p
.next
;
p
.next
= null
;
return next
;
}
public static ListNode
merge(ListNode list1
, ListNode list2
) {
ListNode dummyHead
= new ListNode(Integer
.MIN_VALUE
), p
= dummyHead
;
while (list1
!= null
&& list2
!= null
) {
if (list1
.val
< list2
.val
) {
p
.next
= list1
;
list1
= list1
.next
;
} else {
p
.next
= list2
;
list2
= list2
.next
;
}
p
= p
.next
;
}
if (list1
== null
) {
p
.next
= list2
;
} else {
p
.next
= list1
;
}
return dummyHead
.next
;
}
private static ListNode
createLinkedList(int[] arr
) {
if (arr
.length
== 0) {
return null
;
}
ListNode head
= new ListNode(arr
[0]);
ListNode current
= head
;
for (int i
= 1; i
< arr
.length
; i
++) {
current
.next
= new ListNode(arr
[i
]);
current
= current
.next
;
}
return head
;
}
private static void printLinkedList(ListNode head
) {
ListNode current
= head
;
while (current
!= null
) {
System
.out
.printf("%d -> ", current
.val
);
current
= current
.next
;
}
System
.out
.println("NULL");
}
public static void main(String
[] args
) {
int[] x1
= { 4, 2, 1, 3 };
ListNode list1
= createLinkedList(x1
);
printLinkedList(list1
);
ListNode res1
= sortList(list1
);
printLinkedList(res1
);
System
.out
.println("***************************************");
int[] x2
= { -1, 5, 3, 4, 0 };
ListNode list2
= createLinkedList(x2
);
printLinkedList(list2
);
ListNode res2
= sortList(list2
);
printLinkedList(res2
);
}
}
参考:
Sort List (归并排序链表)148. 排序链表-bottom-to-up O(1) 空间Sort List——经典(链表中的归并排序)