素数筛、快速幂、排序算法——数学与算法的交汇处
算法面试中的数学题不同于竞赛数学,主要考察几个核心知识点:素数判定与筛法、快速幂与取模、最大公约数、进制转换。掌握这些模板,大部分数学题可以套路化解。
a^13 = a^8 × a^4 × a^1(13 = 1101₂)。每次将底数平方,如果当前二进制位为1则乘入结果。# 快速幂 (内置)
result = pow(base, exp, mod) # Python 内置三参数pow
# 最大公约数
import math
math.gcd(12, 8) # → 4
# 最小公倍数
def lcm(a, b):
return a * b // math.gcd(a, b)
# 素数判定 (小范围)
def is_prime(n):
if n < 2: return False
for i in range(2, int(n**0.5) + 1):
if n % i == 0: return False
return True
pow(a, b, mod) 内置了快速幂,三参数版本比 a**b % mod 快得多且不会溢出。面试中直接用内置 pow 即可,但要知道原理。题目描述:统计所有小于非负整数 n 的质数数量。
is_prime[0..n-1],初始化为 True。从 2 开始,如果 is_prime[i] 为 True,则将 i 的所有倍数标记为 False。优化:从 i*i 开始标记(更小的倍数已经被更小的素数标记过)。
class Solution:
def countPrimes(self, n: int) -> int:
if n <= 2:
return 0
is_prime = [True] * n
is_prime[0] = is_prime[1] = False
for i in range(2, int(n ** 0.5) + 1):
if is_prime[i]:
# 从 i*i 开始标记(优化)
for j in range(i * i, n, i):
is_prime[j] = False
return sum(is_prime)
时间复杂度:O(n log log n)
空间复杂度:O(n)
题目描述:你的任务是计算 a^b 对 1337 取模的结果,其中 b 是一个非常大的正整数,以数组形式给出。
a^[d₁d₂...dₖ] = ((a^[d₁d₂...dₖ₋₁])^10) × a^dₖ(a × b) % m = ((a % m) × (b % m)) % m。
class Solution:
def superPow(self, a: int, b: List[int]) -> int:
MOD = 1337
result = 1
a %= MOD
for digit in b:
# result^10 * a^digit
result = (pow(result, 10, MOD) * pow(a, digit, MOD)) % MOD
return result
时间复杂度:O(k × log 10) ≈ O(k),k 为 b 的长度
空间复杂度:O(1)
pow(base, exp, mod) 使用快速幂实现,时间 O(log exp)。LC 372 中 digit ∈ [0,9],所以 pow(a, digit, MOD) 只需 O(log 9) ≈ O(1)。pow(result, 10, MOD) 也只需 O(log 10) ≈ O(1)。题目描述:给你一个整数数组 nums,返回按升序排列的数组。不能使用内置排序函数。
class Solution:
def sortArray(self, nums: List[int]) -> List[int]:
def merge_sort(arr):
if len(arr) <= 1:
return arr
mid = len(arr) // 2
left = merge_sort(arr[:mid])
right = merge_sort(arr[mid:])
return merge_two(left, right)
def merge_two(left, right):
result = []
i = j = 0
while i < len(left) and j < len(right):
if left[i] <= right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
result.extend(left[i:])
result.extend(right[j:])
return result
return merge_sort(nums)
时间复杂度:O(n log n) — 每层合并 O(n),共 log n 层
空间复杂度:O(n) — 合并时的临时数组
def quick_sort(arr, lo=0, hi=None):
if hi is None: hi = len(arr) - 1
if lo >= hi: return
# 随机选pivot避免最坏情况
import random
pivot_idx = random.randint(lo, hi)
arr[pivot_idx], arr[hi] = arr[hi], arr[pivot_idx]
pivot = arr[hi]
i = lo
for j in range(lo, hi):
if arr[j] < pivot:
arr[i], arr[j] = arr[j], arr[i]
i += 1
arr[i], arr[hi] = arr[hi], arr[i]
quick_sort(arr, lo, i - 1)
quick_sort(arr, i + 1, hi)
def fast_pow(base, exp, mod=None):
"""快速幂: O(log exp)"""
result = 1
base = base % mod if mod else base
while exp > 0:
if exp & 1: # 最低位为1
result = result * base
if mod: result %= mod
base = base * base
if mod: base %= mod
exp >>= 1
return result
import math
math.gcd(12, 8) # 4
math.lcm(4, 6) # 12 (Python 3.9+)
# 手写辗转相除
def gcd(a, b):
return a if b == 0 else gcd(b, a % b)
def lcm(a, b):
return a // gcd(a, b) * b # 先除后乘防爆
# 加法取模
(a + b) % m = ((a % m) + (b % m)) % m
# 乘法取模
(a * b) % m = ((a % m) * (b % m)) % m
# 减法取模(注意负数)
(a - b) % m = ((a % m) - (b % m) + m) % m
# 幂取模 → 用快速幂
pow(a, b, m) # Python 内置