概述
归并排序的特点在于它的时间复杂度为O(nlogn)。而根据一个结论性的东西来说:最坏情况下比较方式的排序算法至少需要Ω(nlogn)的时间(结论来自邓俊辉版数据结构P59),这是比较性排序算法的极限。
计算时间复杂度
(函数代码在下面)
不难看出merge函数的时间复杂度是O(n),
sort函数的时间复杂度主要来源于merge函数和两个自身的递归函数,于是:
T(n) = 2 x T(n / 2) + O(n)
T(1) = O(1)
递推函数计算思路学习自这个博客
思路和这个图是一样的。
换元n= 2k,在最后一项时,省略后面的低次项为:T(n) = 2k-1[2T(1) + O(n)] = 2kO(1) + 2k-1O(n)
省略低次项 = 2k-1O(n) = 1/2 x 2kO(n)
去掉常系数 = 2kO(n)
把元换回来 = nlogn
源代码
class Solution {
public:
vector<int> sortArray(vector<int>& nums) {
sort(nums, 0, nums.size());
return nums;
}
private:
void sort(vector<int>& nums, int lo, int hi) {
if(hi - lo < 2)
return ;
int mi = (lo + hi) / 2;
sort(nums, lo, mi);
sort(nums, mi, hi);
merge(nums,lo, mi, hi);
}
void merge(vector<int>& nums, int lo, int mi, int hi){
vector<int> vec(nums.begin() + lo, nums.begin() + mi);
auto backBegin = nums.begin() + mi;
auto backEnd = nums.begin() + hi;
auto frontBegin = vec.begin();
auto frontEnd = vec.end();
for(auto i = nums.begin() + lo; i != nums.begin() + hi; ++i) {
if(frontBegin != frontEnd && (backEnd == backBegin || *frontBegin <= *backBegin)) {
*i = *frontBegin++;
}else {
*i = *backBegin++;
}
}
}
};
leetcode:912. 排序数组
在这个题目中冒泡排序会直接被第8个测试案例超出时间限制,有趣的是:在这个题目的后半段大家都用的是归并排序,很多人的代码中还包含了被注释掉的冒泡排序。
归并排序就是这个题目实际上的守门员(笑)。