doocs/leetcode 数论算法精解:从基础到高阶实战指南

doocs/leetcode 数论算法精解:从基础到高阶实战指南

【免费下载链接】leetcode 🔥LeetCode solutions in any programming language | 多种编程语言实现 LeetCode、《剑指 Offer(第 2 版)》、《程序员面试金典(第 6 版)》题解 【免费下载链接】leetcode 项目地址: https://gitcode.com/doocs/leetcode

还在为LeetCode中的数论题目头疼吗?面对素数判定、最大公约数、模运算等数学问题无从下手?本文带你系统掌握doocs/leetcode项目中所有数论算法核心技巧,一文解决你的数学算法难题!

读完本文你将获得:

  • ✅ 数论算法核心概念与理论基础
  • ✅ 10+种经典数论问题解法模板
  • ✅ 20+道LeetCode数论题目详细解析
  • ✅ 高效算法实现与优化技巧
  • ✅ 实战代码示例与复杂度分析

数论算法基础概念

1. 素数(质数)判定与生成

素数定义:大于1的自然数中,除了1和它本身以外不再有其他因数的数。

埃拉托斯特尼筛法(Sieve of Eratosthenes)
def count_primes(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]:
            for j in range(i*i, n, i):
                is_prime[j] = False
    return sum(is_prime)

复杂度分析

  • 时间复杂度:O(n log log n)
  • 空间复杂度:O(n)

2. 最大公约数(GCD)与最小公倍数(LCM)

欧几里得算法(辗转相除法)
def gcd(a: int, b: int) -> int:
    while b:
        a, b = b, a % b
    return a

def lcm(a: int, b: int) -> int:
    return a * b // gcd(a, b)

数学原理:gcd(a, b) = gcd(b, a mod b)

核心数论算法分类

1. 模运算与同余定理

快速幂算法(Fast Exponentiation)
def pow_mod(base: int, exponent: int, modulus: int) -> int:
    result = 1
    base = base % modulus
    while exponent > 0:
        if exponent % 2 == 1:
            result = (result * base) % modulus
        exponent = exponent >> 1
        base = (base * base) % modulus
    return result

2. 素数相关算法

算法类型时间复杂度空间复杂度适用场景
试除法O(√n)O(1)单个素数判断
埃氏筛O(n log log n)O(n)区间素数统计
线性筛O(n)O(n)需要质因数分解

3. 数论分块与莫比乌斯反演

def sum_divisors(n: int) -> int:
    result = 0
    i = 1
    while i <= n:
        j = n // (n // i)
        result += (n // i) * (i + j) * (j - i + 1) // 2
        i = j + 1
    return result

LeetCode数论题目精选解析

题目1:计数质数(204. Count Primes)

问题描述:统计所有小于非负整数 n 的质数的数量。

解法思路

  1. 使用埃拉托斯特尼筛法标记非素数
  2. 从2开始遍历到√n
  3. 标记所有倍数

代码实现

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]:
                for j in range(i*i, n, i):
                    is_prime[j] = False
        return sum(is_prime)

题目2:快乐数(202. Happy Number)

问题描述:判断一个数是否是快乐数。

解法思路

  1. 使用快慢指针检测循环
  2. 数学性质:不快乐数最终会进入4→16→37→58→89→145→42→20→4的循环
class Solution:
    def isHappy(self, n: int) -> bool:
        def get_next(number):
            total_sum = 0
            while number > 0:
                digit = number % 10
                total_sum += digit * digit
                number //= 10
            return total_sum
        
        slow = n
        fast = get_next(n)
        while fast != 1 and slow != fast:
            slow = get_next(slow)
            fast = get_next(get_next(fast))
        return fast == 1

题目3:分数到小数(166. Fraction to Recurring Decimal)

问题描述:给定两个整数,分别表示分数的分子和分母,返回字符串形式的小数。

解法思路

  1. 处理正负号
  2. 计算整数部分
  3. 计算小数部分,使用哈希表记录余数位置检测循环节
class Solution:
    def fractionToDecimal(self, numerator: int, denominator: int) -> str:
        if numerator == 0:
            return "0"
        
        result = []
        if (numerator < 0) ^ (denominator < 0):
            result.append("-")
        
        num = abs(numerator)
        den = abs(denominator)
        
        result.append(str(num // den))
        remainder = num % den
        if remainder == 0:
            return "".join(result)
        
        result.append(".")
        remainder_map = {}
        while remainder != 0:
            if remainder in remainder_map:
                result.insert(remainder_map[remainder], "(")
                result.append(")")
                break
            
            remainder_map[remainder] = len(result)
            remainder *= 10
            result.append(str(remainder // den))
            remainder %= den
        
        return "".join(result)

数论算法实战技巧

1. 模运算性质应用

mermaid

2. 素数测试优化策略

方法原理适用场景
试除法检查2到√n的因数小范围素数判断
Miller-Rabin概率性素数测试大数素数判断
AKS算法确定性多项式时间理论证明

3. 组合数计算与模运算

def nCr_mod(n: int, r: int, mod: int) -> int:
    if r < 0 or r > n:
        return 0
    if r == 0 or r == n:
        return 1
    
    # 预计算阶乘和逆元
    fact = [1] * (n + 1)
    inv_fact = [1] * (n + 1)
    
    for i in range(1, n + 1):
        fact[i] = fact[i-1] * i % mod
    
    inv_fact[n] = pow(fact[n], mod-2, mod)
    for i in range(n, 0, -1):
        inv_fact[i-1] = inv_fact[i] * i % mod
    
    return fact[n] * inv_fact[r] % mod * inv_fact[n-r] % mod

高级数论问题解析

1. 中国剩余定理(Chinese Remainder Theorem)

问题场景:解决同余方程组

x ≡ a₁ (mod m₁)
x ≡ a₂ (mod m₂)
...
x ≡ aₖ (mod mₖ)

解法模板

def crt(a_list, m_list):
    M = 1
    for m in m_list:
        M *= m
    
    result = 0
    for a, m in zip(a_list, m_list):
        M_i = M // m
        inv = pow(M_i, -1, m)
        result = (result + a * M_i * inv) % M
    
    return result

2. 原根与离散对数

原根定义:模m下的原根g满足g^1, g^2, ..., g^(φ(m))模m两两不同

def find_primitive_root(p):
    if p == 2:
        return 1
    
    factors = prime_factors(p-1)
    for g in range(2, p):
        is_primitive = True
        for factor in factors:
            if pow(g, (p-1)//factor, p) == 1:
                is_primitive = False
                break
        if is_primitive:
            return g
    return -1

性能优化与实战建议

1. 算法选择策略

mermaid

2. 内存优化技巧

  • 使用位图代替布尔数组(8倍空间节省)
  • 分块处理大数据集
  • 利用数学性质减少计算量

3. 常见陷阱与调试技巧

  1. 整数溢出:使用Python自动处理大整数,其他语言注意使用long类型
  2. 边界条件:特别注意0和1的处理
  3. 负数处理:模运算中负数的处理需要特别注意
  4. 循环检测:使用哈希表记录状态避免无限循环

总结与进阶学习

通过本文的系统学习,你已经掌握了LeetCode数论算法的核心知识和实战技巧。数论作为算法竞赛和面试中的重要组成部分,需要不断的练习和总结。

下一步学习建议

  1. 刷完doocs/leetcode中所有数学标签的题目
  2. 学习更高级的数论算法:FFT、NTT、生成函数等
  3. 参加算法竞赛实战锻炼
  4. 阅读《具体数学》、《算法导论》等经典著作

记住,数论算法的学习是一个循序渐进的过程,多思考数学背后的原理,而不仅仅是记忆模板代码。祝你算法学习之路顺利!

如果觉得本文对你有帮助,请点赞收藏支持,欢迎关注后续更多算法精讲文章!

【免费下载链接】leetcode 🔥LeetCode solutions in any programming language | 多种编程语言实现 LeetCode、《剑指 Offer(第 2 版)》、《程序员面试金典(第 6 版)》题解 【免费下载链接】leetcode 项目地址: https://gitcode.com/doocs/leetcode

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值