当前位置:   article > 正文

【算法设计与分析】算法学习导览

【算法设计与分析】算法学习导览

写在前面:

1:本人真的是一个算法菜鸡,但是个人认为这门课听了也对算法没什么提升,自学占大头。(希望真的能够2024年之前学会算法和数据结构,以及24年dp杯能榜上有名吧...)

2:后续可能会更新一个期末复习整理的大纲,由于csdn改版之后图片复制老是加载不了,所以如果要发出来的话挺耗时间的,之后没发就当我没说过这个事情(嗯)。


资料补档:

电子文件大纲(完整梳理版)更新:【算法设计与分析】期末汇总资源-CSDN文库

手写大纲更新:

 


实验重点:

1:

【问题描述】给定一个按值有序(升序)的N元整数数组A,采用折半查找法查找关键值k的位置,并给出查找的过程
【输入形式】

第一行:N

第二行:A[0], A[1], ... , A[N-1]

第三行:k
【输出形式】

第一行:k的位置(索引),若不存在则输出‘no’

第二行:查找的过程,每一次折半的中间(mid)位置的值,以逗号分隔。例如,1 2 3 4 5的中间位置为3,1 2 3 4的中间位置为2。
【样例输入】

样例1

11

2,5,8,11,15,16,22,24,27,35,50

22

样例2

11

2,5,8,11,15,16,22,24,27,35,50

10
【样例输出】

样例1

6

16,27,22

样例2

no

16,8,11
【样例说明】
【评分标准】必须使用折半法,其他方法不能得分。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main(){
  4. //input
  5. int N;
  6. scanf("%d",&N);
  7. int *A=(int*)malloc(sizeof(int)*N);
  8. int i=0;
  9. for(i=0;i<N;i++){
  10. //cin>>A[i];
  11. scanf("%d",&A[i]);
  12. }
  13. int k;
  14. //cin>>k;
  15. scanf("%d",&k);
  16. //half search
  17. int left=0,right=N-1,mid;
  18. int cnt=0;
  19. int flag=0;
  20. while(left<=right){
  21. mid=(left+right)/2;
  22. if(k<A[mid]){
  23. right=mid;
  24. }
  25. else if(k>A[mid]){
  26. left=1+mid;
  27. }
  28. else{//k==mid
  29. flag=1;
  30. break;//found
  31. }
  32. if(cnt==0) //cout<<A[mid];
  33. {
  34. printf("%d",A[mid]);
  35. }
  36. else{
  37. printf(",%d",A[mid]);
  38. }
  39. //else cout<<","<<A[mid];
  40. cnt++;
  41. }
  42. if(flag=1){
  43. //cout<<mid;//output the number
  44. printf("%d",mid);
  45. }
  46. else{
  47. printf("no");
  48. }
  49. return 0;
  50. }
  51. //2 5 8 11 15 16 22 24 27 35 50

2:

【问题描述】一个台阶总共有n级,如果一次可以跳1级,也可以跳2级。求总共有多少种跳法,并分析算法的时间复杂度,例如
n 为1 时只有一种跳法
n 为2 时只有两种跳法
【输入形式】输入一个整数n
【输出形式】n级的跳法数,整数m
【样例输入】

6
【样例输出】

13
【样例说明】

输入与输出均为整数
【答题要求】

要求在注释中首先解释求解思路,如果有递推关系,必须说明为什么是这样的关系,递推计算是通过什么道理建立起来的,否则不得分。
需要指出使用了所学过的什么方法,并明确写出算法的时间复杂度。仅使用蛮力法的求解将严重失分。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <iostream>
  4. using namespace std;
  5. #define MAX 10000000
  6. /*
  7. 用front、mid、rear存放暂态
  8. 类似用三个变量实现dp,使用过程中不断变表
  9. 参考斐波那契数
  10. 跳上n阶梯子需要前面梯子做基础
  11. 若差一阶和f(n-1)相同
  12. 若差两阶f(n-2)相同
  13. 时间复杂度为O(N)
  14. */
  15. int fun(int n){
  16. if(n<2){
  17. return 1;
  18. }
  19. int front=1,mid=1,rear=1;
  20. for(int i=2;i<=n;i++){
  21. front=mid;
  22. mid=rear;
  23. rear=(front+mid)%MAX;
  24. //max为取余,防止数字过大
  25. }
  26. return rear;
  27. }
  28. int main(){
  29. //input
  30. int n;
  31. cin>>n;
  32. cout<<fun(n);
  33. return 0;
  34. }

3:

【问题描述】

输入一个已经按升序排序过的数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字。要求时间复杂度是O(n)。如果有多对数字的和等于输入的数字,输出任意一对即可。
【输入形式】

一个升序排序的数组以空格隔开,以及一个目标数字,换行输入
【输出形式】

如果存在数组中两个数字和为目标数字,则输出数字对;

如果存在多个满足条件的数字对,输出一对即可;

不存在则不输出;
【样例输入】

1 2 4 7 11 15

15

【样例输出】

4 11
【样例说明】

4+11=15
【评分标准】

时间复杂度必须为 O(n),否则酌情给分。

注释中要首先说明求解思路。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <iostream>
  4. using namespace std;
  5. int main(){
  6. //输入
  7. int n;//元素个数
  8. cin>>n;
  9. int *a=(int*)malloc(sizeof(int)*n);
  10. for(int i=0;i<n;i++){
  11. cin>>a[i];
  12. }
  13. int target;
  14. cin>>target;
  15. //查找对应的元素 ,cnt可以用于估算时间复杂度
  16. int flag=0,front=0,rear=n-1,cnt=0;
  17. //双指针,front指向从头开始的元素,rear指向从尾开始的元素
  18. while(front<rear){
  19. //序列非负的情况下,如果target始终大于起始值,则两数一定在前面
  20. //但是好像没说非负
  21. /*
  22. if(a[rear]>target){
  23. rear--;
  24. cnt++;
  25. continue;
  26. }*/
  27. //找到两数
  28. if(a[front]+a[rear]==target){
  29. flag=1;
  30. cnt++;
  31. break;
  32. }
  33. //如果和偏大,则说明rear取大了
  34. else if(a[front]+a[rear]>target){
  35. rear--;
  36. cnt++;
  37. }
  38. //如果和偏小,则说明front取小了
  39. else{
  40. front++;
  41. cnt++;
  42. }
  43. }
  44. if(flag==1){
  45. cout<<a[front]<<" "<<a[rear];
  46. }
  47. //cout<<cnt;
  48. return 0;
  49. }
  50. /*
  51. 6
  52. 1 2 4 7 11 15
  53. 15

4:

【问题描述】在数组中,数字减去它右边的数字得到一个数对之差。求所有数对之差的最大值。例如
在数组{2, 4, 1, 16, 7, 5, 11, 9}中,数对之差的最大值是11,是16减去5的结果。
【输入形式】整数数组,空格隔开
【输出形式】数对之差的最大值,一个数字
【样例输入】
2 5 8 19 3 6

【样例输出】

16
【样例说明】题目要求输出数对之差的最大值,即数字减去右边数字的值,不一定为数组中最大值和最小值的差。
【评分标准】要求设计时间和空间复杂度最低、代码最简洁的方法。性能越好得分越高。
如使用蛮力法求解得分最低。注释中要明确解释求解思路与所采用的方法。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <iostream>
  4. using namespace std;
  5. int main(){
  6. //input
  7. int n;
  8. cin>>n;
  9. int *a=(int*)malloc(sizeof(int)*n);
  10. for(int i=0;i<n;i++){
  11. cin>>a[i];
  12. }
  13. //特殊情况讨论
  14. if(n==0){
  15. return 0;
  16. }
  17. if(n==2){
  18. cout<<a[1]-a[0];
  19. return 0;
  20. }
  21. //动态规划,maxD记录差值最大值,max记录从右侧开始的最大值
  22. int maxD=0,max=a[n-1];
  23. for(int i=n-2;i>=0;i--){
  24. //前面一个数大于当前max
  25. if(a[i]>max){
  26. max=a[i];//更新max
  27. }
  28. //当前值小于max,判断差值大小
  29. else{
  30. //如果max减去当前值比maxD大
  31. if(max-a[i]>maxD){
  32. maxD=max-a[i];//更新maxD
  33. }
  34. }
  35. }
  36. //时间复杂度为O(n),空间复杂度O(1)
  37. cout<<maxD<<endl;
  38. return 0;
  39. }

课件重点:

【一】

1:tsp的英文全称。

2:各类概率算法的全称。

3:根据T(n-1)计算大O。

4:回溯法的TSP问题的解空间树。

5:L型骨牌的数目计算公式。

6:给出概率pi和时间ti,分析算法的时间复杂度。

7:大O、大Ω、大Θ的含义。

【三】

3.1:给出f(n)和g(n)的公式,包括绝对值、log对数、取整等,求阶相关的大O、大Ω、大Θ,并给出其中对应符号最大和最小的函数。

3.2:KMP的主要思想。

3.3:汉诺塔的伪代码。

3.4:根据问题规模和算法时间T(n),求解计算机在速度性能上翻倍之后且算法不变的情况下,能解决的问题规模为多少?

【四】

4.1:根据T(n-1)计算大Θ。

4.2:快排的伪代码,分析时间复杂度。

4.3:用贪心法算开车加油的最少次数(有n个加油站,初始的时候没油,给出了各加油站距离起始点的位置,油箱容量为m),给出具体的贪心策略,并分析时间复杂度。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/891026
推荐阅读
相关标签
  

闽ICP备14008679号