Python如何查找列表中偏差≤0.5%且长度≥3的连续序列
问题分析
需求是从给定数值列表中提取所有满足以下条件的连续子序列:
- 序列长度至少为3
- 序列内元素的相对偏差不超过0.5%
以测试列表[1,2,1.5,2,1.99,2.01,4]为例,符合要求的子序列为[2,1.99,2.01]。
原有代码存在三个核心问题:
- 仅比对相邻两个元素的偏差,没有跟踪当前连续匹配序列的基准值,无法判断序列是否满足长度要求
- 偏差阈值配置错误,代码里写的是5%(对应系数0.95/1.05),和需求要求的0.5%不符
- 仅零散收集符合相邻匹配要求的单个元素,没有做完整序列的拼接、长度校验逻辑,无法输出符合格式的结果
实现方案
采用滑动起点遍历的逻辑实现,逻辑清晰易调试,适配多匹配序列的场景:
- 遍历所有可能的序列起点,起点最大位置为列表倒数第3位(后续元素凑不够最小长度3的要求)
- 记录当前起点的基准值,计算允许的数值上下界
- 从起点下一位开始向后遍历,遇到超出偏差范围的元素立即终止当前轮次遍历
- 若当前收集到的连续序列长度≥3,就将其存入结果集
def find_match_sequences(input_list, allowed_deviation=0.005, min_seq_length=3): match_result = [] list_length = len(input_list) # 遍历所有可能的序列起点 for start_idx in range(list_length - min_seq_length + 1): base_val = input_list[start_idx] val_lower_bound = base_val * (1 - allowed_deviation) val_upper_bound = base_val * (1 + allowed_deviation) current_seq = [base_val] # 向后延伸匹配连续符合偏差要求的元素 for end_idx in range(start_idx + 1, list_length): current_val = input_list[end_idx] if val_lower_bound <= current_val <= val_upper_bound: current_seq.append(current_val) else: break # 长度达标则加入结果 if len(current_seq) >= min_seq_length: match_result.append(current_seq.copy()) return match_result # 测试样例验证 if __name__ == "__main__": test_list = [1,2,1.5,2,1.99,2.01,4] print(find_match_sequences(test_list)) # 输出结果:[[2, 1.99, 2.01]]
注意事项
- 如果需求是相邻元素之间偏差不超过0.5%,而非所有元素和序列起点值的偏差不超过0.5%,只需要把上下界计算的基准值从固定的序列起点值,改成当前序列的最后一个元素,动态更新上下界即可
- 允许偏差、最小序列长度都做成了函数参数,需要调整规则时直接传参即可,比如要改回原代码写的5%偏差,传参
allowed_deviation=0.05就行 - 如果列表长度很大,可以优化成单指针滑动窗口逻辑,不用每个起点都重新向后遍历,时间复杂度可以从O(n²)降到O(n),常规长度列表用上面的写法完全够用
内容的提问来源于stack exchange,提问作者Maximilian Krug
相关产品推荐
相关产品推荐

