Python版数据结构与算法——算法分析(Loading...)

源于MOOC北京大学陈斌老师课程

程序和算法的区别

算法是逻辑层,程序是物理层。

  1. 算法是对问题解决的分步描述。
  2. 程序是采用某种编程语言实显的,同一个算法通过不同程序员采用不同的编程语言,可以产生很多程序。

比较程序的好坏

只要从计算资源消耗的角度:更高效的利用计算资源或占用更少的计算资源。

什么是计算资源

  1. 算法解决问题工程中需要的储存空间或内存
  2. 算法的执行时间
import time
time.time()
'''记录了从1975年0点0分0秒到当前时间的时间,用此方法可以记录
程序的运行时间'''

算法时间度量指标

赋值语句是一个合适的算法度量指标
问题规模

影响算法执行时间的主要因素叫做问题规模。
在前n个整数累计求和计算算法中,需要累积的整数个数合适作为问题规模的指标。
“前100,00个整数求和对比前1,000个整数求和,算是同一个问题的更大规模”
算法分析的目标是找出问题规模会怎么影响一个算法得执行时间。

数量级函数 Order of Magnitude

基本操作数量函数T(n)的精确值并不是特别重要,重要的是T(n)中起决定性因素的主导部分
用动态的眼光看,就是当问题规模增大的时候,T(n)中的一些部分就会覆盖其他部分的贡献

大O表示法

数量级函数描述了T(n)中随着n增加而增加速度最快的主导部分。
计做O(f(n)),其中f(n)表示T(n)中的主导部分。
例1
以下为前n个整数求和函数,共有n+1次赋值。

def sum(n)
	num=0
	for i in range(1,n+1):
		num+=i
	return num

当n增大时,常数1再最终结果中显得越来越无足轻重。
所以可以去掉1,保留n作为主要部分,运行时间是O(n)
例2
假设某一算法T(n) = 5n²+27n+1005
当n趋近于正无穷时,5n²起绝对性作用,其他两项对结果的影响越来与小。
同样,二次项系数5对n²增长速度来说也影响不大。
所以可以在数量级中去掉27n+1005,以及系数5的部分,确定为O(n²)。

影响算法运行时间的其他因素
某些具体数据也会影响算法运行时间

针对算法输入数据而言,分为最好最差平均情况,平均情况体现了算法的主流性能
对算法的分析要看主流,而不能被几种特定的运行状况所迷惑。

常见大O数量级函数

当n非常小的时候,难以确定其数量级
在这里插入图片描述
例3以下赋值语句可以分为4个部分

a = 5
b = 6
c = 10
for i in range(n):
	for j in range(n)
		x = i *i
		y = j * j
		z = i *j
for k in range(n):
	w = a* k + 45
	v = b * b
d = 33
  1. 第一部分是三条赋值语句,执行3次
  2. 第二部分是双重循环,内部循环的循环体是三条计算语句,共执行n次 外层循环又将内层循环执行n次 所以第二部分的循环体共执行了3n²这么多次
  3. 第三部分是单层循环,执行2n次
  4. 第四部分是赋值语句,执行1次
    T(n)=3+3n²+2n+1 →T(n)=3n²+2n+4
    在这里插入图片描述
其他算法复杂度表示法

在这里插入图片描述

变位词判断问题

问题描述

所谓“变位词”是指两个词之间存在 组成字母的重新排列关系
为了简单起见,假设参与判断的两个词仅由小写字母构成,而且长度相等。

解题目标

写一个bool函数,以两个词作为参数,返回这两个词是否是变位词

可以很好的展示同一问题的不同数量级算法

解题思路

1.逐字检查法
原理思路

将1词中的字符逐个到词2中检查是否存在,存在就“打勾”标记(防止重复检查),如果每个字符都能找到则为变位词,如果有一个字符找不到,就不是变位词。

  • 实现打勾标记的做法是将字匹配成功的字符变为“None”

在这里插入图片描述

代码实现
def anagramSolution(s1, s2):
    alist = list(s2)
    pos1 = 0
    stillok = '{}与{}是变位词'.format(s1,s2)
    while pos1 < len(s1) and stillok:
        pos2 = 0
        found = False
        while pos2 < len(alist) and not found:
            if s1[pos1] == alist[pos2]:
                found = True
            else:
                pos2 += 1
        if found:
            alist[pos2] = None
        else:
            stillok = '{}与{}不是变位词'.format(s1,s2)
        pos1 += 1
    return stillok
算法分析

问题规模: 单词中包含的字符个数n
主要本分为双重循环部分: 外层循环遍历s1的每个字符,内层循环执行n次,而内层循环在s2中查找字符,每个字符的对比次数,分别是1至n中的一个,而且各不相同
执行总次数: 1 + 2 + 3 + . . . + n 1+2+3+...+n 1+2+3+...+n
根 据 等 差 数 列 求 和 公 式 可 知 其 数 量 级 为 : 根据等差数列求和公式可知其数量级为: :
∑ i = 0 n i = n ( n + 1 ) n = 1 2 n ² + 1 2 → O ( n ² ) \sum_{i=0}^ni=\frac{n(n+1)} {n}=\frac{1}{2} n²+\frac{1}{2}→O(n²) i=0ni=nn(n+1)=21n²+21O(n²)

2.排序比较
原理思路

将两个字符串按照字母顺序排序
逐个字符对比是否相同,如果想同则是变位词,有任何不同就不是变位词
在这里插入图片描述

代码实现
def anagramSoulution2(s1, s2):
    alist1 = list(s1)
    alist2 = list(s2)
    alist1.sort()
    alist2.sort()
    pos = 0
    matches = '{}与{}是变位词'.format(s1, s2)
    while pos < len(s1) and matches:
        if alist1[pos] == alist2[pos]:
            pos += 1
        else:
            matches = '{}与{}不是变位词'.format(s1, s2)
    return matches
算法分析

简单来看似乎只有一个循环,最多执行 n n n次,所以数量级是 O ( n ) O(n) O(n)
但 是 之 前 的 排 序 语 句 并 不 是 无 代 价 的 , 排 序 算 法 采 用 不 同 解 决 方 案 运 行 时 间 的 数 量 级 差 不 多 是 但是之前的排序语句并不是无代价的,排序算法采用不同解决方案运行时间的数量级差不多是 O(n² ) 或 者 )或者 )O(n log n) , 大 于 循 环 的 ,大于循环的 O(n) , 所 以 本 算 法 主 导 步 骤 是 排 序 的 步 骤 ,所以本算法主导步骤是排序的步骤 ,
所以本算法的运行事件数量及等于排序过程数量级为 O ( n l o g n ) O(n log n) O(nlogn)

3.暴力法
解题思路

穷举所有可能组合
将s1中出现字符进行全排列,再查看s2是否出现在全排列的列表中
这其中最大困难是产生s1所有字符的前排列
根据概率论知识可知,如果n个字符进行全排列,其可能的字符串个数为:
n ! n! n!
在这里插入图片描述

暴力法不是个好的算法

对于2个字符长的单词来说,将产生
20 ! = 2 , 432 , 902 , 008 , 176 , 640 , 000 20!=2,432,902,008,176,640,000 20!=2,432,902,008,176,640,000
个候选词,如果每微妙处理1个候选词的话,需要将近8万年完成全部匹配。

4.技术比较
解题思路

对比两个单词中每个字母出现的次数,如果26个字母出现的次数都相同,则是变位词,否则不是变位词
为每个词设计一个26位的计数器,检查每个词,

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值