什么是复杂度
算法的时间复杂度和空间复杂度
算法的时间复杂度反映了程序执行时间随输入规模增长而增长的量级,在很大程度上能很好反映出算法的优劣与否。
空间复杂度:类似于时间复杂度的讨论,一个算法的空间复杂度(Space Complexity)S(n)定义为该算法所耗费的存储空间,它也是问题规模n的函数。渐近空间复杂度也常常简称为空间复杂度。
时间复杂度的分析
- 对于赋值,输入输出语句为O(1)
- 对于顺序结构,采用求和法则,就是多个复杂度求和取最大的复杂度
- 对于循环结构,采用乘法法则,是复杂度的乘积
第一个for循环的时间复杂度为Ο(n),第二个for循环的时间复杂度为Ο(n2),则整个算法的时间复杂度为Ο(n+n2)=Ο(n2)。
什么是大O表示法
由于程序运行所需的时间往往会受到机器性能与其他因素影响,用绝对的时间单位衡量算法的效率并不合适。在讨论算法复杂度的时候,我们一般关注它的近似值(渐进趋势),即渐进复杂度,常用大O表示法表示。
O(1) | 常数时间复杂度 |
O(log n) | 对数时间复杂度 |
O(n) | 线性时间复杂度 |
O(n^2) | 平方 |
O(n^3) | 立方 |
O(2^n) | 指数 |
O(n!) | 阶乘 |
各个复杂度的增长速度
稳定与不稳定
排序算法的稳定性大家应该都知道,通俗地讲就是能保证排序前2个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同。在简单形式化一下,如果Ai = Aj,Ai原来在位置前,排序后Ai还是要在Aj位置前。
在小薛看来,简单的来讲,就是原来队伍中的数据,排在前面的相同数据,排序后也要排在前面。只要满足这个条件,就是稳定排序,比如冒泡排序,在相同时他是不会交换的,所以就是稳定排序。
选择排序这种,当我们的最小元素在最后面,中间有与这个元素相同的,交换这个最小的相同大小的元素位置就发生变化了。如4(1),5,4(2),2,排序完后。2,4(2),4(1),5。位置发生变化了。
插入排序是在一个已经有序的小序列的基础上,一次插入一个元素。当然,刚开始这个有序的小序列只有1个元素,就是第一个元素。比较是从有序序列的末尾开始,也就是想要插入的元素和已经有序的最大者开始比起,如果比它大则直接插入在其后面,否则一直往前找直到找到它该插入的位置。如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的。
冒泡排序最好是
最好情况下的时间复杂度:如果元素本来就是有序的,那么一趟冒泡排序既可以完成排序工作,比较和移动元素的次数分别是n-1和0,因此最好情况的时间复杂度为O(n)。
最差情况的时间复杂度:如果数据元素本来就是逆序的,许哟啊进行n-1趟排序,所需比较和移动次数分别为n(n-1)/2和3n(n-1)/2。因此最坏情况子下的时间复杂度为O(n^2)。
稳定性:因为每次比较后如果两个相邻元素相等我们并不会将他们交换,所以冒泡不会改变相同元素的下标,所以冒泡排序是一个稳定的排序。
冒泡排序优化:不改变原数组,当循环到没有数据交互就跳出,用一个标志位来判断,break跳出。
选择排序
是原地排序,不稳定排序最好/最坏/平均:O(n²)。即使完全有序,也需要经过 ( n + 1 ) n / 2 次遍历