针对本题排序流程,主要是将链表拆分为长度为subLength的子链表1和子链表2,然后把子链表1和子链表2合并为一条有序链表,重复上述步骤直到把链表都拆分完,这样这条链表每段长度为2的子链表都是有序的,那么要整条链表有序,我们只需要把subLength扩大并重复上述排序步骤即可,也就是每次拆分排序完subLength = subLength * 2后再次进行拆分排序,直到subLength大于或者等于整条链表的长度,画草图如下所示
代码如下,每行都有解释
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);// subLength表示子链表长度,subLength <<= 1 是 subLength = subLength * 2 的意思// 这样写的目的是把链表分成多个子链表进行多次合并有序链表操作,比如两条长度为1的子链表合并变成一条长度为2的有序链表,// 两条长度为2的子链表合并变成一条长度为4的有序链表,以此类推直到子链表长度大于或者等于链表长度即排序完成for (int subLength = 1; subLength < length; subLength <<= 1) {// 定义pre指针,指向已拆分子链表尾结点,用于连接有序子链表,curr用于遍历链表,并指向待拆分链表头结点ListNode prev = dummyHead, curr = dummyHead.next;// 如果没有子链表了,即curr指向null则结束本次循环while (curr != null) {// 第一条子链表的头结点ListNode head1 = curr;// 按subLength拆分为一条长度为subLength的子链表for (int i = 1; i < subLength && curr.next != null; i++) {curr = curr.next;}// 第二条子链表头结点ListNode head2 = curr.next;curr.next = null;curr = head2;// 按subLength拆分为一条长度为subLength的子链表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;}// 合并上面拆分出来的两条长度为subLength的子链表ListNode merged = merged(head1, head2);prev.next = merged;// 遍历合并后的有序子链表,prev指向该链表的尾结点while (prev.next != null) {prev = prev.next;}// curr指向待拆分链表头结点,以便继续进行拆分curr = next;}}return dummyHead.next;}// 合并两条有序链表为一条有序链表public ListNode merged(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;}
}
题目链接:题单 - 力扣(LeetCode)全球极客挚爱的技术成长平台