在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
示例 1:
输入: 4->2->1->3
输出: 1->2->3->4
示例 2:
输入: -1->5->3->4->0
输出: -1->0->3->4->5
首先归并排序
public static void mergeSort(int[] arr) {
sort(arr, 0, arr.length - 1);
}
public static void sort(int[] arr, int L, int R) {
if(L == R) {
return;
}
int mid = L + ((R - L) >> 1);
sort(arr, L, mid);
sort(arr, mid + 1, R);
merge(arr, L, mid, R);
}
public static void merge(int[] arr, int L, int mid, int R) {
int[] temp = new int[R - L + 1];
int i = 0;
int p1 = L;
int p2 = mid + 1;
// 比较左右两部分的元素,哪个小,把那个元素填入temp中
while(p1 <= mid && p2 <= R) {
temp[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
}
// 上面的循环退出后,把剩余的元素依次填入到temp中
// 以下两个while只有一个会执行
while(p1 <= mid) {
temp[i++] = arr[p1++];
}
while(p2 <= R) {
temp[i++] = arr[p2++];
}
// 把最终的排序的结果复制给原数组
for(i = 0; i < temp.length; i++) {
arr[L + i] = temp[i];
}
}
那么链表排序呢
把每个链表分成一部分,之后连接在一起。
注意:要保证存在前驱结点
class Solution {
public ListNode merry(ListNode left,ListNode right){
ListNode pre=new ListNode(0);
ListNode cur=pre;//pre遍历中所以cur指代pre
while(left!=null&&right!=null){
if(left.val>right.val){
pre.next=right;
right=right.next;
}
else{
pre.next=left;
left=left.next;
}
pre=pre.next;
}
if(left==null) pre.next=right;//把剩余链表整个加入到pre中
else pre.next=left;
return cur.next;
}
public ListNode sortList(ListNode head) {
if(head==null||head.next==null) return head;
ListNode slow=head;
ListNode fast=head.next;//头结点后一个结点开始
while(fast!=null&&fast.next!=null){
slow=slow.next;
fast=fast.next.next;
}
ListNode right=slow.next;
slow.next=null;
return merry(sortList(head),sortList(right));
}
}
来源:CSDN
作者:pick豆子
链接:https://blog.csdn.net/qq_42964711/article/details/103489634