二、算法分析

一、什么是算法分析

程序和算法的区别:

  • 算法是对问题解决的分步描述
  • 程序是采用某种编程语言实现的算法,同一个算法通过不同的程序员采用不同的编程语言,能产生很多程序

算法分析的概念:

  • 算法分析主要就是从计算资源消耗的角度来评判和比较算法
  • 更高效利用计算资源,或者更少占用计算资源的算法,就是好算法

计算资源指标:

  • 一种是算法解决问题过程中需要的存储空间或内存
  • 另一种是算法的执行时间

运行时间检测:

 1 # 累计求和程序的运行时间检测
 2 #迭代法
 3 import time
 4 
 5 def sum1(n):
 6     start = time.time()
 7     theSum = 0
 8     for i in range(1,n+1):
 9         theSum += i
10     end = time.time()
11     return theSum, end - start
12     
13 for i in range(5):
14     print('Sum is %d required %10.7f seconds'%sum1(10000))

n = 10000 时,执行5次的结果为

Sum is 50005000 required  0.0000000 seconds
Sum is 50005000 required  0.0009980 seconds
Sum is 50005000 required  0.0000000 seconds
Sum is 50005000 required  0.0000000 seconds
Sum is 50005000 required  0.0009968 seconds

n = 100000 时, 执行5次的结果为

Sum is 5000050000 required  0.0049877 seconds
Sum is 5000050000 required  0.0049853 seconds
Sum is 5000050000 required  0.0049860 seconds
Sum is 5000050000 required  0.0049872 seconds
Sum is 5000050000 required  0.0049863 seconds

n = 1000000时,执行5次的结果为

Sum is 500000500000 required  0.0528579 seconds
Sum is 500000500000 required  0.0518231 seconds
Sum is 500000500000 required  0.0528951 seconds
Sum is 500000500000 required  0.0519009 seconds
Sum is 500000500000 required  0.0527823 seconds

 

 1 # 累计求和程序的运行时间检测
 2 # 利用高斯求和公式的无迭代算法
 3 import time
 4 
 5 def sum2(n):
 6     start = time.time()
 7     theSum = (n * (n+1)) / 2
 8     end = time.time()
 9     return theSum, end - start
10     
11 for i in range(5):
12     print('Sum is %d required %10.7f seconds'%sum2(10000))

n = 10000,100000,1000000时,执行5次的结果时间均相同,为0.0000000 seconds

比较:

  • 第一种迭代算法包含一个循环,这个循环运行次数跟累加值n有关,n增加,循环次数也会增加
  • 第二种无迭代算法运行时间比第一种短很多,运行时间与累计对象n的大小无关

二、大O表示法

算法时间度量指标:

  • 一个算法所实施的操作数量或步骤数可作为独立于具体程序/机器的度量指标
  • 赋值语句是度量指标的一个合适选择,一条赋值语句同时包含了(表达式)计算和(变量)存储两个基本资源

数量级函数(Order of Magnitude)

  • 基本操作数量函数T(n)的精确值不是特别重要,重要的是T(n)中起决定性因素的主导部分
  • 数量级函数描述了T(n)中随着n增加而增加速度最快的主导部分

常见的大O数量级函数:

 

 

 

 

 三、"变位词"判断问题

 1 #解法1:逐字检查
 2 
 3 def anagramSolution1(s1, s2):
 4     alist = list(s2)
 5     pos1 = 0
 6     stillOK = True
 7     while pos1 < len(s1) and stillOK:
 8         pos2 = 0
 9         found = False
10         while pos2 < len(alist) and not found:
11             if s1[pos1] == s2[pos2]:
12                 found = True
13             else:
14                 pos2 = pos2 + 1
15         if found:
16             alist[pos2] = None
17         else:
18             stillOK = False
19         pos1 = pos1 + 1
20     return stillOK
21     
22 print(anagramSolution1('abcd','cabd'))

 1 #解法2:排序比较
 2 
 3 def anagramSolution2(s1, s2):
 4     alist1 = list(s1)
 5     alist2 = list(s2)
 6     
 7     alist1.sort()
 8     alist2.sort()
 9     pos = 0
10     matches = True
11     while pos < len(s1) and matches:
12         if alist1[pos] == alist2[pos]:
13             pos = pos + 1
14         else:
15             matches = False
16     return matches
17     
18 print(anagramSolution2('abcde','edcba'))

 1 #解法4:计数比较
 2 
 3 def anagramSolution4(s1, s2):
 4     c1 = [0] * 26
 5     c2 = [0] * 26
 6     for i in s1:
 7         pos = ord(i) - ord('a')
 8         c1[pos] = c1[pos] + 1
 9     for j in s2:
10         pos = ord(j) - ord('a')
11         c2[pos] = c2[pos] + 1
12     k = 0
13     stillOK = True
14     while k < 26 and stillOK:
15         if c1[k] == c2[k]:
16             k = k + 1
17         else:
18             stillOK = False
19     return stillOK
20     
21 print(anagramSolution4('abcde','edcba'))

四、Python数据类型的性能

1、列表list和字典dict的对比:

 

 

2、4种生成前n个整数列表的方法性能比较

 

 1 #4种生成前n个整数列表的方法性能比较
 2 from timeit import Timer
 3 
 4 def test1():
 5     l = []
 6     for i in range(1000):
 7         l = l + [i]
 8         
 9 def test2():
10     l = []
11     for i in range(1000):
12         l.append(i)
13         
14 def test3():
15     l = [i for i in range(1000)]
16     
17 def test4():
18     l = list(range(1000))
19     
20 t1 = Timer('test1()','from __main__ import test1') #创建一个Timer对象,指定需要反复运行的语句和只需要运行一次的“安装语句”
21 print('concat %f seconds\n' % t1.timeit(number=10000)) #调用Timer对象的timeit方法,其中可以指定反复运行多少次
22 
23 t2 = Timer('test2()','from __main__ import test2')
24 print('append %f seconds\n' % t2.timeit(number=10000))
25 t3 = Timer('test3()','from __main__ import test3')
26 print('comprehension %f seconds\n' % t3.timeit(number=10000))
27 t4 = Timer('test4()','from __main__ import test4')
28 print('list range %f seconds\n' % t4.timeit(number=10000))
concat 14.517047 seconds

append 0.859504 seconds

comprehension 0.517713 seconds

list range 0.127913 seconds

 

3、list.pop的计时试验

# -*- coding: utf-8 -*-
"""
Created on Thu Oct 17 20:30:27 2019

@author: wu
"""

#list.pop的计时试验,比较pop()和pop(0)两种方法
from timeit import Timer
import timeit
import numpy as np
import matplotlib.pyplot as plt

pop0 = timeit.Timer('x.pop(0)','from __main__ import x')
popend = timeit.Timer('x.pop()','from __main__ import x')
print('pop(0)        pop()')
l1 = []
l2 = []
for i in range(1000000,10000001,100000):
    x = list(range(i))
    pt = popend.timeit(number=100)
    l1.append(pt)
    x = list(range(i))
    pz = pop0.timeit(number=100)
    l2.append(pz)
    print('%15.5f,%15.5f' % (pz,pt))
    
j = np.arange(1000000,10000001,100000)
plt.plot(j,l1,label='pop')
plt.plot(j,l2,label='pop0')
plt.xlabel('n')
plt.ylabel('time(s)')
plt.legend()
plt.show()

 

 

 4、list和dict的in操作对比

 1 #验证list中检索一个值,以及dict中检索一个值的对比
 2 import timeit
 3 import random
 4 import numpy as np
 5 import matplotlib.pyplot as plt
 6 
 7 l1,l2 = [],[]
 8 n = []
 9 for i in range(10000,1000001,20000):
10     t = timeit.Timer('random.randrange(%d) in x'%i,'from __main__ import random,x')
11     x = list(range(i))
12     lst_time = t.timeit(number=100)
13     l1.append(lst_time)
14     x = {j:None for j in range(i)}
15     d_time = t.timeit(number=100)
16     l2.append(d_time)
17     print('{},{:10.3f},{:10.3f}'.format(i,lst_time,d_time))
18     
19 for i in range(10000,1000001,20000):
20     n.append(i)
21 
22 plt.plot(n,l1,'go-',label='list')
23 plt.plot(n,l2,'r*-',label='dict')
24 plt.xlabel('n')
25 plt.ylabel('time')
26 plt.legend()
27 plt.show()
28     

 

 

 

posted @ 2019-10-21 16:10  wps168  阅读(437)  评论(0编辑  收藏  举报