当前位置: 首页 > java >正文

【LeetCode 热题 100】62. 不同路径——(解法四)组合数学

Problem: 62. 不同路径

文章目录

  • 整体思路
  • 完整代码
  • 时空复杂度
    • 时间复杂度:O(min(m, n))
    • 空间复杂度:O(1)

整体思路

这段代码旨在解决 “不同路径” 问题,但它采用的是一种与动态规划完全不同的 组合数学 (Combinatorics) 方法。这种方法将问题从一个路径计数问题,抽象成了一个排列组合问题,从而可以直接通过数学公式进行计算,效率极高。

  1. 问题重构

    • 要从 m x n 网格的左上角 (0,0) 移动到右下角 (m-1, n-1),机器人必须且只能向下移动 m-1 步,向右移动 n-1 步。
    • 因此,无论走哪条路径,总的移动步数是固定的,即 (m-1) + (n-1) = m + n - 2 步。
    • 任何一条有效的路径,都可以看作是这 m + n - 2 步的一个序列,其中包含了 m-1 个“向下”和 n-1 个“向右”。
  2. 组合数学模型

    • 问题现在转化为:在一个总长度为 m + n - 2 的序列中,选择 m-1 个位置放置“向下”的移动(剩下的位置自然就是“向右”),总共有多少种不同的选择方法?
    • 这正是一个经典的组合问题,可以用组合数公式 C(n, k) 来表示,即“从 n 个不同元素中取出 k 个元素的组合数”。
    • 在这里,n = m + n - 2(总步数),k = m - 1(选择向下移动的步数)。
    • 所以,路径的总数 = C(m + n - 2, m - 1)
  3. 组合数公式的计算

    • 组合数公式为: C(n, k) = n! / (k! * (n-k)!)
    • 代入我们的变量:C(m+n-2, m-1) = (m+n-2)! / ((m-1)! * (n-1)!)
    • 直接计算阶乘可能会导致非常大的中间数,从而轻易地超出 long 类型的范围,导致溢出。
    • 因此,代码采用了一种更聪明的迭代计算方式来求解组合数。
    • C(m+n-2, m-1)可以展开为:
      [(m+n-2) * (m+n-3) * ... * (n)] / [(m-1) * (m-2) * ... * 1]
    • 代码中的循环 for (int i = 1; i <= m - 1; i++) 正是实现了这个展开式。在每次迭代中:
      • ans 乘以 (n - 1 + i),这对应了分子中的一项。
      • ans 除以 i,这对应了分母中的一项。
    • ans = ans * (n - 1 + i) / i; 这种交替进行乘法和除法的方式,可以有效地保持中间结果 ans 尽可能小,从而避免溢出。同时,由于组合数必然是整数,这里的除法也保证是整除。
  4. 数据类型

    • 使用 long 类型的 ans 变量是为了防止在计算过程中,即使交替乘除,中间结果也可能超出 int 的范围。

完整代码

class Solution {/*** 计算从 m x n 网格的左上角到右下角的不同路径数(组合数学法)。* @param m 网格的行数* @param n 网格的列数* @return 不同的路径总数*/public int uniquePaths(int m, int n) {// ans 用于存储计算结果。使用 long 类型防止中间过程溢出。// 初始化为 1,因为 1 是乘法单位元。long ans = 1;// 该循环用于计算组合数 C(m+n-2, m-1)。// 循环 m-1 次,对应组合数公式展开后的 m-1 项。for (int i = 1; i <= m - 1; i++) {// 核心计算步骤:ans = ans * (分子项) / (分母项)// 分子项从 n 开始,递增 m-1 次,即 n, n+1, ..., n+m-2//   在循环中,当 i=1, (n-1+i) = n; 当 i=m-1, (n-1+i) = n+m-2// 分母项是 (m-1)!,即 1, 2, ..., m-1//   在循环中,i 恰好遍历了 1, 2, ..., m-1ans = ans * (n - 1 + i) / i;}// 将最终的 long 类型结果强制转换为 int 并返回。// 题目的约束保证最终结果不会超出 int 范围。return (int) ans;}
}

时空复杂度

时间复杂度:O(min(m, n))

  1. 循环:算法的核心是一个 for 循环,它从 i = 1 遍历到 m-1
  2. 计算依据
    • 循环的执行次数是 m-1 次。因此,时间复杂度为 O(m)
    • 优化说明:根据组合数的性质 C(n, k) = C(n, n-k),我们可以选择计算 C(m+n-2, m-1)C(m+n-2, n-1)。为了使循环次数最少,我们应该选择 min(m-1, n-1) 作为循环的次数。因此,一个更优化的实现的时间复杂度是 O(min(m, n))
    • 尽管当前代码固定为 O(m),但其本质是线性的,并且可以轻松优化到 O(min(m, n))

空间复杂度:O(1)

  1. 主要存储开销:算法没有创建任何与输入规模 mn 成比例的新的数据结构。
  2. 辅助变量:只使用了 ansi 等几个固定数量的变量。

综合分析
算法所需的额外辅助空间是常数级别的。因此,其空间复杂度为 O(1)。这是解决此问题时空效率最高的方法。

http://www.xdnf.cn/news/19278.html

相关文章:

  • Scikit-learn Python机器学习 - Scikit-learn加载数据集
  • 49.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--扩展功能--集成网关--Refit跨服务调用
  • Photoshop - Ps Camera Raw 滤镜
  • 爱普生L3255打印机故障记录
  • 算法(②排序算法)
  • 在word以及latex中引用zotero中的参考文献
  • JVM架构图是怎样的?
  • Python - 机器学习:从 “教电脑认东西” 到 “让机器自己学规律”
  • 第7.5节:awk语言 switch 语句
  • Kubernetes 部署与发布完全指南:从 Pod 到高级发布策略
  • Ruoyi-vue-plus-5.x第一篇Sa-Token权限认证体系深度解析:1.3 权限控制与注解使用
  • Python爬虫实战:构建Widgets 小组件数据采集和分析系统
  • c++--线程休眠/sleep
  • springboot提前注册bean
  • react组件
  • 【深度学习新浪潮】有没有什么方法可以将照片变成线描稿,比如日式漫画的那种?
  • Java高并发架构核心技术有哪些?
  • MySQL数据库迁移到KingbaseES完整指南
  • 类和反射的机制
  • Redis桌面客户端
  • Windows驱动开发与双机调试环境[驱动开发环境配置高阶]
  • 使用 Ansible 和 Azure Pipelines 增强您的 DevOps
  • Qt实战:如何打开摄像头并实现视频的实时预览
  • 2025年09月计算机二级Java选择题每日一练——第十二期
  • macOs上ffmpeg带入libx264库交叉编译
  • 【龙泽科技】汽车电气故障诊断仿真教学软件【迈腾380TSI】
  • WebGIS视角:体感温度实证,哪座“火炉”火力全开?
  • centos7中MySQL 5.7.32 到 5.7.44 升级指南:基于官方二进制包的原地替换式升级
  • xAI发布全新编码模型 grok‑code‑fast‑1!
  • Kafka 消费模型