题目链接
递归排序三部曲:①快慢指针找中点;②递归调用mergeSort; ③合并两个链表
归并
class Solution { public ListNode sortList(ListNode head){ return mergeSort(head); } //归并排序 private ListNode mergeSort(ListNode head){ //如果没有节点、只有一个节点,无需排序 if(head == null || head.next == null) return head; //快慢指针找中位点 ListNode slow = head,fast = head.next.next,l,r; while(fast!=null && fast.next!=null){ slow = slow.next; fast = fast.next.next; } //对右半部分进行归并排序 r = mergeSort(slow.next); //判断链表是否结束 slow.next = null; //对左半部分进行归并排序 l = mergeSort(head); return mergeList(l,r); } //合并链表 private ListNode mergeList(ListNode l,ListNode r){ //临时头节点 ListNode tmpHead = new ListNode(-1); ListNode p = tmpHead; while(l!=null && r!=null){ if(l.val <r.val){ p.next = l; l = l.next; }else{ p.next = r; r = r.next; } p = p.next; } p.next = l == null?r:l; return tmpHead.next; } }
快排(大佬说头条面到了)
class Solution { public ListNode sortList(ListNode head) { if(head==null||head.next==null) return head; // 没有条件,创造条件。自己添加头节点,最后返回时去掉即可。 ListNode newHead=new ListNode(-1); newHead.next=head; return quickSort(newHead,null); } // 带头结点的链表快速排序 private ListNode quickSort(ListNode head,ListNode end){ if (head==end||head.next==end||head.next.next==end) return head; // 将小于划分点的值存储在临时链表中 ListNode tmpHead=new ListNode(-1); // partition为划分点,p为链表指针,tp为临时链表指针 ListNode partition=head.next,p=partition,tp=tmpHead; // 将小于划分点的结点放到临时链表中 while (p.next!=end){ if (p.next.val<partition.val){ tp.next=p.next; tp=tp.next; p.next=p.next.next; }else { p=p.next; } } // 合并临时链表和原链表,将原链表接到临时链表后面即可 tp.next=head.next; // 将临时链表插回原链表,注意是插回!(不做这一步在对右半部分处理时就断链了) head.next=tmpHead.next; quickSort(head,partition); quickSort(partition,end); // 题目要求不带头节点,返回结果时去除 return head.next; } }