一、题目
二、思路
要求时间复杂度为o(logn),可以使用归并排序。
代码实现步骤如下:
1.找到中间节点,因为是链表,所以用快慢指针的方法确定中间节点,即fast指针的速度是slow指针的二倍,当fast指针走到链表尾结点的时候,slow指针的位置的结点恰好为中间节点;
2.将头结点到中间节点的链表;中间节点到尾结点的链表分别排序;
3.将两个排序好的链表进行合并;
只有一个结点或者头结点为空的时候直接返回头结点,无需排序。
三、代码实现
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode sortList(ListNode head) {
return sortList(head, null);
}
public ListNode sortList(ListNode head, ListNode tail)
{
if(head == null)
return head;
if(head.next == tail)
{
head.next = null;
return head;
}
//递归分组 每次将组分为一半 定义快慢指针 快指针速度为慢指针二倍 当快指针走到尾结点说明慢指针的位置就是链表中间位置
ListNode fast = head, slow = head;
while(fast != tail)
{
slow = slow.next;
fast = fast.next;
if(fast != tail)
fast = fast.next;
}
ListNode mid = slow;
ListNode list1 = sortList(head, mid);
ListNode list2 = sortList(mid, tail);
ListNode sorted = merge(list1, list2);
return sorted;
}
public ListNode merge(ListNode list1, ListNode list2)
{
ListNode dummyHead = new ListNode(0);
ListNode temp = dummyHead, temp1 = list1, temp2 = list2;
//合并两个有序链表
while(temp1 != null && temp2 != null)
{
if(temp1.val <= temp2.val)
{
temp.next = temp1;
temp1 = temp1.next;
}
else if(temp1.val > temp2.val)
{
temp.next = temp2;
temp2 = temp2.next;
}
temp = temp.next;
}
if(temp1 != null)
temp.next = temp1;
if(temp2 != null)
temp.next = temp2;
return dummyHead.next;
}
}