文档详情

力扣912题 排序数组 详细教程(归并排序实现).docx

发布:2025-05-29约2.23千字共5页下载文档
文本预览下载声明

力扣912题排序数组详细教程(归并排序实现)

题目分析与解读

给定一个整数数组nums,将该数组升序排列后返回。要求时间复杂度为O(nlogn),空间复杂度尽可能低。

关键点解析:

1.必须实现真正的排序算法,不能直接调用库函数

2.时间复杂度要求O(nlogn),排除了O(n2)的简单排序算法

3.需要原地排序或使用有限额外空间

4.归并排序、快速排序、堆排序都符合要求

现实生活场景类比

想象你在整理一副扑克牌:

1.把牌分成两半,分别排序(递归过程)

2.然后像洗牌一样,从两叠已排序的牌中轮流取较小的牌

3.最终合并成一叠完全有序的牌

4.这个过程就是归并排序的直观体现

解题步骤详解(归并排序)

1.递归终止条件?:当子数组长度为1时直接返回

2.分割数组?:找到中间点mid,将数组分为左右两部分

3.递归排序?:对左右子数组分别递归调用排序

4.合并过程?:

使用三个指针:index(临时数组)、lnow(左数组)、rnow(右数组)

比较左右数组元素,取较小者放入临时数组

处理剩余元素

复制回原数组?:将临时数组结果复制回原数组对应位置

注意事项

1.临时数组大小要足够(本题设为50000)

2.递归深度可能导致栈溢出(对极大数组)

3.合并时的边界条件要仔细处理

4.可以使用全局变量减少参数传递

5.注意mid计算避免整数溢出(本题使用(l+r)/2)

代码实现与注释

classSolution{

public:

inttmp[50000];//全局临时数组,用于归并过程

voidmysort(vectorintnums,intl,intr){

if(l==r){//递归终止条件:子数组长度为1

return;

}

intmid=(l+r)/2;//计算中间点

//递归排序左右子数组

mysort(nums,l,mid);

mysort(nums,mid+1,r);

intindex=l;//临时数组指针

intlnow=l;//左子数组指针

intrnow=mid+1;//右子数组指针

//合并两个有序子数组

while(lnow=mid||rnow=r){

if(rnowr){//右子数组已全部处理

tmp[index]=nums[lnow];

lnow++;

index++;

}

elseif(lnowmid){//左子数组已全部处理

tmp[index]=nums[rnow];

rnow++;

index++;

}

else{//比较左右子数组当前元素

tmp[index]=min(nums[lnow],nums[rnow]);

if(nums[lnow]nums[rnow]){

lnow++;

}

else{

rnow++;

}

index++;

}

}

//将临时数组复制回原数组

for(inti=l;i=r;i++){

nums[i]=tmp[i];

}

}

vectorintsortArray(vectorintnums){

mysort(nums,0,nums.size()-1);//调用归并排序

returnnums;

}

};

问题与代码分析

问题特点:?

1.标准排序问题,但限制算法复杂度

2.测试用例包含各种边界情

显示全部
相似文档