杨桃的Python进阶讲座2——算法的优劣

本人CSDN博客专栏:https://blog.csdn.net/yty_7

初学者一般都会问一个问题:程序是什么?

有一个很著名的公式:程序 = 数据结构 + 算法

我提供一个不严谨的说法:程序 = 算法 + 实现语言

为啥省略了数据结构?因为对初学者来说,算法和实现语言比数据结构更容易理解一些,那么我们就从算法开始讲。

算法,是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。

我们其实一直都在学算法。我们小学学过的加减乘除就是最简单的算法。到了中学,是不是算法变难了一点呢,出现了负数、指数、对数、甚至还有虚数。到了大学,那就是质的飞跃了,出现了导数、微分、积分、偏微分、重积分……之所以会越来越难,是因为遇到的问题越来越复杂,用之前的无法解决因此提出了新的解题方案。

回到算法定义的本身,解题方案的准确而完整的描述。一个题目,常常会有多个解题方案,也就是有多种算法,那么算法就有优劣之分了。举个历史上的著名例子:

德国数学家高斯,七岁时进了 St. Catherine小学。大约在十岁时,老师在算数课上出了一道难题:「把 1到 100的整数写下来,然后把它们加起来!」高斯早早的交卷了。看到其他同学把数字一个个加起来,额头都出了汗水,但高斯却静静坐着。最后,老师检查同学们的答案:大部分都做错了,最后检查到高斯的考卷,上面只有一个数字:5050(用不着说,这是正确的答案。)老师吃了一惊,高斯就解释他如何找到答案:1+100=101,2+99=101,3+98=101,……,49+52=101,50+51=101,一共有50对和为 101的数目,所以答案是 50×101=5050。

算法的优劣就这么直观的体现出来了。我们用Python语言来写一下这两种算法,并且附上程序运行的时间做比较:

代码1:从1加到100使用直接求和

import time

start_time = time.time()

sum = 0
for i in range(101):
    sum += i
print(sum)

end_time = time.time()

print("elapsed: %f" % (end_time - start_time))
print("complete!")

运行结果:
5050
elapsed: 0.000000
complete!

代码2:从1加到100使用等差数列求和公式

import time

start_time = time.time()

s=list(range(101))
sum = (s[0]+s[-1])*len(s)/2
print(sum)

end_time = time.time()

print("elapsed: %f" % (end_time - start_time))
print("complete!")

运行结果:
5050.0
elapsed: 0.000000
complete!

因为计算机的CPU和内存很强大的原因,所以从1直接加到100根本不是事儿,程序运行的时间都是0!但是如果我们从1加到100000呢?

代码3:从1加到100000使用直接求和

import time

start_time = time.time()

sum = 0
for i in range(100000+1):
    sum += i
print(sum)

end_time = time.time()

print("elapsed: %f" % (end_time - start_time))
print("complete!")

运行结果:
5000050000
elapsed: 0.050983
complete!

代码4:从1加到100000使用等差数列求和公式

import time

start_time = time.time()

s=list(range(100000+1))
sum = (s[0]+s[-1])*len(s)/2
print(sum)

end_time = time.time()

print("elapsed: %f" % (end_time - start_time))
print("complete!")

运行结果:
5000050000.0
elapsed: 0.005998
complete!

比较一下两者运行的时间,代码3的0.050983秒是代码4的0.005998秒的8.5倍!

初学者可以简单认为,实现同样的结果耗费时间更短的算法就是更好的算法。

由此,我们可以得到以下两个简单结论:

1. 循环语句是相当耗时的,要尽可能避免使用循环语句

2. 要充分利用程序语言自身的函数和数据结构(例如列表、字典等)

如果觉得,从1加到100直接求和,写成range(101)是不是写错了?请复习基础教程的第6章:Python控制结构(四)循环结构——range遍历。

其实本题还有更简单的算法,如下:

import time

start_time = time.time()

m=1
n=100000

sum = (m+n)*(n-m+1)/2
print(sum)

end_time = time.time()

print("elapsed: %f" % (end_time - start_time))
print("complete!")

运行结果:
5000050000.0
elapsed: 0.000000
complete!

代码4的特点在于利用了列表这一数据结构,希望大家在编程的时候,要有意识的利用列表、字典、集合这三种结构,会大大简化程序。

本人CSDN博客专栏:https://blog.csdn.net/yty_7

发布了55 篇原创文章 · 获赞 16 · 访问量 6111

猜你喜欢

转载自blog.csdn.net/yty_7/article/details/104249198