漫游算法 01

来源:互联网 发布:莽荒纪披风进阶数据 编辑:程序博客网 时间:2024/05/17 22:46

前言

我是一名初中oier。在开始写这第一篇文章之前,我其实已经反复考虑很久了。起初我不敢冒然写。一是由于我的编程水平不是特别精湛,没有积累足够的经验;二是我的语文比较弱,写出的文章可能并不精彩,甚至难以理解。
但是我最终决定开始博客生涯,因为我相信写文章是每个oier都不得不经历的。写文章不仅仅可以帮助其他人,还能提高自身的编程以及语文水平。希望我能通过写文章,分享自己现有的经验,同时通过他人的评价得到一些新的感悟。


引入

想要漫游算法,首先,要对算法有正确的认识。
算法,你绝对不会陌生,本质上它就是解决问题所用的方法。同一个问题,自然会有多种不同的算法。那么,我们先从一个经典的算式引入算法的概念,同时将算法推广到编程。
经典的算式
小学低年级的你我,碰到这题,第一反应也许是惊诧,若硬是要算出答案,只好在草稿纸上手动一个一个加起来,结果半天时间,竖式列满了整页草稿纸,终于计算出了正确的答案。
到了高年级,才发现当时自己的方法是如此死板!根据加法交换和结合律,可以合并 1 和 100 为一个 101,2 和 99 刚好也可以合并成一个 101,3 和 98,4 和 97,以此类推……最终推算出相邻的 50 和 51 可以合并成最后一个 101,1 到 50 有 50 个整数,也就是合并了 50 个 101,50 乘 101 等于 5050,所以原算式的答案就是 5050,问题完美解决……
想当年数学王子高斯,发现了这种方法,方才受到重视。由此可见,算法作为解决问题的方法,是百变莫测、满具魅力的。


算法性质

若我们将上面经典的算式交给一位幼儿园的小盆友计算,他认识数字却不会任何加法,于是始终得不到答案,这也属于一种算法吗?
不,算法拥有一条很重要的性质。任何算法允许没有指定的前提,但必须要有肯定而正确的结果。不论多么绞尽脑汁,没有正确的答案,这解题方法就不属于正确的算法。
当然,有时候我们将问题复杂化,得到正确但费时的算法。例如,还是那个算式,我们使用以下的算法:找遍整个式子,统计式子里有多少个 1,很显然只有 1 个,所以心中的答案加上 1;继续找遍整个式子,统计式子里有多少个 2,仍然只有 1 个,所以心中的答案再加上 2……直到被统计的数到 100 为止。上面的算法,可以得到正确答案 5050,但比直接一个一个加起来这种算法还要慢。
因此,即使同一个问题有多种算法,但每种算法毕竟存在自身的优劣性,需要我们的探寻与选择。

复杂度

现在我们将算法的概念推广到编程中。这时,我们引入“复杂度”来评价算法的优劣。编程中,它一般分为“时间复杂度”“空间复杂度”。要知道,即使是计算机,运算速度极快,也有自己的限度。时间复杂度特别大的算法,代入程序运行也需要一段时间。同时,空间复杂度也不能过大,计算机的存储空间大但依然是有限的。解一道题,使用的算法,时间复杂度和空间复杂度都尽量要保持在一个限度内。
复杂度使用 Θ(...) 来表示,通常简写为 O(...)。括号内一般填写代数式,若代数式内有变量,则复杂度会随着变量的变化而变化,此时常数项通常省略。例如 O(m2+n log n),其中 log 一般表示底数为 2 的对数运算。有时,复杂度仅会保留一个次数最高的项。若没有变量,整个复杂度都仅仅是常数,一般表示为 O(1)
下面,我们再使用一个式子作为例子。
经典的变式
如果我们要设计一个程序,实现:输入正整数 n(可能很大),输出该算式的结果。
最容易想到的算法,即使用单层循环从 1 到 n 统计入一个总和变量。考虑到使用了一个循环,如果 n 很大,循环次数也会跟着很大。因此时间复杂度不难看出是 O(n)。至于空间复杂度,整个过程都无需使用数组,仅需要少量的变量即可完成,所以空间复杂度为常数复杂度,即 O(1)
更加优秀的算法,即高斯的思想,只需要分析后码上一些式子就同样能求出正解,连循环都不需要,时空复杂度皆为 O(1)
更加费时的算法,上面也讲到过了。枚举要找的数,再找遍整个式子,统计,加入答案。枚举就要一层循环,找遍整个式子更不用说了。时间复杂度是 O(n2),空间复杂度看情况而定。
如果 n=100,似乎三个算法复杂度的差异并不大,跑得都比较快。然而当 n=109 呢?此时差距将异常明显,算法的优劣性也得以展现。解决一道编程问题,我们应该学会估算时空复杂度。


结言

人是活的,算法也是活的。算法的路永远也走不完,所以在学习算法的同时,我们也应探寻更加优秀的算法。

原创粉丝点击