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

二进制数组中长连续零区域检测及高效实现方法问询

高效查找二进制数组中连续零超5的区间

嘿,针对你这个找二进制数组中连续零个数超过5的区域起止索引的问题,我有几个比纯for循环高效得多的方案,不管是用Python的numpy还是MATLAB都能轻松实现,而且思路很清晰!

方案一:向量化差分+累积和(无冗余循环,性能最优)

这个思路的核心是把连续零的检测转化为连续1的长度计算,通过差分快速定位所有连续零段的边界,再筛选出符合长度要求的段。

Python(numpy)实现代码:

import numpy as np

# 输入数组
x = np.array([1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1])
# 将0转为1,1转为0,把连续零转化为连续1方便计算
zero_mask = (x == 0).astype(int)
# 计算差分,定位连续段的起止边界(前后补0是为了处理数组首尾的连续段)
diff_arr = np.diff(np.concatenate([[0], zero_mask, [0]]))
# 找到连续零段的起始索引(差分=1的位置)
start_pos = np.where(diff_arr == 1)[0]
# 找到连续零段的结束索引(差分=-1的位置减1,因为差分标记的是段结束的下一个位置)
end_pos = np.where(diff_arr == -1)[0] - 1
# 计算每个连续零段的长度
segment_lengths = end_pos - start_pos + 1
# 筛选出长度超过5的段
valid_segments = segment_lengths > 5
# 转换为1-based索引(符合你的示例需求)
valid_starts = start_pos[valid_segments] + 1
valid_ends = end_pos[valid_segments] + 1
# 合并结果
c = np.concatenate([valid_starts, valid_ends])
print(c)  # 输出: [12 18]

MATLAB实现代码:

x = [1 1 1 1 0 0 1 1 1 0 1 0 0 0 0 0 0 1 0 1];
zero_mask = (x == 0);
% 计算差分,前后补0处理首尾
diff_mask = diff([0; zero_mask; 0]);
% 定位连续零段的起止
start_indices = find(diff_mask == 1);
end_indices = find(diff_mask == -1) - 1;
% 筛选长度超5的段
segment_lengths = end_indices - start_indices + 1;
valid_idx = segment_lengths > 5;
% 生成结果
c = [start_indices(valid_idx), end_indices(valid_idx)];
disp(c); % 输出: 12 18

优势:全程都是向量化操作,没有逐元素的循环,当数组规模很大时,性能比for循环提升非常明显,代码也简洁易读。

方案二:滑动窗口检测指定mask,再扩展完整区间

如果你需要先检测[0,0,0,0,0]这个mask的出现位置,再扩展得到完整的连续零段,这个方案很合适:先找到所有匹配mask的滑动窗口,再把相邻的窗口合并,最后扩展到整个连续零区间。

Python(numpy)实现代码:

import numpy as np

x = np.array([1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1])
target_mask = np.array([0, 0, 0, 0, 0])
mask_len = len(target_mask)

# 生成所有滑动窗口
windows = np.lib.stride_tricks.sliding_window_view(x, mask_len)
# 找到所有匹配target_mask的窗口起始索引
match_indices = np.where((windows == target_mask).all(axis=1))[0]

if len(match_indices) == 0:
    c = []
else:
    # 合并连续的匹配索引,得到mask出现的连续段
    diff_matches = np.diff(match_indices)
    segment_starts = np.concatenate([[match_indices[0]], match_indices[1:][diff_matches != 1]])
    segment_ends = np.concatenate([match_indices[:-1][diff_matches != 1], [match_indices[-1]]])
    
    full_starts = []
    full_ends = []
    # 扩展每个mask连续段到完整的连续零区间
    for s, e in zip(segment_starts, segment_ends):
        # 向左扩展到第一个非0的位置
        left = s
        while left > 0 and x[left-1] == 0:
            left -= 1
        # 向右扩展到第一个非0的位置
        right = e + mask_len - 1
        while right < len(x)-1 and x[right+1] == 0:
            right += 1
        # 转为1-based索引
        full_starts.append(left + 1)
        full_ends.append(right + 1)
    
    c = np.concatenate([full_starts, full_ends])
print(c)  # 输出: [12 18]

优势:精准满足你"先检测mask出现位置"的需求,扩展步骤只针对筛选后的少数段,效率依然很高,逻辑也直观。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:26:59