如何高效识别含1、0、-1的数组中连续1集合的起止索引?
性能优化方案
你现有代码耗时高主要有两个核心原因:
- 嵌套逐元素遍历的while循环,Matlab的M语言循环本身执行效率远低于内置优化函数
- 未预分配
startt、endd数组,动态扩容会频繁触发内存重新分配,额外增加大量开销
另外你现有代码里的index变量看起来是笔误,按逻辑应该是1。
最优向量化实现(推荐)
利用你数据的规则:-1固定是连续1块的结束标记,完全可以用内置向量化函数实现,性能比手写循环高10~100倍,代码也更简洁:
% 处理数组起始位是1的边界情况,补一个前置0 padded_slots = [0, link_slots]; % 找所有连续1块的起始位置:当前位是1,前一位不是1 start_idx = find(padded_slots(1:end-1) ~= 1 & padded_slots(2:end) == 1); % 找所有-1的位置,减1就是对应连续1块的结束位置 end_idx = find(link_slots == -1) - 1;
拿你给的示例验证:
输入样例[1 1 1 -1 0 0 0 0 1 1 -1 0 0 1 1 1 1 -1 0 0]
- 找到的
-1位置是4、11、18,减1后得到end_idx = [3,10,17] - 找到的起始位置是1、9、14,和你预期的结果完全一致。
优化后的循环版本(如果需要保留循环逻辑)
如果业务场景需要保留循环写法,可按下面的方式优化,性能也比原有代码提升数倍:
n = numel(link_slots); % 预分配足够大的结果数组,避免动态扩容 max_block_num = floor(n/2); % 最坏情况每两个元素一个块(1 + -1) startt = zeros(1, max_block_num); endd = zeros(1, max_block_num); block_count = 0; i = 1; while i <= n if link_slots(i) == 1 block_count = block_count + 1; startt(block_count) = i; % 直接找当前位置后第一个-1,不用逐次累加j next_neg1 = find(link_slots(i:end) == -1, 1, 'first'); endd(block_count) = i + next_neg1 - 2; % 直接跳转到-1之后的位置,减少无效遍历 i = i + next_neg1; else i = i + 1; end end % 截断预分配的多余空间 startt = startt(1:block_count); endd = endd(1:block_count);
对于长度为800的数组,上述两种方案的单次执行耗时都在微秒级,批量处理数千个数组也不会有性能问题。
内容的提问来源于stack exchange,提问作者knowledge_seeker
相关产品推荐
相关产品推荐

