题目:
给定链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
head = [4,2,1,3]
输出:[1,2,3,4]
解题
1,最简单的算法,就是挨个遍历链表,将其加入数组,通过数组排序。但这样的空间复杂度比较高。
2,我们学过归并排序。那就用归并排序来解题。
概念:归并排序就是有 n 个数字:2,4,1,5,3…
先两个两个的排序,再两组两组的排序。
代码
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode sortList(ListNode head) {
if (head == null) {
return head;
}
int length = 0;
ListNode node = head;
while (node != null) {
length++;
node = node.next;
}
ListNode dummyHead = new ListNode(0, head);
for (int sublen=1;sublen<length;sublen<<=1){
ListNode pre = dummyHead;
ListNode curr = dummyHead.next;
ListNode head1;
ListNode head2;
while (curr!=null){
head1 = curr;
for (int i=1;i<sublen && curr.next!=null;i++){
curr = curr.next;
}
head2 = curr.next;
curr.next = null; // 断开链表1
curr = head2;
for (int i=1;i<sublen && curr!=null && curr.next!=null;i++){
curr = curr.next;
}
ListNode next=null;// 用来保存curr
if (curr!=null){
next = curr.next;
curr.next = null; // 断开链表2
}
ListNode mergeNode = merge(head1,head2);
pre.next = mergeNode;
while(pre.next!=null){
pre = pre.next;
}
curr = next;
}
}
return dummyHead.next;
}
public ListNode merge(ListNode head1, ListNode head2) {
ListNode dumpHead = new ListNode();
ListNode temp = dumpHead;
while (head1!=null && head2!=null){
if (head1.val<head2.val){
temp.next = head1;
head1 = head1.next;
} else {
temp.next = head2;
head2 = head2.next;
}
temp = temp.next;
}
if (head1!=null){
temp.next = head1;
}else if(head2!=null){
temp.next = head2;
}
return dumpHead.next;
}
}