148. Sort List 链表排序
方法1:归并排序思路:
(1)设计一个寻找中间节点的函数;(2)设计一个归并两个已经有序的函数;(3) 主函数;
其中第一个函数思想:是在109题转换成BST当中使用的那样,同时也是快慢链表解决环形链表当中的设计一样的思路!
public class Solution { private ListNode findMidNode(ListNode head){ ListNode slow = head; ListNode fast = head; while(fast.next != null && fast.next.next != null){ slow = slow.next; fast = fast.next.next; } return slow; } private ListNode merge(ListNode head1, ListNode head2){ ListNode dummy = new ListNode(0); ListNode index = dummy; while(head1 != null && head2 != null) { if(head1.val < head2.val) { index.next = head1; head1 = head1.next; } else { index.next = head2; head2 = head2.next; } index = index.next; } if(head1 != null) index.next = head1; else index.next = head2; return dummy.next; } public ListNode sortList(ListNode head) { if(head == null || head.next == null){ return head; } ListNode mid = findMidNode(head); ListNode left = sortList(mid.next); mid.next = null; ListNode right = sortList(head); return merge(left,right); } }
思路2:利用快速排序思想!!!
首先,快速排序有两种,一种是三分,一种是二分。但是核心思想是一样的:每次为了一个元素,将整个矩阵或者链表,分成小于,等于,和大于三部分,或者小于等于,大于等于两部分。
二分的算法:
public class Quick { private static void sort(Comparable[] a, int lo,int hi) { if (hi <= lo) return; int j = partition(a, lo, hi); sort(a, lo, j-1); sort(a, j+1, hi); } private static int partition(Comparable[] a, int lo, int hi) { int i = lo; int j = hi +1; Comparable v = a[lo]; while(true) { while(less(a[++i],v)) if(i == hi) break; while(less(v,a[--j])) if(j == lo) break; if(i >= j) break; exch(a,i,j); } exch(a,lo,j); return j; } }
三分快排:
public class Quick3way { private static void sort(Comparable[] a, int lo, int hi) { if(hi <= lo) return; int lt = lo, i = lo+1, gt = hi; Comparable v = a[lo]; while(i <= gt) { int cmp = a[i].compareTo(v); if (cmp < 0) exch(a,lt++,i++); else if (cmp > 0) exch(a,i,gt--); else i++; } sort(a, lo, lt-1); sort(a, gt+1, hi); } }
同样的原理,可以使用三分快排的思想设计这个链表排序:
public class Solution { private ListNode findMidNode(ListNode head) { ListNode slow = head; ListNode fast = head; while(fast.next != null && fast.next.next != null) { fast = fast.next.next; slow = slow.next; } return slow; } public ListNode sortList(ListNode head) { if(head == null || head.next == null) return head; ListNode mid = findMidNode(head); ListNode leftDummy = new ListNode(0), leftIndex = leftDummy; ListNode midDummy = new ListNode(0), midIndex = midDummy; ListNode rightDummy = new ListNode(0), rightIndex = rightDummy; while(head != null) { if(head.val < mid.val) { leftIndex.next = head; leftIndex = leftIndex.next; } else if(head.val > mid.val) { rightIndex.next = head; rightIndex = rightIndex.next; } else { midIndex.next = head; midIndex = midIndex.next; } head = head.next; } leftIndex.next = null; midIndex.next = null; rightIndex.next = null; ListNode left = sortList(leftDummy.next); ListNode right = sortList(rightDummy.next); return concat(left, midDummy.next, right); } private ListNode findTail(ListNode head) { if(head == null || head.next == null) return head; while(head.next != null) { head = head.next; } return head; } private ListNode concat(ListNode left, ListNode mid, ListNode right) { ListNode dummy = new ListNode(0), index = dummy; index.next = left; index = findTail(index); index.next = mid; index = findTail(index); index.next = right; return dummy.next; } }
设计当中遇到的问题:(1)每次重新整合,都必须必须给列三个节点末尾赋值null,方便找tail;(2)注意函数是值传递:基本类型,和对象类型不一样!

浙公网安备 33010602011771号