You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python生成非交叉分区求助:算法低效且n=14时内存溢出

优化集合非交叉分区生成的方案

n=14时非交叉分区的总数是卡特兰数C₁₄=2674440,原算法慢且内存溢出,核心问题在于重复计算和内存占用过高,以下是针对性优化方案:

核心优化思路

1. 利用递归结构+缓存避免重复计算

非交叉分区具有天然的递归拆分特性:固定元素1所在的块包含1和k(k∈[1,n]),则区间[2,k-1]和[k+1,n]可独立生成非交叉分区,最终结果由这三部分组合而来。用缓存存储子区间的分区结果,避免重复计算相同区间的分区。

2. 采用紧凑数据结构+懒加载

  • 用元组块替代多层嵌套列表,减少内存开销:比如用[(1,2), (3,5), (4)]表示分区{{1,2},{3,5},{4}},元组比列表更节省内存。
  • 使用**生成器(yield)**逐个生成分区,而非一次性将所有分区加载到内存。这样处理n=14时,内存仅需保留当前生成的单个分区,不会出现溢出。

3. 减少冗余拷贝

递归组合子分区时,复用已有结构而非每次创建新对象,比如用不可变的元组存储块,避免频繁的内存拷贝操作。

示例实现(Python)

from functools import lru_cache

def non_crossing_partitions(n):
    @lru_cache(maxsize=None)
    def generate(start, end):
        if start > end:
            yield []
            return
        # 遍历元素start所在块的右端点k
        for k in range(start, end + 1):
            # 递归生成左右子区间的分区
            for left in generate(start + 1, k - 1):
                for right in generate(k + 1, end):
                    # 组合当前块与左右分区,用元组存储块减少内存
                    yield [(start, k)] + left + right

    # 若不需要一次性持有所有分区,直接返回生成器即可(内存友好)
    # return generate(1, n)
    # 若需要全部结果,转成列表(n=14时约260万条,需确保内存足够)
    return list(generate(1, n))

额外优化建议

  • 如果需要处理更大的n(比如n>15),可以考虑用C++实现,利用指针和内存池进一步降低内存占用。
  • 若仅需统计数量而非生成所有分区,直接计算卡特兰数即可,无需生成具体分区。

内容的提问来源于stack exchange,提问作者Kinkin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 05:45:22