时间复杂度

数据结构-概念总结

大城市里の小女人 提交于 2020-03-28 19:14:48
数据结构概念总结 Data Structures + Algorithms = Programs 一.数据结构 1.基本概念: 数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合 2.数据结构的逻辑结构分为四种: 集合结构,线性结构,树形结构,图结构。 3.数据结构的物理结构分为两种: 顺序存储结构和链式存储结构. 4.学习数据结构的用途: 数据结构在计算机专业课程体系中起到承上启下的作业,熟练使用数据结构可以使程序运行的更快更流畅 思维导图: 二.算法 1.定义: 对特定问题求解步骤的一种描述,它是指令的特定序列,每一条指令表示一个或多个操作 2.特性: 有穷性,确定性,可行性,输入,输出。 3.算法的描述: 自然语言,流程图,程序设计语言,伪代码。 4.算法分析: (1)算法设计的目标: 正确性,可使用性,可读性,健壮性,时间效率高与存储量低 (2)两种衡量算法效率的方法: 事后统计法(把程序跑一遍): 必须执行程序,且存在其他因素掩盖算法本质 事前估计法(撇开软硬件相关因素,仅考虑算法本身效率): 算法执行时间=基本运算时间*运算次数 基本运算:被视为算术运算的一般是最深层循环内语句 (3)算法效率分析: 算法的执行时间可由其基本运算的执行次数来计算 时间复杂度:记号"O",表示随问题规模n增大,算法执行时间的增长率和f(n

数构与算法 | 什么是大 O 表示算法时间复杂度

烂漫一生 提交于 2020-03-28 18:22:03
 正文: 开篇我们先思考这么一个问题:一台老式的 CPU 的计算机运行 O(n) 的程序,和一台速度提高的新式 CPU 的计算机运 O(n2) 的程序。谁的程运行效率高呢? 答案是前者优于后者。为什么呢?我们从时间复杂度分析就可以知道。 1、什么是时间复杂度? 在进行算法分析时,语句总的执行次数 T(n) 是关于问题的规模n 的函数,进而分析 T(n) 随 n 的变化情况并确定 T(n) 的数量级,算法的时间复杂度,也就是算法的时间度量,记作:T(n) = O(f( ))。它表示随问题的规模 n 的增大,算法的执行时间的增长率 f(n) 的增长率相同,称作算法的渐近时间复杂度,简称为时间的复杂度,其中 f(n) 是问题规模n的某个函数。 这样用大写 [ O( ) ] 来体现算法时间复杂度的记法,我们就称之为大O记法。例如:O(n)、O(1)、O(n2)、O(log n) 等等。一般情况下,随着 n 的增大,T(n) 增长最慢的算法为最优算法。 2、推导大O阶的方法 如何推导大O阶的表示方法,总结了三句口诀: 用时间1取代运算时间中的所有加法常数。 在修改后的运行的函数中,只保留最高阶项。 如果最高阶项存在且不是1,则去除与这个项相乘的常数。得到的结果就是大O阶。 说了太多文字显得太抽象,我们来看看一个例子你就明白了。 如图这个时间复杂度你知道是多少吗? ​ 分析: 当 i = 0时

时间复杂度O()与KMP算法

爷,独闯天下 提交于 2020-03-28 17:49:36
要得到某个结果,可以有很多种方式,算法就是为了寻找一条最快的方式。 而评判其好坏的标准就是时间复杂度。 O(1):   我们把执行一次的时间复杂度定义为O(1)   sum = a +b;   cout << sum <<endl; O(n):   for(int i = 0; i < n ;++n)   {       //do something.   } O(n2): for(int i = 0; i < n ;++n)   {      for(int j = 0; j < n ;++n)     {       //do something.     }   } 我们会碰到这样的需求,从一个主字符串中找到一个子串,首先我们想到的是这种方法: #include "stdafx.h" #include<iostream> #include<string> using namespace std; int findString(string S,string T) { int i = 0; int j = 0; while(i<S.length() && j < T.length()) { if(T[j] == S[i]) { i++; j++; } else { j=0; i = i-j+1; } } if(j = T.length()) { return i-j; }

数据结构中顺序表与链表的性能方面比较

会有一股神秘感。 提交于 2020-03-28 06:59:21
一,时间性能的比较 顺序表由数组实现,是一种随机存取结构,对表中任意节点存取操作时间复杂度为O(1)。 而查找链表的节点,须从头指针开始沿链扫描,平均时间复杂度为O(N).因此,若线性表的操作主要是查找,很少进行插入或删除操作,采用顺序比较合适。 对于链表,对某个节点进行插入删除操作只需修改指针,无需大量移动元素,平均时间复杂度为O(1)。而顺序表在插入或删除时,需要大量移动数据元素,平均移动元素的数目为表长的一般,时间复杂度为O(N)。因此,对线性表频繁的进行插入删除操作时,应采用链表。当插入和删除主要在表头或表尾时,应采用循环链表。 表1:时间性能比较 时间复杂度 查找 插入或删除 顺序表 O(1) O(N) 链表 O(N) O(1) 二,空间性能的比较 1, 顺序表的存储空间是静态分配的,必须提前确定其内存大小。常用于存储规模容易确定的线性表。 2, 动态链表的存储空间是动态分配的,只要其内存空间有空闲就不会出现溢出。常用于长度变化较大或长度难以估计的线性表。 3, 定义:存储密度=(节点中数据域占用的空间)/(节点结构占用的存储空间) 有时需考虑存储密度。 综上,在选取线性表时,应综合考虑时间和空间因素,选择一中最适合的。一般而言,顺序表适用于查询,而链表则更便于插入删除管理。 来源: https://www.cnblogs.com/waiting-for/p

数据结构--线性表之顺序表

假装没事ソ 提交于 2020-03-28 06:53:13
一、引入问题 在程序中,经常需要将一组(通常是同为某个类型的)数据元素作为整体管理和使用,需要创建这种元素组,用变量记录它们,传进传出函数等。一组数据中包含的元素个数可能发生变化(可以增加或删除元素)。 对于这种需求,最简单的解决方案便是将这样一组元素看成一个序列,用元素在序列里的位置和顺序,表示实际应用中的某种有意义的信息,或者表示数据之间的某种关系。 这样的一组序列元素的组织形式,我们可以将其抽象为 线性表 。一个线性表是某类元素的一个集合,还记录着元素之间的一种顺序关系。线性表是最基本的数据结构之一。 二、顺序表概念 将元素顺序地存放在一块连续的存储区里,元素间的顺序关系由它们的存储顺序自然表示 三、顺序表的基本形式 1、顺序表的基本形式: 数据元素本身连续存储,每个元素所占的存储单元大小固定相同,元素的下标是其逻辑地址,而元素存储的物理地址(实际内存地址)可以通过存储区的起始地址Loc (e0)加上逻辑地址(第i个元素)与存储单元大小(c)的乘积计算而得,即:         Loc(ei) = Loc(e0) + c*i 故,访问指定元素时无需从头遍历,通过计算便可获得对应地址,其时间复杂度为O(1)。 2、顺序表的元素外置形式: 如果元素的大小不统一,则须采用图b的元素外置的形式,将实际数据元素另行存储,而顺序表中各单元位置保存对应元素的地址信息(即链接)

排序总结

白昼怎懂夜的黑 提交于 2020-03-27 06:28:30
排序 代码实现: Sort方法GitHub 基于比较 的排序算法时间下限是O(nlogn):归并排序、堆排序、快排。其他都是O(n^2) 插入排序 直接插入 循环n-1次,每次将无序序列的第一个数插入到有序序列中。一开始有序序列只有一个数(第一个数),之后每插入一个有序序列+1 将第一个数作为哨兵,每次移动都将插入位置后到该数前的所有数往后移动一位 时间复杂度 :O(n^2) 最好情况:已经是有序序列,只用比较n-1次(因为是从后往前比较),不用移动。 最坏情况:逆序序列,每次向前比较到哨兵 空间复杂度 :O(1) 稳定 折半插入 其实是在直接插入的基础上,将无序序列的第一个数在有序序列中查找的时候变为折半查找 移动次数和直接插入相同,依赖于初始序列 时间复杂度 :O(n^2) 空间复杂度 :O(1) 稳定 希尔排序 将一组序列分组进行排序(隔5个数一组,隔3个一组...) 做到基本有序后对全体进行直接插入,因为基本有序,所以比较和插入次数能有效减少 时间复杂度 :O(n 1.25)~O(1.6n 1.25) 空间复杂度 :O(1) 不稳定 交换排序 冒泡排序 进行n-1次,从第一个数开始,两两比较,把大的数放后面。从而每次排序能确定最大的数并放到最后 当某次冒泡过程中不存在数值交换,则已为正序,不用再进行排序 时间复杂度 :O(n^2) 最好情况:正序,进行一次排序,比较n-1次

代码题(32)— 排序算法总结

Deadly 提交于 2020-03-26 04:41:17
0、几种排序对比   1. 从平均时间来看,快速排序是效率最高的,但快速排序在最坏情况下的时间性能不如堆排序和归并排序。而后者相比较的结果是,在n较大时归并排序使用时间较少,但使用辅助空间较多。   2. 上面说的简单排序包括除希尔排序之外的所有冒泡排序、插入排序、简单选择排序。其中 直接插入排序最简单,但序列基本有序或者n较小时,直接插入排序是好的方法 ,因此常将它和其他的排序方法,如快速排序、归并排序等结合在一起使用。 一、交换排序 1、冒泡排序   思想 :对待排序元素的关键字从后往前进行多遍扫描,遇到相邻两个关键字次序与排序规则不符时,就将这两个元素进行交换。这样关键字较小的那个元素就像一个泡泡一样,从最后面冒到最前面来。   时间复杂度 :最坏:O(n2); 最好: O(n); 平均: O(n2)   空间复杂度 :O(1)   稳定性 : 稳定 ,相邻的关键字两两比较,如果相等则不交换。所以排序前后的相等数字相对位置不变。 void BubbleSort(vector<int> &a, int num) { bool flag = true; for (int i = 0; i < num ; ++i) { if (!flag)//判断上一次循环有没有交换 break; flag = false; for (int j = num - 1; j > i; --j) {

最长回文子串问题 O(n)算法 manacher URAL1297 HDU3068

不问归期 提交于 2020-03-26 01:44:39
先来看一道简单的题, ural1297 给定一个1000长度的字符串,求最长回文子串。 看起来很Naive,乱搞一下,O(n^2)都可以解决。 再来看这个题 HDU3068 120个110000长度的字符串,是不是感觉有点困难了?据说后缀数组也要TLE 给出一个O(n)的解决方案 manacher算法 很有趣的利用了回文子串的性质,进行递推更新。 转载自 http://blog.csdn.net/ggggiqnypgjg/article/details/6645824 这里,我介绍一下O(n)回文串处理的一种方法。Manacher算法. 原文地址: http://zhuhongcheng.wordpress.com/2009/08/02/a-simple-linear-time-algorithm-for-finding-longest-palindrome-sub-string/ 其实原文说得是比较清楚的,只是英文的,我这里写一份中文的吧。 首先:大家都知道什么叫回文串吧,这个算法要解决的就是一个字符串中最长的回文子串有多长。这个算法可以在O(n)的时间复杂度内既线性时间复杂度的情况下,求出以每个字符为中心的最长回文有多长, 这个算法有一个很巧妙的地方,它把奇数的回文串和偶数的回文串统一起来考虑了。这一点一直是在做回文串问题中时比较烦的地方

最好、最坏、平均、均摊时间复杂度

荒凉一梦 提交于 2020-03-24 12:05:02
关注公众号 MageByte,设置星标点「在看」是我们创造好文的动力。后台回复 “加群” 进入技术交流群获更多技术成长。 本文来自 MageByte-青叶编写 上次我们说过 时间复杂度与空间复度 ,列举了一些分析技巧以及一些常见的复杂度分析比如 O(1)、O(logn)、O(n)、O(nlogn),今天会继续细化时间复杂度。 1. 最好情况时间复杂度(best case time complexity) 2.最坏情况时间复杂度(worst case time complexity) 3. 平均情况时间复杂度(average case time complexity) 4.均摊时间复杂度(amortized time complexity) 复杂度分析 public int findGirl(int[] girlArray, int number) { int i = 0; int pos = -1; int n = girlArray.lentgh(); for (; i < n; ++i) { if (girlArray[i] == number) { pos = i; break; } } return pos; } 代码逻辑你应该很容易看出来,在无序数组 中查找 number 出现的位置,如果没找到就返回 -1。《唐伯虎点秋香》主角星爷通过这个方法遍历数组找到秋香

链表操作 -- 两个链表间的相交性问题

一世执手 提交于 2020-03-23 14:49:15
本文参考:    http://blog.csdn.net/g_brightboy/article/details/6824834    http://blog.csdn.net/huangxy10/article/details/8014233   在此致谢。 问题:   给定两个链表,判断它们是否相交。 注意:   如果两个链表相交的话,则公用相交点开始往后的所有节点。【因为节点的next指针只有一个!】 解答:   1)首先来看最直观的方法,也就是一次判断链表A中的节点是否在链表B中出现。   时间复杂度:O(n 2 )   空间复杂度:O(1)    1 bool List::isIntersect(Node* listA,Node* listB){ 2 for(Node* headA = listA; headA != NULL ; headA = headA->next){ 3 for(Node* headB = listB; headB != NULL; headB = headB->next){ 4 if(headA == headB) 5 return true; 6 } 7 } 8 return false; 9 } View Code      2)在方法(1)中,链表A中节点每次都需要匹配链表B中每个节点,这个匹配动作的时间复杂度为O(n)