程序员必备数学知识
📚 核心内容(按重要性排序)
1. 对数 log n - 复杂度分析
核心概念
log₂(n) 就是问:2的几次方等于n?
听起来抽象,但你每天都在用。
必记数值
这些数字背下来,分析复杂度快很多:
| n | log₂(n) | 实际意义 |
|---|---|---|
| 4 | 2 | 2次比较找到目标 |
| 8 | 3 | 3次比较找到目标 |
| 1024 | 10 | 1KB数据,10次比较搞定 |
| 1,000,000 | ~20 | 百万数据,20次就够了 |
两个关键公式
记住这两个,化简复杂度够用了:
log(a × b) = log(a) + log(b) # 乘法变加法
log(aⁿ) = n × log(a) # 指数拿出来
为什么重要?
- 二分查找:每次砍一半,复杂度是 O(log n)
- 平衡树:树的高度就是 log n,查找飞快
- 归并排序:每层 O(n),总共 log n 层 → O(n log n)
2. 指数与幂运算
核心概念
2ⁿ 告诉你数据量增长有多快。
必记数值
| 表达式 | 结果 | 实际含义 |
|---|---|---|
| 2¹⁰ | 1,024 | 1KB,千这个量级 |
| 2²⁰ | 1,048,576 | 1MB,百万级 |
| 2³¹-1 | 2,147,483,647 | int最大值(21亿) |
| 2³² | 4,294,967,296 | 42亿 |
常见量级
2¹⁰ = 1千(1KB)
2²⁰ = 100万(1MB)
2³⁰ = 10亿
3. 位运算
基本操作
& // 与:两个都是1才是1
| // 或:有一个是1就是1
^ // 异或:相同是0,不同是1
~ // 取反:0变1,1变0
<< // 左移:乘以2
>> // 右移:除以2
常用技巧
// 判断奇偶
x & 1 == 1 // 奇数
// 判断2的幂
(n & (n-1)) == 0
// 找唯一数字(LeetCode 136)
// [2,3,2,4,4] → 3
int result = 0;
for (int num : nums) {
result ^= num; // 相同的数异或抵消
}
4. 等差/等比数列
等差数列
公式:1+2+3+...+n = n×(n+1)/2
用来算嵌套循环次数:
for (int i = 0; i < n; i++) {
for (int j = 0; j < i; j++) {
// 跑了 0+1+2+...+(n-1) = n(n-1)/2 次
// 复杂度 O(n²)
}
}
等比数列
规律:n + n/2 + n/4 + ... ≈ 2n
每次减半,加起来也就2倍。
例子:16 + 8 + 4 + 2 + 1 = 31 ≈ 32
应用:归并排序每层n个数,log n层 → O(n log n)
5. 模运算
核心概念
a % b = a 除以 b 的余数
防溢出
大数运算先取模:
// 错误:先乘后模可能溢出
int result = (a * b) % MOD;
// 正确:先模后乘
int result = ((a % MOD) * (b % MOD)) % MOD;
常见用途
- 哈希表:
hash(key) % size定位槽位 - 循环队列:
(index + 1) % capacity实现循环
📊 时间复杂度速查表
从快到慢排个序,一眼就能看出性能:
| 复杂度 | 速度 | 典型场景 |
|---|---|---|
| O(1) | 超快 | 数组取值、哈希查找 |
| O(log n) | 很快 | 二分查找、平衡树 |
| O(n) | 正常 | 遍历数组 |
| O(n log n) | 还行 | 快排、归并排序 |
| O(n²) | 有点慢 | 冒泡排序、双层循环 |
| O(2ⁿ) | 慢到爆 | 暴力递归、枚举子集 |
记住:从上到下越来越慢,O(2ⁿ) 基本上就是放弃治疗了。
💡 程序员必记数值
# 2的幂
2¹⁰ = 1024 → 1KB
2²⁰ = 104万 → 1MB
2³¹-1 = 21亿 → int最大值
# 数量级
10³ = 1千
10⁶ = 100万
10⁹ = 10亿
🎯 实战速查
如何判断算法复杂度?
一眼看懂代码跑多快:
// O(1) - 常数时间
// 不管数据多大,都是一次操作
arr[i] = 1;
// O(log n) - 对数时间
// 二分查找,每次砍一半
public int binarySearch(int[] arr, int target) {
int left = 0, right = arr.length - 1;
while (left <= right) {
int mid = (left + right) / 2;
// ...
}
}
// O(n) - 线性时间
// 遍历一遍
for (int i = 0; i < n; i++) {
// ...
}
// O(n²) - 平方时间
// 嵌套循环
for (int i = 0; i < n; i++) {
for (int j = 0; j < i; j++) {
// ...
}
}
// O(2ⁿ) - 指数时间(危险!)
// 递归会炸掉
public int fibonacci(int n) {
if (n <= 1) return n;
return fibonacci(n-1) + fibonacci(n-2);
}
如何优化?
看数据范围就知道能不能过:
| 复杂度 | 数据范围 | 能否接受? |
|---|---|---|
| O(n log n) | n ≤ 10⁶ | ✅ 稳过 |
| O(n²) | n ≤ 10³ | ✅ 勉强能过 |
| O(n²) | n ≤ 10⁴ | ❌ 铁定超时 |
| O(2ⁿ) | n ≤ 20 | ✅ 刚好能过 |
| O(2ⁿ) | n ≤ 30 | ❌ 别想了,换算法 |
🔑 总结
这5项必须掌握:
- log n - 搞懂二分和分治的底层原理
- 2的幂 - 判断数据规模,估算内存占用
- 位运算 - 让代码跑得更快,省下更多空间
- 数列求和 - 快速分析时间复杂度
- 模运算 - 防止计算溢出,哈希表的基础
数学不是为了装逼,是为了写出高效代码。这些知识掌握了,你就能一眼看出算法的性能瓶颈,面试的时候也能把面试官唬住。