时间复杂度

计数排序算法——时间复杂度O(n+k)

我与影子孤独终老i 提交于 2020-01-30 00:43:22
计数排序 计数排序是一个非基于比较的排序算法,该算法于1954年由 Harold H. Seward 提出。它的优势在于在对一定范围内的整数排序时,它的复杂度为Ο(n+k)(其中k是整数的范围),快于任何比较排序算法。 算法思想 计数排序对输入的数据有附加的限制条件: 1、输入的线性表的元素属于有限偏序集S; 2、设输入的线性表的长度为n,|S|=k(表示集合S中元素的总数目为k),则k=O(n)。 在这两个条件下,计数排序的复杂性为O(n)。 计数排序的基本思想是对于给定的输入序列中的每一个元素x,确定该序列中值小于x的元素的个数。一旦有了这个信息,就可以将x直接存放到最终的输出序列的正确位置上。例如,如果输入序列中只有17个元素的值小于x的值,则x可以直接存放在输出序列的第18个位置上。当然,如果有多个元素具有相同的值时,我们不能将这些元素放在输出序列的同一个位置上,因此,上述方案还要作适当的修改。 假设输入的线性表L的长度为n,L=L1,L2,..,Ln;线性表的元素属于有限偏序集S,|S|=k且k=O(n),S={S1,S2,..Sk};则计数排序可以描述如下: 1、扫描整个集合S,对每一个Si∈S,找到在线性表L中小于等于Si的元素的个数T(Si); 2、扫描整个线性表L,对L中的每一个元素Li,将Li放在输出线性表的第T(Li)个位置上,并将T(Li)减1。

时间复杂度为O(logn)&O(log(m+n))

会有一股神秘感。 提交于 2020-01-30 00:39:58
Olog(n) 折半查找,欧几里得算法,幂运算。 折半查找 int binary_search(int a[], int x) { //折半查找默认数组已经排序 int low = 0, high = a.length() - 1; while (low <= high) { int mid = (low + high) / 2; if (a[mid] < x) low = mid + 1; else if (a[mid] > x) high = mid - 1; else return mid; } return -1; } 欧几里得算法求最大公因数 int gcd(int m, int n) { //m>n while (n != 0) { int yu = m % n; m = n; n = yu; } return m; } 幂运算 int pow_m(int x, int y) { //x的y次 if (y == 0) return 1; if (y == 1) return x; if (y % 2 == 0) return pow_m(x*x, y / 2); if (y % 2 == 1) return x * pow_m(x*x, y / 2); } O(log(m+n)) 归并排序 float median(vector<int>& nums1,vector

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

吃可爱长大的小学妹 提交于 2020-01-30 00:37:37
(转载请注明出处, http://www.cnblogs.com/fangpei/p/3538331.html ) 以前写过的一篇,搬过来。 上算法课的时候听到老师讲这个问题,觉得还是蛮有意思的。已知数组A,找出A[m]...A[p]中的第k大值。 很容易想到快排和冒泡。 第一种方法:用快排的分治方法,是先任意找数组中的一个元素a(a用数组的第一个元素比较方便),然后进行一次划分,就是将数组中所有大于a的数都移到a的一边,所有小于等于a的数都移到A的另一边。然后选择在哪边继续进行划分,最后找到第k大的值。 第二种方法:用冒泡的方法,是每个元素挨着比,第一趟找出最大的数,第二趟找出第2大的数,一直到找到第k大的数结束。 其实第一种方法的平均复杂度能到O(n),但是它的复杂度依赖于划分元素,最坏的时间复杂度是O(n^2)。 如果在第一种方法之上,加上一个筛选划分元素的过程,就能把最坏时间复杂度降到O(n)。筛选的过程就是把所有的数等分成很多小段,然后求所有小段的中间值。构成一个由所有中间值组成的段,然后再取中间值,作为划分元素。即中间值的中间值作为划分元素。取中间值可以先任选一种排序方法排序之后选择,因为每一小段的长度很短,不是影响复杂度的主要因素;取中间值的中间值,利用递归的方法调用自身即可。 这样就可以把最坏时间复杂度降到O(n)了,复杂度证明比较繁琐。 用C++实现了一下:

LeetCode题解001:两数之和

故事扮演 提交于 2020-01-29 08:57:08
两数之和 题目 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素 示例: 给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1] Java: 方法一:暴力法 暴力法很简单,就是用两遍循环的方式遍历nums class Solution { public int[] twoSum(int[] nums, int target) { for (int i = 0; i < nums.length; i++) { for (int j = i + 1; j < nums.length; j++) { if (nums[j] == target - nums[i]) { return new int[] { i, j }; } } } throw new IllegalArgumentException("No two sum solution"); } } 复杂度分析: 时间复杂度:O(n^2) 对于每个元素,我们试图通过遍历数组的其余部分来寻找它所对应的目标元素,这将耗费 O(n) 的时间。因此时间复杂度为 O(n^2)

排序算法汇总(二)

心已入冬 提交于 2020-01-29 03:16:20
我们继续接着插入排序法往下聊。 直接插入排序法的时间复杂度问题 插入排序法(或者叫做直接插入排序法)的原理很简单,也很自然,而且也是后面很多排序法的基础,是不得不会的。它的思想是,每一次将待排序的数据插入到已排好顺序的数组中去。所以一开始,任何一个数据都认为是已排好序的。也就是数组的首元素A[0],设数组长度为n,那么第一次插入是从A[1]开始的,先将A[0]赋值给临时变量key.这是一个临时保存待插入数据的新内存空间,防止数据丢失的,而将A[0]赋值给A[1].key与A[0]比较,若大,则将key赋值给A[1],否则将key赋值给A[0].如此就完成了A[1]的插入操作。这是完全可行的。如果现在是A[j] (j<n)要插入,那么一定是A[:j]已经排好序了,而插入A[j]也是要将它赋值给key,将A[j-1]赋值给A[j],相当于数据后移,先后移,再进行比较,若key大,则key赋值给A[j],否则与A[j-1]比较,这里涉及到一个迭代过程,用i标记前j个元素的下标,将j当做一个常数,i递减。只有当i<0或者key大于等于某个A[i] 时循环才会退出。将key的值赋值给A[i+1],操作完成。 最后,由于数组长度时有限的,当k遍历到n时,整个插入排序的算法结束。下面是算法导论中提供的伪码: 插入排序法最坏和平均情况下时间复杂度都是O(n^2),最好情况下时间复杂度为O(n)

绪论

六月ゝ 毕业季﹏ 提交于 2020-01-29 01:22:47
基本概念 数据 数据元素 数据对象 数据类型 抽象数据类型(ADT) 数据结构 数据元素之间的关系称为数据结构 . 数据结构包括逻辑结构,存储结构和数据的运算 逻辑结构(构想) 线性结构和非线性结构(集合,树,图) 存储结构(实现) 顺序结构(数组,连续存储) 链接结构(链表) 索引结构(索引表) 散列结构(哈希值计算) 运算 运算的定义 运算的实现 算法和算法评价 算法 解决特定问题的步骤 . 有穷性(步骤有穷) 确定性(结果确定) 可行性(可以操作) 输入 输出 算法评价 时间复杂度 所有语句执行的次数和 主要考虑 最坏时间复杂度 最好时间复杂度 平均时间复杂度 大O表示法,f(n)=O(g(n)),f(n)阶不高于g(n),上界 O(max(f,g))=O(f)+O(g) O(f+g)=O(f)+O(g) O(f*g)=O(f)*O(g) Ω表示法,与大O定义相反,下界 θ表示法,确界 题型:给一段代码计算时间复杂度 基本方法: 循环终止条件 循环变量增加形式 确定循环次数 小结论: for(i=a;i<n^b;i=i*c)时间复杂度为O(logn) for(i=a;i<n*b;i=i+c)时间复杂度为O(n) 题型:递归方程求时间复杂度 方法一:迭代 方法二:求通项,数列 方法三:主定理 空间复杂度 来源: CSDN 作者: 陈&sl 链接: https://blog

NP问题

吃可爱长大的小学妹 提交于 2020-01-28 14:12:49
希望通过这篇文章可以不仅让计算机相关专业的人可以看懂和区分什么是P类问题什么是NP类问题,更希望达到的效果是非专业人士比如学文科的朋友也可以有一定程度的理解。 有一则程序员界的笑话,就是有一哥们去google面试的时候被问到一个问题是:在什么情况下P=NP,然后他的回答是”当N=1的时候”。这是我第一次听说P=NP问题,大概是在临近毕业为找工作而准备的时候。 这几天科技类新闻的头条都被阿尔法狗大战李世石刷爆了,虽然我也不是AI专家,但是也想从普通人的角度来写点东西来聊聊这个有意思的事情,在搜集资料的时候又一次看到了NP问题,于是想开个小差,先说说这个NP问题。 P类问题最简单的定义是这样的: P问题:一个问题可以在多项式(O(n^k))的时间复杂度内解决。 NP问题:一个问题的解可以在多项式的时间内被验证。 NP-hard问题:任意np问题都可以在多项式时间内归约为该问题,但该问题本身不一定是NP问题。归约的意思是为了解决问题A,先将问题A归约为另一个问题B,解决问题B同时也间接解决了问题A。 NPC问题:既是NP问题,也是NP-hard问题。 这样的定义虽然简单,但是对于第一次接触P、NP的人来说,就像前一阵问你什么是“引力波”而你回答:引力波是时空的涟漪。从答案中几乎没有得到任何有意义的理解。所以接来来的内容希望不仅计算机相关专业的人可以看懂

洛谷P3375 【模板】KMP字符串匹配

China☆狼群 提交于 2020-01-28 04:56:49
题目传送门: 戳我进入 KMP算法是用来处理字符串匹配的问题的,也就是给你两个字符串,你需要回答B串是否是A串的子串,B串在A串中出现了几次,B串在A串中出现的位置等问题。 KMP算法的意义在于,如果你在洛谷上发了一些话,kkksc03就可以根据KMP算法查找你是否说了一些不和谐的字,并且屏蔽掉你的句子里的不和谐的话( 比如cxk鸡你太美就会被屏蔽成cxk**** ),还会根据你句子中出现不和谐的字眼的次数对你进行处罚 举个栗子:A:GCAKIOI B:GC ,那么我们称B串是A串的子串 我们称等待匹配的A串为主串,用来匹配的B串为模式串。 一般的朴素做法就是枚举B串的第一个字母在A串中出现的位置并判断是否适合,而这种做法的时间复杂度是O(mn)的,当你处理一篇较长文章的时候显然就会超时。 我们会发现在字符串匹配的过程中,绝大多数的尝试都会失败,那么有没有一种算法能够利用这些失败的信息呢? KMP算法就是 KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的 设主串(以下称为T) 设模式串(以下称为W) 用暴力算法匹配字符串过程中,我们会把T[0] 跟 W[0] 匹配,如果相同则匹配下一个字符,直到出现不相同的情况,此时我们会丢弃前面的匹配信息,然后把T[1] 跟 W[0]匹配,循环进行,直到主串结束,或者出现匹配成功的情况

P类问题、NP类问题与NPC类问题

谁说胖子不能爱 提交于 2020-01-28 02:16:26
(转载自作者 “ Matrix67原创 ” 的文章,链接为: http://www.matrix67.com/blog/archives/105 ) 你会经常看到网上出现“这怎么做,这不是NP问题吗”、“这个只有搜了,这已经被证明是NP问题了”之类的话。你要知道,大多数人此时所说的NP问题其实都是指的NPC问题。他们没有搞清楚NP问题和NPC问题的概念。NP问题并不是那种“只有搜才行”的问题,NPC问题才是。好,行了,基本上这个误解已经被澄清了。下面的内容都是在讲什么是P问题,什么是NP问题,什么是NPC问题,你如果不是很感兴趣就可以不看了。接下来你可以看到,把NP问题当成是 NPC问题是一个多大的错误。 还是先用几句话简单说明一下时间复杂度。时间复杂度并不是表示一个程序解决问题需要花多少时间,而是当问题规模扩大后,程序需要的时间长度增长得有多快。也就是说,对于高速处理数据的计算机来说,处理某一个特定数据的效率不能衡量一个程序的好坏,而应该看当这个数据的规模变大到数百倍后,程序运行时间是否还是一样,或者也跟着慢了数百倍,或者变慢了数万倍。不管数据有多大,程序处理花的时间始终是那么多的,我们就说这个程序很好,具有O(1)的时间复杂度,也称常数级复杂度;数据规模变得有多大,花的时间也跟着变得有多长,这个程序的时间复杂度就是O(n),比如找n个数中的最大值;而像冒泡排序、插入排序等

顺序表和链表的优点和缺点

北慕城南 提交于 2020-01-26 22:30:35
顺序表: 优点:空间连续,支持随机访问,查找元素的时间复杂度为O(1) 缺点:1.插入或者删除元素的时间复杂度为O(n) 2.扩容的代价比较大 链表: 优点:1.空间不连续 2.插入或者删除的时间复杂度为O(1) 3.扩容容易 缺点:1.不支持随机访问 2.查找元素的时间复杂度为O(n) 来源: CSDN 作者: 丶独醒 链接: https://blog.csdn.net/m1059247324/article/details/104089400