import java.util.*; /* * public class ListNode { * int val; * ListNode next = null; * public ListNode(int val) { * this.val = val; * } * } */ public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param head ListNode类 the head node * @return ListNode类 */ public ListNode sortInList (ListNode head) { // write code here /** int n = 0; ListNode tmp = head; while(tmp != null){ n++; tmp = tmp.next; } return mergeSort(head, n); */ return mergeSort(head); } /** ListNode mergeSort(ListNode leftNode, int n){ ListNode tmp = leftNode; //如果n为1,说明已经划分到最小 if(n == 1) return leftNode; int mid = n/2; ListNode midNode = leftNode; //遍历到B链表的头节点的前一个节点 for(int i=0; i<mid-1; i++){ midNode = midNode.next; } //截断链表 tmp = midNode; midNode = midNode.next; tmp.next = null; leftNode = mergeSort(leftNode, n/2); midNode = mergeSort(midNode, n-n/2); //合并 return merge(leftNode, midNode); }*/ ListNode mergeSort(ListNode leftNode){ ListNode tmp = leftNode; //说明已经划分到最小 if(leftNode.next == null) return leftNode; ListNode fast=leftNode,slow=leftNode; ListNode midNode = leftNode; //midNode遍历到B链表的头节点的前一个节点 while(fast!=null&&fast.next!=null){ midNode = slow; slow = slow.next; fast = fast.next.next; } //截断链表 tmp = midNode; midNode = midNode.next; tmp.next = null; leftNode = mergeSort(leftNode); midNode = mergeSort(midNode); //合并 return merge(leftNode, midNode); } //**太繁琐了 */ ListNode merge(ListNode leftNode, ListNode midNode){ //需要一个空头节点来处理合并,否则无法返回第一个节点 ListNode dummy = new ListNode(0); dummy.next = leftNode; ListNode tmp = dummy.next; //处理比B链中比A链第一个节点小的归并 while(midNode!=null){ if(midNode.val <= leftNode.val){ dummy.next = midNode; midNode = midNode.next; dummy.next.next = leftNode; leftNode = dummy.next; } else break; } tmp = dummy.next; while(midNode!=null){ if(midNode.val>=tmp.val ){ if(tmp.next == null) { tmp.next = midNode; break; } if(tmp.next.val <= midNode.val) { tmp = tmp.next; continue; } if(tmp.next.val > midNode.val){ ListNode next = midNode.next; midNode.next = tmp.next; tmp.next = midNode; midNode = next; } } } return dummy.next; } //别人写的 public ListNode merge1(ListNode left, ListNode right) { ListNode dummy = new ListNode(-1); ListNode cur = dummy; while (left != null && right != null) { if (left.val < right.val) { cur.next = left; left = left.next; } else { cur.next = right; right = right.next; } cur = cur.next; } if (left != null) { cur.next = left; } if (right != null) { cur.next = right; } return dummy.next; } }
归并排序,时间复杂度为O(nlogn)
分为两个步,一步是分,一步是合。
需要注意的有,mergeSort函数中,从中间切分链表,中间节点可以通过快慢指针寻找,也可以计算出链表长度,划分的时候多传一个链表长度参数。
//midNode遍历到B链表的头节点的前一个节点 while(fast!=null&&fast.next!=null){ midNode = slow; slow = slow.next; fast = fast.next.next; }
遍历以后slow指向的就是后一个链表的头节点,而midNode指向的是前一半链表的尾节点。
然后就是merge函数,这个我写的太复杂了。参考了别人的写法merge1,比较清晰。思路是直接用一个伪头节点来依次连接两个链表头节点中,小的那个节点。这里的写法很简洁,不需要一个个节点连到dummy后面,直接将头节点小的链表连到dummy后面,然后用cur的指向已排序好的链表尾部。