Sort a linked list in O(n log n) time using constant space complexity.
题目分析:看到此题,想到一般的数组排序有快排和归并排序。想到用归并排序,常见的数组归并排序,时间,空间复杂度都为o(nlogn),但是链表不需要重新分配空间,所以可以使用固定空间。排序的时候就想想有没有常见
解决此题的步骤如下:
1.通过快指针(一次进两步)和慢指针(1次进一步)找到链表的中间节点
2. 将指针分为两部分分别进行归并排序
3. 将归并排序后的两组链表进行合并
源代码如下:
/**
* @param 给定的头结点
* @return 归并排序后的头结点
* 通过将链表一分为二,然后分别进行排序之后再归并
* */
public ListNode sortList(ListNode head) {
if(head==null||head.next==null) return head;
ListNode middle=getMiddleNode(head);
ListNode next=middle.next;
middle.next=null;
return Merge(sortList(head),sortList(next));
}
/**
* @param 给定的链表头
* @return 返回链表的中间位置
* 采用快指针和慢指针两个指针来获取链表的中间位置,慢指针一次进1步,快指针一次进2步
* */
public ListNode getMiddleNode(ListNode head)
{
if(head==null||head.next==null) return head;
ListNode p=head;
ListNode q=head;
while(q.next!=null&&q.next.next!=null)
{
p=p.next;
q=q.next.next;
}
return p;
}
/**
* @param 给定两个排好序的待归并的指针
* @return 给出归并后的指针
* 通过先预先设一个头指针,然后从两个排好序的链表中选择值较小的那一个插入。
* 要记得处理未结束的链表
* */
public ListNode Merge(ListNode a,ListNode b)
{
ListNode tmphead=new ListNode(-1);
ListNode curr=tmphead;
while(a!=null&&b!=null)
{
if(a.val>b.val)
{
curr.next=b;
b=b.next;
}
else
{
curr.next=a;
a=a.next;
}
curr=curr.next;
}
curr.next=a==null?b:a;
return tmphead.next;
}