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

如何解决数组中的魔法子数组计数问题?现有代码超时求优化

优化解法:统计魔法子数组数量(O(n)时间复杂度)

超时原因分析

暴力枚举所有子数组并统计奇数个数的解法时间复杂度为O(n²),当n达到105时,总操作量会突破1010级别,远超出时间限制,必然导致超时。必须采用线性时间的前缀和+计数思路来优化。

核心思路

魔法子数组的定义是「包含非零偶数个奇数的子数组」,可以拆解为:

所有包含偶数个奇数的子数组总数 - 所有全偶数子数组总数(这类子数组的奇数个数为0,不符合「非零」要求)

1. 计算偶数个奇数的子数组总数

将原数组转化为0(偶数)和1(奇数)的二进制数组,定义前缀和s[i]为前i个元素中奇数的个数。子数组[j+1, i]的奇数个数为s[i] - s[j],若该值为偶数,则s[i]与s[j]的奇偶性相同。

统计前缀和中偶数的数量cnt_even和奇数的数量cnt_odd(注意前缀和s[0] = 0,初始时cnt_even = 1),则偶数个奇数的子数组总数为:

total_even = cnt_even * (cnt_even - 1) // 2 + cnt_odd * (cnt_odd - 1) // 2

这是因为从cnt_even个偶数前缀和中任选两个,对应子数组的奇数个数为偶数;同理奇数前缀和的组合也是如此。

2. 计算全偶数子数组总数

遍历数组,统计连续偶数段的长度l,每段贡献l*(l+1)//2个全偶数子数组(连续长度为l的序列,子数组数量为l+(l-1)+...+1),累加所有段的贡献得到total_zero。

3. 最终答案

魔法子数组数量 = total_even - total_zero

代码实现(Python)

def count_magic_subarrays(arr):
    cnt_even = 1  # 前缀和s[0]=0,初始为偶数
    cnt_odd = 0
    current_sum = 0
    
    # 统计前缀和奇偶性数量
    for num in arr:
        if num % 2 == 1:
            current_sum += 1
        if current_sum % 2 == 0:
            cnt_even += 1
        else:
            cnt_odd += 1
    
    total_even = cnt_even * (cnt_even - 1) // 2 + cnt_odd * (cnt_odd - 1) // 2
    
    # 统计全偶数子数组数量
    total_zero = 0
    current_length = 0
    for num in arr:
        if num % 2 == 0:
            current_length += 1
        else:
            total_zero += current_length * (current_length + 1) // 2
            current_length = 0
    # 处理最后一段连续偶数
    total_zero += current_length * (current_length + 1) // 2
    
    return total_even - total_zero

# 测试用例1
print(count_magic_subarrays([2,1,2,3]))  # 输出2
# 测试用例2
print(count_magic_subarrays([1,2,5,2,3,7]))  # 输出7

复杂度分析

  • 时间复杂度:O(n),仅需两次遍历数组,完全满足n≤10^5的约束。
  • 空间复杂度:O(1),仅使用常数额外空间。

内容的提问来源于stack exchange,提问作者Amal T vinod

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 14:41:43