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

Python约瑟夫排列O(n²)时间复杂度优化方案咨询

优化约瑟夫排列的时间复杂度

原代码性能瓶颈

你的代码核心问题在于array.pop(index)操作:Python的list基于动态数组实现,删除中间元素时需要将后续所有元素向前移动,单次操作时间复杂度为O(n),循环n次后整体时间复杂度达到O(n²),当n规模扩大到万级以上时,耗时会急剧上升。

优化方案

方案1:使用SortedList(第三方库,快速实现)

如果可以引入第三方库sortedcontainers,它的SortedList提供O(logn)时间复杂度的pop(index)操作,直接替换原代码的list即可,几乎无需修改逻辑:

from sortedcontainers import SortedList

def solution(array, k):
    permutation = []
    sl = SortedList(array)
    index = 0
    while sl:
        index = (index + k - 1) % len(sl)
        permutation.append(sl.pop(index))
    return permutation

# 测试
people = 8
arr = [p+1 for p in range(people)]
k = 3
print(solution(arr, k))  # 输出: [3, 6, 1, 5, 2, 8, 4, 7]

该方案时间复杂度为O(nlogn),处理十万级数据也能快速完成。

方案2:手动实现线段树(无第三方库依赖)

若无法使用第三方库,可以实现线段树维护剩余元素的数量,快速定位并删除第k个元素,每次操作时间复杂度为O(logn):

class SegmentTree:
    def __init__(self, size):
        self.n = 1
        while self.n < size:
            self.n <<= 1
        self.tree = [0] * (2 * self.n)
        # 初始化叶子节点:1表示元素存在
        for i in range(size):
            self.tree[self.n + i] = 1
        # 构建线段树
        for i in range(self.n - 1, 0, -1):
            self.tree[i] = self.tree[2*i] + self.tree[2*i+1]
    
    def query(self, k):
        # 找到第k个剩余元素的索引(0-based)
        node = 1
        while node < self.n:
            left_count = self.tree[2*node]
            if k < left_count:
                node = 2*node
            else:
                k -= left_count
                node = 2*node + 1
        return node - self.n
    
    def update(self, idx):
        # 标记idx位置的元素已删除
        node = self.n + idx
        self.tree[node] = 0
        node >>= 1
        while node >= 1:
            self.tree[node] = self.tree[2*node] + self.tree[2*node+1]
            node >>= 1

def solution(array, k):
    permutation = []
    n = len(array)
    st = SegmentTree(n)
    pos = 0
    for m in range(n, 0, -1):
        pos = (pos + k - 1) % m
        idx = st.query(pos)
        permutation.append(array[idx])
        st.update(idx)
    return permutation

# 测试
people = 8
arr = [p+1 for p in range(people)]
k = 3
print(solution(arr, k))  # 输出: [3, 6, 1, 5, 2, 8, 4, 7]

该方案同样为O(nlogn)时间复杂度,完全依赖Python标准库,适合生产环境使用。

方案3:针对连续整数输入的简化

如果你的输入是连续整数(如1到n),可以简化逻辑,但注意该方案本质仍为O(n²),仅代码更简洁,不适用于大规模数据:

def josephus_permutation(n, k):
    permutation = []
    people = list(range(n))
    pos = 0
    for m in range(n, 0, -1):
        pos = (pos + k - 1) % m
        permutation.append(people.pop(pos) + 1)  # 转为1-based编号
    return permutation

# 测试
print(josephus_permutation(8, 3))  # 输出: [3, 6, 1, 5, 2, 8, 4, 7]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 20:35:10