• 程序员的数学课开篇词 数学,编程能力的营养根基


    你好,我是公瑾,欢迎来到《程序员的数学课》。一些同学可能知道,之前我在就开设了一个《数据结构与算法》课程,目的是帮助大家提升编码能力,打牢代码基础,在结课时也受到许多同学的好评,表示所讲的内容在面试和工作中都很有实用性。

    编程一类的基础能力固然重要,但这些依旧不是程序员全部的“立足之本”。个人角度而言,从我在中科院的博士研究生经历,再到后来从事机器学习、数据挖掘等算法研发工作,都是数学作为我的基础思维能力支撑我一路走来。

    程序员为什么要注重数学?

    在《数据结构与算法》<课程中,许多留言问题高频集中在:复杂度如何计算、某个代码优化是否降低了时间复杂度,或者是动态规划的状态转移方程问题,等等。这的确是在学习数据结构中遇到的困难,但剥离了外壳之后,你会发现本质上都是数学问题。

    举个例子,对于一个有序数组中查找目标值的问题,应该采用二分查找算法。而且随着数组元素越来越多,二分查找相对全局遍历而言,性能上的优势会越来越明显。从数学视角来看,这是因为当 x 很大时,lnx <

    Lark20201026-155638.png

    y=lnx 与 y=x 的函数图

    可能许多同学知道二分查找效率更高,但二分查找的代码,是需要采用递归进行实现的。很多同学为了实现方便,就会考虑采用暴力搜索的查找方式,也就是一个 for 循环搞定。但如果你知道了它背后的数学原理,并且深刻体会到 ln100=4.6 << 100,你就再也不会用 for 循环去实现有序数组的查找问题了。

    此外,数学还可以帮助你降低代码的复杂度。

    我们看一个编程问题。一个数组中,只有数字 obj 出现了一次,其他数字都出现了两次。请查找出 obj,约束为 O(n) 的时间复杂度、O(1) 的空间复杂度。

    例如在数组 a = [2,1,4,3,4,2,3] 中,则输出 1。因为 2、3、4 都出现了两次,唯独 1 只出现一次。

    这是个在无序数组中,涉及与其他元素匹配的查找问题。常规解法的复杂度应该是:O(n²) 时间复杂度、O(1) 空间复杂度,或者 O(n) 时间复杂度、O(n) 空间复杂度。显然,这并不符合题目的约束。

    要想解决这个问题,需要借助数学的异或运算。异或有这样两个性质:第一,任何数异或自己为零;第二,任何数异或零,是它自己。借助异或运算,你只需要把数组 a 中所有元素计算一下异或就可以得到 obj 了。实现起来,就是如下所示的 O(n) 时间复杂度的 for 循环,且不需要额外开辟复杂变量。

    a = [2,1,4,3,4,2,3]
    result = a[0]
    for i in range(1,len(a)):
        result = result ^ a[i]
    print result
    

    从上面的例子中你便能认识到数学的重要性,越是优雅的程序,越是能用简单的代码实现同样的需求。

    工作场景之外,在求职面试中,大量的算法题也是对程序员数学能力的考察,与其直接海量刷题,不如先打好知识基础和建好思维逻辑,再有方法论地刷题,才能未雨绸缪、有备无患。

    程序员学数学有哪些痛?

    下定决心开始学习数学之后,绝大多数的程序员都会面临下面几个问题。

    第一,数学的海洋过于广阔,不知道学什么。

    从数学的知识体系看,它至少包括了微积分、线性代数、几何、概率论、数理统计等内容。而对于程序员,只需要精通那些对代码开发有指导性帮助的数学知识就足够了。那么哪些数学是必要的呢?又如何区分必备的数学知识的边界呢?这对于许多程序员来说是模糊的。

    第二,各种数学理论,如何联系到工作实践中?

    结合前面“降低代码复杂度”的例子,你会发现自己很难想到利用“异或”去查找前面数组中的 obj。先从编程思想来看:时间复杂度是 O(n),这就意味着可以使用一个 for 循环;空间复杂度是 O(1),这就意味着处理过程只能做一些基本运算。

    接着围绕题目来看,除了 obj 以外的元素都出现两次。突发奇想一下,如果可以有一个类似于“连连看”的计算,能把相同元素清掉,最终不就只保留了 obj 吗?“相同元素”清掉,这就是异或运算口诀中的“同零异一”,这就与异或的数学运算构建了联系。因此,学习数学时,死读书是没用的,必须落地到实践,做到知行合一。

    第三,数学本身很难,工作又很忙,不知道怎么学?

    不得不说,数学并不简单。学好数学,必要的时间、脑力投入肯定少不了。然而程序员节奏紧张,工作压力大,这就要求程序员在学习数学的时候,必须掌握学习方法,提高学习效率。这也是我们本课程要解决的问题。

    我将怎么带你学数学?

    如果你是数学专业者,需要追求大而全,但如果是程序员用得上的数学,大而全便会失去意义。工作若干年后的你会发现,很多数学知识学得慢、忘得快,而且工作中还用不到。所以,你应该放弃学生时代学习数学的思路,这里我很建议你遵循以下学习理念。

    首先,聚焦自己的工作领域,明确哪些是你必备的。例如,位运算、数学归纳法、最优化算法等。对这些知识的精通,可以奠定你知识体系的基础。此外,所有的学习都要落地在实践。你需要不断复习巩固知识、加深对知识点的理解深度,达到灵活运用的状态。在实际工作中,利用数学思想去解决问题。

    因此,这门专栏会非常聚焦“程序员场景”。我会根据我多年的从业经历,提炼出程序员必须具备的数学知识,专栏主要分为以下四个模块:

    • 模块一,无处不在的数学思维。 带你在数制中体验编程,用逻辑工具提升沟通能力,并通过数学思维进行业务决策,再从数学角度出发,重新审视万物背后的数学原理,让你对数学思维有全新认知。

    • 模块二,编程基础,代数与统计。 数学作为编程基础,我从“线性代数”“概率论与统计”等基础内容中,精挑细选出程序员必备的数学知识,并结合大量案例讲解,以全新视角带你认识“理论数学”在实际工作中的应用。而这些内容也是之后实战、应用部分的理论基础,便于你之后的学习。

    • 模块三,数学实战,算法与数据结构。 算法和数据结构中存在大量的数学问题,脱离数学去孤立地看它们,一定是事倍功半的。在这个模块,我会与你一起复习基础算法,并从数学的角度向你诠释基础算法背后的规律。同时对每个知识点,我还会给出实战场景,加强你的理解深度。

    • 模块四,数学应用,AI 与机器学习。 AI 是近年来很火的技术方向,其实,把 AI 和机器学习技术的外壳剥开,它就是一个最优化的问题,也就是个数学问题。在这个模块,我会围绕 AI 的几个常用技术点,从数学的角度抽象出它的技术核心。即使你对 AI 还不是很熟悉,也可以从数学的角度,把握住 AI 建模的主要脉络。

    最后彩蛋部分,我将与你分享工作与生活中的数学智慧,带你在数学方法论的指导下击破算法题,告别盲刷;并在决策的十字路口,教你用数学为自己补充智慧锦囊。

    以上这几个模块虽然仅是数学的冰山一角,但已经足够程序员的工作所需。希望学会这些知识后,你能在意识方面建立起必备的数学敏感度,并具备对业务问题分析拆解的数学逻辑,以及掌握实际开发中利用数学原理优化代码结构的能力。

    讲师寄语

    最后我想告诉你的是,数学如同“阅读”一样,我们无法说清我们现在的思维、能力、见识是由哪本书带来的,就像我们不知道是曾经的哪口食物,把我们从婴孩变成了健康活力的大人。

    所以说,数学虽然无法立竿见影,但却能潜移默化地影响我们的思维、行动、工作,为我们提供思维的“营养根基”。魏征的《谏太宗十思疏》有云:求木之长者,必固其根本;欲流之远者,必浚其泉源。同样,我们在成长路上,不仅需要学完即用的“技能”,更需要静下心来修炼“基本功”,最后希望数学能够伴随你在成长路上越走越远。


    精选评论

    Rayom:

    代码写的越久,了解的知识越多,越觉得数学重要性,还有英语能力,大学的债,早晚得还😖

    **叶:

    从《数据结构与算法》来的小伙伴,举手

    **阳:

    编程要求更多的是算法和逻辑思维能力,数学好的人这两样肯定不差吧?就像跳水需要协调力和肌肉控制力,没有好的身体机能素质,说啥都白搭吧

    *盼:

    看了开篇词觉得讲的很好,感觉老师对事情有很深的见解,也有厚实的文化底蕴,并非空中楼阁~😛

    **贵:

    讲师寄语讲得很有深度,挺好的

    **振:

    很久没有看数学了,忽然有些怀念

    **义:

    大学欠的数学,迟早要还

    。:.゚ヽ(。◕‿◕。)ノ゚.:

    研究方向跟算法相关性很大,数学对我来说很重要

    kingsburial:

    写代码越久就越发现数学的重要性以及不可分割性

    **7982:

    我觉得异或的例子解释的不太到位,应该强调一下异或的结合律(a ^ b) ^ b == a ^ ( b ^ b) == a ^ 0 == a这就使得循环下来,偶数个数的数字都被消除,只留下了只出现一次的数字

        讲师回复:

        嗯,异或运算是满足交换律和结合律的。所以,偶数个数字都会被消除。

    **_web前端:

    老师很棒,再多出几门课啊😀

        讲师回复:

        好啊好啊,敬请期待吧

    **慈:

    数学思维真的太重要了,就是吃了这块的亏,导致现在高不成低不就的😑

    *盼:

    知行合一

    **辉:

    顺便查了下异或,发现还能这样,但是还是没太清楚运算原理,看来得补补二进制转十进制了?int[] array = {2,1,3,2,3,4,4};int v = 0;for (int i=0;i" data-darkreader-inline-color=“”>length;i++){ v^=array[i];}

        讲师回复:

        我们这里讲到了二进制和十进制的转换方法。异或运算会帮我们处理不用自己单独写。

    **强:

    两个不同的数字异或呢?比如1和2?

        讲师回复:

        异或是二进制的位运算,对于十进制数字则需要先转换为二进制,再按位来计算。例如,1的二进制是01,2的二进制是10。两个bit位分别进行异或,则结果是11,也就是3。

    **个咪的汪:

    我的意思是,按照文中的题目–‘例如在数组 a = [2,1,4,3,4,2,3] 中,则输出 1。因为 2、3、4 都出现了两次,唯独 1 只出现一次’,代码的输出应该是1,而result=a[0]的话,输出就是3,所以应该是result = 0

        讲师回复:

        同学,你的for循环可能是从0开始的,那样给result=0也可以,而我是直接给了result=a[0]for循环从1开始的。这种都是代码细节了,肯定是代码哪块写错了,得靠自己来检查。如果有问题可以继续问我啊~

    **个咪的汪:

    亲测原文中代码的执行结果是3,应该是这样a = [2,1,4,3,4,2,3]
    result = 0
    for i in range(1,len(a)):
    result = result ^ a[i]
    print result

        讲师回复:

        同学,我们的计算是 result = a[0],而你算的是 result=0,所以结果不同

    **强:

    异或那里没有听懂,哪位大神指导下~🙌

        讲师回复:

        这里背后有几个逻辑:1、异或运算满足交换律和结合律。2、两个数字相同,则异或结果为0。3、0异或任何数字,还是它自己。因此,利用这3个性质,把所有数字用异或运算连在一起,出现两次的数字会像对对碰一样被“清”为零,出现一次的数字与0做异或,还是它自己。就输出了这个obj

    **翔:

    异或确实很神奇,但这个问题有实际应用场景吗?毕竟只存在唯一一个数据时可以使用这个方法,如果是多个数字只出现一个次怎么办呢

        讲师回复:

        异或还有很多的应用,例如交换两个变量的值。如果是多个,不妨用map临时保存一下。

    awang:

    充电充电😀

    smile:

    卑微舔狗,在线祈求。数学在爱我一次吧!🙏🙏

    **5075:

    如果是2,2,2,1老师的例子就有问题了

        讲师回复:

        题目条件是,只有一个数字出现一次,其他出现两次。这个例子不满足条件

    **文:

    搞搞😀

  • 相关阅读:
    HAL库与Cubemx\rt-thread Nano系列教程-01-新建HAL工程及移植RT-Nano到Alios Developer Kit
    通过浏览器,将webp格式图片转jpg格式
    JVM学习——6——JVM常用命令
    03UE4 C++ 入门【世界坐标系与局部坐标系】
    MySQL教程,学MySQL这一篇就够了,全文累计 50000 字
    密码学系列之:使用openssl检测网站是否支持ocsp
    SpringBoot整合Docker实现一次构建到处运行
    矩阵分析与应用
    HTTP基础知识
    这些4K手机、电脑壁纸网站,你一定要知道
  • 原文地址:https://blog.csdn.net/fegus/article/details/127116870