给你链表的头结点 head
,请将其按 升序 排列并返回 排序后的链表 。
自底向上归并
1.获取当前链表长度
2.归并
首先子串长度分组 1、2、4、8、16、32..
选两个子串:选完一个子串记得断开它和后面的连接,pre.next=merged
3.有序链表合并算法
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 subLength = 1; subLength < length; subLength <<= 1) {
ListNode prev = dummyHead, curr = dummyHead.next;
//按当前分组长度对所有子串分组合并
while (curr != null) {
//选两个子串合并
//子串1
ListNode head1 = curr;
for (int i = 1; i < subLength && curr.next != null; i++) {
curr = curr.next;
}
//此时curr为子串1的末尾
//子串2
ListNode head2 = curr.next;
//断开子串1和2
curr.next = null;
curr = head2;
for (int i = 1; i < subLength && curr != null && curr.next != null; i++) {
curr = curr.next;
}
//如果后续还有 断开其与后续子串连接
ListNode next = null;
if (curr != null) {
next = curr.next;
curr.next = null;
}
//合并两个子串
ListNode merged = merge(head1, head2);
//连接pre和子串
prev.next = merged;
//pre移动至合并
while (prev.next != null) {
prev = prev.next;
}
//curr从下一个子串开始
curr = next;
}
}
return dummyHead.next;
}
//参照有序链表合并
public ListNode merge(ListNode head1, ListNode head2) {
ListNode dummyHead = new ListNode(0);
ListNode temp = dummyHead, temp1 = head1, temp2 = head2;
while (temp1 != null && temp2 != null) {
if (temp1.val <= temp2.val) {
temp.next = temp1;
temp1 = temp1.next;
} else {
temp.next = temp2;
temp2 = temp2.next;
}
temp = temp.next;
}
if (temp1 != null) {
temp.next = temp1;
} else if (temp2 != null) {
temp.next = temp2;
}
return dummyHead.next;
}
}