归并排序要先分解再合并
代码其实核心就是一个合并函数merge函数,合并两个有序数组
public static void mergeSort(int[] nums,int left,int high)
{
if(left>=right) return;
int mid=(left+right)/2;
mergeSort(nums.left,mid);
mergeSort(nums,mid+1,right);
merge(nums,left,mid,right);
}
//merge函数的功能,合并两个有序数组
public static void merge(int[] nums,int left,int mid,int right)
{
int i=left,j=mid+1;//合并[left,mid]和[mid+1,right]这两个数组
//用一个临时数组保存[left,mid]和[mid+1,right]这两个子数组合并之后的结果
int[] temp=new int[right-left+1];
int index=0;//新数组的索引,从第0号开始确定新数组每一位的元素是多少
while(i<=mid&&j<=right)//当两个子数组都有数据的时候,谁小就temp[index]等于谁
{
if(nums[i]<=nums[j])
{
temp[index]=nums[i];//注意这三行代码其实可以用一行代替:temp[index++]=nums[i++]
i++;
index++;
}
else
{
temp[index]=nums[j];
j++;
index++;
}
}
//跳出循环,有可能其中一个子数组中还有元素没有比较完
while(i<=mid)
{
temp[index]=nums[i];
index++;
i++;
}
while(i<=mid)
{
temp[index]=nums[i];
index++;
i++;
}
//最后将temp数组拷贝到原数组nums里面
for(int k=0;k<temp.length;k++)
{
nums[k+left]=temp[k];
}
}
链表的归并排序:力扣148 排序链表
和数组的归并排序也是一样的,
(1) 找中点
(2)左右子链表(左右子数组)分别排好序
(3)将两个有序链表进行合并(两个链表合并)
class Solution
{
public ListNode sortList(ListNode head)
{
if(head==null||head.next==null) return head;
//step1:找中间结点
ListNode fast = head.next, slow = head;
while (fast != null && fast.next != null)
{
slow = slow.next;
fast = fast.next.next;
}
ListNode temp=slow.next;//中点的下一个结点
slow.next=null;//将链表一分为二
ListNode left= sortList(head);//将前半段链表进行排序
ListNode right=sortList(temp);//将后半段链表进行排序
//接下来合并两个有序链表
ListNode result=merge(left,right);
return result;
}
public ListNode merge(ListNode left,ListNode right)
{
ListNode dummy=new ListNode(0);
ListNode current=dummy;
while(left!=null&&right!=null)
{
if(left.val<=right.val)
{
current.next=left;
left=left.next;
current=current.next;
current.next=null;
}
else
{
current.next=right;
right=right.next;
current=current.next;
current.next=null;
}
}
//跳出循环,一定有一个链表还没有比较完
if(left!=null)//这个if-else结构可以用三元表达式来代替:current.next=left!=null?left:right;
{
current.next=left;
}
else
{
current.next=right;
}
return dummy.next;
}
}