复试准备--算法设计与分析

递归与分治

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数组

递归与递推的区别:

    使用递推写法的计算方式是自底向上,从边界开始,不断解决问题,直到解决了目标问题。

    使用递归写法的计算方式是自顶向下,从目标问题开始,将它分解为子问题的组合,直到分解至边界为止。

 

posted @ 2021-03-01 15:13  Jelonzz  阅读(189)  评论(0)    收藏  举报