本期主题:
算法的大O表示法
1.什么是大O表示法
大O表示法是一种特殊的表示方式,指出了算法的速度,指出了最糟情况下的运行时间。
例如去电话本里查找电话,用简单查找的方式就是一个个对比,因此最糟情况下就是所有的都对比完了,因此简单查找的大O表示法就是O(n)。
2.时间复杂度
2.1 时间复杂度定义
时间复杂度是指输入的数据大小为N时,算法运行所花费的时间。注意以下两点:
- 算法运行所花费的时间不是指算法运行的绝对时间(算法运行绝对时间与各方面有关,无法用来评估算法),而是统计算法的计算操作次数;
- 体现的是计算操作随数据大小N的操作次数变化情况。例如一个算法需要运行10次,或者100次操作,并且不随着输入的变化而变化,那么这个算法的时间复杂度就是常数级O(1);如果需要N次,100N次,那么算法的时间复杂度就是O(N);
2.2 常见算法的时间复杂度
- 二分查找法,O(log n)
- 简单查找,线性时间,O(n)
- 快速排序,O(n * log n)
- 选择排序,O(n²)
- 旅行商问题,O(n!)
这些算法在以后的文章中一一详细描述
1.二分查找法示例:
在一个有序的容器中,不停缩小寻找范围,搜索找到最终的元素,看下面这个例子:
#!/usr/bin/python
# -*- coding:utf-8 -*-
# 二分查找
def binary_search(list, target_item):
i = 1
low = 0
high = len(list) - 1
while (low <= high):
mid = int((low+high) / 2)
tmp = list[mid]
if (tmp == target_item):
print("find the correct item, use %d times" % i)
break
elif (tmp < target_item):
low = mid
else:
high=mid
print("%d times, low %d, high %d" % (i, low, high))
i+=1
def main():
item_list=[1,2,3,4,5,6,7,8,11,15]
binary_search(item_list, 5)
if __name__ == "__main__":
main()
3.数组与链表对比
从内存的角度而言,数组放在内存中的连续地址的元素,而链表是可以拆分开的元素,地址不需要连续。
数组 | 链表 | 备注 | |
---|---|---|---|
读取 | O(1) | O(n) | 链表需要从第一个元素找起,才能找到最后一个元素,而数组由于位置关系是固定的,所以可以直接找到 |
插入 | O(n) | O(1) | 数组最差的插入情况是需要在第一个元素前插入元素,这样就导致所有元素的位置都需要移动,而链表的插入,只需要找到有前一个和后一个即可 |
删除 | O(n) | O(1) | 与插入方式同理,删除可能是删除第一个元素,所以所有的元素都需要后移 |