当前位置:   article > 正文

算法学习(持续更新)

算法学习

目录

一、认识复杂度和简单排序算法

1.1 时间复杂度(忽略了N前面的常数项,只保留幂项)

1.2 额外空间复杂度、选择排序、冒泡排序

1.3 插入排序及其时间复杂度


一、认识复杂度和简单排序算法

1.1 时间复杂度(忽略了N前面的常数项,只保留幂项)


(1) 直接看N的幂,越小越快(当然)
但对于O(N^2)和O(N)来说,你也不能武断的就判断说后者比前者更好,因为你在表示时间复杂度的时候忽略了常数项,你只能说,当实验进程无限长的时候,后者比前者更好。

因此这个“好”的判断,是在数据样本足够大的时候给予的判断。

(2)对于相同时间复杂度O(N) 无法用理论预估的方式来判断谁好,给予超大的样本量让两个程序去跑,直接比较时间就可以了。

例:B的复杂度没有化简之前是1000N*(a操作)+500
而C是2000N*(b操作)+300

每种操作的固定时间差别导致了无法使用理论预估。

1.2 额外空间复杂度、选择排序、冒泡排序


选择排序:O(N^2)  额外空间复杂度O(1)
冒泡(Bubble 同样的)

**额外空间复杂度
要完成自己设计流程 需要多少额外的空间

如果程序运行过程中,不需要额外的数据结构,只是使用了额外的几个变量。那么额外空间复杂度为O(1);
如果要申请一个和原数组大小一样的数组,那额外空间复杂度为O(n);
如果申请一个是原数组大小一半的数组,那额外空间复杂度为O(n)(因为系数是可以忽略的)

随堂:BubbleSort Code(反正我是没搞明白为什么内嵌的循环只需要n-1,回头再看看

  1. #include <iostream>
  2. using namespace std;
  3. void Bubble(int n)
  4. {
  5. int temp;
  6. int *arr=new int [n];
  7. for(int i=0;i<n;i++)
  8. {
  9. cin>>arr[i];
  10. }
  11. for(int i=0;i<n;i++)
  12. {
  13. for(int j=0;j<n-1;j++)
  14. {
  15. if(arr[j]>arr[j+1])
  16. {
  17. temp=arr[j+1];
  18. arr[j+1]=arr[j];
  19. arr[j]=temp;}
  20. }
  21. }
  22. for(int i=0;i<n;i++)
  23. {cout<<arr[i]<<" ";}
  24. }
  25. int main()
  26. {
  27. int n;
  28. cin>>n;
  29. Bubble(n);
  30. return 0;
  31. }

随堂:SelectSort Code

  1. #include <iostream>
  2. using namespace std;
  3. void sort(int n)
  4. {
  5. int minIndex=0;
  6. int min=0;
  7. int *arr=new int[n];
  8. for(int i=0;i<n;i++)
  9. {
  10. cin>>arr[i];
  11. }
  12. for(int i=0;i<n;i++)
  13. {
  14. minIndex=i;
  15. min=arr[i];
  16. for(int j=i+1;j<n;j++)
  17. {
  18. if(arr[j]<min)
  19. {
  20. minIndex=j;
  21. min=arr[j];
  22. }
  23. }
  24. int temp=arr[i];
  25. arr[i]=min;
  26. arr[minIndex]=temp;
  27. }
  28. for(int i=0;i<n;i++)
  29. {
  30. cout<<arr[i]<<" ";
  31. }
  32. }
  33. int main()
  34. {
  35. int n;
  36. cin>>n;
  37. sort(n);
  38. return 0;
  39. }

1.3 插入排序及其时间复杂度

说起来比较简单的一类排序

比如 2 3 5 2 3 9 1 0,依照顺序给每个数字标号0—i

考虑顺序为:从0开始,先看0-0上是否排好了,再看0-1号是否排好,再看0-2号是否排好。

实际编写代码的时候,基于前面所有数都已经排列好的情况,只需要考虑最末位的i号数字是否比前面大(小),令j=i-1,则每次比较j和j+1即可

时间复杂度 O(N^2)

插入排序的进行弹性很大,他可能是最坏的情况,每次都要比较到底,这种情况下的计算量为等差数列,显然时间复杂度为O(N^2)。

同时他也可能是最好的情况,每次都只需要看一下就发现根本不需要交换位置,这种情况下的时间复杂度就是O(N)。

那么我们取最坏的情况所以他的时间复杂度为O(N^2),但插入排序显然仍然在常数级别的排序上,比冒泡排序和选择排序优秀的多。

随堂:InsertSort Code

两个注意的地方(我写错的地方)

1、i=1。  i=0的情况必然正确无需讨论

2、j>=0而不是j-1>=0.

  1. #include <iostream>
  2. using namespace std;
  3. void InsertSort(int n)
  4. {
  5. int *arr=new int [n];
  6. for(int i=0;i<n;i++)
  7. {
  8. cin>>arr[i];
  9. }
  10. for(int i=1;i<n;i++)
  11. {
  12. for(int j=i-1;j>=0&&arr[j]>arr[j+1];j--)
  13. {
  14. int temp=0;
  15. temp=arr[j];
  16. arr[j]=arr[j+1];
  17. arr[j+1]=temp;
  18. }
  19. }
  20. for(int i=0;i<n;i++)
  21. {
  22. cout<<arr[i]<<" ";
  23. }
  24. }
  25. int main()
  26. {
  27. int n;
  28. cin>>n;
  29. InsertSort(n);
  30. return 0;
  31. }

1.4 二分法的使用和复杂度分析

(1)原理

很简单,一串数字里找一个数字,砍一半,去剩下的一半里找,继续砍一半,直至找到。

那么最差的情况就是全砍完,砍到最后只剩下你要找的那个数,你砍的次数就是你的操作量。

(2)时间复杂度 O(logN)

所以二分法的时间复杂度是log2N(比如说,32个数,2^5你就要砍5次,所以是log2 32)

写作O(logN),默认以2为底,若不是以2为底,则写成O(log n N)(n是那个底数)

(3)适用问题

1)在一个有序数组中,找某个数是否存在

2)在一个有序数组中,找>=某个数最左的位置或找<=某个数最右的位置

3)局部最小值问题

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

闽ICP备14008679号