算法基础.docx
《算法基础.docx》由会员分享,可在线阅读,更多相关《算法基础.docx(9页珍藏版)》请在冰豆网上搜索。
算法基础
算法基础
简介
算法在宏观上来说,就是一种解决问题的思想——系统化、逻辑化、通用化地解决某一类问题,任何问题无论涉及数学、物理等等甚至是生活问题都可以提出相应的算法,而在微观上,则是设计一个解决办法,旨在将数学或是生活问题以可通过计算机编程的方式实现(因为计算机不具有人类思考的一些能力诸如抽象思维)
目录
简介2
第一部分初级4
一、前言4
二、模拟5
三、穷举7
四、数组操作8
五、递推8
六、贪心9
七、递归11
八、时空复杂度计算12
第一部分初级
一、前言
第一部分主要涉及模拟、穷举、数组操作、简单的递推,贪心以及递归算法。
实际上大多数coder都不能很好掌握这一部分的技巧。
之所以称之为技巧,是因为以上算法在实际编程中用的较为广泛,其核心思想也比较实用。
这部分是无论如何都需要掌握的技巧,但在以后的实际编程过程中涉及到的小技巧,这里是不能完全涵盖的。
二、模拟
模拟其实是最没什么可讲的地方,因为如字面意思,就是按照题目叙述编写成程序语言。
2.1.2进制转换
描述:
从屏幕输入一个十进制整数N,将其转化为二进制数输出。
(提示:
十进制转K进制只需N不断除以K直到N为0,并将余数倒序输出即为转化后的K进制数)
K进制转换
描述:
从屏幕输入一个十进制整数N和要转化的进制K,将N转化为K进制数输出,K≥2。
(提示:
当K大于10时需要注意一些问题)
十进制转换
描述:
从屏幕输入一个K进制整数N,将其转化为十进制整数。
(提示:
与上面做法不同,自己查)
2.2.寻找质数
描述:
找出200以内的所有质数并输出。
(优化:
对某个数进行判断其是否为质数时,可以进行许多优化。
优化是一种编程技巧)
2.3.回文数判断
描述:
给定一个数N,判断他是否为回文数。
(提示:
涉及数的剥离)
数的剥离
描述:
已知一个数N,将其每一位都剥离出来。
算法:
1.令M=N%10,M即为N当前最后一位;
2.N=N/10,将N最后一位抛除;
3.重复1、2步操作,直到N为零,每次得到的M即为N的各位。
代码:
while(N>0)
{
m=n%10;
n=n/10;
}
2.4.ISBN码(NOIP2008年普及组第一题)
描述:
每一本正式出版的图书都有一个ISBN号码与之对应,ISBN码包括9位数字、1位识别码和3位分隔符,其规定格式如“x-xxx-xxxxx-x”,其中符号“-”就是分隔符(键盘上的减号),最后一位是识别码,例如0-670-82162-4就是一个标准的ISBN码。
ISBN码的首位数字表示书籍的出版语言,例如0代表英语;第一个分隔符“-”之后的三位数字代表出版社,例如670代表维京出版社;第二个分隔符后的五位数字代表该书在该出版社的编号;最后一位为识别码。
识别码的计算方法如下:
首位数字乘以1加上次位数字乘以2……以此类推,用所得的结果mod11(mod为取余),所得的余数即为识别码,如果余数为10,则识别码为大写字母X。
例如ISBN号码0-670-82162-4中的识别码4是这样得到的:
对067082162这9个数字,从左至右,分别乘以1,2,...,9,再求和,即0×1+6×2+……+2×9=158,然后取158mod11的结果4作为识别码。
你的任务是编写程序判断输入的ISBN号码中识别码是否正确,如果正确,则仅输出“Right”;如果错误,则输出你认为是正确的ISBN号码。
输入格式
输入只有一行,是一个字符序列,表示一本书的ISBN号码(保证输入符合ISBN号码的格式要求)。
输出格式
输出共一行,假如输入的ISBN号码的识别码正确,那么输出“Right”,否则,按照规定的格式,输出正确的ISBN号码(包括分隔符“-”)。
样例输入
【样例1】
0-670-82162-4
【样例2】
0-670-82162-0
样例输出
【样例1】
Right
【样例2】
0-670-82162-4
三、穷举
穷举是算法中很基础也很重要的一个思想,穷举的思想为:
列举出问题中所有的可能情况,进行验证筛选后得到正解。
列举一般通过循环实现,验证筛选在循环的内部。
3.1水仙花数
描述:
水仙花数是指一个n位数(n≥3),它的每个位上的数字的n次幂之和等于它本身。
(例如:
1^3+5^3+3^3=153)严格来说三位数的3次幂数才成为水仙花数。
请找出所有为3位数的水仙花数。
(提示:
涉及到数的剥离)
3.2验证哥德巴赫猜想
描述:
任意一个大于2的偶数都可以写成两个质数的和,请验证100以内的数哥德巴赫猜想成立,并将每个数的拆分输出。
3.3鸡兔同笼问题
描述:
有一些鸡和兔混在一起,输入他们的头和脚的总数N和M,求分别有多少只鸡和兔。
四、数组操作
目前很多题目都要涉及到数组操作,因此能够熟练运用数组是搞算法的重要技能,包括
1.通过循环操作数组
2.对数组下标的灵活运用
4.1杨辉三角
描述:
给定K,输出前K行的杨辉三角。
例:
1
11
121
1331
14641
五、递推
递推其实就是通过推导出一个递推公式,由F(i),F(j)进行一些变换等得到F(n),其中I,j5.1切饼
描述:
王小二自夸刀工不错,有人放一张大的煎饼在砧板上,问他:
“饼不许离开砧板,切100刀最多能分成多少块?
”
5.2兔子繁殖问题
描述:
如果有一对小兔,每一个月都生下一对小兔,而所生下的每一对小兔在出生后的第三个月也都生下一对小兔。
那么,由一对兔子开始,满一年时一共可以繁殖成多少对兔子?
(提示:
第一个月,这对兔子生了一对小兔,于是这个月共有2对(1+1=2)兔子。
第二个月,第一对兔子又生了一对兔子。
因此共有3对(1+2=3)兔子。
第三个月,第一对兔子又生了一对小兔而在第一个月出生的小兔也生下了一对小兔。
所以,这个月共有5对(2+3=5)兔子。
第四个月,第一对兔子以及第一、二两个月生下的兔子也都各生下了一对小兔。
因此,这个月连原先的5对兔子共有8对(3+5=8)兔子。
)
5.3数字三角形(NT)
【问题描述】给定一个具有N层的数学三角形如下图,从顶至底有多条路径,每一步可沿左斜线向下或沿右斜线向下,路径所经过的数字之和为路径得分,请求出最小路径得分。
2
62
184
1568
【输入数据】
第1行,一个正整数n,表示三角形的行数
第2至n+1行,照描述输入三角形
【输出数据】最小路径得分,行末有换行
【样例输入】
4
2
62
184
1568
【样例输出】
10
六、贪心
贪心法是从问题的某一个初始状态出发,通过逐步构造最优解的方法向给定的目标前进,并期望通过这种方法产生出一个全局最优解的方法。
贪心选择性质:
算法中每一步选择都是当前看似最佳的选择,这种选择依赖于已做出的选择,但不依赖于未作出的选择。
最优子结构性质:
算法中每一次都取得了最优解(即局部最优解),要保证最后的结果最优,则必须满足全局最优解包含局部最优解。
6.1删数问题
键盘输入一个高精度的正整数n(n<=240位),去掉其中任意s个数字后剩下的数字按原左右次序将组成一个正整数编程对给定的n和s,寻找一种方案,使得剩下的数字组成的新数最小。
输入:
n s
输出:
最后剩下的最小数。
样例输入:
178543
4
样例输出:
13
6.2排队接水
【问题描述】
有n个人在一个水龙头前排队接水,假如每个人接水的时间为Ti,请编程找出这n个人排队的一种顺序,使得n个人的平均等待时间最小。
【输入】
输入文件共两行,第一行为n;第二行分别表示第1个人到第n个人每人的接水时间T1,T2,„,Tn,每个数据之间有1个空格。
【输出】
输出文件有两行,第一行为一种排队顺序,即1到n的一种排列;第二行为这种排列方案下的平均等待时间(输出结果精确到小数点后两位)。
七、递归
递归其实是搜索算法的一种,被称为深度优先搜索(DFS)。
经典的递归题目有很多。
7.1数字拆分
描述:
给定一个数字N,找出他的所有拆分情况(限于和的形式)
如7拆分的结果是
7=1+6
7=1+1+5
7=1+1+1+4
7=1+1+1+1+3
7=1+1+1+1+1+2
7=1+1+1+1+1+1+1
7=1+1+1+2+2
7=1+1+2+3
7=1+2+4
7=1+2+2+2
7=1+3+3
7=2+5
7=2+2+3
7=3+4
7.2八皇后问题(这是递归中最经典的一道题,这道题完全搞懂后其他递归题目不在话下)
描述:
现在有一个8*8的棋盘,要在这个棋盘上放置8个皇后,并且满足:
任意两个皇后不在同一条直线上(不同行、列、斜线)。
输出所有满足要求的情况。
7.3骑士游历
设有一个m×n的棋盘(2≤m≤50,2≤n≤50),在棋盘上任一点有一个中国象棋“马”,马走的规则为:
马走日字;马只能向右走。
当m,n给出后,同时给出马起始的位置和终点的位置,试找出从起点到终点所有路径的数目。
输入:
m,n,x1,y1,x2,y2(分别表示m,n、起点坐标和终点坐标)
输出:
路径数目(若不存在,则输出0)
八、时空复杂度计算
作为一个coder应该要对自己的程序有一些性能上的了解,诸如:
健壮性:
是否在各种条件下(包括不合法的情况)都能稳定运行;
耦合性:
程序是否将功能都进行分模块,耦合度越低证明每个模块越独立,模块独立的好处是:
出现BUG的时候不会影响到其他模块的正常运行,便于DEBUG;并且模块的功能可以反复利用。
时空复杂度:
这在算法中是最重要的一项属性。
当一个算法没有冗余状态时,时间复杂度和空间复杂度总体达到最优,此时的时间和空间是不可调和的。
如果想要减少时间,就必须增加空间(例:
寻找质数的优化算法),反之也一样。
一般情况下,对于一台计算机配置单核2Ghz左右CPU保守估计运算次数在1s一亿次左右(不要拿去显摆,这个是我们老师讲的,具体CPU总频数我也不记得了,其实计算次数要明显高于1亿次,以一亿次为准是防止题目超时)
时间复杂度计算:
平均时间复杂度用O来表示,当然也有最坏时间复杂度和最优时间复杂度的表示方法。
1.赋值、判断、运算语句都算是进行一次计算。
2.循环则按照循环上下界来确定。
比如for(i=1;i<=n;i++)就是O(n)的时间复杂度。
如果多重循环嵌套则累乘,比如
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
表达式;
}时间复杂度为O(n2)
如果是
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
表达式1;
}
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
表达式2;
}则时间复杂度为O(2*n2),不过一般系数K的影响不大,因此也称之为n2级别的算法。
3.递归的时间复杂度与循环计算相同,但由于递归是堆栈,所以占用内存很大,效率比循环低很多。
空间复杂度计算:
首先要了解char、int、bool等数据类型的字节数,以4字节的int为例:
intx[100];即声明了一个占用400字节(400B)的内存空间。
Intx[1000][1000];声明了一个占用4,000,000字节(4*1000*1000)即4MB大小的空间。