算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。如果一个算法有缺陷,或不适合于某个问题,执行这个算法将不会解决这个问题。不同的算法可能用不同的时间、空间或效率来完成同样的任务。一个算法的优劣可以用空间复杂度与时间复杂度来衡量。
算法中的指令描述的是一个计算,当其运行时能从一个初始状态和(可能为空的)初始输入开始,经过一系列有限而清晰定义的状态,最终产生输出并停止于一个终态。一个状态到另一个状态的转移不一定是确定的。随机化算法在内的一些算法,包含了一些随机输入。
贪心
1、特点:
最优化问题(但并不是所有的最优化问题都能用贪心算法来解决,eg:0-1背包问题)
在某种意义上的局部最优解
2、应用:
(1)找零问题
def change(n, t):
"""贪心算法:找零问题"""
m = [0 for _ in range(len(t))]
for i, money in enumerate(t):
m[i] = n // money
n = n % money
return m, n
print(change([100, 50, 20, 5,1], 376))
(2)背包问题:
def fraction_backpack(goods, w):
"""贪心算法:分数背包问题"""
# 先给商品按单位重量的价格排序
goods.sort(key=lambda x: x[0]/x[1], reversed=True)
# 最后返回每个商品拿的数量
m = [0 for _ in range(len(goods))]
# 拿走的总价值
total_v = 0
for i, (prize, weight) in enumerate(goods):
# 当背包重量w足够时全部拿走该商品的同时背包重量自减,否则按比例拿(此时背包已满)
if w >= weight:
m[i] = 1
w -= weight
total_v += prize
else: # 按比例拿(此时背包已满)
m[i] = w / weight
w = 0
total_v += m[i] * prize
break
return m
# 每个商品元组表示价(价格,重量)
goods = [(60,10),(100,20),(120,30)]
fraction_backpack(goods, 50)
(3)拼接最大数字问题
from functools import cmp_to_key
def xy_cmp(x,y):
if x+y < y+x:
return 1
elif x+y > y+x:
return -1
else:
return 0
def number_join(li):
"""贪心算法:拼接最大数字问题"""
li = list(map(str, li))
li.sort(key=cmp_to_key(xy_cmp))
return "".join(li)
li = [32, 94, 128, 1286, 6, 71]
print(number_join(li)) # 94716321286128