时间复杂度

时间复杂度

和自甴很熟 提交于 2019-12-23 15:23:07
一个算法是由控制结构(顺序、分支和循环3种)和原操作(指固有数据类型的操作)构成的,则算法时间取决于两者的综合效果。为了便于比较同一个问题的不同算法,通常的做法是,从算法中选取一种对于所研究的问题(或算法类型)来说是基本操作的原操作,以该基本操作的重复执行的次数作为算法的时间量度。 1、时间复杂度 (1)时间频度 一个算法执行所耗费的时间,从理论上是不能算出来的,必须上机运行测试才能知道。但我们不可能也没有必要对每个算法都上机测试,只需知道哪个算法花费的时间多,哪个算法花费的时间少就可以了。并且一个算法花费的时间与算法中语句的执行次数成正比例,哪个算法中语句执行次数多,它花费时间就多。一个算法中的语句执行次数称为语句频度或时间频度。记为T(n)。 (2)时间复杂度 在刚才提到的时间频度中,n称为问题的规模,当n不断变化时,时间频度T(n)也会不断变化。但有时我们想知道它变化时呈现什么规律。为此,我们引入时间复杂度概念。 一般情况下,算法中基本操作重复执行的次数是问题规模n的某个函数,用T(n)表示,若有某个辅助函数f(n),使得当n趋近于无穷大时, T(n)/f(n) 的极限值为不等于零的常数,则称f(n)是T(n)的同数量级函数。记作 T(n)=O(f(n)), 称 O(f(n)) 为算法的渐进时间复杂度,简称时间复杂度。 另外,上面公式中用到的

《数据结构与算法》-2-线性表

我的梦境 提交于 2019-12-23 13:24:02
目录 1. 线性表的定义和基本操作 1.1 线性表的定义 1.2 线性表的基本操作 2. 线性表的顺序表示 2.1 顺序表的定义 2.2顺序表上基本操作的实现 3. 线性表的链式表示 3.1 单链表的定义 3.2 单链表基本操作的实现 3.3 双链表 3.4 循环链表 3.5 静态链表 4. 顺序表与链表的比较 5. 如何选择存储结构   该系列博客的目的是为了学习一遍数据结构中常用的概念以及常用的算法,为笔试准备;主要学习过程参考王道的《2018年-数据结构-考研复习指导》; 已总结章节: 《数据结构与算法》-1-绪论 《数据结构与算法》-2-线性表   上篇博客 《数据结构与算法》-1-绪论 中说到数据结构的三要素:逻辑结构、存储结构、数据的运算;其中,逻辑结构表示的是数据元素之间的关系,逻辑结构根据数据元素之间关系的不同,分成了线性结构与非线性结构,这里我们将要介绍的就是线性结构中的线性表,并根据线性表在计算机中存储结构的不同,分别介绍了:顺序存储(顺序表)、链式存储(链表);   这篇主要介绍的内容有: 线性表的定义以及基本操作 ; 线性表的顺序存储 ; 线性表的链式存储 ; 顺序表与链表的比较 ;   其知识框架如下图所示: 1. 线性表的定义和基本操作   这一节主要介绍线性表,主要内容包括:线性表的定义及基本操作; 1.1 线性表的定义   定义: 线性表是具有 相同

什么是P问题、NP问题和NPC问题

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

计算时间复杂度

旧巷老猫 提交于 2019-12-23 02:35:17
究竟什么是时间复杂度呢?让我们来想象一个场景:某一天,小灰和大黄同时加入了一个公司...... 一天过后,小灰和大黄各自交付了代码,两端代码实现的功能都差不多。大黄的代码运行一次要花100毫秒,内存占用5MB。小灰的代码运行一次要花100秒,内存占用500MB。于是...... 由此可见,衡量代码的好坏,包括两个非常重要的指标: 1.运行时间; 2.占用空间。 关于代码的基本操作执行次数,我们用四个生活中的场景,来做一下比喻: 场景1: 给小灰一条长10寸的面包,小灰每3天吃掉1寸,那么吃掉整个面包需要几天? 答案自然是 3 X 10 = 30天。 如果面包的长度是 N 寸呢? 此时吃掉整个面包,需要 3 X n = 3n 天。 如果用一个函数来表达这个相对时间,可以记作 T(n) = 3n。 场景2: 给小灰一条长16寸的面包,小灰每5天吃掉面包剩余长度的一半,第一次吃掉8寸,第二次吃掉4寸,第三次吃掉2寸......那么小灰把面包吃得只剩下1寸,需要多少天呢? 这个问题翻译一下,就是数字16不断地除以2,除几次以后的结果等于1?这里要涉及到数学当中的对数,以2位底,16的对数,可以简写为log(2)16。 因此,把面包吃得只剩下1寸,需要 5 X log(2)16 = 5 X 4 = 20 天。 如果面包的长度是 N 寸呢? 需要 5 X logn = 5log(2)n天,记作

如何写出高效的链表代码

谁说胖子不能爱 提交于 2019-12-23 00:26:05
本篇文章将介绍下面这些内容,阅读预计15分钟。 文章目录 链表和数组区别 面试题常考的链表算法 LeetCode练习题索引 总结: 链表和数组区别  我们在问两个事物的区别时,我们实质是在问这两者分别是什么?而非真的关注差别本身。 数组: 数组是一种线性表数据结构。它用 连续的内存空间 ,存储 相同类型的数据 。  数组因为申请内的存是连续的内存空间,所以在知道First Index 的内存地址后,可以立即通过位置的 偏移 计算出其他任何位置(下标)的内存地址。也就是我们常说的随机访问的特性。 例如存储整数的一个Array,每个整数占4字节,在内存中的情况如下: 在知道arr[0]的内存地址是 0x100后,可以通过公式求取任意位置的内存地址: adrr[n] = 100+4*n 因为这个特性,可以利用CPU的高速缓存,在读取数组时,预读取一组数据,加快访问效率。 链表: 链表也是一种线性表数据结构,它通过 指针 把各个 零散 的节点串联起来。  将数组和链表放在一起看,可以发现,链表的内存地址不一定是连续的,系统不会预先分配给链表指定大小的内存空间。当向链表中存放数据,系统会寻找未使用的内存块,存放数据,然后把前一个节点的指针指向该内存。 所以当数组申请一个1G大小的空间时,系统可能因为没有足够的内存空间而创建失败。而链表不存在这样的问题,它使用的是系统中零散的内存。

算法时间复杂度

我是研究僧i 提交于 2019-12-22 18:34:56
原文链接: https://blog.csdn.net/szlg510027010/article/details/82426240 步骤: 1、找到执行次数最多的语句 2、语句执行语句的数量级 3、用O表示结果 计算时间复杂度的3个出发点,掌握这三个出发点,那么一向搞不懂的时间复杂度就可以迎刃而解啦。 然后: 1、用常数1取代运行时间中的所有加法常数 2、在修改后的运行次数函数中,只保留最高阶项 3、如果最高阶项存在且不是1,那么我们就去除于这个项相乘的常数。比如3n^2我们取n^2 最后就可以得到你们想要的结果了。 举几个例子: 我们来看一下这个例子,用的是java,内容就是打印8条语句,问这个程序的时间复杂度是多少? public class TS { public static void main(String[] args) { System.out.println("111"); System.out.println("111"); System.out.println("111"); System.out.println("111"); System.out.println("111"); System.out.println("111"); System.out.println("111"); System.out.println("111"); } } O(8)?

java面试题2020

筅森魡賤 提交于 2019-12-22 17:52:51
1:String类 能被继承吗?为什么? 不能,因为String类有final修饰符,final类无法被继承。 2:ArrayList和LinkedList有什么区别? a:ArrayList 底层是数组,而LinkedList底层是双向链表结构。 b:都是不同步的,不保证线程安全 c:插入和删除是否受元素位置的影响:ArrayList采用数组存储,所以插入和删除元素的时间受数组的复杂度影响,默认插入是在最后一位 时间复杂度是O(1),如果指定位置插入(add(int index,E element)时间复杂度就是(O(n-i)。因为在执行的时候集合中第i和第i个元素之后的(n-i)都要执行向前或向后一位的操作 LinkedList采用链表存储,所以插入,删除不受时间复杂度影响 都是近似O(1) d:是否支持快速随机访问:LinkedList 不支持高校的随机元素访问,而ArrayList支持。快速随机访问就是通过元素的序号快速获取元素对象(对应于get(index)方法。 e. 内存空间占用: ArrayList的空 间浪费主要体现在在list列表的结尾会预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗比ArrayList更多的空间(因为要存放直接后继和直接前驱以及数据) 3:g1和cms区别,吞吐量优先和响应优先的垃圾收集器选择。

链表和队列

对着背影说爱祢 提交于 2019-12-22 10:07:34
1.单链表 所谓单链表,是指数据结点是单向排列的。它包含两个域,一个信息域和一个指针域。 单链表可以解决顺序表需要大量的连续存储空间的缺点,但单链表附加指针域,也带来了浪费存储空间的缺点。 head NULL时则表示一个空链表 此外为了操作上的方便,可以在单链表第一个结点之前附加一个结点,称为头结点。 头结点的指针域指向链表的第一个结点,数据域可以不设任何信息,也可以存放链表元素个数等信息,带头结点的单链表head为空的判定条件为: head->next NULL。 单链表的插入、删除的时间复杂度均为O(n),单链表取数据元素操作的时间复杂度也为O(n)。 2.顺序表 将表中元素一个接一个的存入一组连续的存储单元中,这种存储结构是顺序结构。 1.顺序表是线性表,逻辑结构与存储位置吻合。 2.一般采用数组存储。 3.顺序的分类: 顺序表具有头插法,尾插法,从中间任何位置插入,头删法,尾删法,从中间任何位置删除。 3.顺序表和链表的比较 1)存取方式 顺序表可以顺序存取,也可以随机存取,链表只能从表头顺序存取元素。 2)查找、插入和删除操作 对于按值查找,当顺序表在无序的情况下,两者的时间复杂度均为O(n);而当顺序表有序的时候,可以折半查找,此时的时间复杂度为O(logn);对于按序号查找,顺序表支持随机访问,时间复杂度仅为O(1),而链表的平均时间复杂度为O(n)。顺序表的插入

排序算法以及其java实现

╄→尐↘猪︶ㄣ 提交于 2019-12-21 20:09:17
一、术语了解 稳定 :如果a原本在b前面,而a=b,排序之后a仍然在b的前面; 不稳定 :如果a原本在b的前面,而a=b,排序之后a可能会出现在b的后面; 内排序 :所有排序操作都在内存中完成; 外排序 :由于数据太大,因此把数据放在磁盘中,而排序通过磁盘和内存的数据传输才能进行; 时间复杂度: 一个算法执行所耗费的时间。 空间复杂度 :运行完一个程序所需内存的大小。 图片名词解释: n: 数据规模 k: “桶”的个数 In-place: 占用常数内存,不占用额外内存 Out-place: 占用额外内存 二、基础算法 1、冒泡算法 (1)思想:两两比较,每一趟都把最大或最小的数浮出 (2)优化:设置一个boolean isOrdered ;       在第一轮排序中一旦a[j] > a[j+1],就把isOrdered设为false,否则isOrdered设为true,然后我们在每趟排序前检查isOrdered,一旦发现它为false,即认为排序已完成。 (3)时间复杂度:要进行的比较次数为: (n-1) + (n-2) + ... + 1 = n*(n-1) / 2,因此冒泡排序的时间复杂度为O(n^2)。          最好的为O(n):数组已经有序,比较次数为n-1        public static void bubbleSort(int[] arr) {

跳表

空扰寡人 提交于 2019-12-21 17:15:58
跳表 文章目录 跳表 跳表概念 跳表结构 跳表性能 跳表的高度 查找时间复杂度 插入时间复杂度 删除时间复杂度 内存消耗 索引动态更新 跳表概念 二分查找法依赖于数组的随机访问特性,只能用数组实现 跳表是基于链表实现类似于二分查找的算法 查找、插入、删除各方面性能都不错的动态数据结构,甚至可以替代红黑树 Redis 中的有序集合(Sorted Set)就是用跳表来实现的 跳表结构 对于一个有序的单链表,想在其中查找某个数据,只能从头到尾遍历链表。效率很低 对链表建立一级索引,每两个结点提取一个结点到上一级,抽出来的一级称为索引层 索引层结点有指针指向下一级结点 在查找结点时,先在索引层遍历,再下降到原始链表,就能减少遍历次数 当链表很长,使用多级索引结构可以大大提高查找效率 跳表性能 跳表的高度 第 k 级索引的结点个数是第 k-1 级索引的结点个数的 1 2 \frac{1}{2} 2 1 ​ ,那么第 k 级索引 结点的个数就是 n 2 k \frac{n}{2^k} 2 k n ​ 假设索引有 h 级,最高级的索引有 2 个结点。通过上面的公式,可以得到求得 h = l o g 2 n − 1 h=log_2n-1 h = l o g 2 ​ n − 1 如果包含原始链表这一层,整个跳表的高度就是 l o g 2 n log_2n l o g 2 ​ n 查找时间复杂度