LeetCode 1359题解析:有效快递序列的动态规划解法

发布时间:2026/11/3 12:56:15
LeetCode 1359题解析:有效快递序列的动态规划解法 1. 问题背景与理解1359题Count All Valid Pickup and Delivery Options是LeetCode上一道典型的排列组合数学题。题目要求计算所有有效的快递取件和送件序列数目其中每个快递必须先取件(P)后送件(D)n个快递意味着有2n个操作步骤。我第一次看到这个题目时直觉认为可以通过全排列除以重复排列来计算。但实际操作中发现单纯的排列组合无法满足P必须出现在对应D之前的约束条件。这让我意识到需要更系统性的解法。2. 暴力解法与问题分析最直观的暴力解法是生成所有可能的排列然后筛选出满足条件的序列。对于n2的情况总共有4! 24种排列其中有效的只有以下6种P1, P2, D1, D2P1, P2, D2, D1P1, D1, P2, D2P2, P1, D1, D2P2, P1, D2, D1P2, D2, P1, D1显然暴力解法的时间复杂度是O((2n)!)这在n较大时完全不现实。我们需要寻找更高效的数学规律或动态规划解法。3. 动态规划解法推导3.1 状态定义与递推关系设f(n)表示n个快递的有效序列数目。我们可以从n-1的情况推导n的情况当新增第n个快递时我们需要在已有的2(n-1)个操作中插入Pn和Dn且Pn必须位于Dn之前。这相当于在2n-1个位置中选择2个位置第一个放Pn第二个放Dn。因此递推公式为 f(n) f(n-1) * C(2n-1, 2) f(n-1) * (2n-1)*n3.2 数学证明与简化让我们更严格地证明这个递推关系对于n-1个快递有2(n-1)个操作。插入Pn和Dn时有2n-1个间隙可以插入Pn包括开头和结尾插入Pn后序列长度变为2n-1此时有2n个位置可以插入Dn但因为Dn必须在Pn之后所以实际可插入Dn的位置是2n - (Pn的位置)因此总的选择数是 sum_{k1 to 2n-1} (2n - k) sum_{i1 to 2n-1} i (2n-1)*n3.3 基础情况与递推实现基础情况 f(1) 1 (只有P1,D1一种序列)递推实现 f(n) f(n-1) * (2n-1) * n mod 1e974. 代码实现与优化4.1 基本动态规划实现def countOrders(n: int) - int: MOD 10**9 7 dp [0] * (n 1) dp[1] 1 for i in range(2, n 1): dp[i] dp[i - 1] * (2 * i - 1) * i % MOD return dp[n]4.2 空间优化版本观察到当前状态只依赖前一个状态可以优化空间def countOrders(n: int) - int: MOD 10**9 7 res 1 for i in range(2, n 1): res res * (2 * i - 1) * i % MOD return res4.3 数学公式直接计算进一步推导可以得到直接计算公式 f(n) (2n)! / (2^n) product_{k1 to n} (2k-1)*k实现代码def countOrders(n: int) - int: MOD 10**9 7 return math.factorial(2 * n) // (2 ** n) % MOD5. 复杂度分析与边界条件5.1 时间复杂度动态规划解法时间复杂度O(n)只需一次遍历空间复杂度O(1)优化后版本数学公式解法时间复杂度取决于阶乘计算实现通常为O(n)空间复杂度O(1)5.2 边界条件处理需要特别注意n0时根据题意应该返回1空序列大数取模运算避免中间结果溢出Python中整数除法与模运算的优先级修正后的鲁棒实现def countOrders(n: int) - int: if n 0: return 1 MOD 10**9 7 res 1 for i in range(2, n 1): res res * (2 * i - 1) * i % MOD return res6. 测试用例与验证6.1 手工验证小规模案例n1: 1 (P1D1) n2: 6 (如上所列) n3: 90 n4: 25206.2 自动化测试代码import unittest class TestCountOrders(unittest.TestCase): def test_cases(self): test_cases [ (1, 1), (2, 6), (3, 90), (4, 2520), (8, 729647433), (500, 764678010) ] for n, expected in test_cases: with self.subTest(nn): self.assertEqual(countOrders(n), expected) if __name__ __main__: unittest.main()7. 算法优化与变种思考7.1 并行计算优化对于极大的n如n1e6可以考虑将乘积分解为多个区间并行计算使用快速幂算法优化模运算7.2 相关变种问题如果每个快递有k个操作而非2个序列数目如何计算如果某些快递有优先级约束如P1必须在P2之前如何计算如果考虑时间窗口约束如某些D必须在P后特定时间内完成如何建模7.3 数学性质深入这个问题实际上与电话杆问题Telephone Pole Problem相关计算的是有约束的排列数。更一般地这类问题可以使用多重排列公式生成函数方法群论中的对称性分析8. 实际应用与扩展虽然题目设定是快递序列但类似模型可以应用于任务调度有先后依赖关系的任务安排编译器优化指令重排中的约束满足工作流引擎有状态转换的业务流程游戏AI动作序列的合法性验证我在实际工作中曾遇到一个类似问题设计一个分布式事务系统需要确保所有子事务的准备和提交操作满足特定顺序约束。这道题的解法给了我很大启发。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询