目录
1、算法简介
(1)大O表示法
通俗来讲,大O表示法计算的是“操作数”,讨论算法的速度时,指的是随着输入的增加,其运行时间以什么样的速度增加
常见的大O表示法(log 指的是以二为底的对数):
O(log n)——对数时间,常见的有二分查找
O(n)——线性时间,常见的有简单查找
O(n*log n)——快速排序
O(n^2)——选择排序
O(n!)——旅行商问题
(2)二分查找
仅适用于有序列表
比如猜数游戏——猜测100以内的一个数字,从50开始猜,如果小了,就猜75(50和100中间),如果大了,就猜63(50和75中间的数字),依次类推。这种方法为二分查找,最多只用猜7次(log 100),而采用简单查找,却需要100次——最糟情况下的运行时间
2、选择排序
(1)内存的工作原理
电脑中的内存,就比如是商场寄存处柜子上一排排的抽屉,计算机就像是很多抽屉的集合体,每个抽屉都有地址。
(2)数组和链表
数组:内存都是相连的,链表:元素可以存储在内存的任何地方,每个元素都存储了下一个元素的地址,从而使一系列随机的内存地址串在一起。
数组支持随机访问,而链表只支持顺序访问。我们将元素的位置称为索引,如果要找到20号元素,通过数组,我们可以马上访问该元素,而通过链表,我们只能先访问1号元素,再访问2号元素……依次类推,直至访问到20号元素。
链表的优势在插入和删除元素方面,数组的优势在于在于读取(随机访问)
(3)选择排序
假设你的计算机存储了很多乐曲,并记录了播放次数,现在你需要将该列表按播放次数由多到少进行排列。你可以遍历这个列表,找到播放次数最多的乐曲,再遍历这个列表,找到播放次数第二多的乐曲,继续下去,将得到一个有序列表,假设列表里有n个元素,对于这n个元素,每一个元素你都要遍历n次,则你需要的总时间是O(n^2),这就是选择排序实例。
3、递归
(1)递归之基线条件和递归条件
递归:调用自己的函数
例如:你需要在一个大盒子里找到一把钥匙,而大盒子里有盒子。盒子里还有盒子,钥匙就在某个盒子里,你可以采用以下方法:
(1)检查盒子里的每样东西;
(2)如果是盒子,就回到第一步;
(3)如果是钥匙,就大功告成!
这就是递归的直观理解。
(2)栈
栈是“后进先出”的。假设你有一个代办事项清单,你可将代办事项放在该清单的任何地方,也可删除任何一个代办事项;读取待办事项时,你只需要读取最上面的那个,并将其删除。因此这个代办事项清单只有两种操作:压入(插入)和弹出(删除并读取)。栈这种数据结构就好比是“摞砖头”,“后来居上”,再次使用时,上面的先用,所以是“后进先出”。
4、快速排序
(1)分而治之(D&C)
假设你有一块土地,你要将这块土地均匀地分成方块,切分出的方块要尽可能地大,可以使用D&C策略!
(1)找出基线条件,这种条件必须尽可能简单;
(2)不断将问题分解(或者说缩小规模),直到符合基线条件。
可以找到一条简单的基线条件(一条边的长度是另一条边的整数倍),然后是找到递归条件,要求每次递归调用都必须找到缩小问题的规模,我们可以首先找到这块地课容纳的最大方块。插入一种算法——欧几里得算法(辗转相除法,常见于求最大公约数)。
例如,对于一块640*400的土地,可以从中划出的最大方块为400*400,这将余下一块更小的土地,其尺寸为400*240,你可以从这块土地上划出最大的方块,余下一块更小的土地,其尺寸为240*160……最后,你发现剩余一块160*80的土地,刚好满足基线条件,所以对于最开始的那块土地,适用的最大方块为80*80。
(2)快速排序
快速排序也使用了D&C。下面来使用快速排序对数组进行排序,对排序算法来说,最简单的数组就是不需要排序的数组——空数组或只有一个元素的数组。因此,基线条件为数组为空或只包含一个元素。而要使用D&C,需要对数组进行分解。首先要从数组中选一个元素作为基准值。
例如以下数组:
20 | 33 | 16 |
快速排序的步骤是:
(1)选择基准值;
(2)将数组分成两个子数组:小于基准值的元素组成的子数组和大于基准值的元素组成的子数组。
(3)对这两个子数组进行快速排序。
5、散列表
(1)散列表简介
假设你在水果店上班,有顾客来买东西时,你得在一个本子上查找价格,这种找法非常麻烦,如果你能将该商品的价格熟记于心,将会很快解决问题,那么计算机里有没有一种数据结构可以满足你输入一个值,就马上告诉你结果呢?答案是有的!他就是散列表。
散列函数 “将数字映射到数字”,散列函数必须满足一些条件——它必须是一致的,例如你输入
Apple,得到的结果是4,那么每次输入Apple得到的结果都应该是4;它应将不同的输入映射到不同的数字,最理想的结果是,将不同的输入映射到不同的数字。
使用散列表:首先创建一个空数组,然后将商品的价格存储到该数组中,这样你每次只需要输入商品名称就可以找到商品的价格。散列表获取元素的速度和数组一样快。散列表由键和值组成,键为商品名,值为商品价格,散列表将键映射到值。
(2)散列表应用
散列表用于查找(大海捞针式的查找),比如你在访问某个网站,计算机必须将该网站映射到IP地址,这个过程被称为DNS解析,散列表是提供这种功能的方式之一。
散列表用于防止重复,假设你负责管理一个投票站,每人只能投一票,为了防止重复,你可以创建一个散列表,用于记录已投票的人,有人来投票时,检查他是否在散列表中,如果在,返回ture,否则返回none,来防止重复。
将散列表进行缓存,比如Facebook中你要访问一些东西,你会向Facebook的服务器发出一些请求;服务器做出处理,生成一个网页并发送给你;你获得一个网页。缓存的工作原理就是:网站将数据记住,而不再重新计算。
6、广度优先搜索
(1)图简介
(2)广度优先搜索
广度优先搜索是解决最短路径问题的算法,是一种用于图的查找算法,可用于两类问题——从节点A出发,有前往节点B的路径吗;从节点A出发,前往节点B的哪条路径最短?
队列(First In First Out,FIFO)类似于栈(Last In First Out,LIFO),你不能随机访问队列中的元素,队列只支持两种操作——入队和出队。队列就好比是日常生活中的排队(先进先出)。