时间复杂度

如何更规范化的编写JAVA 代码

泪湿孤枕 提交于 2019-12-02 15:53:12
如何更规范的编写JAVA代码 一、MyBatis 不要为了多个查询条件而写 1 = 1 当遇到多个查询条件,使用where 1=1 可以很方便的解决我们的问题,但是这样很可能会造成非常大的性能损失, 因为添加了 “where 1=1 ”的过滤条件之后,数据库系统就无法使用索引等查询优化策略,数据库系统将会被迫对每行数据进行扫描(即全表扫描) 以比较此行是否满足过滤条件, 当表中的数据量较大时查询速度会非常慢;此外,还会存在SQL 注入的风险。(解决办法采用<where>标签),UPDATE 操作也一样,可以用<set> 标记代替 1=1。 <select id="selectTypes" parameterType="map" resultMap="BaseResultMap"> select type_id, type_name, company_id, updated_at, update_user from type <where> <if test="companyId != null and companyId != ''"> company_id = #{companyId} </if> <if test="name != null and name != ''"> and type_name like #{name} </if> </where> order by

排序算法(五):快速排序

牧云@^-^@ 提交于 2019-12-02 15:36:28
基本思想 在数组中选取一个数作为基准值,进行一个partition过程,将小于该数的放在左边,大于的放在右边,等于的放在中间,再对左右分别进行该操作。 时间复杂度:每次partition可以将一个数字位置确定,将数组划分为两部分,因此想要有序,理想情况每次刚好两边大小一样,则一共需要logn次partition过程,每次partition过程时间复杂度O(n),因此最好时间复杂度O(nlogn),平均时间复杂度O(nlogn),但是时间复杂度和选取的基准值有关,如果选取的基准值不好,则每次划分的区间很不均匀,会影响时间复杂度,极限情况每次选取的基准值为最大值或者最小值,则一共需要n次partition过程,时间复杂度退化为O(N^2),为了解决这个问题,引入随机快排,即选取基准值时选择数组一个随机值,时间复杂度的计算变成概率问题,长期期望下时间复杂度为O(nlogn) 空间复杂度:O(1) 算法描述 选取数组末尾值作为基准值进行partition过程 一次partition过程后,数组划分为两部分,两部分分别进行partition过程 logn次partition过程后,数组有序 代码实现 package cn.lzx.sort; /** *@ClassNameQuickSort *@Description 快排 *@Author lzx *@Date2019/10/28 13

形象讲解时间复杂度

这一生的挚爱 提交于 2019-12-02 14:55:47
正文: 时间复杂度的意义 究竟什么是时间复杂度呢?让我们来想象一个场景:某一天,小灰和大黄同时加入了一个公司...... 一天过后,小灰和大黄各自交付了代码,两端代码实现的功能都差不多。大黄的代码运行一次要花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的对数,可以简写为log16。 因此,把面包吃得只剩下1寸,需要 5 X log16 = 5 X 4 = 20 天。 如果面包的长度是 N 寸呢? 需要 5 X

B树和B+树画图详解

老子叫甜甜 提交于 2019-12-02 14:32:35
B树系列 文章目录 B树系列 1. B树 1. B树特点 2. B树的分裂过程:(插入) 3. B树的删除操作 2. B+树 1. B树和B+树的相同点: 2. B树和B+树的不同点 3. B+树的插入操作 3. B树和B+树总结⭐ 4. 搜索树总结 B树和B+树的出现是为了查询数据时减少磁盘的IO次数,我们知道平衡二叉查找树是一种查询速度很快的数据结构。它的时间复杂度为(logN),但是它由于是一个二叉树,所以树的高度相对于多叉树来讲是比较高的,所以为了平衡磁盘IO与时间复杂度直接的关系,我们引入了B树和B+树; 1. B树 上图为一个3-4树,或者叫4阶树,即一个节点最多存储3个key,一个节点最多有4个孩子(3+1); 在B树里,一个节点里面有多个key; 1. B树特点 每个节点最多有 m-1 个关键字(可以存有的键值对); 根节点最少可以只有一个关键字; 非根节点至少有m / 2 个关键字; 每个节点中的关键字都按照从小到大的顺序排列,每个关键字的左子树中的所有关键字都小于它,而右子树中的所有关键字都大于它; 所有叶子节点都位于同一层,或者说根节点到每个叶子节点的长度都相同; 每个节点都存有索引和数据,也就是对应的key和value; 所以得到结论: 根节点的关键字数量范围: 1 <= k <= m-1; 非根节点的关键字数量范围: m/2 <= k <= m-1;

JAVA-基础知识-ArrayList,LinkedList,Vector的区别

混江龙づ霸主 提交于 2019-12-02 12:55:40
JAVA-基础知识-ArrayList,LinkedList,Vector的区别 vector与ArrayList底层实现都是数组,基本的操作差不多就不单独写了。另外java官方已经不建议使用Vector了,不过具体原因还没有进行了解。 存储结构 ArrayList和Vector是按照顺序将元素存储(从下表为0开始),默认的初始容量都是10,插入删除元素时,需要使部分元素移位。 ArrayList和Vector是基于数组实现的,LinkedList是基于双向链表实现的(含有头结点)。 线程安全 ArrayList,LinkedList不具有有线程安全性,如果在并发环境下使用它们,可以用Collections类中的静态方法synchronizedList()对ArrayList和LinkedList进行调用即可。 Vector实现线程安全的,即它大部分的方法都包含关键字synchronized,但是Vector的效率没有ArraykList和LinkedList高。 扩容机制 ArrayList与Vector底层均使用数组实现,再添加元素时,若容量不足,需要进行扩容,ArrayList扩容为之前的 1.5倍 ,而Vector默认情况下扩容为 2倍 ,扩容之后再将原数据拷贝到新建的数组中去。 Vector可以设置容量增量,ArrayList不行。在Vector中

时间复杂度与空间复杂度的理解与计算

五迷三道 提交于 2019-12-02 11:28:09
小白的我总是搞不清楚 因此做个整理(来源http://data.biancheng.net/view/2.html) 算法 是解决某个问题的想法、思路;而 程序 是在心中有算法的前提下编写出来的可以运行的代码。 算法的运行时间。(称为“时间复杂度”) 运行算法所需的内存空间大小。(称为“空间复杂度”) 时间复杂度 由于是估算算法的时间复杂度,相比而言,循环结构对算法的执行时间影响更大。 所以,算法的时间复杂度,主要看算法中使用到的循环结构中代码循环的次数(称为“频度”)。次数越少,算法的时间复杂度越低。 a) ++x; s=0; b) for (int i=1; i<=n; i++) { ++x; s+=x; } c) for (int i=1; i<=n; i++) { for (int j=1; i<=n; j++) { ++x; s+=x; } } 上边这个例子中,a 代码的运行了 1 次,b 代码的运行了 n 次,c 代码运行了 n*n 次。 算法的时间复杂度的表示方式为: O(频度) 这种表示方式称为 大“O”记法 。 对于上边的例子而言,a 的时间复杂度为 O(1) ,b 的时间复杂度为 O(n) ,c 的时间复杂度为为 O(n 2 ) 。 如果a、b、c组成一段程序,那么算法的时间复杂度为 O(n 2 +n+1) 。但这么表示是不对的,还需要对 n 2 +n+1

图的遍历

你。 提交于 2019-12-02 11:20:46
给出一个图G和其中任意一个顶点V 0 ,从V 0 出发系统的访问G中所有的顶点,每个顶点访问一次,这叫 图的遍历 。 深度优先搜索(depth-first search)简称DFS 基本思想 访问 一个顶点 V ,然后访问 该顶点邻接 到的 未被访问过的顶点V’ 再从V’出发递归地按照深度优先的方式遍历; 当遇到一个所有邻接于它多的顶点都被访问过了的顶点U时,则回到已访问顶点序列中最后一个未被访问的相邻顶点的顶点W; 在从W出发递归地按照深度优先的方式遍历 最后,当任何已被访问过的顶点都未被访问的相邻顶点时,则遍历结束。 深度优先搜索时间复杂度 对于具有 n个顶点 和 e条边 的无向图或有向图,深度优先搜索算法对图中 每一个顶点至多调用一次DFS 函数 用 邻接矩阵 表示图时,共需检查n 2 个矩阵元素,所需时间为 O(n 2 ) 用 邻接表 表示图时,找邻接点需将邻接表中所有边结点检查一遍,需要时间O(e),对应的深度优先搜索算法时间复杂度为 O(n+e) 。 深度优先搜索(breadth-first search)简称BFS 基本思想 访问顶点V 0 然后访问顶点V 0 邻接到的所有未被访问的顶点V 1 ,V 2 ,…,V i 再依次访问V 1 ,V 2 ,…,V i 邻接道德所有未被访问的顶点 如此进行下去,直到访问遍所有顶点 广度优先搜索时间复杂度 对于具有 n个顶点 和

面经连接池 - 集合框架(一)

帅比萌擦擦* 提交于 2019-12-02 11:08:06
List List是Java非常常用的数据集合框架。List是有序的Colletion(对映下标与插入顺序有关) Java List一共有三个实现类:ArrayList、LinkList、Vector(不常用,渐渐被取代) 1.ArrayList(数组、随机访问、不同步 线程不安全) ArrayList 是最常用的List实现类,底层通过数组实现,所以它允许对元素快速随机访问 get (int index)时间复杂度为O(1), add ( E e)、 addAll ( Collection <? extends E > c) 默认添加到数组末尾(时间复杂度为O(1))、 remove ( Object o)从列表中删除指定元素的第一个出现(如果存在)。时间复杂度为O(1) 数组的缺点就是每个元素之间不能有间隔,当从ArrayList 的中通过下标的方式插入或者删除,都需要对数组进行复制、移动代价比较高(时间复杂度为O(n)) 源码解析: public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { ... /** * Default initial capacity. */ private static

算法的时间复杂度解惑

纵然是瞬间 提交于 2019-12-02 08:55:42
前言 算法很重要,但是一般情况下做移动开发并不经常用到,所以很多同学早就将算法打了个大礼包送还给了老师了,况且很多同学并没有学习过算法。这个系列就让对算法头疼的同学能快速的掌握基本的算法。过年放假阶段玩了会游戏NBA2K17的生涯模式,没有比赛的日子也都是训练,而且这些训练都是自发的,没有人逼你,从早上练到晚上,属性也不涨,但是如果日积月累,不训练和训练的人的属性值就会产生较大差距。这个突然让我意识到了现实世界,要想成为一个球星(技术大牛)那就需要日积月累的刻意训练,索性放下游戏,接着写文章吧。 1.算法的效率 虽然计算机能快速的完成运算处理,但实际上,它也需要根据输入数据的大小和算法效率来消耗一定的处理器资源。要想编写出能高效运行的程序,我们就需要考虑到算法的效率。 算法的效率主要由以下两个复杂度来评估: 时间复杂度:评估执行程序所需的时间。可以估算出程序对处理器的使用程度。 空间复杂度:评估执行程序所需的存储空间。可以估算出程序对计算机内存的使用程度。 设计算法时,一般是要先考虑系统环境,然后权衡时间复杂度和空间复杂度,选取一个平衡点。不过,时间复杂度要比空间复杂度更容易产生问题,因此算法研究的主要也是时间复杂度,不特别说明的情况下,复杂度就是指时间复杂度。 2.时间复杂度 时间频度 一个算法执行所耗费的时间,从理论上是不能算出来的,必须上机运行测试才能知道

C++面试中的排序算法总结

梦想与她 提交于 2019-12-02 06:48:56
查找和排序算法是算法的入门知识,其经典思想可以用于很多算法当中。因为其实现代码较短,应用较常见。所以在面试中经常会问到排序算法及其相关的问题。但万变不离其宗,只要熟悉了思想,灵活运用也不是难事。一般在面试中最常考的是快速排序和归并排序,并且经常有面试官要求现场写出这两种排序的代码。对这两种排序的代码一定要信手拈来才行。还有插入排序、冒泡排序、堆排序、基数排序、桶排序等。 面试官对于这些排序可能会要求比较各自的优劣、各种算法的思想及其使用场景。还有要会分析算法的时间和空间复杂度。通常查找和排序算法的考察是面试的开始,如果这些问题回答不好,估计面试官都没有继续面试下去的兴趣都没了。所以想开个好头就要把常见的排序算法思想及其特点要熟练掌握,有必要时要熟练写出代码。 接下来我们就分析一下常见的排序算法及其使用场景。限于篇幅,某些算法的详细演示和图示请自行寻找详细的参考。 冒泡排序 冒泡排序是最简单的排序之一了,其大体思想就是通过与相邻元素的比较和交换来把小的数交换到最前面。这个过程类似于水泡向上升一样,因此而得名。举个栗子,对5,3,8,6,4这个无序序列进行冒泡排序。首先从后向前冒泡,4和6比较,把4交换到前面,序列变成5,3,8,4,6。同理4和8交换,变成5,3,4,8,6,3和4无需交换。5和3交换,变成3,5,4,8,6,3.这样一次冒泡就完了,把最小的数3排到最前面了