[思路]
就是简单的归并排序。
其实算法还可以优化,因为用链表进行归并,无法像数组那样直接取中间位置,进行遍历获取中间的话效率会降低挺多。可以定义一个全局变量notSortedStart,记录当前的无序位段的起始位,作为right的起点。当串长为1时将notSortedStart 右移,则notSortedStarted记录的是中间位置。只要保证递归的顺序是先左后右,即可保证当前节点一定是所属左边串的最后一个节点。因为串长为1时其左边的串肯定都是排序过,只待合并了,所以notSortedStart必定是右串的起点,即下次递归的头结点参数。
[代码]468ms
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode mergeSort(ListNode head,int length)
{
if(head == null) return null;
if(length == 1)
{
head.next = null;
return head;
}
ListNode secondhead = head ;
for(int i = 0; i < length/2; i++)
{
secondhead = secondhead.next;
}
ListNode leftSorted = mergeSort(head,length/2);
ListNode rightSorted = mergeSort(secondhead,length - length/2);
head = merge(leftSorted,rightSorted);
return head;
}
public ListNode merge(ListNode first,ListNode second)
{
if(first == null)return second;
if(second == null)return first;
ListNode mergedHead ;
if(first.val < second.val)
{
mergedHead = first;
first = first.next;
}
else
{
mergedHead = second;
second = second.next;
}
ListNode current = mergedHead;
while(first != null && second != null)
{
if(first.val < second.val)
{
current.next = first;
first = first.next;
}
else
{
current.next = second;
second = second.next;
}
current = current.next;
}
current.next = first == null ? first : second;
if(first != null)
//开始错写为first==null细节要小心
current.next = first;
else
current.next = second;
return mergedHead;
}
public ListNode sortList(ListNode head) {
int length = 0;
ListNode tmp = head;
while(tmp != null)
{
tmp = tmp.next;
length ++;
}
return mergeSort(head, length);
}
}
[优化后代码]408ms
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
ListNode notSortedStart;
public ListNode mergeSort(ListNode head,int length)
{
if(head == null) return null;
if(length == 1)
{
notSortedStart = head.next;//保证notSortedStart指向右边无序串的其实位置
head.next = null;
return head;
}
// ListNode secondhead = head ;
// for(int i = 0; i < length/2; i++)
// {
// secondhead = secondhead.next;
// }
ListNode leftSorted = mergeSort(head,length/2);
ListNode rightSorted = mergeSort(notSortedStart,length - length/2);
head = merge(leftSorted,rightSorted);
return head;
}
public ListNode merge(ListNode first,ListNode second)
{
if(first == null)return second;
if(second == null)return first;
ListNode mergedHead ;
if(first.val < second.val)
{
mergedHead = first;
first = first.next;
}
else
{
mergedHead = second;
second = second.next;
}
ListNode current = mergedHead;
while(first != null && second != null)
{
if(first.val < second.val)
{
current.next = first;
first = first.next;
}
else
{
current.next = second;
second = second.next;
}
current = current.next;
}
current.next = first == null ? first : second;
if(first != null)
current.next = first;
else
current.next = second;
return mergedHead;
}
public ListNode sortList(ListNode head) {
int length = 0;
ListNode tmp = head;
while(tmp != null)
{
tmp = tmp.next;
length ++;
}
//notSortedStart = head;
return mergeSort(head, length);
}
}