原理
分治思想,二叉树思想,n/2到元素分到个体(个体有序),然后再往上走,到n/2,一开始创建一个空数组,比较左一和右一大小,小的放入然后右移。最后实现拷贝。
上面两张图片图片来自 www.cnblogs.com/chengxiao/p…
复杂度
时间复杂度:O(log2n) 空间复杂度:O (n)
数组代码实现
class Solution {
public int[] mergeSort(int[] arry) {
return sort(arry,0,length-1);
}
// "分" 把数组分到一个子元素,然后排序,再 归
public int[] sort(int[] arry,int L,int R){
if (L==R){
return arry;
}
// 防止溢出,(R - L)>>1右移一位,相当于除以2
int mid = L +((R - L)>>1);
sort(arry,L,mid);
sort(arry,mid+1,R);
return merge(arry,L,mid,R);
}
// “治”对分完的数组进行排序
public int[] merge(int[] arry,int L ,int mid,int R){
int[] temp =new int[R-L+1];
int i = 0;
int p1 = L;
int p2 = mid+1;
// 比较左右,在临时数组中填入小的
while(p1 <= mid && p2 <= R){
temp[i++] = arry[p1] < arry[p2] ? arry[p1++]:arry[p2++];
}
// 循环退出,一边走完了,将没有走完的那边(剩下的都是大的),拷贝到临时数组
while(p1 <= mid){
temp[i++] = array[p1++];
}
while(p2 <= R){
temp[i++] = array[p2++];
}
// 将排序结果拷贝到原数组
for(i = 0;i<temp.length;i++){
arry[L+i]=temp[i];
}
return arry;
}
}
链表代码实现
- 排序链表 给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
进阶:
你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?
class Solution {
public ListNode sortList(ListNode head) {
return merge(head);
}
// 实现 “分” 利用快慢指针找中点,然后递归,实现分
public ListNode merge(ListNode head){
if(head == null || head.next == null){
return head;
}
ListNode slow = head, fast = head,pre = null;
while(fast != null && fast.next != null){
pre = slow;
slow = slow.next;
fast = fast.next.next;
}
ListNode r=merge(slow);
// pre比slow慢一步,pre.next置为null用来得到独立的前半部分,
pre.next = null;
// ListNode l = merge(pre);
ListNode l = merge(head);
return Listmerge(l,r);
}
// 实现 “治” 比较左右的大小:左右头结点比较,记录小的并++
public ListNode Listmerge(ListNode l, ListNode r){
// dummyHead 返回next
ListNode dummyHead =new ListNode(0);
ListNode head = dummyHead;
while(l != null && r != null){
if(l.val <= r.val){
head.next = l;
l = l.next;
head = head.next;
}else{
head.next = r;
r = r.next;
head = head.next;
}
}
// 直到一边为空,拷贝另一边
if(l != null){
head.next = l;
}
if(r != null){
head.next = r;
}
// head.next = l != null?l:r;
return dummyHead.next;
}
}