模块1课程链接:Algorithmic Toolbox | Coursera
案例1:斐波拉契数列
简单算法
原理
运行时间
当n变大时,T(n)会变得非常巨大
原因是设计到大量的重复运算(红色部分):
改进算法
原理
简单来说就是把“从后往前算”改进成“从前往后算”,就可以大大的减少重复运算
代码
def get_fib_number(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
prev = [0,1]
for i in range(n-1):
cur = prev[0] + prev[1]
prev[0] = prev[1]
prev[1] = cur
return cur
案例2:寻找最大公约数
简单算法:遍历
虽然可以解决问题,但是不够高效
改进算法:辗转相除法
原理
如果GCD是a和b的公约数,那么他一定也是(a-b)的约数
代码
a,b辗转相除取余数,直至某一方为0,剩下的就是最大公约数
def get_GCD(a,b):
if a>b:
temp = a
a = b
b = temp
while a != 0:
temp = a
a = b % a
b = temp
return b
大O表示法
由案例1和2可以看出,运行时间是在优化算法的工程中的一个重要因素,但由于复杂的现实情况,准确的运行时间是不可计算的。但好处在于一些琐碎的因素可以被排除在考虑范围之外,于是在这里通过引入大O表示法(Big O Notation)来估算某一个算法的大致运行时间。
常见函数的增长率
红框内的内容是需要记忆的
计算大O表示法
定义
简单来说,大O表示法f(n)=O(g(n))
中的f(n)是g(n)的等阶无穷大或者是同阶无穷大。
计算规则1:当g(n)表达成乘积的形式时,忽略常数项
计算规则2:当 g(n)表达成和的形式时,忽略增长较慢的项
这里参考前文:常见函数增长率中红框内的结论
这里可以搭配课堂Quiz食用,巩固以下Big O的用法
Week3 - 贪婪算法
贪婪算法 Greedy Algirithm
定义
贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。
贪婪算法解决问题的步骤
1. 列出当前的所有选择
2. 找到当前的最优解(Safe Choice),这个部分需要论证:为什么是最优/最安全?
3. 做出选择后,原本的问题变成一个更小的子问题
4. 对于子问题,回到步骤1,继续寻找当前最优解,直至问题解决
案例 - 找零问题
目标
现在需要用1元,5元,10元的零钱找零n元,请问我最少能用几枚硬币完成找零?
思路
1. 列出所有解:第一块硬币可以是1元,5元,10元
2. 找出当前最优解:找n元以内的最大面值硬币X (X=1或5或10)
3. 子问题:现在需要用1元,5元,10元的零钱找零(n-X)元,请问最少能用几枚硬币完成找零?
4. 继续用贪婪算法:找(n-X)元以内的最大面值硬币X (X=1或5或10),直至完成找零
(注意:这是贪婪算法的一个经典案例,但贪婪算法旨在寻找局部最优,并不能保证整体最优。事实证明这个算法有时会得出错误结论,在后续的Dynamic Programming 算法中会详细讲解)
代码
def money_change(total):
change = 0
coins = [10,5,1]
for i in range(len(coins)):
if total/coins[i] > 0:
change += int(total/coins[i])
total = total % coins[i]
return change