归并排序 (分而治之算法) java代码实现(java完整代码)java递归实现(分而治之)MergeSort(分治法)

归并排序是分而治之算法策略的典型代表之一

分而治之算法的思路:

分而治之三步骤:分解原问题,解决子问题,合并问题解
1.分解原问题:将原问题分解为若干个规模较小,相对独立,与原问题形式相同的子问题。
2.解决子问:若子问题规模较小且易于解决时,则直接解。否则,递归地解决各子问题。
3.合并:将各子问题的解合并为原问题的解。

归并排序:

以数组为例,假设数组长度为n
1.首先把其拆分n组每组一个,
2.然后每相连的两组进行比较,并排序;
(第一遍排序之变成了n/2组,每组为2个,当然若n为奇数,则最后一组只有一个元素;)
3.继续执行2,直到排序后只有一组。
它的时间复杂度是O(nlogn).

java完整代码(递归实现):

public void toMergeSort(int []arr,int left,int right) {
	//递归出口
	if(left >= right) {										
		return;
	}
	int mid = (int)((left+right)/2);
	toMergeSort(arr,left,mid);     //先左边递归
	toMergeSort(arr,mid+1,right);     //再右边递归
	toSort(arr,left,mid,right);						//调用排序函数
}
public void toSort(int []arr,int left,int mid, int right) {
	int i = left ,j = mid+1 ,tempIndex = left;				//i指向左半边,j指向右半边
	int []tempArr = arr.clone();
	while(i <= mid && j <= right) {
		if(tempArr[i]>tempArr[j]) {
			arr[tempIndex] = tempArr[j];
			j++;
			tempIndex++;
		}
		else {
			arr[tempIndex] = tempArr[i];
			i++;
			tempIndex++;
		}
	}
	while(i<=mid) {				//左边还没有完,右边已完
		arr[tempIndex] = tempArr[i];
		i++;
		tempIndex++;
	}
	while(j<=right){
		arr[tempIndex] = tempArr[j];  //右边还没有完,左边已完
		j++;
		tempIndex++;
	}
}

测试算法,运行结果:

在这里插入图片描述
在这里插入图片描述

上述代码存中有一个弊端,在循环中每次都会调用clone方法,所以我们进行如下优化

class Solution {
    public int[] sortArray(int[] nums) {
        toMergeSort(nums,0,nums.length-1,nums.clone());
        return nums;
    }
    public void toMergeSort(int[] nums,int left,int right,int[] tempArr){
        if(left >= right)
            return;
        int mid = (left+right) / 2;
        toMergeSort(nums,left,mid,tempArr);
        toMergeSort(nums,mid+1,right,tempArr);
        mergeArr(nums,left,mid,right,tempArr);
    }
    public void mergeArr(int[] nums,int left,int mid, int right,int[] tempArr){
        int i = left, j = mid+1, tempIndex = left;
        while(i<=mid && j<=right){
            if(tempArr[i] > tempArr[j])
                nums[tempIndex++] = tempArr[j++];
            else
                nums[tempIndex++] = tempArr[i++];
        }

        // 左半边结束,右半边还未结束
        while(j<=right)
            nums[tempIndex++] = tempArr[j++];
        // 右半边结束,左半边还未结束a
        while(i<=mid)
            nums[tempIndex++] = tempArr[i++]; 

        // 一次合并后临时数组要和nums同步
        for(i = left;i<=right;i++)
            tempArr[i] = nums[i];
    }
}
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MrYuShiwen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值