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

Codewars任务Simple Fun #159: Middle Permutation执行超时求助

解决Codewars Simple Fun #159: Middle Permutation的超时问题

我完全懂你的困扰——暴力生成所有排列再取中间项的思路,在字符串长度稍大时(比如n≥10)会直接因为阶乘级的计算量超时,毕竟10!就有360多万个排列,更别说更长的字符串了。咱们换个思路:直接构造中间排列,不需要生成所有排列,这样时间复杂度能降到O(n²),完全能在12000ms内跑过所有测试用例。

核心思路

要构造中间排列,我们可以利用阶乘的特性:对于已排序的字符数组,每个字符作为开头时,后面的字符能生成(n-1)!个排列。我们可以通过计算中间位置对应的每一位字符,逐步确定最终的排列。

具体步骤如下:

  • 先排序字符:把输入字符串的字符按字典序升序排列,这是后续计算的基础。
  • 预计算阶乘:提前算出从0!到(n-1)!的阶乘值(n是字符串长度),方便后续每一步的索引计算。
  • 确定中间位置:排列总数是n!,题目要求:
    • 当n!为偶数时,中间项是第n!/2项(1-based),对应0-based索引为(n!//2) - 1;
    • 当n=1时,唯一的排列就是结果。
  • 逐位构造排列:
    1. 对于当前剩余的字符,计算每个字符开头对应的排列数(即(剩余字符数-1)!);
    2. 用当前剩余位置除以这个排列数,得到要选的字符在剩余列表中的索引;
    3. 把选中的字符加入结果,从剩余列表中移除该字符;
    4. 更新剩余位置为当前位置对排列数取余;
    5. 重复直到所有字符都被选中。

示例实现(Python)

import math

def middle_permutation(s):
    chars = sorted(s)
    n = len(chars)
    if n == 1:
        return s
    
    # 预计算阶乘数组,fact[i] 表示 i!
    fact = [1] * n
    for i in range(1, n):
        fact[i] = fact[i-1] * i
    
    # 计算0-based的中间位置
    mid_position = fact[n] // 2 - 1
    result = []
    remaining_chars = chars.copy()
    
    for i in range(n, 0, -1):
        group_size = fact[i-1]
        # 确定当前要选的字符索引
        char_index = mid_position // group_size
        result.append(remaining_chars.pop(char_index))
        # 更新剩余位置
        mid_position = mid_position % group_size
    
    return ''.join(result)

为什么这个方法高效?

  • 时间复杂度:主要开销在排序(O(n log n))和逐位构造(O(n²),因为每次从列表中移除元素是O(n)操作),对于n=20来说,20²=400次操作,和20!的天文数字比完全不在一个量级。
  • 空间复杂度:只需要存储剩余字符和结果,是O(n)级别的,非常节省内存。

样例验证

比如输入"abc":

  • 排序后为['a','b','c'],n=3,阶乘数组为[1,1,2,6],中间位置是6//2 -1=2;
  • 第一次循环:每组排列数是2! =2,选中索引1的'b',剩余['a','c'],剩余位置更新为2%2=0;
  • 第二次循环:每组排列数是1! =1,选中索引0的'a',剩余['c'];
  • 最后加入'c',结果为"bac",和题目要求的中间项一致(6个排列的第3项,1-based)。

这个方法完全避免了生成所有排列,不管n多大(只要阶乘在Python整数范围内),都能快速计算出结果,肯定能通过所有测试用例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 10:39:48