第四章 算法简介
4.1 概念
¶
算法是求解问题步骤的有序集合,它能够产生结果并在有限时间内结束。
4.2 特性
¶
- 确定性
- 有穷性
- 有效性
- 可以无输入
- 可以有多个输出 思考:随机数算法,产生伪随机数。
4.3 分类
¶
- 数值计算
- 针对特定数学模型求出数值解
- 非数值计算
- 处理符号、表格
4.4 结构
¶
- 顺序结构
- 分支结构
- 循环结构
-
当型(While) e.g.
-
直到型(Until)
4.5 表示
¶
- 流程图
- 伪代码
4.6 算法举例
¶
4.6.1 基本算法
¶
例一 求最大公约数¶
① 枚举法
A = int(input())
B = int(input())
for i in range(min(A,B),0,-1):
if A%i==0 and B%i==0:
break
print(i)
★② Euclid算法
例二 求最小值¶
data=[6,15,4,2,8,5,11,9,7,13]
min_index = 0 #只要不越界,初值可任意选
for i in range(1,len(data)): #注意i的开始和结束
if data[min_index]>data[i]:
min_index = i
print(min_index,data[min_index])
4.6.2 迭代
¶
e.g. 求平方根\(\sqrt a\)
递推公式:$$ x_{i+1}=\frac{x_i+\frac{a}{x_i}}{2},~a>0 $$
a = float(input())
count = 0 #数循环次数
x1 = 1
while True:
x2 = (x1+a/x1)/2
count += 1
if x1 == x2: #x1与x2足够接近的时候,会被判定为二者相等
break
x1 = x2
print(x1)
print(count)
e.g.2 计算 \([\log_2x]\)
即求一个数能被2整除多少次。
4.6.3 递归
¶
函数调用自身
定义函数¶
e.g. 求阶乘
e.g.2 Fibonacci数列
#该问题用递归较慢 O((3/2)^n)
def fib(n): #返回第n+1个Fibonacci数
if n==0 or n==1:
return 1
else:
return fib(n-1)+ fib(n-2)
4.6.4 排序
¶
4.6.4.0 双层循环¶
#输出质数
n = int(input())
for i in range(1,n+1):
flag = 1
for j in range(2,i): #n=1或2时不进入该循环
if i%j == 0:
flag = 0
break
if flag == 1 and i != 1:
print(i,end=' ')
4.6.4.1 选择排序¶
(升序)扫描所有数据,挑出最小的放在第一个,再扫描剩下的,如此循环。
e.g.
a = [3,1,5,2,4]
for i in range(len(a)-1):
index = i
for j in range(i+1,len(a)):
if a[j] < a[index]:
index = j
a[i],a[index] = a[index],a[i]
print(a)
4.6.4.2 冒泡排序¶
for i in range(len(a)-1):
for j in range(len(a)-1-i):
if a[j] > a [j+1]:
a[j],a[j+1] = a[j+1],a[j]
print(a)
4.6.5 查找
¶
4.6.5.1 顺序查找¶
4.6.5.2 折半查找¶
要求:列表有序
a = [1,2,3]
x = int(input())
left = 0
right = len(a)-1
found = -1
while left <= right:
mid = (left + right)//2
if x > a[mid]:
left = mid + 1
elif x < a[mid]:
right = mid - 1
else:
found = 1
break
print(found)
4.7 算法的方法学
¶
4.7.1 贪心算法
¶
基本思想:寻找局部最优解,不考虑全局。
特点:速度快,使用内存小 | 一般不是最优解
- 可行性:每一步选择必须满足问题的约束
- 局部最优:它是当前可选择的方案中最优的
- 不可取消性:选择一旦做出,在算法的其后步骤中不能被取消
e.g. 霍夫曼编码
e.g.2 找零钱问题 若面值为1,5,10,25,50,100,从面值大的从面值小的找零是最优解。 63元,若有21元的面值,则只要3张,贪心法失效。
4.7.2 分治算法
¶
基本思想: 分:大问题拆成小问题,递归求解子问题。 治:从小问题的解构建大问题的解。
e.g. 比较列表中数的大小
def min_max(a):
if len(a)==1:
return (a[0],a[0])
elif len(a)==2:
return (min(a),max(a))
else:
m=len(a)//2
lmin,lmax=min_max(a[:m])
rmin,rmax=min_max(a[m:])
return (min(lmin,rmin),max(lmax,rmax))
a,b = min_max([3,8,9,4,10,5,1,17])
print("最小值是",a,",最大值是",b)
4.7.3 回溯算法
¶
暂略
4.7.4 动态规划
¶
基本思想:大问题的子问题具有重叠,可以将每个子问题的解存放到一个表中,这样就可以通过查表解决问题。以空间换时间!
e.g. Fibonacci数列