时间复杂度

数据结构—算法时间复杂度、空间复杂度和问题规模

我怕爱的太早我们不能终老 提交于 2020-01-20 02:11:57
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)) 为算法的渐进时间复杂度,简称时间复杂度。 另外,上面公式中用到的 Landau符号其实是由德国数论学家保罗·巴赫曼(Paul Bachmann)在其1892年的著作《解析数论》首先引入,由另一位德国数论学家艾德蒙·朗道(Edmund Landau)推广。 Landau符号的作用在于用简单的函数来描述复杂函数行为,给出一个上或下(确)界 。在计算算法复杂度时一般只用到大 O

【IOI2001】【poj1195】Mobile phones(二维树状数组)

浪尽此生 提交于 2020-01-19 00:19:34
一维树状数组维护的是区间和,最后统计的是1~x数的和,而二维树状数组维护的是一个面的和,最后统计的是 (1,1)~(x,y)区域内数的和 (x ,y)所维护的面大小由x,y共同决定,x决定高度,y决定宽度 add和query操作的两层循环结合二分图理解比较直观 如何分呢?首先,我们按照X坐标,把整个表格分成部分,并对每个部分按照X坐标继续二分下去,同时,我们将分得的每个部分再按Y坐标进行二分,并记下最终分得的每个部分的移动电话总数。 “多重二分”的结果,实际上类似于一维情况下二分的结果,也是形成一种“树”状的结构,只不过由于是多重二分,所以这棵“树”的每个节点仍然是一棵“树”。 在这棵“二分树”上进行“改动”操作,只要按照X坐标从“根”到“叶”,处理路径上每个节点,由于这些节点也是树,所以要按照Y坐标从“根”到“叶”,依次修改路径上的每个节点的数据。这样,处理每个节点的时间复杂度为O(log 2 n),每次修改需要处理的节点数为log 2 n,所以每次“改动”操作的时间复杂度为O(log 2 n* log 2 n)。 在“二分树”上从“根”到“叶”查找X,如果某步是向右子树走,则须处理相应的左子树的根节点,直到找到X,再处理此叶节点。 以X坐标为标准的“二分树”上的每个节点同时也是一棵以Y坐标为标准的“二分树”,对其处理的方法为:从“根”到“叶”查找Y,如果某步是向右子树走

Johnson's Algorithm for ASPS(All Pairs Shortest Path)

爱⌒轻易说出口 提交于 2020-01-19 00:18:23
之前由于觉得博客写起来没有笔记方便,所以停了很久。 最近开始使用markdown来写博客,感觉挺清爽,又要开始增产啦~ Johnson's Algorithm = Bellman-Ford + Dijkstra 若是仅仅使用|V|次Dijkstra算法跑完全图可以求得最短路径,时间复杂度(V2log|V| + VE) 虽然效率比Floyd高,但是只能处理正权图 Johnson算法就是将所有边预处理重新赋值,使全部边权为正,再利用Dijkstra处理 注意:不能单纯地每条边加上某个权值w,这样会改变最短路径 Example: s --> t 1 1 1 s ------ a ----- b ----- t \____________________/ 4 初始最短路,s-->a-->b-->t 若全部边同时+1,最短路变成s-->t 所以不能以边为单位来进行权值相加,应以**路径**为单位进行边的相加 Johnson算法Bellman-Ford预处理: 赋予每个顶点权值h[v] 对于边e(u,v),reweight之后的边权 = w(u,v) + h[u] - h[v] 那么对于u,v之间的任意路径增加的总权值是一样的(h[t]-h[s]),且每条边的边权>=0 获得h[i]的预处理步骤: 新建一个辅助点k, k与所有图中的点相连 从k到原图中各点i的最短距离就是h[i]

数据结构之排序基础知识笔记

北战南征 提交于 2020-01-18 22:14:17
概述 最近在温习数据结构,现在针对排序算法写一篇随笔,其中附带原理说明和代码。 插入排序 直接插入排序(Straight Insertion Sort)的基本思想是:把n个待排序的元素看成为一个有序表和一个无序表。开始时有序表中只包含1个元素,无序表中包含有n-1个元素,排序过程中每次 从无序表中取出第一个元素,将它插入到有序表中的适当位置,使之成为新的有序表,重复n-1次可完成排序过程。 假设{20,30,40,10,60,50}中的前3个数已经排列过,是有序的了;接下来对10进行排列。示意图如下: 图中将数列分为有序区和无序区。我们需要做的工作只有两个:(1)取出无序区中的第1个数,并找出它在有序区对应的位置。(2)将无序区的数据插入到有序区;若有必要的话,则对有序区中的相关数据进行移位。 时间复杂度和稳定性 直接插入排序的时间复杂度是O(N2)。 假设被排序的数列中有N个数。遍历一趟的时间复杂度是O(N),需要遍历多少次呢?N-1!因此,直接插入排序的时间复杂度是O(N*N)。 直接插入排序是稳定的算法,它满足稳定算法的定义。 算法稳定性 -- 假设在数列中存在a[i]=a[j],若在排序之前,a[i]在a[j]前面;并且排序之后,a[i]仍然在a[j]前面。则这个排序算法是稳定的。 插入排序JAVA实现 1 import static javaTest.SortUtils

快速幂取模

淺唱寂寞╮ 提交于 2020-01-18 05:01:08
快速幂取模 快速幂取模,就是对幂的运算进行优化(博主的理解)。 朴素的幂运算时间复杂度高,为了降低运算的时间复杂度,我们可以使用快速幂运算。 快速幂的数学依据如下: 朴素算法中,b的大小即为循环次数,在快速幂中,b可以由于a的变化而减小,循环次数也随之减小,因此可以有效降低时间复杂度。 具体算法实现: ![在这里插入图片描述] 需要注意的是当b为偶数时,变化的是底数,即循环次数。在进行模运算的同时对ans取模,即可以较小的时间复杂度完成目的。 在对底数进行处理的时候,我们也同样可以对其取模优化。 来源: CSDN 作者: huang_c_c 链接: https://blog.csdn.net/huang_c_c/article/details/103994036

数据结构与算法概述

依然范特西╮ 提交于 2020-01-18 04:36:23
一、基本概念和术语 数据:是描述客观事物的符号,是计算机中可以操作的对象,是能被计算机识别,并输入给计算机处理的符号集合。 数据元素:是组成数据的、有一定意义的基本单位,在计算机中通常作为整体进行处理。也被称为记录。 数据项:一个数据元素可以由多个数据项组成。数据项是数据不可分割的最小单位。 数据对象:是性质相同的数据元素的集合,是数据的子集。 数据结构:是相互之间存在一种或多种特定关系的数据元素的集合。 二、逻辑结构与物理结构 逻辑结构:是指数据对象中数据元素之间的相互关系。 物理结构:是指数据的逻辑结构在计算机中的存储形式。 数据结构中的“线性表”、“栈与队列”、“串”、“树”、“图”的逻辑结构结构都基于以下的四种形式构思,在计算机中的存储都是基于以下两种结构实现存储。 三、算法 算法是解决特定问题求解步骤的描述,在计算机中表现为指令的有限序列,并且每条指令表示一个或多个操作 。 算法的特性: (1)输入输出 (2)有穷性(3)确定性 (4)可行性 算法效率的度量方法: (1)时间复杂度 1. 一般情况下,算法的基本操作重复执行的次数是模块n的某一个函数f(n),因此,算法的时间复杂度记做:T(n)=O(f(n)) 分析:随着模块n的增大,算法执行的时间的增长率和 f(n) 的增长率成正比,所以 f(n) 越小,算法的时间复杂度越低,算法的效率越高。 2.

算法分析——浅析算法的时间复杂度

荒凉一梦 提交于 2020-01-16 18:51:31
算法分析——算法的时间复杂度 绪论 1.电脑运行程序是需要时间的 2.算法的时间复杂度 简单计算方法 最后的话 绪论 时间复杂度是学习算法的基石,也是判断一个算法优劣的重要因素,今天我们来聊聊什么是时间复杂度以及如何去算一个算法的时间复杂度。 本文以C++语言为例 1.电脑运行程序是需要时间的 void print ( ) { //这段代码会运行多久? int n = 100 ; for ( int i = 0 ; i < n ; i ++ ) { cout << n << endl ; } } 想知道这段代码运行多久,首先得知道程序运行的时候时间都花费在哪里, 重要概念 :电脑运行代码片段的时候,执行任何一条语句都需要花费时间,这是时间花费的主要地方。 为了方便运算,这里我们把每一条语句的执行时间都看做是一样的,记为一个 时间单元 。(实际上每条语句的时间不会完全一样,根据复杂程度而定。就类似于人看书一样,阅读文字是需要时间的) 这样可以简单的计算: 运行时间 = 语句数量* 时间单元 那么刚刚的代码中有多少语句呢? 1.红框两个语句只运行一次,花费2个时间单元。 2.黄框两个语句运行n次,花费2*n个时间单元。 3.绿框一个语句运行n+1次,花费n+1个时间单元。 所以该代码运行时间3n+3个时间单元,可以看出该代码的时间消耗与n成 线性关系 ,现在用T(n

【算法】——Leetcode 287 Find the Duplicate Number 找重复元素

送分小仙女□ 提交于 2020-01-16 13:19:05
目录 题目 随想 思路及代码 方法1 哈希表 优点: 缺点: 方法2 排序 优点: 缺点: 方法3 二分查找 优点: 缺点: 代码 方法4 利用索引交换 优点: 缺点: 代码: 方法5 链表判环 优点: 缺点: 代码: 题目 原题链接 Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one. 给定一个包含 n + 1 n+1 n + 1 个元素的数组,每个元素都在 1 1 1 到 n n n 之间(闭区间),证明至少一个元素重复,找出重复元素。 随想 这也是我遇到的一个面试题,当时想了很长时间,表现也不太好。 这个题和另外一个题:每个元素出现两次,有一个出现一次( Leetcode 136 Single Number )较为类似,有正好反过来的感觉。Leetcode136那道题异或位运算直接秒之。 证明一定有一个重复元素并不难,根据 抽屉原理 即可。 下面说如何找到它。 注意:并不要求 1 1 1 到

常用的十大排序算法,经典图解版,『精』!!!

倾然丶 夕夏残阳落幕 提交于 2020-01-16 08:33:26
前言 本文或许是东半球分析十大排序算法最好的一篇文章,配有 70 张图片和动画,和你一起一步步看懂排序算法的运行过程。 预计阅读时间 47 分钟,强烈建议先收藏然后通过电脑端进行阅读。 No.1 冒泡排序 冒泡排序无疑是最为出名的排序算法之一,从序列的一端开始往另一端冒泡(你可以从左往右冒泡,也可以从右往左冒泡,看心情),依次比较相邻的两个数的大小(到底是比大还是比小也看你心情)。 冒泡排序动图演示 图解冒泡排序 以 [ 8,2,5,9,7 ] 这组数字来做示例,上图来战: 从左往右依次冒泡,将小的往右移动 冒泡排序1 首先比较第一个数和第二个数的大小,我们发现 2 比 8 要小,那么保持原位,不做改动。位置还是 8,2,5,9,7 。 指针往右移动一格,接着比较: 冒泡排序2 比较第二个数和第三个数的大小,发现 2 比 5 要小,所以位置交换,交换后数组更新为:[ 8,5,2,9,7 ]。 指针再往右移动一格,继续比较: 冒泡排序3 比较第三个数和第四个数的大小,发现 2 比 9 要小,所以位置交换,交换后数组更新为:[ 8,5,9,2,7 ] 同样,指针再往右移动,继续比较: 冒泡排序4 比较第 4 个数和第 5 个数的大小,发现 2 比 7 要小,所以位置交换,交换后数组更新为:[ 8,5,9,7,2 ] 下一步,指针再往右移动,发现已经到底了,则本轮冒泡结束,处于最右边的

数据结构与算法二最好、最坏、平均、均摊时间复杂度

本秂侑毒 提交于 2020-01-16 06:03:33
前言 知识让生活更具能量。希望我们在以后学习的路上携手同行。您的点赞、评论和打赏都是对我最大的鼓励。一个人能走多远要看与谁同行,希望能与优秀的您结交。 我们在上一章, 主要是介绍了一下时间复杂度的分析,接下来接着跟大家聊一下时间复杂度的知识点。 最好、最坏情况时间复杂度 我们可以尝试分析下面的代码 //n表示数据array的长度 int find ( int [ ] array , int n , int x ) { int i = 0 ; int pos = i ; for ( ; i < n ; ++ i ) { if ( array [ i ] = x ) { pos = i ; } } return pos ; } 这段代码的功能是:在一个无序是的数组中找出x所在的位置。如果没有找到,就返回-1。 我们可以用让一章的内容分析出,这段代码阶位最高的为for循环中的代码,代码复杂度为O(n)。 大家可以看出,这段代码的效率不是很高,我们是可以对代码的效率进行优化的。如果我们中途找到这x的值就可以直接退出for循环。 int find ( int [ ] array , int n , int x ) { int i = 0 ; int pos = i ; for ( ; i < n ; ++ i ) { if ( array [ i ] = x ) { pos = i ;