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

生成无循环旋转冗余的指定长度二进制序列的优化方案咨询

更优的二进制循环无重复序列生成方案

现有实现的核心问题

你的当前代码完全无法处理size≥20的场景,更别说目标中的1000,根源有两个:

  • 内存爆炸:先生成所有2^size个二进制序列,size=20时就有104万条记录,size=30突破10亿,size=1000更是天文数字,根本不可能存入内存。
  • 效率极低:嵌套循环遍历所有序列和位移,加上多次调用np.delete(每次都是O(n)操作),时间复杂度达到O(2^size * size),完全不可扩展。

核心优化思路:直接生成循环等价类的代表元

你需要的其实是二进制项链(Necklace)——每个项链是一个二进制序列,且是其所有循环位移中的唯一代表(通常选字典序最小/最大的)。我们不需要生成所有序列再去重,而是直接构造这些代表元,这是唯一能处理大size的方式。

高效实现方案

方案1:递归生成字典序最小的项链

通过递归构造满足「自身是所有循环位移中字典序最小」的序列,每个生成的序列都是一个唯一的循环等价类代表:

import numpy as np

def generate_binary_necklaces(size):
    necklaces = []
    def backtrack(current):
        length = len(current)
        if length == size:
            necklaces.append(np.array(current))
            return
        # 只尝试添加0或1,且保证当前序列是字典序最小的
        for bit in [0, 1]:
            candidate = current + [bit]
            # 检查所有循环位移是否都不小于当前候选序列
            is_min = True
            for shift in range(1, length + 1):
                shifted = candidate[shift:] + candidate[:shift]
                if shifted < candidate:
                    is_min = False
                    break
            if is_min:
                backtrack(candidate)
    backtrack([])
    return np.array(necklaces)

方案2:Fredricksen-Maiorana算法(专业项链生成)

这是专门用于高效生成项链的经典算法,时间复杂度为O(N)(N为项链总数),比递归方法效率更高,适合更大的size:

import numpy as np

def fredricksen_maiorana(size):
    necklaces = []
    a = [0] * (size + 1)  # 用1-based索引简化逻辑
    k = 1
    while True:
        if k > size:
            necklaces.append(np.array(a[1:size+1]))
            k = size
        while a[k] == 1:
            a[k] = 0
            k -= 1
        if k == 0:
            break
        a[k] = 1
        # 仅当当前前缀无法通过重复更小周期得到时,才生成项链
        if size % k != 0:
            m = size // k
            candidate = a[1:k] * m
            is_necklace = True
            # 检查所有更小周期的位移是否比当前候选更小
            for d in range(1, k):
                if size % d == 0:
                    m_d = size // d
                    shifted = a[d+1:k] + a[1:d+1]
                    shifted_full = shifted * m_d
                    if shifted_full < candidate:
                        is_necklace = False
                        break
            if is_necklace:
                necklaces.append(np.array(candidate))
        k += 1
    return np.array(necklaces)

方案优势说明

  • 数量级差距:二进制项链的数量远小于2^size,比如size=10时项链数是102,而总组合数是1024;size=20时项链数仅6275,远小于100万的总组合数。
  • 可扩展性:即使size=1000,虽然项链数量依然很大,但至少不需要生成2^1000个序列,而是直接构造代表元,内存和时间上具备可行性。

结果验证

以size=5为例,运行fredricksen_maiorana(5)会得到和你现有实现完全一致的结果:

[[1 1 1 1 1]
 [1 0 1 1 1]
 [0 0 1 1 1]
 [0 1 0 1 1]
 [0 0 0 1 1]
 [0 0 1 0 1]
 [0 0 0 0 1]
 [0 0 0 0 0]]

内容的提问来源于stack exchange,提问作者Даніель Скрибайло-Леськів

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 20:06:33