快速排序平均时间复杂度O(nlogn)的推导
快速排序作为随机算法的一种,不能通过常规方法来计算时间复杂度
wiki上有三种快排平均时间复杂度的分析,本文记录了一种推导方法。
先放快速排序的伪代码,便于回顾、参考
quicksort(int L, int R, int array[]) {
if (L >= R) {
return;
}
int pivot = RANDOM(L, R);
int l = L, r = R;
int support_array[array.length()]
for (i = L -> R) {
if (i == pivot) {
return;
}
else if (array[i] <= array[pivot]){
support_array[l++] = array[i];
}
else {
support_array[r--] = array[i];
}
}
support_array[l] = array[pivot];
array <- support_array;
quicksort(L, l-1, array);
quicksort(l+1, R, array);
}
n为序列长度,对于长度为n的序列,我们总共需要调用n次quicksort函数,我们将序列中元素与pivot的比较操作(代码8-18行,以下简称为“比较”)提出来总体考虑,每调用一次函数,除开比较操作,时间复杂度均为O(1),设x为n次调用函数总共的比较次数,快排的时间复杂度T(n) = O(n+x)
以下为x的计算过程
设ei为原序列中第i小的数,ej为第j小的数, j > i。在对原序列完整排序的整个过程中,每一个位置都会被选作为pivot一次。ei与ej会被比较,当且仅当在ei, ei+1, ei+2 , ... , ej-1, ej 这个子序列中(按照假设,此为非降序序列),ei与ej其中一个最先在这个子序列中被选为pivot ,否则一个大小介于他们中间的数被选为pivot,在一轮比较过后,ei和ej就会被分在两个子序列中,没有被比较且以后也不会被比较。当我们使用的生成随机数算法能保证每个数被选中为pivot的概率相等时,P(ei与ej被比较) = 2 / ( j - i + 1 )。设Y为ei与ej比较的次数,Y = 0 或 1, Y的期望计算如下
\]
\]
而在序列中,任意两项比较次数的期望均是 2 / ( j - i + 1 )
x是总共比较次数,则x的期望的表达式为
\]
后半部分的求和是调和级数(harmonic series), 调和级数求和公式如下
\]
用于计算E(x)
\]
\]
\]
到此,快速排序的平均时间复杂度O(nlogn)也就推导完成了。
快速排序平均时间复杂度O(nlogn)的推导的更多相关文章
- 平均时间复杂度为O(nlogn)的排序算法
本文包括 1.快速排序 2.归并排序 3.堆排序 1.快速排序 快速排序的基本思想是:采取分而治之的思想,把大的拆分为小的,每一趟排序,把比选定值小的数字放在它的左边,比它大的值放在右边:重复以上步骤 ...
- 快速排序的时间复杂度nlogn是如何推导的??
本文以快速排序为例,推导了快排的时间复杂度nlogn是如何得来的,其它算法与其类似. 对数据Data = { x1, x2... xn }: T(n)是QuickSort(n)消耗的时间: P(n)是 ...
- 最长递增子序列 LIS 时间复杂度O(nlogn)的Java实现
关于最长递增子序列时间复杂度O(n^2)的实现方法在博客http://blog.csdn.net/iniegang/article/details/47379873(最长递增子序列 Java实现)中已 ...
- PHP快速排序及其时间复杂度
<?php function quickSort(&$arr, $l, $r) { if (count($arr)<2 || $l>$r) return; $tmp_l = ...
- 稳定排序nlogn之归并排序_一维,二维
稳定排序nlogn之归并排序_一维,二维 稳定排序:排序时间稳定的排序 稳定排序包括:归并排序(nlogn),基数排序[设待排序列为n个记录,d个关键码,关键码的取值范围为radix,则进行链式基数排 ...
- php算法之快速排序
/** * 快速排序 * 原理: * 快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists). * 最差时间复杂度 O(n*n) * ...
- JS-排序详解-快速排序
说明 时间复杂度指的是一个算法执行所耗费的时间 空间复杂度指运行完一个程序所需内存的大小 稳定指,如果a=b,a在b的前面,排序后a仍然在b的前面 不稳定指,如果a=b,a在b的前面,排序后可能会交换 ...
- 用非递归、不用栈的方法,实现原位(in-place)的快速排序
大体思路是修改Partition方法将原本枢数的调整放到方法结束后去做.这样因为数组右侧第一个大于当前枢数的位置就应该是未划分的子数组的边界.然后继续进行Partition调整.这种写法照比递归的写法 ...
- 快速排序及查找第K个大的数。
本文提供了一种基于分治法思想的,查找第K个大的数,可以使得时间复杂地低于nlogn. 因为快排的平均时间复杂度为nlogn,但是快排是全部序列的排序, 本文查找第k大的数,则不必对整个序列进行排序.请 ...
随机推荐
- 鸿蒙内核源码分析(定时器篇) | 哪个任务的优先级最高 | 百篇博客分析OpenHarmony源码 | v31.02
百篇博客系列篇.本篇为: v31.xx 鸿蒙内核源码分析(定时器篇) | 哪个任务的优先级最高 | 51.c.h .o 本篇说清楚定时器的实现 读本篇之前建议先读鸿蒙内核源码分析(总目录)其余篇. 运 ...
- P6113-[模板]一般图最大匹配【带花树】
正题 题目链接:https://www.luogu.com.cn/problem/P6113 题目大意 给出一张无向图,求最大匹配. \(1\leq n\leq 10^3,1\leq m\leq 5\ ...
- CF444C-DZY Loves Colors【线段树,set】
正题 题目链接:https://www.luogu.com.cn/problem/CF444C 题目大意 \(n\)个物品第\(i\)个颜色为\(i\),权值为\(0\).要求支持\(m\)次操作 给 ...
- Dapr + .NET Core实战(六)绑定
什么是绑定 处理外部事件或调用外部接口的功能就是绑定,绑定可以提供以下好处: 避免连接到消息系统 ( 如队列和消息总线 ) 并进行轮询的复杂性 聚焦于业务逻辑,而不是如何与系统交互 使代码不受 SDK ...
- Idea进行java应用的远程调试Remote debugging
本文可以解决如下两个问题: 1.如何处理和调试那些只发生在生产环境(或其他远程环境)而本地开发环境可能没办法重现的"问题". 2.只有一个可以部署的war/jar包,只有class ...
- Python中字符串常用方法
capitalize() String.capitalize() 将字符串首字母变为大写 name = 'xiaoming' new_name = name.capitalize() print(ne ...
- 你对微信小程序的理解?优缺点?
一.是什么 2017年,微信正式推出了小程序,允许外部开发者在微信内部运行自己的代码,开展业务 截至目前,小程序已经成为国内前端的一个重要业务,跟 Web 和手机 App 有着同等的重要性 小程序是一 ...
- .jar文件没有Java(TM) Platform SE binary打开方式解决办法
下面是我个人在打开.jar文件时候的一些小问题: 明明已经配置好了环境变量.jar文件却没有 Java(TM) Platform SE binary 的打开方式, 网上查了资料点明是环境变量的问题,后 ...
- 在Vue&Element前端项目中,对于字典列表的显示处理
在很多项目开发中,我们为了使用方便,一般都会封装一些自定义组件来简化界面的显示处理,例如参照字典的下拉列表显示,是我们项目中经常用到的功能之一,本篇随笔介绍在Vue&Element前端项目中如 ...
- 技术博客--微信小程序canvas实现图片编辑
技术博客--微信小程序canvas实现图片编辑 我们的这个小程序不仅仅是想给用户提供一个保存和查找的平台,还希望能给用户一个展示自己创意的舞台,因此我们实现了图片的编辑部分.我们对对图片的编辑集成了很 ...