今天刷的题是LeetCode第148题,难度中等
题目的要求是在O(nlogn)的时间复杂度情况下和常数级的空间复杂度对链表进行排序
一般地数据排序,冒泡、插入和选择排序都是O(N2),而归并排序和快速排序的时间复杂度是O(nlogn)。因此在算法上可以考虑归并排序和快速排序
如果采用一般的上述排序算法,需要O(N)的空间复杂度。因此需要对上述算法进行改进
本文选择的是链表中的归并排序算法。该算法也同样需要对数据进行分割和合并。在分割的时候,是采用的双指针策略。
然后合并操作。合并操作就是比较链表的节点的值。最后返回合并后的链表即可。具体的代码如下所示:
public class SortList { public static void main(String[] args) { int[] a={-5,-10,-2,1,0,10,12,9,4}; ListNode head=ListNode.generateListNode(a); head=SortList.sort(head); while (head!=null){ System.out.println(head.val); head=head.next; } } public static ListNode sort(ListNode head){ return head==null ? null:SortList.mergeSort(head); } public static ListNode mergeSort(ListNode head){ //边界条件 if (head.next==null)return head; //定义双指针,将链表分为两部分 ListNode fast=head; ListNode slow=head; ListNode pre=null; while (fast!=null && fast.next!=null ){ pre=slow; fast=fast.next.next; slow=slow.next; } pre.next=null; ListNode left=head; ListNode right=slow; ListNode l=mergeSort(left); ListNode r=mergeSort(right); return merge(l,r); } public static ListNode merge(ListNode left,ListNode right){ ListNode result=new ListNode(0); ListNode current=result; while (left!=null && right!=null){ if (left.val<right.val){ current.next=left; current=current.next; left=left.next; }else if (left.val>=right.val){ current.next=right; right=right.next; current=current.next; } if (left!=null){ current.next=left; }if (right!=null){ current.next=right; } } return result.next; } }