跳转至

程序员面试必备的数学基础

覆盖:初中/高中数学核心知识点,与算法和数据分析直接相关 适用:快速复习数学基础,为算法面试和数据工程打底 方法:5W1H(为什么学、学什么、何时用、在哪用、谁在用、怎么用)


一、为什么程序员需要数学基础?

Why - 为什么要学?

1. 算法背后的数学原理
   - 时间复杂度分析 → 对数、指数、级数
   - 空间复杂度 → 组合数学、排列
   - 概率算法 → 概率论基础

2. 面试必考
   - 动态规划 → 递推关系、最优化
   - 概率题 → 期望、条件概率
   - 复杂度推导 → 级数求和

3. 职业发展
   - 数据工程师 → 统计分析
   - 机器学习 → 线性代数、微积分
   - 密码学 → 数论、模运算

What - 学什么?

初中核心:
- 代数:方程、因式分解
- 函数:一次/二次函数
- 几何:三角形、圆
- 统计:平均数、方差、基础概率

高中核心:
- 函数与导数:指数/对数、导数应用
- 数列:等差/等比、级数求和
- 排列组合:P(n,m)、C(n,m)
- 概率:随机变量、分布、贝叶斯
- 向量与矩阵:点积、矩阵乘法

When - 何时用?

刷 LeetCode 时:
- 看到 O(log n) → 想到对数函数
- 看到排列组合题 → 想到 C(n,m)
- 看到概率题 → 想到期望和条件概率

分析算法复杂度时:
- 双层循环 → Σ i = O(n²)
- 二分查找 → log n
- 分治算法 → T(n) = 2T(n/2) + O(n) = O(n log n)

Where - 在哪用?

算法场景:
- 二分查找 → 对数函数单调性
- 动态规划 → 递推关系、最优化
- 回溯算法 → 排列组合
- 贪心算法 → 不等式、极值
- 概率算法 → 期望计算

数据工程:
- A/B 测试 → 假设检验、置信区间
- 数据质量 → 方差、标准差
- 采样算法 → 概率分布

Who - 谁在用?

岗位需求:
- 算法工程师 → 全量数学知识
- 数据工程师 → 统计、概率、线性代数
- 后端开发 → 复杂度分析、基础概率
- 机器学习 → 微积分、线性代数、概率论

面试官期望:
- 能推导复杂度公式
- 能解释为什么选择某个算法
- 能做概率分析

How - 怎么用?

学习方法:
1. 理解公式来源(为什么这样设计)
2. 配合代码实现(用 Java/Python 写出来)
3. 找 LeetCode 题目练习(至少 3 题)
4. 面试时能解释(能说清楚推导过程)

复习节奏:
- 每天 1-2 个知识点
- 每个知识点配套 2-3 道题目
- 周末复习本周内容

人类为什么需要数学?(比「面试」更深一层)

下面回答「数学是不是西方发明的奢侈品」——不是。数学是人在数不过来、量不准、预测不了时,被迫造出的共享语言

1. 现实逼出来的,不是象牙塔里的爱好

人的处境 没有数学会怎样 数学在干什么
分粮食、分地、征税 吵翻、不公平 比例
盖房、丈量、治水 塌了、淹了 几何方程
历法、航海、天文 误期、触礁 三角周期
利滚利、人口、疫情 算错就破产或误判 指数概率
数据太多、脑子太小 记不住 符号把经验压成可重复的规则

所以:数学 = 用极少的规则,描述极大的世界,并在多人之间对齐「算得一样」
程序员里的 O(log n)、对数表、复利公式,和四千年前分田、六百年前对数表,是同一种刚需脑子和纸笔算不动,就要找捷径

2. 和「聪明」无关,和「可协作」有关

  • 一个人可以凭直觉估一估;十万人交税、修长城、跑网络集群,必须有一套谁按同样步骤都得到同样结果的术。
  • 证明、公理、符号,后来是为了减少歧义教下一代;早期很多文明用口诀、例题、算筹步骤达到同样目的——形式不同,刚需相同

3. 和程序员的关系(收束到本文档)

现实世界有约束(时间、内存、钱、人数)
    → 要比较「哪种做法更省」
    → 要预测「数据变大后会怎样」
    → 这就是复杂度、概率、建模
    → 背后都是数学,只是你用的是 Java 而不是算筹

一句话:人类需要数学,是因为世界可度量、可重复、可协作;数学是压缩现实 + 对齐彼此的工具,不是某国独有的装饰。


中国(东方)有没有数学?——先纠正一个常见误解

结论:有,而且很早、很深。
容易产生的错觉是:「课本里的定理都是希腊/欧洲名字 → 中国没数学」。那是近代课本叙事表达方式造成的,不是历史事实。

为什么你会觉得「东方没有数学」?

原因 说明
课本叙事 20 世纪以来中小学、大学教材大量引进欧几里得式「定义—定理—证明」体系;中国古代文献多是应用题 + 算法步骤(术),很少用现代符号写成「定理 3.2」,看起来像没理论
符号与术语 我们今天说的「几何」「代数」「函数」,多是译词;中国古代分的是算术、测圆、方程、勾股等,门类不同,不等于不存在
高峰错开 中国古典数学在宋元达到很高水平;明清以后相对停滞;同时欧洲微积分、解析几何爆发——对比之下像「只有西方在前进」。
传播与话语权 科学史长期以欧洲为中心书写;中国成果写入全球教科书较晚(如大衍求一术杨辉三角)。

中国数学史上值得记住的(和本文档相关)

时代 / 人物 贡献(白话) 和算法/工程的联系
《九章算术》(约成书于汉,更早材料更早) 分数、比例、面积体积、勾股联立一次方程组(《方程》章) 线性方程组、应用建模;消元思想早于西方同类系统叙述数百年
刘徽(3 世纪) 割圆术算 π;立体体积 极限直觉、数值逼近 → 今天仍用「割圆/迭代」思想
祖冲之(5 世纪) π 约 3.1415926~7,密率 355/113 高精度近似、分数表示
算筹、算盘 位值制运算工具 和计算机「按位运算」一样,是执行算法的硬件
杨辉三角(约 11 世纪,可更早) 二项式系数表 组合数 C(n,k)、帕斯卡三角同一对象
秦九韶(13 世纪)《数书九章》 大衍求一术 中国剩余定理——密码、哈希、同余、分布式里仍常见
宋元(李冶、朱世杰等) 天元术(设元列方程)、高次方程数值解 代数化、方程思维,接近「设未知数」的现代写法

和西方对比时,记住差异而不是「有无」

欧洲(尤其希腊传统)偏:从少数公理推出定理,几何证明写在书上
中国古典偏:解决具体问题,给出可执行的「术」,在例题里传承
印度—阿拉伯:位值制、代数符号、三角函数表等经翻译传入欧洲

三条线都在算同一片天空、同一块地不是东方没有数学,而是长期用另一套文体记录,且近代课堂主要教的是欧洲那套写法

「东方」更广一点

  • 印度:十进制位值、0 作为数、早期代数与三角;经阿拉伯传入欧洲,改变世界算术。
  • 伊斯兰黄金时代(8–13 世纪):保存并发展希腊、印度、波斯数学;花拉子米的《代数学》等(见上文 §3.1 基础函数从何而来)。
  • 日本、朝鲜、越南等:曾大量吸收中国算学,并有本土发展(如日本和算)。

和「程序员学数学」的关系

  • 你学的 模运算、CRT、组合、方程组、二分/对数,在中国古典里都有 cousin(同族思想),只是符号不同。
  • 自卑或对立都不必要:现代数学语言是全世界的汇合——包括中国宋元、印度数字、阿拉伯代数、欧洲分析。

一句话
人类需要数学,因为要把复杂世界变可算、可教、可协作;
中国不仅有数学,而且曾独立解决过方程、数论、组合、数值计算等高难度问题——只是写在《九章》式的「题+术」里,不等于没出现过。


为什么明清后中国数学「相对停滞」?

先说清「停滞」指什么:不是明清没人算数,而是没有跟上 17 世纪以后欧洲那条「解析几何 → 微积分 → 近代科学」的爆发链,和宋元高峰比增量变慢;同时欧洲在指数级拉开差距。下面用多因素解释,避免「中国人不行」或「只差科举」这种单点归因。
不宜把明清混为一谈:明末有 西学东渐窗口;清初中期仍有 会通派乾隆朝《四库全书》+ 明史定稿 才是「考据盛世、精英编书、禁毁并行」的集中体现——见下文 §明清要不要分开看

1. 先纠正:明清不是「零数学」

人物 / 事件 说明
徐光启、李之藻 等 + 利玛窦 明末译 《几何原本》 前六卷,把欧氏证明体系引进中国
薛凤祚、方中通 清初吸收对数、三角、西洋算法,做 会通(中西算法对照)
梅文鼎(清初) 历算、几何、代数兼通,著书极多,是清代数学代表人物之一
程大位《算法统宗》(明) 珠算普及教材,影响民间和商业计算
戴震、阮元 乾嘉考据中整理古算(如《畴人传》),抢救文献而非开创微积分

所以更准确的说法是:传统算学仍在,但未能自主完成「从术到近代数学语言」的第二次革命;西洋微积分体系进来得晚、进课堂更晚


2. 制度与激励:算学不在「上升通道」中心

宋元时商业、历法、水利仍催生高次方程、天元术等新问题

明清科举主流路径是 四书五经 + 八股,算学:

  • 不进入进士考试的核心科目;
  • 实用算学多服务于 钦天监历算、田赋丈量、工程估料 —— 往往是技术吏员、家学、私塾传承,而不是全国精英竞相创新的公共赛场。

结果:最聪明的一批人大量时间在 经义、考据、诗文;算学高手有,但社会声望与资源难与欧洲近代「大学 + 学会 + 出版」里的数学家相比。

欧洲(简化):商人/航海/炮术/天文 → 需要预测 → 资助数学与出版
明清(简化):帝国治理稳定后 → 算学常是「够用术」+ 宫廷历算

3. 知识形态:「术」很强,但缺一条通往微积分的桥

中国古典数学极擅:

  • 具体问题的算法(方程消元、大衍求一、数值开方);
  • 有限步骤、可手算 的术。

欧洲在 16–17 世纪形成的关键跳跃是:

  • 符号代数 统一几何(笛卡尔);
  • 无穷小、极限、动力学 统一运动与曲线(牛顿、莱布niz);
  • 公理—证明 书写习惯与代数符号结合,便于教下一代继续叠高

中国宋元天元术已很接近「设元列式」,但:

  • 少写 「为何永远成立」 的普适证明,多写 「这道题怎么算」
  • 当欧洲整门学科转向 函数、连续、微分 时,中国一侧缺少同级别的内部语言升级,对接西洋书时就要 整本翻译、整体系改教材 —— 慢一代人。

这不是「笨」,是 问题包装 + 书写传统 不同,在近代转折点上的 转换成本 极高。


4. 需求结构:少了一类「逼出微积分」的连环压力

欧洲同期(重叠讲,便于记忆):

压力 逼出的数学
航海定位、天文 三角、对数、误差
炮弹弹道、力学 微分方程雏形
光学、真空泵 实验 + 量化
商业利息、人口模型 指数、级数

明清帝国:

  • 农业—官僚治理 仍强,丈量、赋税、历法仍要算,但许多问题 在算筹/珠算 + 已有公式内可解
  • 没有同等规模的商业—军事—工业复合体,持续砸钱要 「预测运动、预测轨道」 的国家级竞赛(直到 19 世纪中叶鸦片战争后才痛感「算不如人」)。

数学发展常被 「什么痛苦最花钱、最要命」 驱动;明清上层社会的 最致命焦虑 往往不在「证明行星轨道」,而在 边疆、漕运、纲常、考试 —— 算学优先级随之靠后。


5. 交流与出版:欧洲在「联网」,中国在「精注旧书」

欧洲:印刷术普及 → 公式与证明可 cheap copy → 数学家跨城通信(如牛顿—莱布尼茨网络)→ 知识复利 快。

明清

  • 印刷也有(如《算法统宗》流传),但精英学术风尚在 考据、辑佚、注疏(乾嘉为盛)—— 对 古籍算书 极有价值,对 发明新符号体系 激励弱;
  • 海禁与政策时紧时松,西洋新知识 主要靠耶稣士来华、少数士大夫译书未变成全国中学的默认大纲(要到 洋务、戊戌、民国教育改革 才系统换轨)。

6. 时间线:不是「突然不行」,而是「别人换赛道了」

中国:汉—唐—宋—元  持续累加「术」的高峰
欧洲:中世纪保存希腊—阿拉伯—文艺复兴—17C 微积分  赛道切换

明清中国:在原有赛道上仍有人(梅文鼎、会通派),但全球前沿已搬到
         「微积分 + 力学 + 实验科学」
→ 对比起来像「停滞」,实为「相对滞后」+「范式没跟上」

19 世纪后:林则徐、魏源「师夷长技」、洋务派办新式学堂、留学生、民国数学系 —— 几十年强力补课,说明滞后主要来自 制度与知识体系切换,不是民族智力。


7. 对照案例:日本明治 —— 说明「能追,但要换轨」

日本在明治初 系统引进西方数学教材、建大学、送留学生,几十年内追上;中国也在 20 世纪 出现华罗庚、陈景润等世界级成果。

启示:明清的相对停滞,是历史结构(激励 + 范式 + 传播)问题,不是「东方没有数学天赋」 —— 和上一节「中国有深厚算学」不矛盾。


8. 收束(给程序员读历史用)

误区 更稳的说法
明清中国人不会数学 会,且有人做中西会通,但前沿范式换了
只差一个科举 科举是激励结构之一,还有需求、符号、出版、科学共同体
中国从未参与现代数学 20 世纪起全面接入;今天用的是全球同一套符号

一句话
宋元把「术」推到极高;明清精英的上升通道与帝国需求 不再逼出微积分那条链;欧洲因航海、力学、出版与公理代数 换赛道爆发;西洋数学 晚进课堂,叠加考据盛世 精研古书胜于发明新符号 —— 于是相对停滞。要追,靠的是 翻译、教育、工业与战争带来的痛感 —— 近代中国走的正是这条路。


9. 明清要不要分开看?明史、四库与数学

短答不应混为一谈。 讲数学史时至少拆成 明末(开放接触)清初(会通吸收)乾隆及以后(大型文献工程 + 思想控制) 三段;《明史》修纂《四库全书》 主要属 清代国家工程,对数学是 间接影响(占用人、定正统、毁部分书),不是「专门为消灭数学」。

9.1 为什么不宜把「明清」合成一个词?
阶段 大致时间 和数学的关系(概括)
明前期—中期 14–16 世纪初 承元明初,实用算学、历算延续;程大位《算法统宗》(1593)普及珠算
明末 16 世纪末–1644 西学东渐高峰:利玛窦、徐光启译 《几何原本》(1607)等——是 主动引进 欧氏体系,不是封闭
清初 17 世纪 会通派(薛凤祚、梅文鼎等)吸收对数、三角;康熙 本人向耶稣士学天文数学
清中叶(乾隆) 18 世纪 《四库全书》《明史》定稿;考据极盛;西洋新知识 引进节奏变慢(直到鸦片战争痛感)
粗线条:
  明末  ≈ 「开窗」—— 几何原本进来
  清初  ≈ 「会通」—— 梅文鼎一代
  乾隆  ≈ 「编书 + 筛书」—— 四库、明史;精英时间被文献工程占满

若把 明末的开放乾隆的编修+禁毁 都塞进「明清停滞」,会 冤枉明代晚期,也 看不清清代政策变化


9.2 《明史》修纂:是什么?和数学什么关系?
项目 内容
性质 清朝官修的 前朝正史(二十四史之一),论证清承明统、确立 官方历史叙事
时间 康熙年间起步(如万斯同私修《明史稿》),雍正朝设馆,乾隆初定稿(1739)
人力 张廷玉等总纂,大量翰林、考据学者 数十年 投入
和数学 不直接删算书;影响在于 占用同一批最顶尖的书生,强化 史学、义例、文献真伪 能力,而非 发明新数学

间接影响(要记这种「结构」)

  • 国家把学术荣誉导向 「修史正确」 → 和算学 抢人、抢时间
  • 四库、乾嘉考据 同一套 文化治理逻辑:正本清源、定于一尊;
  • 数学内容 几乎无「专门打压」,但对 「谁算前沿」机会成本

9.3 《四库全书》:编了什么?对算学利弊

是什么(1773–1782,乾隆朝):

  • 征集全国图书,经学、史、子、集 四部 分类钞录;
  • 子部 下有 算学 类(如《周髀》《九章算术》及刘徽等注、历代畴人著作)—— 大量古算书因编修而精校保存
  • 戴震等参与 辑校、辨伪、补阙,对古籍数学文本的 准确性 贡献很大。

正面(数学史角度)

没有四库,许多宋元明算学版本可能更散、更难读
→ 今天研究《九章》、天元术,仍依赖这一代的辑校成果
→ 这是「保存 + 校勘」,不是「创造微积分」

负面(为何仍说拖慢「前沿」)

机制 说明
人力虹吸 一流学者 十年级 投入编书、写提要、辨真伪 → 少人做会通后的新理论
禁毁书 同时开 《禁毁书目》,毁禁数千种;虽 不以算书为主靶子,但 异端、反清、「僭越」 类著作遭殃;整体氛围 抑制自由探讨
定正统 什么是「可入国库的学问」由朝廷框定 → 强化 注疏古人 而非 挑战公理体系
与欧洲不同步 编四库时欧洲已在 欧拉时代;中国精英在 精刻宋本赛道差距继续拉大

关键区分

  • 四库对算学:抢救古籍 ≠ 推动近代化
  • 不是「四库禁止数学」,而是 国家工程的方向 把聪明人的 边际时间 押在 文献安全与正统 上。

9.4 明史 + 四库:放在一起怎么理解?
清代文化治理(简化):

  修《明史》  →  前朝历史只能有一个官方版本
  编《四库》  →  当代知识只能有一个入库标准
  禁毁书目    →  异端与危险文本物理消失

对数学:
  古算书 largely 被收入、校勘  →  传统算学「博物馆化」做得好
  微积分、力学新范式          →  没有变成四库之后全国教材的默认下一步

和「明清混谈」的关系

  • 明史、四库主要是清中叶乾隆朝的事,不能用来解释 万历年间徐光启为什么能译《几何原本》
  • 说明 「停滞」若发生在政策层面,清 > 明,且集中在乾隆文献工程之后的社会风气,而不是整个明代都封闭。

9.5 收束表
问题 建议说法
明清能混谈吗? 不能粗混;至少分 明末开放 / 清初会通 / 乾隆编修
明史修纂打击数学吗? 无专门打击间接占用精英、强化史学正统
四库对算书? 子部算学大量保存校勘;同时 禁毁、定尊不利于自由创新
和停滞叙事? 停滞 = 范式没切换 + 激励结构;四库是 清代中后期「保存古算、拖慢前沿」的放大器,不是唯一原因

数学的乐趣在哪里?如何感知?

乐趣很少来自「又多背了一个公式」;多半来自 突然少算了很多步两件看似无关的事原来是同一件事一个猜想在脑子里长成了证明
程序员最容易感知到的,是 复杂度从爆炸变成可算 那一刻——和纳皮尔把乘法变加法同一种爽感。

乐趣的几种「味道」(不必全开,有一种就够)

味道 是什么感觉 例子(程序员向)
省力 原来要算 100 步,现在 7 步 二分 O(log n):每次减半;对数表:乘变加
统一 三个问题其实是同一道题 排雷、盛水、对账都是双指针;ln x 互逆
必然 不是凑答案,是「只能这样」 勾股定理;「排序比较下界」Ω(n log n)
构造 自己造出一个能用的东西 写出一个 DP 状态;用 CRT 拼回整数
极限/逼近 越来越准,且知道误差去哪 刘徽割圆;数值迭代;A/B 检验置信区间
游戏 规则简单,组合爆炸,仍可控 数独、概率谜题;LeetCode 当谜题而非 KPI

和「考试/面试」的关系:面试考的是 省力 + 统一(模板、复杂度);乐趣若只绑在 通过率 上,容易枯竭。把乐趣绑在「我少想了一步却做对了」,续航更长。


如何感知?——从身体到符号,四层阶梯

很多人「感觉不到乐趣」,是因为只见过 符号层,没见过下面三层。可以 刻意往下走一层

第 4 层  符号:公式、证明、代码模板     ← 课本、面试默认在这
第 3 层  结构:为什么 O(n log n)、为何互逆
第 2 层  图像/数量:画曲线、列表规模翻一倍会怎样
第 1 层  动作/故事:折纸、对账、减半查找、纳皮尔造表

感知练习(每次 5~15 分钟,任选)

  1. 数量感n=1000 时,nn log n2ⁿ 各多大?用计算器点一次,记住数量级差距——乐趣常在「原来 2ⁿ 这么恐怖,所以我要用 log」。
  2. 画一张图:指数上扬、对数平缓;或双指针在数组上走三步——眼睛比符号快
  3. 讲一个人话故事:纳皮尔为何花 20 年——「乘法太累」;你为何用二分——「猜数字每次砍一半」。
  4. 一道题只追求一种爽:今天不刷题量,只求 「我发现这和昨天那题是同一类」(统一感)。
  5. 写三行代码看运行:CRT、二分、快速幂——机器替你验证「必然」,比干看公式踏实。

感知不到的常见原因(不是你的错)

原因 对策
只见过刷题 KPI 「今日一种乐趣」 即可,见 数据结构与算法·低电量模式
符号没接上故事 读本文档 §3.1 基础函数从何而来
疲劳 乐趣在 清醒边缘 最明显;晕时只做 复习一种已懂的味道
以为乐趣 = 天赋 乐趣多是 练出模式识别;同一类题见第三次会突然「变轻」

和「人类为什么需要数学」连起来

  • 需要数学 = 现实逼你省力、协作、预测。
  • 乐趣数学 = 大脑发现 「规则压缩了世界」 时的奖赏——多巴胺常出现在 「原来可以这样想」,不是 「又背了一条」

对数据开发/计费的你:对账、聚合、窗口、采样 里都有 统一与省力;算法面试里的 双指针、哈希、二分 是同一套奖赏的 小游戏版本


今日 10 分钟「尝乐趣」(不做题版)

1. 想一件你工作中「算不动」的事(对账、去重、查区间)
2. 问:若数据排序了,能否少扫一遍?→ 二分或双指针故事
3. 在纸上画 6 个数的数组,标两个指针走 2 步
4. 停。写下一句:今天我感知到的是「省力」还是「统一」?

一句话:数学的乐趣在 压缩、统一、必然、可构造;感知方式是 先数量、再图像、再故事、最后符号——和纳皮尔、刘徽、欧拉经历的是同一种爽,只是你现在用 Java 和 O(log n) 来写。

乐趣容易诱发深挖:尝过「统一感」后想一口气读完明清史、推完所有公式——请用 数据结构与算法·克制深挖 里的 停车场 + 够用止损,把乐趣留在 周末时间盒,别占每日主线。


二、初中数学核心(5W1H 展开)

2.1 代数基础

方程与不等式

Why - 为什么要学?

面试中涉及数学推导的题目需要方程求解能力。
例如:优化问题中找到最优解、递推关系求通项。

What - 核心公式是什么?

一元二次方程:ax² + bx + c = 0
求根公式:x = (-b ± √(b² - 4ac)) / 2a

判别式:Δ = b² - 4ac
- Δ > 0:两个不等实根
- Δ = 0:两个相等实根
- Δ < 0:无实根

韦达定理:
x₁ + x₂ = -b/a
x₁ × x₂ = c/a

When - 什么时候用?

- LeetCode 中涉及数学推导
- 动态规划状态转移方程求解
- 最优化问题找极值

Where - 在哪些场景用?

算法题:
- "两数之和" → 方程思维
- "盛最多水的容器" → 最优化
- "接雨水" → 方程建模

数据工程:
- 成本优化模型
- 资源分配问题

Who - 谁会考你?

面试官常见问题:
- "这个时间复杂度是怎么推导出来的?"
- "能不能给出一个数学证明?"
- "有没有更优的解法?"

How - 怎么用?(代码示例)

// Java 实现:求解一元二次方程
public class QuadraticSolver {
    public static double[] solve(double a, double b, double c) {
        double delta = b * b - 4 * a * c;

        if (delta < 0) {
            return new double[]{};  // 无实根
        } else if (delta == 0) {
            double x = -b / (2 * a);
            return new double[]{x};  // 一个根
        } else {
            double x1 = (-b + Math.sqrt(delta)) / (2 * a);
            double x2 = (-b - Math.sqrt(delta)) / (2 * a);
            return new double[]{x1, x2};  // 两个根
        }
    }

    public static void main(String[] args) {
        double[] roots = solve(1, -3, 2);  // x² - 3x + 2 = 0
        for (double x : roots) {
            System.out.println("x = " + x);  // x = 2.0, x = 1.0
        }
    }
}


因式分解

Why - 为什么要学?

因式分解能简化计算,优化算法时间复杂度。
例如:把 O(n) 的循环变成 O(1) 的公式计算。

What - 核心公式是什么?

1. 平方差:a² - b² = (a+b)(a-b)
2. 完全平方:a² ± 2ab + b² = (a±b)²
3. 立方和/差:a³ ± b³ = (a±b)(a² ∓ ab + b²)

When - 什么时候用?

- 优化循环计算
- 减少时间复杂度
- 数学推导简化

Where - 在哪些场景用?

LeetCode 题目:
- "连续整数求和" → 用等差数列求和公式
- "完全平方数" → 因式分解判断

数据工程:
- 批量计算优化
- 聚合查询加速

Who - 谁会考你?

面试官可能问:
- "这个计算能不能优化到 O(1)?"
- "有没有数学公式可以直接用?"

How - 怎么用?(代码示例)

// 优化前:O(n) 循环求和
public int sumSlow(int n) {
    int sum = 0;
    for (int i = 1; i <= n; i++) {
        sum += i;
    }
    return sum;
}

// 优化后:O(1) 公式计算
public int sumFast(int n) {
    return n * (n + 1) / 2;  // 等差数列求和公式
}


2.2 函数基础

一次函数与二次函数

Why - 为什么要学?

函数的单调性判断是二分查找、三分查找的基础。
最优化问题需要找函数的极值点。

What - 核心公式是什么?

一次函数:y = kx + b
- 斜率 k = (y₂-y₁)/(x₂-x₁)
- 截距 b(与 y 轴交点)
- 单调性:k>0 递增,k<0 递减

二次函数:y = ax² + bx + c
- 顶点:(-b/2a, (4ac-b²)/4a)
- 对称轴:x = -b/2a
- 开口方向:a>0 向上,a<0 向下

When - 什么时候用?

- 二分查找判断单调性
- 最优化问题找极值
- 算法复杂度分析

Where - 在哪些场景用?

LeetCode 题目:
- "寻找峰值" → 函数单调性
- "最小化去加油站的最大距离" → 二分答案

数据工程:
- 成本函数优化
- 资源分配最优化

Who - 谁会考你?

面试官可能问:
- "这个函数是单调的吗?为什么?"
- "能不能用二分查找优化?"

How - 怎么用?(代码示例)

// 二分查找应用:寻找峰值
// 前提:函数在某个区间内单调
public int findPeak(int[] nums) {
    int left = 0, right = nums.length - 1;

    while (left < right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] < nums[mid + 1]) {
            left = mid + 1;  // 右侧递增,峰值在右边
        } else {
            right = mid;     // 左侧递减,峰值在左边
        }
    }
    return left;
}


2.3 几何基础

平面几何

Why - 为什么要学?

计算几何题目需要几何知识。
图形学、碰撞检测、路径规划都依赖几何。

What - 核心公式是什么?

三角形:
- 面积:S = ½ × 底 × 高
- 勾股定理:a² + b² = c²(直角三角形)
- 余弦定理:c² = a² + b² - 2ab·cosC

圆:
- 周长:C = 2πr
- 面积:S = πr²

When - 什么时候用?

- LeetCode 计算几何题
- 图形渲染
- 碰撞检测
- 路径规划

Where - 在哪些场景用?

LeetCode 题目:
- "有效的正方形" → 勾股定理
- "最大三角形面积" → 面积公式
- "圆和矩形相交" → 几何判断

游戏开发:
- 碰撞检测
- 弹道计算

Who - 谁会考你?

面试官可能问:
- "怎么判断两个矩形是否相交?"
- "怎么计算点到直线的距离?"

How - 怎么用?(代码示例)

// 判断三点是否能构成三角形(任意两边之和大于第三边)
public boolean isValidTriangle(double a, double b, double c) {
    return (a + b > c) && (a + c > b) && (b + c > a);
}

// 计算两点距离(勾股定理)
public double distance(double x1, double y1, double x2, double y2) {
    return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
}


2.4 统计与概率

基础统计

Why - 为什么要学?

数据分析、A/B 测试、质量监控都需要统计知识。
面试中经常问数据分布和异常检测。

What - 核心公式是什么?

集中趋势:
- 平均数:x̄ = Σxᵢ/n
- 中位数:排序后中间的数
- 众数:出现次数最多的数

离散程度:
- 方差:σ² = Σ(xᵢ-x̄)²/n
- 标准差:σ = √σ²
- 极差:max - min

When - 什么时候用?

- 数据分析
- A/B 测试
- 质量监控
- 异常检测

Where - 在哪些场景用?

数据工程:
- 数据质量巡检
- 指标异常告警
- 用户行为分析

机器学习:
- 特征工程
- 数据标准化

Who - 谁会考你?

面试官可能问:
- "怎么判断数据是否有异常?"
- "均值和中位数哪个更适合描述这组数据?"

How - 怎么用?(代码示例)

// 计算平均数和方差
public class Statistics {
    public static double mean(double[] nums) {
        double sum = 0;
        for (double n : nums) sum += n;
        return sum / nums.length;
    }

    public static double variance(double[] nums) {
        double m = mean(nums);
        double sum = 0;
        for (double n : nums) {
            sum += Math.pow(n - m, 2);
        }
        return sum / nums.length;
    }

    public static double stdDev(double[] nums) {
        return Math.sqrt(variance(nums));
    }
}


基础概率

Why - 为什么要学?

概率题是面试高频题型。
随机算法、蒙特卡洛方法都依赖概率知识。

What - 核心公式是什么?

概率定义:P(A) = 事件 A 发生的次数 / 总试验次数

基本公式:
1. 互斥事件:P(A∪B) = P(A) + P(B)
2. 独立事件:P(A∩B) = P(A) × P(B)
3. 条件概率:P(A|B) = P(A∩B) / P(B)
4. 全概率公式:P(B) = Σ P(B|Aᵢ)·P(Aᵢ)

When - 什么时候用?

- LeetCode 概率题
- 随机算法
- A/B 测试
- 风险评估

Where - 在哪些场景用?

LeetCode 题目:
- "硬币游戏"
- "随机数生成器"
- "概率最大路径"

数据工程:
- 用户转化漏斗
- 风险评估模型

Who - 谁会考你?

面试官经典题:
- "掷两个骰子,点数和为 7 的概率是多少?"
- "已知某事件发生了,求另一个事件的条件概率"

How - 怎么用?(代码示例)

// 计算两个事件同时发生的概率(独立事件)
public double jointProbability(double pA, double pB) {
    return pA * pB;  // P(A∩B) = P(A) × P(B)
}

// 计算条件概率
public double conditionalProbability(double pAB, double pB) {
    return pAB / pB;  // P(A|B) = P(A∩B) / P(B)
}


三、高中数学核心(5W1H 展开)

3.1 函数与导数

基础函数从何而来?(历史与人物)

重要前提:没有一位神仙某天宣布「今天发明对数」。
多数是 几百年里,很多人为解决具体痛苦(算不动、测不准、利滚利) 慢慢凑出来的工具;后来 Euler、Leibniz 等人才把符号写统一。


为啥需要「函数」这个概念?

函数 = 输入一个数,按固定规则得到另一个数:y = f(x)

时代的痛苦 需要什么
丈量土地、盖房子 长度与面积的关系
天文、航海 角度与高度、周期
贸易、利息 本金与时间的关系
炮弹、行星 变化有多快(后来的微积分)
大数乘除 把乘变成加(对数

「函数」这个词:Leibniz(莱布尼茨,17 世纪末)用 f(x) 这种写法;Euler(欧拉,18 世纪)把指数、对数、三角写进统一体系。
程序员今天用的,是三四百年前算表、天文、工程问题的遗产。


各类基础函数:谁、为啥、经历了啥(一张总表)
函数类型 典型式子 最初在解决什么 关键人物 / 时代 和算法的关系
常数 y = c 不变量 自古就有 O(1)
一次(线性) y = kx + b 匀速、按比例变化 古埃及、巴比伦度量 线性扫描 O(n)
二次 y = ax² + bx + c 面积(正方形边长→面积)、抛物运动 巴比伦 ~2000 年前;代数解法的系统化 花拉子米(9 世纪) O(n²) 两重循环
多项式 / 幂 y = xⁿ 体积、更高次几何 古希腊;17 世纪代数符号成熟 O(n^k)
有理式 分式 比例分配、平均速度 随代数发展 常数因子
三角 sin, cos 天文、日晷、航海测角、周期现象 巴比伦星表;希腊 希帕恰斯;印度、阿拉伯学者完善 周期性、几何题
指数 y = aˣ 复利、人口增长、放射性——「每期乘固定倍数」 17 世纪利息问题;欧拉e 讲透(18 世纪) O(2ⁿ)O(kⁿ)
对数 y = log_a x 把乘法变加法,大数算表、天文 纳皮尔(1614);比吉、布里格斯(常用底 10) O(log n)、二分
自然对数 ln ln x 配套,微积分最简 欧拉;Mercator 级数(1668) Σ 1/i ≈ ln n
反函数 log 与 exp 互逆 一种运算的「撤销」 纳皮尔时代已隐含;欧拉系统化 二分 ↔ 倍增

重点故事 1:对数——纳皮尔(John Napier)经历了啥?

时间:1614 年出版《奇妙对数表的描述》(拉丁文原名 Mirifici Logarithmorum Canonis Descriptio)。

他是谁:苏格兰贵族、数学家,同时代的天文学很依赖 开普勒 的行星表——里面全是大量乘除。

他的痛苦(你要记住的动机)

要做:  1234567 × 8901234
没有计算器,只有纸笔 → 极易错、极耗时

他的想法(革命性)

若有一张表,把每个数 x 映到 L(x),使得
L(x × y) = L(x) + L(y)
乘法变加法,除法变减法。

L(x) 就是后来的 对数
他花了大约 20 年 造表、打磨方法(不是拍脑袋一天搞定)。

之后

  • 瑞士钟表匠 比吉(Jost Bürgi) 约 1610 年独立做出类似思想(出版稍晚)
  • 英国 亨利·布里格斯(Henry Briggs) 把系统改成大家熟悉的 以 10 为底(常用对数),并和纳皮尔合作
  • 对数表一直用到 20 世纪计算器 才退居幕后

和程序员的联系
二分查找「每次减半」是在数 几次除 2——这就是 log₂ n 的灵魂;纳皮尔当年是在数 几次乘除能变成加


重点故事 2:指数与自然常数 e——欧拉(Leonhard Euler)经历了啥?

指数 思想更早:复利、棋盘放麦粒(每格翻倍)古希腊就有传说。

问题形状

银行复利:本金 1,年利率 100%,一年结一次 → 2
若一年结 n 次: (1 + 1/n)ⁿ
n 越来越大 → 会趋近一个常数 ≈ 2.71828… = e

欧拉(1707–1783,瑞士) 的贡献(概括):

  • e 命名这个常数,研究 ln x
  • 证明 ln x 互为反函数(现代课本写法很多来自欧拉传统)
  • 写出 e^(iπ) + 1 = 0 等,把指数、三角、复数连成一张网

他经历了啥(人物侧写,帮助记忆)

  • 一生高产到离谱(论文/著作体量惊人),部分时间 失明后仍口算写作
  • 在圣彼得堡、柏林等地工作,解决 航海、力学、数论、天文 里的大量「算不动」问题
  • 对程序员:O(eⁿ)O(2ⁿ) 在复杂度里同属指数级;工程里更常写 2ⁿ(二进制)

重点故事 3:一次、二次、三角——更早的「基础函数」

一次函数 y = kx + b

  • 场景:匀速走路——时间 × 速度 = 路程
  • 历史:商业、税收、土地测量里比比皆是;不必归功于单人

二次函数

  • 场景:边长 × 边长 = 面积;抛体高度随时间近似抛物线
  • 历史:巴比伦泥板上有二次方程思想;花拉子米(al-Khwarizmi,约 820 年《代数学》)系统化一元二次(「代数」一词来自其名)
  • 经历:伊斯兰黄金时代保存并发展希腊、印度数学,再传回欧洲

三角函数

  • 场景:只知道角度,要算塔高、星体位置、周期
  • 历史:巴比伦天文;希腊 希帕恰斯(约公元前 150 年)造弦表(三角前身);印度 阿耶波多 等发展;阿拉伯学者 阿尔·巴塔尼 推进
  • 经历:航海大发现时代(15–17 世纪)极度依赖三角表,与对数表 一起 减少海难

发散小结:不是「谁发明了函数」,而是「一类类问题逼出工具」
土地测量  →  一次、二次、几何
天文航海  →  三角
复利增长  →  指数
大数运算  →  对数(纳皮尔 20 年磨表)
统一符号  →  莱布尼茨 f(x)、欧拉 eˣ 与 ln x
计算机时代 →  我们拿它们数「操作次数」→ O(log n)、O(2ⁿ)

一句话
对数 是纳皮尔等人为了让 乘除变加减
指数 是复利、增长问题里 反复乘同一个数
一次/二次/三角 是测量、天文、工程里 现实世界的关系
Euler、Leibniz 后来把这些写进 同一套语言,你才在高中和复杂度里见到它们。


指数函数与对数函数(重点专题 · 算法向)

程序员最常用的一对函数:指数 = 爆炸式增长对数 = 反复减半
复杂度里 O(2ⁿ)O(log n)O(n log n) 都从这里来。
上面 纳皮尔 / 欧拉 的故事是「人话起源」;下面是「面试向公式与推导」。


读前 30 秒:先建立直觉
函数 一句话 算法里的脸
指数 每走一步 乘以固定倍数 暴力回溯 O(2ⁿ)、分治层数 2^h
对数 log_a x 问「要乘几次 a 才到 x」= 反复除到 1 要几步 二分 O(log n)、树高 log n
互为反函数 指数「涨」,对数「数涨了几层」 log_a(aˣ) = x
n = 1024 时(数量级感受):

  log₂ n = 10        ← 二分最多约 10 次
  n      = 1024      ← 扫一遍
  n log n ≈ 10⁴      ← 排序
  n²     ≈ 10⁶
  2ⁿ     ≈ 10³⁰⁸   ← 直接不可做

1. 指数函数 y = aˣ(a > 0, a ≠ 1)

定义:底数 a 固定,指数 x 变,结果按 幂次 增长。

底数 a 图像趋势 例子
a > 1 递增,且越往后涨得越猛 , 10ˣ,
0 < a < 1 递减 0.5ˣ(可写成 2⁻ˣ

常用写法

  • 2ⁿ:计算机里最常见(二进制、子问题翻倍)
  • :自然指数,\ln xe 为底(微积分、ML)
  • 增长:指数 >> 多项式 >> 对数(n 稍大就碾压)

算法对应

表达式 含义 场景
O(2ⁿ) n 每 +1,工作量 ×2 子集枚举、暴力回溯
O(kⁿ) 每步 k 种选择 排列/搜索树分支因子 k
2^h 树高 h 的满二叉树节点数 递归树节点上界

数值直觉(n 从 10 到 20,2ⁿ 翻 1024 倍)

n 2ⁿ
10 1,024
15 32,768
20 1,048,576
30 ≈ 10⁹

所以面试常说:n > 20 的 O(2ⁿ) 基本别想跑完


2. 对数函数 y = log_a x(a > 0, a ≠ 1, x > 0)

定义log_a x = y 等价于 aʸ = x

人话:把 x 每次 除以 a,除到 ≤ 1 一共几步,就是 log_a x

log₂ 8 = 3   因为  8 → 4 → 2 → 1,除 2 共 3 次
log₂ 1024 = 10   因为  2¹⁰ = 1024
底数 记号 谁在用
底 2 log₂ nlg n 算法、二分、树高(计算机默认思维)
底 10 log₁₀ n 数量级、科学计数
底 e ln x 微积分、\sum 1/i ≈ ln n

换底公式(面试可一笔带过)

log_a b = log_c b / log_c a

所以 O(log₂ n) 与 O(log₁₀ n) 只差常数因子 → 大 O 里都写成 O(log n)

核心性质(推导复杂度必用)

性质 公式 算法用处
积变和 log_a(xy) = log_a x + log_a y 分治:T(n)=2T(n/2)+O(n) → 层数相加
商变差 log_a(x/y) = log_a x - log_a y 规模缩小
幂次提出 log_a(xᵏ) = k · log_a x 的对数级仍是 O(log n) 量级(常数不同)
底数换常数 换底公式 底 2/10/e 不影响 Big O

3. 指数与对数:互为反函数(一张图记住)
        y
        │      y = 2ˣ  (指数:x 走一点,y 跳很多)
        │     ╱
        │   ╱
        │ ╱    y = log₂ x (对数:要 y 才翻倍,x 要乘 2)
        │╱___________
        └────────────── x

  沿 y=x 对称 → 互为反函数
  log_a(aˣ) = x
  a^(log_a x) = x

程序员版对应

  • 指数:问题规模 +1 → 工作量 ×2(爆炸)
  • 对数:问题规模 ÷2 → 工作量 +1 层(二分、平衡树一层一层削)

4. 复杂度增长:为什么是这个顺序?
O(1) < O(log n) < O(n) < O(n log n) < O(n²) < O(n³) < O(2ⁿ) < O(n!)
复杂度 数学本质 n=10⁶ 量级直觉
O(log n) log₂ 10⁶ ≈ 20 二十步量级
O(n) 线性 一百万
O(n log n) n × log n 约两千万次操作
O(n²) 平方 10¹²(易爆)
O(2ⁿ) 指数 不可接受

O(n log n) 从哪来?(归并/快排)

每一层处理约 n 个元素,共约 log₂ n 层(每次规模减半)
→ 总工作量 ≈ n × log n

5. 手把手:为什么二分查找是 O(log n)?

过程:有序数组长度 n,每次看中间,丢掉一半。

n → n/2 → n/4 → … → 1

设一共 k 步:n / 2ᵏ ≈ 1  →  2ᵏ ≈ n  →  k ≈ log₂ n
// 二分查找
public int binarySearch(int[] nums, int target) {
    int left = 0, right = nums.length - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) return mid;
        else if (nums[mid] < target) left = mid + 1;  // 丢掉左半
        else right = mid - 1;                          // 丢掉右半
    }
    return -1;
}
// 循环次数 ≈ ⌊log₂ n⌋ + 1

推广

操作 为何是 log n
平衡 BST 查找 树高 h ≈ log n,每层 O(1)
push/pop 沿树高调整 ≈ log n
B+ 树索引 层数少,每层一页,层数 ∝ log n
倍增(翻倍扩容) 容量 1,2,4,…,n 共 O(log n) 次扩容

6. 手把手:为什么分治常是 O(n log n)?

模型T(n) = 2T(n/2) + O(n)(归并排序、快排平均)

规模:  n
       / \
    n/2  n/2        ← 一层:合并代价 O(n)
   / \  / \
  ...  ...          ← 共约 log₂ n 层

每层总工作量 ≈ O(n)
层数 ≈ log₂ n
→ T(n) = O(n log n)

若变成 T(n) = 2T(n/2) + O(1)(只分不合并)→ O(n)
若变成 T(n) = 2T(n/2) + O(n²)O(n² log n)


7. 常见误区
误区 正解
O(log n)O(lg n) 不一样 算法里常指同阶,底只影响常数
log nn 错,n 足够大时 log n ≪ n
O(2n) 是指数 2n = O(n),指数是 O(2ⁿ),底在指数上
二分一定 O(log n) 前提:有序 + 随机访问;链表二分仍是 O(n) 找中点

8. Java 里怎么写 / 怎么算
// 以 2 为底的对数(算二分步数上界)
int steps = (int) (Math.log(n) / Math.log(2));  // ≈ log₂ n

// 自然对数 ln
double ln = Math.log(x);       // 默认 e 为底

// 判断 n 是否是 2 的幂
boolean isPowerOfTwo(int n) {
    return n > 0 && (n & (n - 1)) == 0;
}
// 若 n = 2^k,则 log₂ n = k(整数)

// 复杂度对比实验(感受增长)
void compareGrowth(int n) {
    System.out.println("n=" + n);
    System.out.println("log2(n) ≈ " + (Math.log(n) / Math.log(2)));
    System.out.println("n log n ≈ " + n * (Math.log(n) / Math.log(2)));
    // 2^n 用 long 很快溢出,勿对大的 n 直接算
}

9. 5W1H 速记(面试用)

Why:分析「规模变大时慢多少」——指数爆炸、对数削层。

What

  • 指数:,倍增
  • 对数:log_a x,除 a 几次到 1
  • 顺序:1 < log n < n < n log n < n² < 2ⁿ

When:见二分、树、分治、枚举子集、问复杂度。

Where:二分、BST/B+ 树、排序、回溯剪枝、DP 状态数估算。

Who:面试官问「复杂度多少」「能否优化」「为什么 log n」。

How:规模减半 → log n;规模翻倍层数 → 2^h;每层扫 n → n log n


其他常见函数(简表)

函数 要点 算法
幂函数 xⁿ n²、n³ 多项式 双重循环、三重循环
一次 kx+b 单调性 二分答案前提
二次 ax²+bx+c 顶点、开口 抛物线最值题

导数(与指数/对数衔接)

(eˣ)' = eˣ
(ln x)' = 1/x     ← 解释 ln 增长比 x 慢:导数 1/x → 0
(2ˣ)' = 2ˣ ln 2
(log_a x)' = 1 / (x ln a)

用途:判断函数增减、最优化(梯度下降);算法面试 复杂度用离散 log/指数 更多,导数了解即可。


3.2 数列与级数

等差数列

Why - 为什么要学?

等差数列求和公式可以把 O(n) 循环优化到 O(1)。
前缀和、批量计算都依赖这个公式。

What - 核心公式是什么?

通项公式:aₙ = a₁ + (n-1)d
前 n 项和:Sₙ = n(a₁ + aₙ)/2 = n·a₁ + n(n-1)d/2

性质:
- 任意两项之差为常数 d
- 求和时间复杂度 O(1)

When - 什么时候用?

- 前缀和计算
- 批量数据求和
- 优化循环

Where - 在哪些场景用?

LeetCode 题目:
- "等差数列划分"
- "连续子数组的最大和"
- "前缀和" 类题目

数据工程:
- 批量聚合计算
- 指标预计算

Who - 谁会考你?

面试官可能问:
- "这个求和能不能用公式优化?"
- "时间复杂度能从 O(n) 降到 O(1) 吗?"

How - 怎么用?(代码示例)

// 优化前:O(n)
public int sumArithmeticSlow(int a1, int d, int n) {
    int sum = 0;
    for (int i = 0; i < n; i++) {
        sum += a1 + i * d;
    }
    return sum;
}

// 优化后:O(1)
public int sumArithmeticFast(int a1, int d, int n) {
    int an = a1 + (n - 1) * d;  // 末项
    return n * (a1 + an) / 2;    // 求和公式
}


等比数列

Why - 为什么要学?

分治算法的时间复杂度分析需要等比数列求和。
递归树的高度分析也用到这个知识。

What - 核心公式是什么?

通项公式:aₙ = a₁·qⁿ⁻¹
前 n 项和:Sₙ = a₁(1-qⁿ)/(1-q)  (q≠1)

无穷等比级数(|q|<1):
S = a₁/(1-q)

典型应用:
分治算法 T(n) = 2T(n/2) + O(n)
递归树高度:log n
每层工作量:O(n)
总复杂度:O(n log n)

When - 什么时候用?

- 分治算法复杂度分析
- 递归树求和
- 等比增长问题

Where - 在哪些场景用?

LeetCode 题目:
- "汉诺塔问题"
- "分治算法类题目"
- "递归树分析"

算法设计:
- 归并排序 O(n log n)
- 快速排序 O(n log n)

Who - 谁会考你?

面试官可能问:
- "归并排序为什么是 O(n log n)?"
- "能不能画一下递归树?"

How - 怎么用?(代码示例)

// 归并排序复杂度分析
// T(n) = 2T(n/2) + O(n)
//      = 2[2T(n/4) + O(n/2)] + O(n)
//      = 4T(n/4) + 2O(n)
//      = 8T(n/8) + 3O(n)
//      = ...
//      = nT(1) + log n · O(n)
//      = O(n log n)

// 等比数列求和验证:
// 第 k 层工作量:2^k · O(n/2^k) = O(n)
// 共 log n 层
// 总工作量:O(n) · log n = O(n log n)


3.3 排列组合

Why - 为什么要学?

回溯算法、组合问题、子集问题都依赖排列组合。
动态规划状态转移也常用组合数学。

What - 核心公式是什么?

排列(有序):
P(n,m) = n!/(n-m)!
全排列:P(n,n) = n!

组合(无序):
C(n,m) = n!/[m!(n-m)!]

性质:
1. C(n,m) = C(n,n-m)
2. C(n,m) = C(n-1,m-1) + C(n-1,m)  (杨辉三角)

When - 什么时候用?

- LeetCode 排列组合题目
- 回溯算法
- 动态规划
- 概率计算

Where - 在哪些场景用?

LeetCode 题目:
- "全排列" → P(n,n)
- "组合总和" → C(n,m)
- "子集" → C(n,0) + C(n,1) + ... + C(n,n) = 2ⁿ

Who - 谁会考你?

面试官可能问:
- "有多少种不同的排列方式?"
- "能不能用动态规划优化回溯?"

How - 怎么用?(代码示例)

// 计算组合数 C(n,m)
public long combination(int n, int m) {
    if (m < 0 || m > n) return 0;
    if (m == 0 || m == n) return 1;
    if (m > n / 2) m = n - m;  // 利用 C(n,m) = C(n,n-m)

    long result = 1;
    for (int i = 1; i <= m; i++) {
        result = result * (n - i + 1) / i;
    }
    return result;
}

// 全排列(回溯)
public List<List<Integer>> permute(int[] nums) {
    List<List<Integer>> result = new ArrayList<>();
    backtrack(result, new ArrayList<>(), nums, new boolean[nums.length]);
    return result;
}

private void backtrack(List<List<Integer>> result, List<Integer> temp, 
                       int[] nums, boolean[] used) {
    if (temp.size() == nums.length) {
        result.add(new ArrayList<>(temp));
        return;
    }

    for (int i = 0; i < nums.length; i++) {
        if (used[i]) continue;
        used[i] = true;
        temp.add(nums[i]);
        backtrack(result, temp, nums, used);
        temp.remove(temp.size() - 1);
        used[i] = false;
    }
}


3.4 概率论进阶

随机变量

Why - 为什么要学?

期望 DP 是面试难题。
随机算法分析需要期望和方差知识。

What - 核心公式是什么?

离散型随机变量:
- 期望:E(X) = Σ xᵢ·pᵢ
- 方差:D(X) = E[(X-E(X))²] = E(X²) - [E(X)]²

性质:
- E(aX + b) = a·E(X) + b
- D(aX + b) = a²·D(X)
- 独立变量:E(X+Y) = E(X) + E(Y)

When - 什么时候用?

- LeetCode 期望 DP 题
- 随机算法分析
- 风险评估

Where - 在哪些场景用?

LeetCode 题目:
- "掷骰子的期望"
- "随机指针"
- "期望 DP 类题目"

数据工程:
- 用户行为建模
- 转化率预估

Who - 谁会考你?

面试官经典题:
- "一个骰子掷出点数的期望是多少?"
  答:E = (1+2+3+4+5+6)/6 = 3.5

How - 怎么用?(代码示例)

// 计算掷骰子的期望
public double expectedValue(int[] values, double[] probabilities) {
    double expectation = 0;
    for (int i = 0; i < values.length; i++) {
        expectation += values[i] * probabilities[i];
    }
    return expectation;
}

// 使用:骰子点数 1-6,概率各 1/6
public double diceExpectedValue() {
    int[] values = {1, 2, 3, 4, 5, 6};
    double[] probs = {1.0/6, 1.0/6, 1.0/6, 1.0/6, 1.0/6, 1.0/6};
    return expectedValue(values, probs);  // 3.5
}


3.5 向量与矩阵

向量基础

Why - 为什么要学?

机器学习特征向量、相似度计算、推荐系统都用向量。
点积可以计算相似度(余弦相似度)。

What - 核心公式是什么?

向量点积:a·b = Σ aᵢbᵢ = |a||b|cosθ

余弦相似度:
cosθ = (a·b) / (|a|·|b|)
- 取值范围:[-1, 1]
- 1:完全相同
- 0:正交(无关)
- -1:完全相反

When - 什么时候用?

- 推荐系统
- 相似度计算
- 机器学习特征

Where - 在哪些场景用?

LeetCode 题目:
- "两个向量的夹角"
- "相似度计算"

数据工程:
- 用户画像相似度
- 商品推荐
- 文本相似度

Who - 谁会考你?

面试官可能问:
- "怎么计算两个用户的相似度?"
- "余弦相似度和欧氏距离有什么区别?"

How - 怎么用?(代码示例)

// 计算两个向量的点积
public double dotProduct(double[] a, double[] b) {
    if (a.length != b.length) throw new IllegalArgumentException();

    double sum = 0;
    for (int i = 0; i < a.length; i++) {
        sum += a[i] * b[i];
    }
    return sum;
}

// 计算余弦相似度
public double cosineSimilarity(double[] a, double[] b) {
    double dot = dotProduct(a, b);
    double normA = Math.sqrt(dotProduct(a, a));
    double normB = Math.sqrt(dotProduct(b, b));
    return dot / (normA * normB);
}


3.6 数学归纳法

Why - 为什么要学?

证明算法正确性。
证明递推关系的通项公式。
面试中要求你证明某个结论。

What - 证明步骤是什么?

1. 基础步骤:验证 n=1 时命题成立
2. 归纳步骤:假设 n=k 时成立,证明 n=k+1 时也成立

When - 什么时候用?

- 算法正确性证明
- 递推关系证明
- 面试证明题

Where - 在哪些场景用?

LeetCode 题目:
- 需要证明正确性的题目
- 动态规划状态转移证明

算法设计:
- 递归算法证明
- 数学推导题

Who - 谁会考你?

面试官可能问:
- "你能证明这个算法是正确的吗?"
- "为什么这个递推公式成立?"

How - 怎么用?(代码示例)

// 用数学归纳法证明:1+2+...+n = n(n+1)/2

// 基础步骤:n=1
// 左边 = 1
// 右边 = 1×2/2 = 1
// 左边 = 右边,成立

// 归纳步骤:假设 n=k 时成立
// 1+2+...+k = k(k+1)/2
// 证明 n=k+1 时也成立

public class InductionProof {
    // 用代码验证(非严格证明)
    public static boolean verifyFormula(int n) {
        int sum1 = 0;
        for (int i = 1; i <= n; i++) {
            sum1 += i;
        }

        int sum2 = n * (n + 1) / 2;

        return sum1 == sum2;
    }

    public static void main(String[] args) {
        for (int n = 1; n <= 100; n++) {
            assert verifyFormula(n) : "Failed at n=" + n;
        }
        System.out.println("验证通过");
    }
}


四、算法面试中的数学应用

4.1 时间复杂度分析(5W1H)

Why - 为什么要分析复杂度?

- 选择最优算法
- 向面试官展示专业能力
- 避免超时

What - 常见复杂度有哪些?

O(1):常数时间
O(log n):对数时间(二分查找、平衡树)
O(n):线性时间(遍历、双指针)
O(n log n):线性对数(快速排序、归并排序)
O(n²):平方时间(双层循环、冒泡排序)
O(2ⁿ):指数时间(暴力回溯)
O(n!):阶乘时间(全排列)

When - 什么时候分析?

- 写代码前先分析
- 提交前检查是否超时
- 面试时主动说明

Where - 在哪些场景分析?

LeetCode 提交:
- 数据规模 10⁵ → 必须 O(n log n) 或 O(n)
- 数据规模 10³ → O(n²) 可以接受
- 数据规模 20 → O(2ⁿ) 可以接受

Who - 谁会要求你分析?

面试官必问:
- "时间复杂度是多少?"
- "空间复杂度是多少?"
- "能不能优化?"

How - 怎么分析?

// 示例:分析代码复杂度

// O(n) - 单层循环
public void linear(int n) {
    for (int i = 0; i < n; i++) {
        // O(1)
    }
}

// O(n²) - 双层循环
public void quadratic(int n) {
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            // O(1)
        }
    }
}

// O(log n) - 每次减半
public void logarithmic(int n) {
    for (int i = n; i > 0; i /= 2) {
        // O(1)
    }
}

// O(n log n) - 外层 n,内层 log n
public void nlogn(int n) {
    for (int i = 0; i < n; i++) {
        for (int j = n; j > 0; j /= 2) {
            // O(1)
        }
    }
}


五、学习建议

5.1 复习优先级(5W1H)

Why - 为什么按优先级复习?

时间有限,必须聚焦高频考点。
面试不会考所有知识点。

What - 优先级如何划分?

P0(必须掌握):
- 对数/指数运算(复杂度分析)
- 排列组合(回溯/DP)
- 基础概率(面试概率题)

P1(建议掌握):
- 导数基础(最优化理解)
- 数列求和(复杂度推导)
- 向量的点积/叉积(相似度)

P2(了解即可):
- 矩阵运算(高级算法)
- 贝叶斯定理(机器学习)
- 微积分(数值计算)

When - 什么时候复习?

- 每天 1-2 小时
- 刷 LeetCode 前复习
- 面试前一周突击

Where - 在哪练习?

- LeetCode 数学相关标签
- 牛客网概率题
- 自测题目

Who - 谁能帮你?

- AI 助手讲解知识点
- 刷题社区讨论
- 面试官反馈

How - 怎么高效复习?

1. 理解公式来源(为什么这样设计)
2. 配合代码实现(用 Java 写出来)
3. 找 LeetCode 题目练习(至少 3 题)
4. 面试时能解释(能说清楚推导过程)


六、快速查表

6.1 常用公式

名称 公式 应用场景
等差求和 Sₙ = n(a₁+aₙ)/2 前缀和、O(1) 计算
等比求和 Sₙ = a₁(1-qⁿ)/(1-q) 分治复杂度
排列数 P(n,m) = n!/(n-m)! 回溯、全排列
组合数 C(n,m) = n!/[m!(n-m)!] 子集、DP
二项式 (a+b)ⁿ = Σ C(n,k)aⁿ⁻ᵏbᵏ 概率、展开
贝叶斯 P(A|B) = P(B|A)P(A)/P(B) 推断、分类

6.2 复杂度常用级数

级数 复杂度 典型场景
Σ i (1..n) n(n+1)/2 O(n²) 双层循环
Σ log i (1..n) log(n!) O(n log n) 归并排序
Σ 2ⁱ (0..n) 2ⁿ⁺¹-1 O(2ⁿ) 暴力回溯
Σ 1/i (1..n) ≈ ln n O(log n) 调和级数
Σ i² (1..n) n(n+1)(2n+1)/6 O(n³) 三层循环

相关文档: - 数据结构与算法 7 天冲刺 - ClickHouse 深度解析 - 算法复杂度分析


二、初中数学核心

2.1 代数基础

方程与不等式

一元二次方程:ax² + bx + c = 0
求根公式:x = (-b ± √(b² - 4ac)) / 2a

判别式:Δ = b² - 4ac
- Δ > 0:两个不等实根
- Δ = 0:两个相等实根
- Δ < 0:无实根

韦达定理(Vieta's Formulas):
x₁ + x₂ = -b/a
x₁ × x₂ = c/a

应用:LeetCode 中涉及数学推导的题目

因式分解

常用公式:
1. 平方差:a² - b² = (a+b)(a-b)
2. 完全平方:a² ± 2ab + b² = (a±b)²
3. 立方和/差:a³ ± b³ = (a±b)(a² ∓ ab + b²)
4. 十字相乘法:ax² + bx + c = (px+q)(rx+s)

应用:优化计算、减少时间复杂度

2.2 函数基础

一次函数与二次函数

一次函数:y = kx + b
- 斜率 k = (y₂-y₁)/(x₂-x₁)
- 截距 b(与 y 轴交点)

二次函数:y = ax² + bx + c
- 顶点:(-b/2a, (4ac-b²)/4a)
- 对称轴:x = -b/2a
- 开口方向:a>0 向上,a<0 向下

应用:算法中的最优化问题、二分查找的单调性判断

2.3 几何基础

平面几何

三角形:
- 面积:S = ½ × 底 × 高
- 勾股定理:a² + b² = c²(直角三角形)
- 正弦定理:a/sinA = b/sinB = c/sinC = 2R
- 余弦定理:c² = a² + b² - 2ab·cosC

四边形:
- 矩形面积:S = 长 × 宽
- 平行四边形:S = 底 × 高
- 梯形:S = ½ × (上底+下底) × 高

圆:
- 周长:C = 2πr
- 面积:S = πr²
- 弧长:l = rθ(θ 为弧度)

应用:计算几何题目、图形渲染、碰撞检测

2.4 统计与概率

基础统计

集中趋势:
- 平均数:x̄ = Σxᵢ/n
- 中位数:排序后中间的数
- 众数:出现次数最多的数

离散程度:
- 方差:σ² = Σ(xᵢ-x̄)²/n
- 标准差:σ = √σ²
- 极差:max - min

应用:数据分析、A/B 测试、质量监控

基础概率

概率定义:P(A) = 事件 A 发生的次数 / 总试验次数

基本公式:
1. 互斥事件:P(A∪B) = P(A) + P(B)
2. 独立事件:P(A∩B) = P(A) × P(B)
3. 条件概率:P(A|B) = P(A∩B) / P(B)
4. 全概率公式:P(B) = Σ P(B|Aᵢ)·P(Aᵢ)

应用:随机算法、蒙特卡洛方法、概率题面试

三、高中数学核心

3.1 函数与导数

指数/对数完整版见上文 §3.1 指数函数与对数函数(重点专题)(含二分、n log n 推导、误区、Java)。

常见函数(速查)

指数 y=aˣ:O(2ⁿ) 爆炸;对数 y=logₐx:O(log n) 减半
顺序:O(1) < O(log n) < O(n) < O(n log n) < O(n²) < O(2ⁿ)
幂函数 y=xⁿ:O(n²)、O(n³)

导数基础

导数定义:f'(x) = lim(h→0) [f(x+h) - f(x)] / h

常用导数:
- (xⁿ)' = n·xⁿ⁻¹
- (sin x)' = cos x
- (cos x)' = -sin x
- (eˣ)' = eˣ
- (ln x)' = 1/x

导数应用:
1. 判断单调性:f'(x)>0 递增,f'(x)<0 递减
2. 求极值:f'(x)=0 的点是驻点
3. 最优化问题:梯度下降的基础

应用:机器学习、最优化算法、数值计算

3.2 数列与级数

等差数列

通项公式:aₙ = a₁ + (n-1)d
前 n 项和:Sₙ = n(a₁ + aₙ)/2 = n·a₁ + n(n-1)d/2

性质:
- 任意两项之差为常数 d
- 求和时间复杂度 O(1)

应用:前缀和、滑动窗口、批量计算

等比数列

通项公式:aₙ = a₁·qⁿ⁻¹
前 n 项和:Sₙ = a₁(1-qⁿ)/(1-q)  (q≠1)

无穷等比级数(|q|<1):
S = a₁/(1-q)

应用:分治算法复杂度 T(n) = 2T(n/2) + O(n) = O(n log n)

常见级数

1. 调和级数:1 + 1/2 + 1/3 + ... + 1/n ≈ ln n + γ
   应用:快速排序平均复杂度分析

2. 等差级数:1 + 2 + 3 + ... + n = n(n+1)/2
   应用:双层循环时间复杂度 O(n²)

3. 几何级数:1 + 2 + 4 + ... + 2ⁿ = 2ⁿ⁺¹ - 1
   应用:二叉树节点数、分治算法

3.3 排列组合

排列(Permutation)

定义:从 n 个不同元素中取出 m 个元素的有序排列

公式:P(n,m) = n!/(n-m)!

全排列:P(n,n) = n!

应用:回溯算法、排列组合题目

组合(Combination)

定义:从 n 个不同元素中取出 m 个元素的无序组合

公式:C(n,m) = n!/[m!(n-m)!]

性质:
1. C(n,m) = C(n,n-m)
2. C(n,m) = C(n-1,m-1) + C(n-1,m)  (杨辉三角)

应用:子集问题、组合问题、动态规划状态转移

二项式定理

(a+b)ⁿ = Σ C(n,k)·aⁿ⁻ᵏ·bᵏ  (k=0 to n)

应用:概率计算、多项式展开

3.4 概率论进阶

随机变量

离散型随机变量:
- 概率分布:P(X=xᵢ) = pᵢ
- 期望:E(X) = Σ xᵢ·pᵢ
- 方差:D(X) = E[(X-E(X))²] = E(X²) - [E(X)]²

连续型随机变量:
- 概率密度函数 f(x)
- 期望:E(X) = ∫ x·f(x)dx
- 方差:D(X) = ∫ (x-E(X))²·f(x)dx

应用:期望 DP、随机算法分析

常见分布

二项分布 B(n,p):
- n 次独立重复试验,每次成功概率 p
- P(X=k) = C(n,k)·pᵏ·(1-p)ⁿ⁻ᵏ
- E(X) = np, D(X) = np(1-p)

泊松分布 P(λ):
- 单位时间内事件发生次数
- P(X=k) = λᵏ·e⁻λ/k!
- E(X) = λ, D(X) = λ

正态分布 N(μ,σ²):
- 钟形曲线,对称分布
- 68-95-99.7 规则
- 应用:A/B 测试、统计推断

应用:概率题、蒙特卡洛、统计学习

条件概率与贝叶斯

条件概率:P(A|B) = P(A∩B) / P(B)

贝叶斯定理:
P(A|B) = P(B|A)·P(A) / P(B)

全概率公式:
P(B) = Σ P(B|Aᵢ)·P(Aᵢ)

应用:贝叶斯分类器、推荐系统、概率推断

3.5 向量与矩阵

向量基础

向量:有大小和方向的量

运算:
- 加法:a + b = (a₁+b₁, a₂+b₂, ...)
- 数乘:k·a = (ka₁, ka₂, ...)
- 点积:a·b = Σ aᵢbᵢ = |a||b|cosθ
- 叉积:a×b(三维,结果是向量)

模长:|a| = √(a₁² + a₂² + ...)

应用:机器学习特征向量、相似度计算、图形学

矩阵基础

矩阵乘法:C = AB
- C[i][j] = Σ A[i][k]·B[k][j]

矩阵性质:
- (AB)ᵀ = BᵀAᵀ
- (AB)⁻¹ = B⁻¹A⁻¹

应用:动态规划优化、图论、线性方程组

3.6 数学归纳法

证明步骤:
1. 基础步骤:验证 n=1 时命题成立
2. 归纳步骤:假设 n=k 时成立,证明 n=k+1 时也成立

应用:算法正确性证明、递推关系证明

例子:证明 1+2+...+n = n(n+1)/2
- n=1: 1 = 1×2/2 ✓
- 假设 n=k: 1+2+...+k = k(k+1)/2
- 证明 n=k+1: 
  1+2+...+k+(k+1) = k(k+1)/2 + (k+1)
                  = (k+1)(k+2)/2 ✓

四、算法面试中的数学应用

4.1 时间复杂度分析

O(1):常数时间
O(log n):对数时间(二分查找、平衡树)
O(n):线性时间(遍历、双指针)
O(n log n):线性对数(快速排序、归并排序)
O(n²):平方时间(双层循环、冒泡排序)
O(2ⁿ):指数时间(暴力回溯)
O(n!):阶乘时间(全排列)

级数求和:
- Σ i (i=1 to n) = O(n²)
- Σ log i (i=1 to n) = O(n log n)
- Σ 2ⁱ (i=0 to n) = O(2ⁿ)

4.2 空间复杂度

O(1):常数空间(原地算法)
O(n):线性空间(数组、哈希表)
O(log n):对数空间(递归栈、二分)
O(n²):平方空间(二维数组、邻接矩阵)

4.3 概率算法

蒙特卡洛方法:
- 随机采样估计结果
- 精度与采样次数成正比
- 应用:π 计算、积分估计

随机化算法:
- 快速排序随机 pivot
- 哈希表随机哈希函数
- 应用:避免最坏情况

五、常见数学面试题型

5.1 数论基础

1. 最大公约数(GCD)
   辗转相除法:gcd(a,b) = gcd(b, a%b)

2. 最小公倍数(LCM)
   lcm(a,b) = a×b / gcd(a,b)

3. 质数判断
   试除法:O(√n)
   埃拉托斯特尼筛法:O(n log log n)

4. 模运算
   (a+b)%m = (a%m + b%m)%m
   (a×b)%m = ((a%m)×(b%m))%m
   aⁿ%m = (a%m)ⁿ%m(快速幂)

5.2 组合数学题

典型题目:
1. 排列组合:C(n,m) 计算
2. 杨辉三角:动态规划生成
3. 卡特兰数:Cₙ = C(2n,n)/(n+1)
   应用:合法括号序列、二叉树计数

公式记忆:
- C(n,0) = C(n,n) = 1
- C(n,m) = C(n-1,m-1) + C(n-1,m)

5.3 概率题

1. 掷骰子问题
   - 期望 E = Σ xᵢ·pᵢ
   - 方差 D = E(X²) - [E(X)]²

2. 抽奖问题
   - 超几何分布
   - 二项分布近似

3. 生日悖论
   - n 人中至少两人生日相同的概率
   - n=23 时概率 > 50%

六、学习建议

6.1 复习优先级

P0(必须掌握):
- 对数/指数运算(复杂度分析)
- 排列组合(回溯/DP)
- 基础概率(面试概率题)

P1(建议掌握):
- 导数基础(最优化理解)
- 数列求和(复杂度推导)
- 向量的点积/叉积(相似度)

P2(了解即可):
- 矩阵运算(高级算法)
- 贝叶斯定理(机器学习)
- 微积分(数值计算)

6.2 学习资源

在线资源:
- 3Blue1Brown(YouTube):直观理解线性代数
- 可汗学院:系统复习初高中数学
- B 站:宋浩高等数学(系统性强)

实践方法:
1. 每学一个公式,找 1-2 道 LeetCode 应用
2. 复杂度分析必须熟练掌握
3. 概率题多做练习(面试常考)

七、快速查表

7.1 常用公式

名称 公式 应用
等差求和 Sₙ = n(a₁+aₙ)/2 前缀和、O(1) 计算
等比求和 Sₙ = a₁(1-qⁿ)/(1-q) 分治复杂度
排列数 P(n,m) = n!/(n-m)! 回溯、全排列
组合数 C(n,m) = n!/[m!(n-m)!] 子集、DP
二项式 (a+b)ⁿ = Σ C(n,k)aⁿ⁻ᵏbᵏ 概率、展开
贝叶斯 P(A|B) = P(B|A)P(A)/P(B) 推断、分类

7.2 复杂度常用级数

级数 复杂度
Σ i (1..n) n(n+1)/2 O(n²)
Σ log i (1..n) log(n!) O(n log n)
Σ 2ⁱ (0..n) 2ⁿ⁺¹-1 O(2ⁿ)
Σ 1/i (1..n) ≈ ln n O(log n)
Σ i² (1..n) n(n+1)(2n+1)/6 O(n³)

相关文档: - 数据结构与算法 7 天冲刺 - ClickHouse 深度解析 - 算法复杂度分析