基础与算法
❶ 算法基础
谨以此文,感谢我在这个学校最喜欢的两个老师之一——肖my老师。本文基本为老师上课说讲授内容加上一部分自己的感悟拼凑而来,写作文本的目的是为自己的算法课程留下一点点东西,站在老师肩膀上形成粗糙的框架,方便以后的复习以及深入。文笔有限,其中包含的错误还请多多包容,不吝赐教。
to do list:
时间复杂度中递归树法;动规,分治新的感悟;
点覆盖:一组点的集合,使得图中所有边都至少与该集合中一个点相连。
支配集:一组点的集合,使得图中所有的点要么属于该集合,要么与该集合相连。
最大团:在一个无向图中找出点数最多的完全图。
独立集:一组点的集合,集合中的顶点两两不相邻。(团转过来)
SAT问题:也称布尔可满足性问题。给一组变
其中Ci被称为句子。
点覆盖<->独立集<->最大团
最小割:割是一组边集。如s-t割就是如果去掉这些边,将把原图划分为两个点集,其中一个点集包含s,一个点集包含t。(两个是指不相连,而不是代表不存在边相连,如反向边)
decision problem: 是否存在。
search problem:找到一个解。
(这个还能扩展,比如decision problem在多项式时间内解决,所以他是P问题吗)
渐进符号:
注意以上三种都是紧的,对应的两个小写的符号是不紧的,即如下图所示:
概念:算法的时间复杂度是一个函数,用于定性描述算法的运行时间。注意,这个一个代表算法输入字符串长度的函数。
[注]输入字符串长度是一个比较关键的理解,比如在背包问题中,其时间复杂度为O(nW),因为W不定,所以只能是一个伪多项式时间。
比较:c < log2N < n < n * Log2N < n^2 < n^3 < 2^n < 3^n < n! < n^n
大致:常数<对数<幂函数<指数函数<阶乘
对于指数是n相关的进行比较,优先比较指数,再比较底数。
记住一个特例:n (logn)<n!<n n
计算:
一般来说,计算采用主方法和递归树法,其中递归树技巧性比较强,主方法其实也是递归树推导归纳而来,且主方法能得到一个比较紧的结果。
主方法:
f(n) = af(n-b)+g(n) =>O( a^(n/b) *g(n) )
P:decision problems有一个多项式算法。
NP(nondeterministic polynomial-time):decision problems能够在多项式时间内验证。
NPC:NP完全问题,首先这个问题是NP的,其次,其他所有问题都可以多项式时间内归约到它。
NPH:如果所有NP问题都可以多项式时间归约到某个问题,则称该问题为NP困难。
因为NP困难问题未必可以在多项式时间内验证一个解的正确性(即不一定是NP问题),因此即使NP完全问题有多项式时间的解(P=NP),NP困难问题依然可能没有多项式时间的解。因此NP困难问题“至少与NP完全问题一样难”。
一些NP问题能在多项式时间内解决,因为 P∈NP
NP难类型问题的证明:
先选好一个已知NP难的问题,然后将已知NP难问题多项式归约到要证明的问题上。先给出这个归约,然后再证明这个归约的正确性。
NPC类型问题的证明:
证明一个问题Y是NPC问题,先说明Y是NP的,然后找到一个NPC问题X,将这个问题X归约到问题Y上,即证明完成。
常见的NPC问题(重要,规约的时候有用!):
packing problems: set-packing,独立集
覆盖问题:集合覆盖问题,顶点覆盖问题
严格满足问题(constraint satisfaction problems):SAT,3SAT
序列问题:哈密尔顿回路,旅行商问题
划分问题:3D-matching, 3着色问题
数字问题:子集合问题(子集元素之和为t),背包问题
其他:分团问题(是否存在一个规模为k的团)
规约的概念与理解
规约:意味着对问题进行转换,例如将一个未知的问题转换成我们能够解决的问题,转换的过程可能涉及到对问题的输入输出的转换。
自归约:search problem <=p decision problem
归约:A归约到B,也就是说,我们对A套一个函数f,在f函数的作用下形成一个新的问题,对这个问题运用B的黑盒解法,能够解决问题A。
(B <=p A)一般说来,B问题如果可以归约到A问题,也就是说,一个解决A问题的算法可以被用做子函数(子程序)来解决B问题,也就是说,求解B问题不会比求解A问题更困难。因此,如果B问题是困难的,那么A问题也就是困难的,因为不存在求解A问题的高效算法。(最后一句不懂)
我简单说一下我理解的规约,以X规约到Y为准,大概分成两个方面:
注:在 三 的一些实例中细品。
概念:在对问题求解时,总是做出在当前看来是最好的选择。
贪心的证明:先假设贪心算法得到的解不是最优解,假设S1是贪心算法得到的解,而S2是所有最优解中和S1具有最多相同元素的解,然后比较S1和S2,观察S1和S2中第一个(最前面一个)不一样的元素,然后在贪心解S2中将不一样的元素换成S1中的那个元素得到另一个最优解S3,这样S3和S1比S2和S1有更多相同元素,和假设S2是与S1有最多相同元素的最优解矛盾,这样来推导S1是最优解。
我的理解:假设这个不是最优的,但是一定存在一个最优的解在某一个位置之前和我当前解结构是一样的,那么在这个位置,选最优解也可以选当前解,不影响最终答案。
[注]概念很简单,但是实际操作的时候,贪心的角度很重要,同样的贪心,方向对了,算法就是对的。
例子:
给你一系列活动,每个活动有一个起始时间和一个结束时间,要求在活动不冲突的情况下找到一种有最多活动的安排。
对于这个问题,我们有一下几种贪心的角度:
①将任务按照 开始时间 升序排列。
②将任务按照 结束时间 升序排列。
③将任务按照 任务时长 升序排列。
④对于每一个任务,都记录与其他任务冲突的数量,按照 冲突数量 的升序排列。
其中1,3,4都是不可以的。
任务结束时间的贪心证明(反证法):
假设贪心不是最最优的,那我们在最优解中找一个与当前解有最相似的解。
由图可以知道,贪心贪的就是最早结束,所以如果不是最优,那么最优的结束时间一定晚于贪心的结束时间。
由上图就可以证明。
最大流通常与最小割相联系。
f 为任意一个流,cap为容量,对于任意的s-t割出来的点集(A,B),v( f ) <= cap(A, B)。
当流增加到与割的容量相等时候,就不可能再有增长空间了,称为最大流。
对于割的容量来说,不同的割法会有不同流量,有些割法永远不会有流达到,比如部分A = {s}, B = {V - s},这种把源点割出来的割法。
综上,通过这种感性的认识,如果能找到一个最小的割,那么这个割就一定是最大能跑到的流(如果流能更高的话在这个割上就会超过容量,反证。)
上图为一条增广路,一条增广路即为一条s-t的路径,在路径上仍有流可以跑,其曾广的流就是该条路径上最小的剩余容量。(相当于每找一条增广路,就至少有一条边达到满流。)
直到在图中找不到增广路,此时已经达到了最大流。
找ST集合:把满流的边去掉,从S出发走到能到的点,遍历的点就是S集合;剩下的点就属于T集合。注意,如果找到了在找S集合的时候找到了T点,说明还可以继续找增广路。
[补]有一个很有趣的延伸,如多源点多终点问题。问:如果我有两个源点s1,s2,两个终点t1,t2,我想求一组流,使得s1-t1,s2-t2的流达到最大,是否可以加一个源点S,S与s1,s2相连,边流无限大;加一个终点T,T与t1,t2相连,边流无限大,然后这组ST的最大流即可。——答案是No,无法保证是s1-t1,s2-t2,有可能交错。
例子讲的感觉不是特别好,对理解感觉起不到很大作用,希望以后有新的想法后进行补充。
规约是一个重要的概念和思想。
一个图的 最大独立集 与 最小点覆盖 是不相交的两个点集,它们的并就是整个点集。
个人理解:独立集和点覆盖都是从点的角度进行划分的,如果我们从边的角度来看,①一个最小的点覆盖即为我集合中的每一个点都尽可能与更多的边相连,②同时,一条边的两个端点中,只能有一个端点在最小点覆盖中[下注]
[注]我们假设有一条边两个端点(u,v)都在点覆盖之中,首先显然u,v都不是端点,因为假设u是端点的话只需要选择v即可;
给一个集合S和一堆S的子集S1,S2,...,Sm,问是否存在存在k个子集,使它们的并集为S。
构造:
集合为点,集合中的元素为边,有相同元素的边相连。(注意如果某一元素只在一个子集中出现,应该怎么处理呢!)
规约:在构造的图中找最小的点覆盖,选中的点能覆盖所有的边即为对应集合的并集能包含所有的元素。所以就完成了集合覆盖到点覆盖的规约。
构造:每个句子构造一个三角形,把对应变量但是相反取值的点相连。
规约:3SAT的有一个特点就是,每一个句子中至少有一个为真即可,每个句子都必须是真。将相同变量相反取值相连的目的就是,在最大独立集中,比如选择x为真,则剩下所有句子中x-ba一定不会被选中,同时由独立集和构造出来三角形的性质可以知道,每一个句子,有且仅有一个会被选中(为真)。如上图,x1-ba为真,x2-ba和x3任选一个为真即可满足。
search problem <=p decision version
比如:如果能在多项式时间内找到一个哈密尔顿圈,那么就能在多项式时间内找到一个哈密尔顿圈(删边)
在此再谈P和NP:
我们知道有些问题是可以从搜索问题规约到判断问题的,也就是所该问题如果能在多项式内判断,那么久能在多项式中搜索到,那么我们只需要说,这个判断问题能在多项式时间内求解,就叫做P问题,也就是上图红字的意思;那NP问题呢,必须要给出一个解的实例,判断的是这个实例是否满足求解问题,这个才是上图中的红字。比如,我如果能在多项式时间内判断哈密尔顿圈是否(Yes/No)存在,那这个就是ploy-time algorithm,如果我给出了一系列点,能过多项式时间内判断这些点能否构成哈密尔顿圈,那这个就是poly-time certifier。
构造:把一个点拆分成三个点。
构造:(下面两个图要连在一起看)
从行的角度看,一行代表一个变量;从列的角度来看,每三列代表一个句子。两边中一边是两个点,一边是一个点,所以有k个句子的话,每一行有3k+3个节点。从哈密尔顿圈的答案转到3SAT的答案看这个圈在每一行是从左到右还是从右到左。
子集和问题:给一个集合S,问是否能在集合中选取元素,使得总和为W。
构造:如下图,按照前六行和前三列进行分割,可以分成4部分,其中1,3,4部分是固定的,即在第一部分,变量v列和 变量为v(包括变量及取反)的行对应的格子为0,其余为0;第三部分全为0;第四部分按照12依次写下来。第二部分,如果Ci句子中有变量v,则记为1,因为一个句子只有三个变量,可以简单通过第二部分每一列和为3进行判定。此时集合已经构造出来,W为111444,与上面的规约相似,可以通过3SAT的简单性质进行感性的认知。
近似的想法很简单,要解决一个问题,我们希望能够做到①求解结果是最优的 ②在多项式时间内解决 ③对于任意的实例都能够通过该算法解决。现在对于部分问题,无法完全满足以上要求,所以就牺牲了①,但是我们希望结果不是盲目的,所以就引入了近似的概念。
近似算法。比如2-近似,认为W为近似解,W 为最优解,在求最小值的情况下W<=2W ;在求最大值的情况下,W>=1/2W*
给m个机器和n个任务,每个任务有一个ti的执行时间,我们认为完成最后一个任务所需的时间为负载时间,希望能够让这个负载时间最短。
第一种:将任务依次放在机器上,当某个机器空闲时立即放入新任务。此时是2近似的。
证明:
引理1.最短时间安排是大于等于任务中时间最长的任务,L* >= max tj
我们在考虑放入最后一个任务前,根据我们放置的规则,该机器是耗时最短,也就是说,该机器此时的用时是低于除掉最后一个任务后的平均时长,更低于所有任务的平均时长(引理2);再根据引理1,最后一个任务应该是小于最优解的。
补充:
在这里,我还想讨论一下这个近似算法的中等于符号,先上结论:等号不一定能够找到一个实例,但是可以构造出一种结构,通过取极限求得,我们认为这样 也算是紧的。
构造实例:有m个机器,其中m(m-1)个任务的用时为1,1个任务的用时为m。肯定有一种任务集合,可以按照以下方式进行安排,此时的贪心解为19。
此时最佳的解为10,如下图:
通过推广可以知道此时的比为(2m-1)/m,当m取极限,能够达到2倍。
第二种:将任务从大到小排序,然后依次放在机器上,当某个机器空闲时立即放入新任务。此时是2近似的。
引理3:如果有大于m个任务,那么L*>=2t(m-1)。证明:t(m+1)是目前最短的任务,且目前所有机器上都有任务了,所以该任务加入时最优的情况不过是加入设备的原有任务刚好和t(m+1)相等,即等号。
(2近似)在n个点中,选取k个中心点,使得这些中心点能够以半径R的圆包含所有的点,让其中最大的半径最小,如下图所示:
基础:距离需要满足的三个定理①(同一性)dist(x, x) = 0 ②(自反)dist(x, y) = dist(y, x) ③(三角不等式)dist(x, y) <=dist(x, z)+dist(z, y)
r(C)为C集合中所有点的最大覆盖半径。(需要求min r(C))
算法:在点集中任选一个作为中心点,然后重复以下步骤k-1次:选取距离已选点集中最远的点,加入点集。
证明:先假设r(C )< 1/2 * r(C)以选好的点画半径为1/2 * r(C)的圆,显然可知[注],这个圆里有且仅有一个r(C )中的点。那么根据在下图中,根据三角不等式可以得出:
[注]在每个点上r(c )一定会包含到c点,而r(C )<1/2 * r(C),相当于大圆套小圆,所以c*一定在c的圆中。
(2近似)问题还是很好理解的,在点上加权值,要找一个点覆盖,使得权值最小。如下图左边就是一个带权的最小点覆盖。
算法: 任选一条边(i, j)加上代价,这个代价从零开始,且这个代价的最大值低于i和j节点的权值。显然,这个边权值的最大值取决于两个端点权值的最小值,我们认为当边权值与点权值相等时,对应的那个点是紧的。把所有紧的点找出来即为点覆盖。
流程:
证明:
引理:边权之和小于等于点覆盖的点权之和。这主要是由于涉及到一条边上两个点都被选(紧的)的情况,感性认知可以看上图,缩放证明如下:
w(S)是等于所选的节点的权值之和的,等于所选节点节点所对应的边权之和,可以把它放大到所有节点对应边权之和,这样因为一条边(u, v)在u上算过一次后还要在v上算一次,所以等于边权和的两倍。再由上面引理可得。
主要为了线性规划和整数规划。
(2近似)没啥好说的,只需要把方程构造出来就行了。
由于求解出来结果不一定是整数,所以我们认为某一点的值大于1/2,就选入点集。
证明:
因为xi+xj >=1,且都是正数,那必至少一个点是大于1/2的(反证,两个都小于1/2则和小于1)。
给你n个物品和一个背包,每个物品有一个价值v和一个大小w,背包的容量是W,要求让背包装下尽可能大价值。
背包的时间复杂度:O(nW)
注意其中n表示物品的个数,无论是1个还是999个,他都是多项式的,这个很好理解。但是W就不一样了,这是一个数字。我理解的是这个数字会很奇特,比如1.00001,比如99999,这些有可能看起来不大但是实际在处理的时候很难处理的数字,统一的来说,如果我们把这些数字放在电脑上,都会以二进制的方式存储起来,有些数字用十进制表示很小,但是放在二进制上面就会很大,由W导致不能在多项式时间内解决(找不到一个范围/上界来框它)。
算法: 为了处理这个问题,我们改动了dp的状态转移方程,要让这个转移方程和W无关[注]。
此时还不是多项式的,然后我们再对value进行约。[注]
[注]这两步中,我们把w改成v,并对v进行近似处理。OPT的含义变成了,在面对是否选择第i个物品时,要想让价值达到当前值,最少的weight。理由是更改后的误差是可以忍受的:对v进行近似,结果只会出现最大价值的上下误差,如果对w进行近似,则有可能出现该物品不能放入背包中,导致整个物品直接放弃的情况。
❷ 学习算法分析与设计需要那些基础(是否需要学习离散数学和线性代数)
算法分析与设计,目前国内本科生和硕士生的教材好像都是从国外翻译过来的。听起来挺复杂的样子,如果简单地掌握和运用还是不难的,大部分内容在数据结构中都涉及过,实际编程中也运用比较多,难的在于算法的理论研究,如21世纪的七大难题之一的NP问题就是算法问题(涉及逻辑可满足性问题)。
简单地讲需要的基础有以下几类:
1、基础类(相对一般本科生而言):(1)把数据结构学好了算法就不难的,而数据结构其实就是图论的运用,如果是非数学专业的学生可以看离散数学中的图论部分。(2)算法分析设计时间和空间复杂度的计算,常用的还是毛泽东的战略思想——以空间换取时间。所以要学会简单的数量级运算,涉及部分代数式和数论的知识。只要简单掌握运算就可以了,不必深究。
2、提高型(研究生水平):图论、组合数学、数理逻辑学要专门学习,可以采用数学系本科生的图论、组合数学、数理逻辑学等专业课的教材。其中组合数学中的组合设计在一定程度上和算法设计有异曲同工之处。
3、研究型(专业研究):这主要看自己的研究方向了,如果研究能力强的话可以在很短时间内可以把需要遇到的数学知识搞懂,没有现成的固定模式。其中如研究NP问题,需要非常精深的逻辑学知识和数论基础。但不管哪个研究方向,数学的缜密思维和推理能力都是必备的,这不是一朝一夕可以练就的,需要长时间的锻炼。
以上仅个人一点点体会,仅供参考。
❸ 关于算法的基础知识
所谓解析法(analysis algorithm)是指用解析的方法找出表示问题的前提条件与结果之间关系的数学表达式,并通过表达式的计算来实现问题求解。
在实际问题中, 有些变量的取值被限定在一个有限的范围内。例如,一个星期内只有七天,一年只有十二个月, 一个班每周有六门课程等等。如果把这些量说明为整型, 字符型或其它类型显然是不妥当的。 为此,C语言提供了一种称为“枚举”的类型。在“枚举”类型的定义中列举出所有可能的取值, 被说明为该“枚举”类型的变量取值不能超过定义的范围。应该说明的是, 枚举类型是一种基本数据类型,而不是一种构造类型, 因为它不能再分解为任何基本类型。
❹ 计算机基础理论和算法
学习计算机:
1.计算机的历史由来
2.计算机基础知识。协议啊什么的
3.常用的编程算法和编程语言
4.看了懂得了上面的就可以买本编程方面的书来学习编程
------------------------------------
1、计算机的诞生与发展,及其特点
2、计算机在现代社会中的应用
3、计算机的基本组成及其相互联系
4、计算机的工作原理
5、计算机中的数的表示
6、计算机网络及安全基础知识
7、计算机软件知识
8、WINDOWS9X的操作及基本使用
9、收发电子邮件(OUTLOOK)的相关设置
10、构成计算机主机板的主要部件
11、ASCII码
12、中央处理器和存储器
13、计算机技术发展的一个新方向—量子计算机
14、二进制及十、八、十六进制数
15、二进制与十、八、十六进制数之间的转换
16、位、字节和字及内存容量
17、计算机语言
18、操作系统
19、计算机网络的基本概念
20、计算机网络系统的组成
21、多媒体的基本概念
22、多媒体技术发展现状
23、多媒体计算机的配置
24、多媒体应用领域及前景
----------------------------
网上有很多相关资料和电子书的,你可以去下。
比如:《计算机基础知识》
【作 者】陈星火
【出 版 社】 人民邮电出版社
【书 号】 9787115077493
【上架时间】 2007-12-14
【出版日期】 1999 年1月 【版 次】第1版第7次
❺ 数据结构与算法基础知识
1.数据结构的逻辑结构
(1)集合结构
(2)线性结构(存在唯一的第一个元素与唯一的最后一个元素)(eg: 线性表、队列、栈、字符串、数组、链表)
(3)树形结构(一对多)
(4)图形结构(多对多)
2.数据结构的物理(存储)结构
(1).顺序存储结构(插入与删除低效因为要挪动其他元素的位置。但是遍历简单)
(2).链式存储结构(插入与删除高效,但是遍历低效)
3.大O表示法(注意大O表示法表达的是最坏的情况)
规则:
(1)用常数1取代其他所有的常数(注意常数0也当1算)(3 -> 1, O(1))
(2) 只保留最高阶项(n^3+2n^2+5 ->n^3, O(n^3))
(3) 若存在最高阶,省略与其想成的常数(2n^3 -> n^3, O(n^3))
4. 时间复杂度类型
(1)常数阶
(2)线性阶
(3)平方阶
(4)对数阶
(5)立方阶
(6)nlog阶
(7)指数阶(O(2^n)或O(n!), 往往会造成噩梦般的时间消耗)
5. 空间复杂度(用大O表示法求解改算法的辅助空间即可,例如用于交换变量用的临时变量的数量)
六. 顺序存储的线性表
线性表结构特点:
(1) 存在唯一一个的被称作”第一个”的数据元素;
(2) 存在唯一一个的被称作”第二个”的数据元素;
(3) 除了第一个元素以外,结构中的每个数据元素均有一个前驱;
(4) 除了最后一个元素以外,结构中的每个数据元素均有一个后继。
七. 链式存储的线性表(单链表)
首元结点是链表中第一个值域不为空的结点。
头结点是一个值域为空且处于首位的结点。
首指针可指向首元结点也可指向头结点,但是如果指向头结点可以更加方便的处理单链表的插入和删除问题,不用再对首位做额外判断,并且指向头节点的指针永远不用变化。
*注意一下单链表的前插法和尾插法。尾插法更符合逻辑