复试准备--算法设计与分析
递归与分治
1、求n!
2、汉罗塔
汉诺塔1
f(n-1):将n-1个盘子从小到大由一个盘子全部移动到一个空盘上
f(n) = 2*f(n-1)+1
f(1) = 1
令an = f(n) bn = an +1 -> bn = 2(a(n-1) +1)->bn = 2b(n-1) b1=a1+1=2 ->bn = 2^n ->an = 2^n-1
汉诺塔3:
F(n):将n个盘子从大到小由第一个盘子全部移动到第三个盘子上 (此时盘子只能放相邻盘子上)
F(n) = 3F(n-1)+2
F(1) = 2
bn = 3^n-1
3、全排列问题:二叉树思想
字符串全排列
递归方式:标记数组visit
字符数组sequence
非递归: 求下一个排列 例:1234为首,4321为尾
给定一个数字排列
从后往前看,1求拐点 2交换(从后往前第一个比拐点大的数) 3排序(拐点后面的段)
4、斐波那契数列
1、分治法
2、递推法
3、矩阵快速求幂(未完成)
5、二叉树:求以第m个顶点为子树的二叉树包含的顶点个数
采用分治法
数字问题
1、二进制数 十进制->二进制
先取模,再除法相消
2、十六进制转十进制
先乘,后加
3、m进制转换为n进制
m-10:字符串--int
10-n:int--字符串
4、GCD求(A,B)的最大公约数
辗转相除法
5、求质数
枚举法 一直从2枚举到根号n
筛法
6、快速幂
利用二进制 求
7、矩阵运算(+、*)
运用结构体
贪心策略:总是做出当前最好的选择
分 治 合
1、猫鼠贸易
航电:1009
2、枪与怪兽
航电:5281
假如每次只打一次枪
3、箱子打包:能够包含所有物品的最小的箱子总数。
有n个物品 m个箱子 箱子长度l
假如每次只装一个箱子
选最大和最小的商品装箱,若溢出则只装最大的商品
装箱的数目
4、母牛与谷仓的问题:求最大的最小间隔距离 -- 二分策略 判定性问题
谷仓有n个摊位,arr[i]表示摊位坐标,有m头母牛
5、衣服晾干问题:求最小晾干时间 二分法
有n件衣服,water[i]:每件衣服需要晾干的时间,k:烘干机的烘干能力,
北大3104
6、电视节目问题:求最多能看多少个节目
n个节目,有各自的开始时间和结束时间,
图论
1、并查集
查询
Father[i],父节点 初始化时每个结点单独构成一个集合
合并
应用:判断图是否连通 牛客网:连通图
2、生成树:连通图的极小连通子图
最小生成树:权值最小的生成树
3、prim和kruskal
4、Dijkstra最短路径
memset函数,memset(数组名,值,sizeof(数组名))
需要添加string.h头文件,只适合赋值0或-1
algorithm头文件下的常用函数
1、max(a,b)和min(a,b):a,b可以是浮点数
2、abs(x):返回x的绝对值 x必须是整数 浮点数需用fabs(x):math头文件下
3、swap(a,b)
4、reverse(it,it2)可以将数组指针在[it,it2)之间的元素反转,或者容器内的元素(例如string字符串)
5、next_permutation(it,it2):求下一个全排列
6、fill(a,a+5,233):将a[0]-a[4]全部填为233
7、sort(a,a+5,compare):只有vector、string、deque是可以使用sort的
8、upper_bound和lower_bound(a,a+5,1)
vector和iterator迭代器
访问元素:1、下标 2、迭代器:类似指针
push_back()、pop_back()、size()、clear()、insert()、erase(pos,length)、length()/size()
string容器
substr(pos,length)
find(str2):返回子串第一次出现的位置
replace(pos,len,str2):将str中从pos开始,长为len的子串替换为str2
spilt分割字符串:1、借助char*的strtok函数:char * strtok (char *str, char * delim);
2、借助string容器中,find和substr函数
atoi()将char*转换为int
c_str()将string转换为char*
queue容器
front()和back():返回首元素和尾元素
push()和pop():队尾入队、队首出队
empty():检测queue是否为空,返回true为空,返回false为非空
size():返回queue元素个数
priority_queue容器:优先级队列 底层堆会按元素优先级随时调整结构
只有top()函数,没有front()和back()
基本数据类型的优先级设置:
priority_queue<int,vector<int>,less<int> > q;
less<int>:表示数字大的优先级更高
greater<int>:表示数字小的优先级更高
结构体的优先级设计:
struct fruit{
string name;
int price;
friend bool operator <(fruit a,fruit b){ return a.price<b.price }
}f1,f2,f3;
stack容器:
push()、top()、pop()、empty()、size()
散列:标记数组就源于散列的思想
散列函数:除留余数法:H(key) = key % mod; mod取最接近表长的一个素数
直接定址法:H(key) = key;或线性函数 H(key) = a*key+b
map映射:map<type1,type2> mp 键值对 其中键是唯一的,map内部是使用红黑树定义的(set也是),所以键会自动排序
访问方式:1、下标 mp['c'] = 30; mp['c']
2、迭代器 map<type1,type2>::iterator it; it->first, it->second 访问键值对
函数:1、find(key):返回键为key的迭代器
2、erase(it):it为需要删除元素的迭代器
erase(first,last):first为需要删除的区间的起始迭代器,而last为需要删除的区间的末尾迭代器的下一个地址
3、size():映射的对数
4、clear()
动态规划问题:若一个问题拥有若干个重叠子问题,则可以采用动态规划去解决。
以数塔为例:元素本身的值f[i][j],元素的状态数组dp[i][j],数塔的最后一层dp值总是等于元素本身 即dp[n][j] == f[n][j]
直接能够确定状态结果的部分称为边界,而动态递归的递推写法总是从边界出发,通过状态转移方程扩散到整个dp数组
递归与递推的区别:
使用递推写法的计算方式是自底向上,从边界开始,不断解决问题,直到解决了目标问题。
使用递归写法的计算方式是自顶向下,从目标问题开始,将它分解为子问题的组合,直到分解至边界为止。

浙公网安备 33010602011771号