时间复杂度

JAVA专项练习

£可爱£侵袭症+ 提交于 2020-02-23 17:04:28
解析:排序过程就是进行比较和交换过程,而时间复杂度就与比较和交换的次数相关。 解析:二维数组为4*3,可表示为 1 0 0 3 2 0 6 7 8 9 0 0 因为数组的起始位置为a[0][0],所以a[2][1]为第三行第二列,即7。 解析:递归工作栈里面包括返回地址、本层的局部变量和递归调用的形参代换用实参,所以正常情况下,无论递归过程有没有使用局部变量,转换为非递归过程都需要用栈来模拟这个递归调用过程。 不稳定:快选堆希 稳 定:插冒归基 归并排序的平均时间复杂度为O(nlogn), 其他三个排序的平均时间复杂度为O(n^2) 快速排序、归并排序和插入排序必须等到整个排序结束后才能够求出最小的 10 个数,而堆排序只需要在初始堆的基础上再进行 10 次筛选即可,每次筛选的时间复杂度为 O(log2n) 外部排序指的是大文件的排序,即待排序的记录存储在外存储器上,待排序的文件无法一次装入内存,需要在内存和外部存储器之间进行多次数据交换,以达到排序整个文件的目的。外部排序最常用的算法是多路归并排序,即将原文件分解成多个能够一次性装入内存的部分,分别把每一部分调入内存完成排序。然后,对已经排序的子文件进行多路归并排序。 尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次

python之random模块分析(一)

可紊 提交于 2020-02-22 16:01:32
random是python产生伪随机数的模块,随机种子默认为系统时钟。下面分析模块中的方法: 1.random.randint(start,stop): 这是一个产生整数随机数的函数,参数start代表最小值,参数stop代表最大值,两端的数值都可以取到; 函数算法时间复杂度:O(1) 核心源代码: return self.randrange(a, b+1) # 由randrange函数封装而来 例子: 1 for i in range(20): 2   print(rm.randint(0, 10), end=' ') 2.random.randrange(start,stop,step): 也是一个随机整数函数,参数可选; 当只有一个参数时,默认随机范围0到该 参数,前闭后开;两个参数,最小值和最大值,前闭后开;三个参数,最小值,最大值和步长,前闭后开。 算法时间复杂度:O(1) 核心源代码: return istart + istep*self._randbelow(n) # 该函数由_randbelow函数封装得到 例子: 1 for i in range(10): 2   print(random.randrange(10)) # 产生0到10(不包括)的随机数 3   print(random.randrange(5,10)) # 产生5到10(不包括)的随机数 4  

转:一文学会递归解题

独自空忆成欢 提交于 2020-02-22 15:53:40
前言 递归是算法中一种非常重要的思想,应用也很广,小到阶乘,再在工作中用到的比如统计文件夹大小,大到 Google 的 PageRank 算法都能看到,也是面试官很喜欢的考点 最近看了不少递归的文章,收获不小,不过我发现大部分网上的讲递归的文章都不太全面,主要的问题在于解题后大部分都没有给出相应的时间/空间复杂度,而时间/空间复杂度是算法的重要考量!递归算法的时间复杂度普遍比较难(需要用到归纳法等),换句话说,如果能解决递归的算法复杂度,其他算法题题的时间复杂度也基本不在话下。另外,递归算法的时间复杂度不少是不能接受的,如果发现算出的时间复杂度过大,则需要转换思路,看下是否有更好的解法 ,这才是根本目的,不要为了递归而递归! 本文试图从以下几个方面来讲解递归 什么是递归? 递归算法通用解决思路 实战演练(从初级到高阶) 力争让大家对递归的认知能上一个新台阶,特别会对递归的精华:时间复杂度作详细剖析,会给大家总结一套很通用的求解递归时间复杂度的套路,相信你看完肯定会有收获 什么是递归 简单地说,就是如果在函数中存在着调用函数本身的情况,这种现象就叫递归。 以阶乘函数为例,如下, 在 factorial 函数中存在着 factorial(n - 1) 的调用,所以此函数是递归函数 public int factorial ( int n ) { if ( n < = 1 ) {

寻找和为定值的两个数

烈酒焚心 提交于 2020-02-22 07:40:49
题目: 输入一个数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字。 要求时间复杂度是O(n)。如果有多对数字的和等于输入的数字,输出任意一对即可。 例如输入数组1、2、4、7、11、15和数字15。由于4+11=15,因此输出4和11。 解析:如果数组是 无序 的,先排序(n*logn),然后用两个指针i,j,各自指向数组的首尾两端,令i=0,j=n-1,然后i++,j--,逐次判断 a[i]+a[j]?=sum,如果某一刻a[i]+a[j]>sum,则要想办法让sum的值减小,所以此刻i不动,j--,如果某一刻 a[i]+a[j]<sum,则要想办法让sum的值增大,所以此刻i++,j不动。所以,数组无序的时候,时间复杂度最终为 O(n*logn+n)=O(n*logn),若原数组是 有序 的,则不需要事先的排序,直接O(n)搞定,且空间复杂度还是O(1),此思路是相对于上述 所有思路的一种改进 。(如果有序,直接两个指针两端扫描,时间O(N),如果无序,先排序后两端扫描,时间O(N*logN+N)=O(N*logN),空间始终都为O(1)) 。 总结 : 不论原序列是有序还是无序,解决这类题有以下三种办法:1、二分(若无序,先排 序后二分),时间复杂度总为O(n*logn),空间复杂度为O(1);2、扫描一遍X-S[i] 映射到一个数组或构造hash表

树链剖分详解

给你一囗甜甜゛ 提交于 2020-02-22 06:44:30
  问题是这样的:对于一株树(无向无环连通图),为每个结点分配对应的权重。要求能高效计算任意两个结点之间的路径的各类信息,其中包括路径长度(路径上所有结点的权重加总),路径中最大权重,最小权重等等。到这里一切都还是比较简单的,我们可以利用Tarjan的LCA算法在线性时间复杂度内快速求解。但是如果还要求允许动态修改任意结点的权值,那么问题就不简单了。很容易发现这有些类似于线段树的问题,但是线段树是作用在区间上,而我们的问题是发生在树上的,因此线段树并不适用。而树链剖分则是可以用于求解这类问题的高效算法,其更新权值的时间复杂度为O(log2(n)),而统计路径信息的时间复杂度为O((log2(n))^2)。下面对树链剖分进行讲解。   对于任意一株树,我们记r.size表示以结点r为根的子树中的结点总数,称为r的大小。记r.next表示r的所有子结点中size属性最大的一个结点(如果没有子结点允许留空),称为r的重孩子,而其余子结点称为r的轻孩子,与重孩子相连的边称为重边,而与轻孩子相连的边称为轻边。利用深度优先搜索算法可以在O(n)时间复杂度内计算所有结点的size和next属性。   很容易发现通过将每个结点与其重孩子通过一条特殊的链条连接,那么我们就在图中建立了多条互不相交的链路,每个结点都处于一个链路中(链路可能只有一个结点),这些链路称为重链。每一条重链中所有结点深度不同

LCA最近公共祖先(Tarjan离线算法)详解(转)

只谈情不闲聊 提交于 2020-02-21 04:55:15
转自 https://www.cnblogs.com/ECJTUACM-873284962/p/6613379.html 首先是最近公共祖先的概念(什么是最近公共祖先?):     在一棵没有环的树上,每个节点肯定有其父亲节点和祖先节点,而最近公共祖先,就是两个节点在这棵树上 深度最大 的 公共 的 祖先节点 。     换句话说,就是两个点在这棵树上 距离最近的公共祖先节点 。     所以LCA主要是用来处理当两个点仅有 唯一一条 确定的最短路径时的路径。     有人可能会问:那他本身或者其父亲节点是否可以作为祖先节点呢?     答案是肯定的,很简单,按照人的亲戚观念来说, 你的父亲也是你的祖先 ,而LCA还可以 将自己视为祖先节点 。     举个例子吧,如下图所示 4 和 5 的 最近公共祖先是2 , 5 和 3 的 最近公共祖先 是 1 , 2 和 1 的 最近公共祖先 是 1 。      这就是最近公共祖先的基本概念了,那么我们该如何去求这个最近公共祖先呢?     通常初学者都会想到最简单粗暴的一个办法:对于每个询问,遍历所有的点,时间复杂度为 O(n*q) ,很明显, n和q一般不会很小 。     常用的求LCA的算法有:Tarjan/DFS+ST/倍增     后两个算法都是在线算法,也很相似,时间复杂度在 O(logn)~O(nlogn) 之间

《算法学习签到》

拈花ヽ惹草 提交于 2020-02-20 06:39:26
bilibili学习算法ing~ 网址:https://www.bilibili.com/video/av18109226?from=search&seid=435070662036623495 2020年2月19日 最大连续数组:暴力:三个for 时间复杂度:n的立方 分治:递归的/2 时间复杂度:nlogn 分析法: 时间复杂度:n 一开始不懂,后来看了别人的文章懂了 https://www.jianshu.com/p/12188ee5ba5b 通俗易懂~顺便完成了 lintcode 41. 最大子数组 来源: CSDN 作者: lmy9213 链接: https://blog.csdn.net/lmy9213/article/details/104393554

第二章 算法时间复杂度

做~自己de王妃 提交于 2020-02-19 23:23:36
一、主定理 1、 主要是计算 n_log_b_a 。求出来之后和后面的Fn进行比较,然后按照规则些出结果就行。 2、一句话解释:这两个值哪一个大就取谁;想等的话先看Fn里面log的次数,最终的结果在log的基础之上+1就是最终结果log的次数。例题如右下角 3、要注意的一点就是:保证T(n)的形式要和定理里面的一样,一个大问题拆解成为几个相等的小问题。 1、例题如上。 2、N!是阶数最高的,属于NP难问题。复杂度是最大的。 3、n的n次方乘以log n。 Fib数列递推公式的证明(斐波那契数列) 斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、…… 斐波纳契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N*) 斐波那契数列:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, … 如果设F(n)为该数列的第n项(n∈N*),那么这句话可以写成如下形式::F(n)=F(n-1)+F(n-2) 显然这是一个线性递推数列。 先回顾一下常微分方程:fib数列。假设y=e的lλx次方,解出y。

python常用排序算法

空扰寡人 提交于 2020-02-16 22:55:41
常见排序算法 算法:一个计算过程,解决问题的方法 程序 = 数据结构 + 算法 1.算法基本概念 1.时间复杂度 用什么方式来体现算法运行的快慢? 通过运行的次数表示时间复杂度 示例: print("hello world") print("hello python") print("hello algorithm") #以上时间复杂度O(1) for i in range(n): print("hello world") for j in range(n): print("hello world") #时间复杂度O(n**2) while n>1: print(n) n = n//2 时间复杂度记为O(log 2 n)或O(log n) 当算法过程出现循环折半的时候复杂度式子中会出现log n 时间复杂度小结 时间复杂度是用来计算算法运行的时间的一个式子(单位) 一般来说,时间复杂度高的算法比复杂度低的算法慢。 创建的时间复杂度(按效率排序) O(1) < O(logn) < O(nlogn) < O(n2) < O(n2 log n) < O(n3) 复杂问题的时间复杂度 O(n!) O(2**n) O(n**n) 如何简单快速地判断算法复杂度 快速判断算法复杂度,适用于绝大多数简单情况 确定问题规模n 循环减半过程---> log n k层关于n的循环 --->n**k

哈希是什么?为什么哈希存取比较快?

随声附和 提交于 2020-02-16 07:56:35
  不太恰当的比喻:     XM 指的是“小明”,也指的是“小萌”     XM就是哈希值,小明和小萌就是拥有同一个哈希值的,存在同一个链表的元素。     想要获取小萌,首先使用hashcode获取到这两个人,然后再通过equals获取到小萌。   个人理解      哈希表其实就是一个一维数组,而数组中的每一个元素都是一个单向链表而已。这样的数据结构 解决了数组的增删元素的不足和链表的查询效率的不足 。    数组是存在连续的存储空间,而链表的存储空间不连续 --------------------------------   哈希算法将任意长度的二进制值映射为固定长度的较小二进制值,这个小的二进制值称为哈希值。哈希值是一段数据唯一且极其紧凑的数值表示形式。如果散列一段明文而且哪怕只更改该段落的一个字母,随后的哈希都将产生不同的值。要找到散列为同一个值的两个不同的输入,在计算上是不可能的,所以数据的哈希值可以检验数据的完整性。   哈希表是根据设定的哈希函数H(key)和处理冲突方法将一组关键字映象到一个有限的地址区间上,并以关键字在地址区间中的象作为记录在表中的存储位置,这种表称为哈希表或散列,所得存储位置称为哈希地址或散列地址。作为线性数据结构与表格和队列等相比,哈希表无疑是查找速度比较快的一种。   哈希通过将单向数学函数(有时称为“哈希算法”