时间复杂度

T(n)=2T(n/2)+n=o(nlogn)

纵然是瞬间 提交于 2020-03-23 14:08:16
T(n)=2T(n/2)+n 设n=2^k T(n/2)=2T(n/2^2)+n/2 T(n/2^2)=2T(n/2^3)+n/2^2 T(n)=2T(n/2)+n=2^2T(n/2^2)+2*n/2+n=2^3T(n/2^3)+2^2*n/2^2+2*n/2+n =2^kT(1)+kn=nT(1)+kn=n(logn+T(1))=o(nlogn) 注:T(1)=0 快速排序的最优时间复杂度是 O ( n l o g n ) O(nlogn),最差时间复杂度是 O ( n 2 ) O(n2),期望时间复杂度是 O ( n l o g n ) O(nlogn)。 这里我们证明一下快排的期望时间复杂度。 设 T ( n ) T(n) 为对长度为 n n 的序列进行快速排序所需要的期望时间。我们有: <script type="text/javascript" src="http://common.cnblogs.com/script/ASCIIMathML.js"></script> T ( 0 ) = 0 T(0)=0 以及: T ( n ) = n + 1 n ∑ i = 0 n − 1 ( T ( i ) + T ( n − i − 1 ) ) T(n)=n+1n∑i=0n−1(T(i)+T(n−i−1)) 我们可以通过放缩来获得对 T ( n ) T(n) 上界的一个估计。 T

找第k大数,最坏时间复杂度O(n)

£可爱£侵袭症+ 提交于 2020-03-22 15:08:50
转载自: https://www.cnblogs.com/fangpei/p/3538331.html 第一种方法:用快排的分治方法,是先任意找数组中的一个元素a(a用数组的第一个元素比较方便),然后进行一次划分,就是将数组中所有大于a的数都移到a的一边,所有小于等于a的数都移到A的另一边。然后选择在哪边继续进行划分,最后找到第k大的值。 第二种方法:用冒泡的方法,是每个元素挨着比,第一趟找出最大的数,第二趟找出第2大的数,一直到找到第k大的数结束。 其实第一种方法的平均复杂度能到O(n),但是它的复杂度依赖于划分元素,最坏的时间复杂度是O(n^2)。 如果在第一种方法之上,加上一个筛选划分元素的过程,就能把最坏时间复杂度降到O(n)。筛选的过程就是把所有的数等分成很多小段,然后求所有小段的中间值。构成一个由所有中间值组成的段,然后再取中间值,作为划分元素。即中间值的中间值作为划分元素。取中间值可以先任选一种排序方法排序之后选择,因为每一小段的长度很短,不是影响复杂度的主要因素;取中间值的中间值,利用递归的方法调用自身即可。 这样就可以把最坏时间复杂度降到O(n)了,复杂度证明比较繁琐。 #include<iostream> using namespace std; int r = 5; //定义全局变量r, r个元素一段 void InSort( int A[], int m,

排序算法

落花浮王杯 提交于 2020-03-22 10:50:37
目录 快速排序(基于交换) 特性 思想 代码 冒泡排序(交换排序) 思想: 特点: 代码: 直接插入排序(插入排序) 思想: 特点: 代码: 折半插入排序(插入排序) 思想: 特点: 代码: 希尔排序(插入排序) 思想: 特点: 代码: 简单选择排序: 思想: 特点: 代码: 堆排序 (选择排序) 思想:按照层次遍历的顺序标号映射到数组中。 特点: 代码: 归并排序 特性 思想 代码 基数排序 思想: 特点: 快速排序(基于交换) 特性 每次使一个数归位。不稳定 思想 每次partition划分数组为两部分并返回下标。随后递归地对左右序列快速排序。 代码 int Partition(int arr[],int left,int right) { int i = left; int j = right; int pivotindex = left; //基准坐标可以任意选 int pivotnum = arr[pivotindex]; //基准数 cout << "pivotnum = " << pivotnum << endl; while(i < j) //当i==j的时候,i和j的下标就是基准数的正确位置。 { while (i < j && arr[j] >= pivotnum) //先从后面往前找小于基准数 j--; arr[i] = arr[j]; //复制到前面i的位置

Python常见的几种算法

人盡茶涼 提交于 2020-03-21 10:48:59
冒泡排序 冒泡排序 (英语:Bubble Sort)是一种简单的排序算法。它重复地遍历要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。 冒泡排序算法的运作如下: 比较相邻的元素。如果第一个比第二个大(升序),就交换他们两个。 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。 针对所有的元素重复以上的步骤,除了最后一个。 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。 冒泡排序的分析 交换过程图示(第一次): 那么我们需要进行n-1次冒泡过程,每次对应的比较次数如下图所示: def bubble_sort(alist): for j in range(len(alist)-1,0,-1): # j表示每次遍历需要比较的次数,是逐渐减小的 for i in range(j): if alist[i] > alist[i+1]: alist[i], alist[i+1] = alist[i+1], alist[i] li = [54,26,93,17,77,31,44,55,20] bubble_sort(li) print(li) 时间复杂度

时间复杂度o(1), o(n), o(logn), o(nlogn) 说明

落花浮王杯 提交于 2020-03-21 00:44:29
3 月,跳不动了?>>> 在描述算法时通常用o(1), o(n), o(logn), o(nlogn) 来说明时间复杂度 o(1):是最低的时空复杂度,也就是耗时/耗空间与输入数据大小无关,无论输入数据增大多少倍,耗时/耗空间都不变。 哈希算法就是典型的O(1)时间复杂度,无论数据规模多大,都可以在一次计算后找到目标(不考虑冲突的话) O(n):代表数据量增大几倍,耗时也增大几倍。(n)代表输入的数据量,比如 常见的遍历算法 O(n^2):代表数据量增大n倍,时间复杂度就是n的平方倍,比如 冒泡排序,就是典型的O(n^2)的算法 ,对n个数排序,需要扫描n×n次。 O(logn):当数据增大n倍时,耗时增大logn倍(这里的log是以2为底的,比如,当数据增大256倍时,耗时只增大8倍,是比线性还要低的时间复杂度)。 二分查找就是O(logn)的算法 ,每找一次排除一半的可能,256个数据中查找只要找8次就可以找到目标 O(nlogn):同理,就是n乘以logn,当数据增大256倍时,耗时增大256*8=2048倍。这个复杂度高于线性低于平方。 归并排序就是O(nlogn)的时间复杂度 。 来源: oschina 链接: https://my.oschina.net/u/3905482/blog/1861154

【转】算法中时间复杂度概括——o(1)、o(n)、o(logn)、o(nlogn)

为君一笑 提交于 2020-03-21 00:02:23
3 月,跳不动了?>>> 在描述算法复杂度时,经常用到o(1), o(n), o(logn), o(nlogn)来表示对应算法的时间复杂度。 这里进行归纳一下它们代表的含义:这是算法的时空复杂度的表示。不仅仅用于表示时间复杂度,也用于表示空间复杂度。 O后面的括号中有一个函数,指明某个算法的耗时/耗空间与数据增长量之间的关系。其中的n代表输入数据的量。 比如时间复杂度为O(n),就代表数据量增大几倍,耗时也增大几倍。比如常见的遍历算法。 再比如时间复杂度O(n^2),就代表数据量增大n倍时,耗时增大n的平方倍,这是比线性更高的时间复杂度。比如冒泡排序,就是典型的O(n^2)的算法,对n个数排序,需要扫描n×n次。 再比如O(logn),当数据增大n倍时,耗时增大logn倍(这里的log是以2为底的,比如,当数据增大256倍时,耗时只增大8倍,是比线性还要低的时间复杂度)。二分查找就是O(logn)的算法,每找一次排除一半的可能,256个数据中查找只要找8次就可以找到目标。 O(nlogn)同理,就是n乘以logn,当数据增大256倍时,耗时增大256*8=2048倍。这个复杂度高于线性低于平方。归并排序就是O(nlogn)的时间复杂度。 O(1)就是最低的时空复杂度了,也就是耗时/耗空间与输入数据大小无关,无论输入数据增大多少倍,耗时/耗空间都不变。 哈希算法就是典型的O(1

【Leetcode 做题学算法周刊】第四期

流过昼夜 提交于 2020-03-18 13:32:44
首发于微信公众号《前端成长记》,写于 2019.11.21 背景 本文记录刷题过程中的整个思考过程,以供参考。主要内容涵盖: 题目分析设想 编写代码验证 查阅他人解法 思考总结 目录 67.二进制求和 69.x的平方根 70.爬楼梯 83.删除排序链表中的重复元素 88.合并两个有序数组 Easy 67.二进制求和 题目地址 题目描述 给定两个二进制字符串,返回他们的和(用二进制表示)。 输入为非空字符串且只包含数字 1 和 0 。 示例: 输入: a = "11", b = "1" 输出: "100" 输入: a = "1010", b = "1011" 输出: "10101" 题目分析设想 这道题又是一道加法题,所以记住下,直接转数字进行加法可能会溢出,所以不可取。所以我们需要遍历每一位来做解答。我这有两个大方向:补0后遍历,和不补0遍历。但是基本的依据都是本位相加,逢2进1即可,类似手写10进制加法。 补0后遍历,可以采用先算出的位数推入数组最后反转,也可以采用先算出的位数填到对应位置后直接输出 不补0遍历,根据短数组的长度进行遍历,长数组剩下的数字与短数组生成的进位进行计算 查阅他人解法 Ⅰ.补0后遍历,先算先推 代码: /** * @param {string} a * @param {string} b * @return {string} */ var

数据结构与算法9-排序1

北城余情 提交于 2020-03-17 22:39:49
本篇文章讲解冒泡、插入、选择排序。 1.衡量排序算法执行效率(不太用的到) 时间复杂度 时间复杂度的系数、常数、低阶 比较次数和交换(或移动)次数 2.一些前提概念 上述使用稳定排序算法的例子蛮实用的。 3.冒泡排序 平均时间复杂度呢?—— 使用有序度、逆序度 满有序度 = n*(n-1)/2 逆序度 = 满有序度 - 有序度 最坏情况的逆序度是 n*(n-1)/2,所以算平均是 n*(n-1)/4,所以平均时间复杂度为O(n^2)。 4.插入排序(就是打扑克牌,所以很常用) 上述关于逆序度的trick,了解一下即可。 5.选择排序(就是选苹果) 6.为什么插入排序更受欢迎 7.小结 8.扩展 冒泡排序 动图:https://pic1.zhimg.com/v2-1543c0b97237bb55063e033959706ca0_b.webp 插入排序 动图:https://pic2.zhimg.com/v2-f87ad7d8ad54379dd81f02fcf9b91f49_b.webp 选择排序 动图:https://pic1.zhimg.com/v2-f20b8898585b3ca03843d93ce2c35a68_b.webp 来源: CSDN 作者: Xu_Wave 链接: https://blog.csdn.net/qq_22795223/article/details

跳跃表

不想你离开。 提交于 2020-03-17 05:35:32
这是发生在很多年以前的故事…… 几天以前…… 几天之后…… 拍卖行的商品总数量有几十万件,对应数据库商品表的几十万条记录。 如果是按照商品名称精确查询还好办,可以直接从数据库查出来,最多也就上百条记录。 如果是没有商品名称的全量查询怎么办?总不可能把数据库里的所有记录全查出来吧,而且还要支持不同字段的排序。 所以,只能提前在内存中存储有序的全量商品集合,每一种排序方式都保存成独立的集合,每次请求的时候按照请求的排序种类,返回对应的集合。 比如按价格字段排序的集合: 比如按等级字段排序的集合: 需要注意的是,当时还没有Redis这样的内存数据库,所以小灰只能自己实现一套合适的数据结构来存储。 拍卖行商品列表是线性的,最容易表达线性结构的自然是数组和链表。可是,无论是数组还是链表,在插入新商品的时候,都会存在性能问题。 按照商品等级排序的集合为例,如果使用数组,插入新商品的方式如下: 如果要插入一个等级是3的商品,首先要知道这个商品应该插入的位置。使用二分查找可以最快定位,这一步时间复杂度是O(logN)。 插入过程中,原数组中所有大于3的商品都要右移,这一步时间复杂度是O(N)。所以总体时间复杂度是O(N)。 如果使用链表,插入新商品的方式如下: 如果要插入一个等级是3的商品,首先要知道这个商品应该插入的位置。链表无法使用二分查找,只能和原链表中的节点逐一比较大小来确定位置

刷了力扣题之后,我也变的一发不可收拾了?

笑着哭i 提交于 2020-03-17 01:15:37
作为程序员界的一枚小菜鸟,可谓是,从大量的 CRUD 业务中,练就了一身复制粘贴即可用的本领。 因为大家不是都说:程序 = 复制 + 百度 吗,再高级一点的就是复制 + 谷歌喽。(我不禁想,难道科学^上网就高级了?) 反正都是拿来主义嘛,代码能跑起来就完事,实在不行,删库跑路也很轻松呀 ^_^。 但是呢,迫于网上不断流出的 “35岁程序员危机” 话题,我不得不开始认真思考,我这马上奔三的大龄青年,离 35 岁还差多远呢 。 再加上,身边大佬朋友都在说算法的重要性,看来,我真的需要重新考虑“程序”的定义了。看下边严肃版的官方定义。。。 程序 = 算法 + 数据结构 于是乎,我也开始重视算法和数据结构的重要性了。 那些躺在网盘里的收藏版,也是时候拿出来晒一晒了。 但是,只看理论,不做题,那不是耍流氓吗。好歹我也是一正经,正直的好青年,不能辜负力扣(LeetCode)对广大适龄程序员的好心啊。 万丈高楼平地起,我总得先去申请个账号吧(话说,貌似我之前好像申请过?但是都忘得一干二净了)。怎么个刷题法呢,又犯难了,好在我有百度啊,谷歌啊(咳咳,说好的不用搜索引擎呢)。 这时,查出来在某乎上看到一句特别有意思的话,说是有哥们从“两数之和”开始算法之路,从此变的一发不可收拾。当上总经理,出任CEO,迎娶富婆哦不白富美,走上人生巅峰。 我哩乖乖,有这么神奇么。我都不信了