前言

我经常听到教计算机的老师说:“想要学好计算机,冲高薪,你英语可以不好,但 数学一定要好,因为玩计算机玩到最后玩的就是数学。”这时候恐怕有人会说:我从小就不喜欢数学,大学高数课都是睡过来的。确实,课堂上数学的各种符号和表达式让人望而生畏。但学习算数也可以很有趣,就像玩一个有趣的游戏一样。慢慢的你就会爱上算法,喜欢琢磨一个问题的多种解决方案,因此找到最快最简便的解决方法。

首先,什么是算法呢?算法是一系列解决任务的指令。任何一段代码都可以称为算法,但本文只展现算法的魅力,而不是大量的代码,那样也太乏味了。我们先从最简单的二分查找开始。

何为二分查找?

假设你要曾经看过的书中查找一段内容,你已不记得大概位置了,只能根据看到的内容来推测,这个时候人们往往会从中间翻开书,然后根据翻到的内容往前或往后翻找。 又假设你要你登录一个网站,当你输完账号和密码点击登陆时,网站必须核实你的账号是否存在,因此去先去数据库里查找你的账号。可能它会从数据库的第一个账号开始往后一个个查找,但好的做法是从中间开始查找。 这是关于查找问题,而在上面提到的情境中都可使用二分查找算法来解决问题。

一个小游戏 假设我们来玩一个猜数字的游戏。你在纸上写一个数字,范围在1~100,然后找一个人来猜这个数字是多少。如果对方没有猜中,你就告诉他,他猜的数字是大了还是小了,然后让对方继续猜,直到猜中这个数字为止。 问题是怎么猜才能用最少的次数来猜到这个数字呢?假设从1开始猜,而你写的数字是100。对方先猜1,你说小了,对方继续猜2,你还是告诉对方小了,对方又猜3……,直到你说99次小了,对方终于猜到了这个数字,但整整猜了100次,这实在是一种很槽糕的算法。 那如何更快的猜到数字呢?这次对方学聪明了,他不从头开始猜,而是从中间开始猜。比如这次你还是写了100,而对方猜的第一个数字是50,你说小了。对方又猜75,还是小了。对方又猜88(75和100之间的数字)……,当对方第七次猜的时候就能猜中这个数字。实际上无论你写的数字是多少,对方总能在7次之内猜中这个数字,因为对方每次猜都能排除待选项中一半的数字。

示例代码

# 一个关于二次查找的示例,给一个列表和数字,输出这个数
# 字在列表中的序号(从1开始)和猜测的次数。
def binary_search(list, item):
    low = 0  # 计算机中的的数字从0开始
    high = len(list)  # 列表的长度是可被猜测的最大序号
    times = 1  # 猜测的次数

    # 只要范围没有缩小到只有一个元素,就检查中间的元素
    while low <= high:
        # 将第一个数加上最后一个数除以二得出中间值,并取整。
        mid = int((low + high)/2)
        guess = list[mid - 1]
        # 如果猜测的数字等于给定的数字,则打印猜测的次数,并返回中间值
        if guess == item:
            print(times)
            return mid
        # 如果猜测的数字大于给定的数字则在中间值和最小值之间继续寻找。
        if guess > item:
            high = mid - 1
            times = times + 1
        # 如果猜测的数字大于给定的数字则在中间值和最大值之间继续寻找。
        else:
            low = mid + 1
            times = times + 1
    # 如果没有这个数就返回None
    return None

测试一下

# 创建一个列表和待猜测的数字传递给函数。
my_list = range(1, 101)
print(binary_search(my_list, 75))

在这里插入图片描述 显示一共猜测了2次,这个数字是列表的第75个数字。

可以看出二分查找拥有比简单查找更快的运行时间,虽然简单查找比二分查找的代码更简单不容易出bug,但所用的时间在大型项目中会造成很大的影响(比如有上千万个数据时)。一个好的算法的判别条件有很多,比如时间代价,空间代价。但一定要有有穷性,确切性,可行性,和至少一个输出。

一个笑话

可能有人就想二分查找就这么简单吗?大佬曾经说过:思路很简单,细节是魔鬼。这里讲一个笑话:

一天,小陈从图书馆出来,通过安检门的时候警报响了,保安就让他把书包里的N本书拿出来过一下,小陈刚准备一本本过的时候,保安露出鄙夷的目光说道:你难道不懂二分查找吗?于是让小陈把所有的书分成两份后拿出一份过安检,然后警报响了。然后在把那一份在分成两份……。经过logN次后,保安找到了那本引起警报的书,露出得意和嘲讽的笑容。然后小陈拿着剩下的书走了。

从此,图书馆丢了N-1本书。

因此可见先要写一个算法,需要考虑很多细节,并且要有很好的数学底子。在这里推荐两本书,一本是普林斯顿微积分读本 这本书对于,数学底子不好的人非常友善,从简到难,循序渐进的进行教学,拥有大量通俗易懂说明让你对基本的公式和原理有更好的理解。比起学校里的数学书更加让人有兴趣阅读。

另一本叫做算法图解在这里插入图片描述 这是一本非常有趣的算法书,能让你像看漫画一样愉快的学习算法,其中的例子也鲜明有趣,其中还使用编程语言python的代码作示例。可以让你学习算法的同时,学习到一门当下最火的编程语言。