题目:给你链表的头结点 head
,请将其按 升序 排列并返回 排序后的链表 。
进阶:你可以在 O(n logn)
时间复杂度和常数级空间复杂度下,对链表进行排序吗?
思路:对于链表的排序在o(n logn)
这个级别下,可以使用归并排序。
归并排序:
将数组从中递归的分成两部分,直到每部分只有一个数。
将这两个数有序排列,随后回归,变成两个有序链表的有序排列。
分成两步:
- 将链表递归的分成两部分(找到链表的中间结点,使用快慢指针)
- 将左右两部分进行排列
代码如下:
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 slow = head, fast = head; //对于链表找中间位置,快慢指针
while(fast != tail){
slow = slow.next;
fast = fast.next;
if(fast != tail){
fast = fast.next;
}
}
ListNode mid = slow;
ListNode left = sortList(head, mid);
ListNode right = sortList(mid, tail);
return merge(left, right);
}
//对链表进行排序
public ListNode merge(ListNode head1, ListNode head2){
ListNode headNode = new ListNode(0);
ListNode temp = headNode;
while(true){
if(head1 == null){
temp.next = head2;
break;
}
if(head2 == null){
temp.next = head1;
break;
}
if(head1.val < head2.val){
temp.next = head1;
head1 = head1.next;
}else{
temp.next = head2;
head2 = head2.next;
}
temp = temp.next; //不能忘记这一步,temp也需要往后挪
}
return headNode.next;
}
}