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

Python中如何避免多层嵌套for循环(含迭代范围依赖外层场景)

优化多层嵌套循环:寻找满足等差数列条件的三元组

首先,我们来拆解你的问题:你需要找出数组中满足 arr[i] - arr[j] = arr[j] - arr[k] = d 且 i < j < k 的三元组。原代码用了三层嵌套循环,时间复杂度是O(n³),当数组规模变大时效率会极低。下面我会给出几种优化方案,帮你摆脱多层嵌套的困扰。

核心思路:把循环验证转化为查找问题

原问题的条件可以等价转换:对于中间元素 arr[j],我们需要找到arr[j] - d(对应arr[k],且k < j)和arr[j] + d(对应arr[i],且i > j)——哦不对,等一下,根据你给出的条件arr[i]-arr[j] = d和arr[j]-arr[k] = d,应该是arr[i] = arr[j] + d,arr[k] = arr[j] - d,同时i < j < k?这在递增数组里其实不成立(因为k > j的话arr[k]应该比arr[j]大),所以我推测你可能是想找公差为d的等差数列三元组,也就是arr[j] - arr[i] = arr[k] - arr[j] = d且i < j < k。下面的方案我会基于这个更常见的场景来写,如果你的需求确实是原条件,只需要调整查找的目标值即可。

方案一:用哈希表快速定位元素和索引

我们可以先把数组元素和对应的索引存到字典里,然后遍历每个可能的中间索引j,直接查找是否存在符合条件的左右元素,同时验证索引顺序:

from collections import defaultdict

arr = [1, 2, 4, 5, 7, 8, 10]
d = 3
list1 = []

# 构建元素到所有索引的映射(处理重复元素)
element_indices = defaultdict(list)
for idx, num in enumerate(arr):
    element_indices[num].append(idx)

# 遍历每个中间元素的索引j
for j in range(len(arr)):
    left_val = arr[j] - d  # 左边需要的元素值(arr[i])
    right_val = arr[j] + d  # 右边需要的元素值(arr[k])
    
    # 检查左边是否存在符合条件的i(i < j)
    if left_val in element_indices:
        for i in element_indices[left_val]:
            if i < j:
                # 检查右边是否存在符合条件的k(k > j)
                if right_val in element_indices:
                    for k in element_indices[right_val]:
                        if k > j:
                            list1.append((arr[i], arr[j], arr[k]))

print(list1)  # 输出: [(1, 4, 7), (2, 5, 8), (4, 7, 10)]

这个方案的时间复杂度平均情况下是O(n²)(最坏情况如果有大量重复元素可能接近O(n³),但远好于原生三层循环),因为我们用哈希表把内层的遍历查找变成了快速定位。

方案二:有序数组用二分查找优化

如果你的数组是有序的(比如示例中的数组),可以用二分查找进一步降低查找的时间复杂度:

import bisect

arr = [1, 2, 4, 5, 7, 8, 10]
d = 3
list1 = []

n = len(arr)
for j in range(n):
    left_val = arr[j] - d
    # 二分查找左边元素的位置
    left_pos = bisect.bisect_left(arr, left_val)
    if left_pos < j and arr[left_pos] == left_val:
        # 找到所有符合i < j的索引
        left_start = bisect.bisect_left(arr, left_val)
        left_end = bisect.bisect_right(arr, left_val)
        right_val = arr[j] + d
        # 二分查找右边元素的位置
        right_pos = bisect.bisect_right(arr, right_val) - 1
        if right_pos > j and arr[right_pos] == right_val:
            # 找到所有符合k > j的索引
            right_start = bisect.bisect_left(arr, right_val)
            right_end = bisect.bisect_right(arr, right_val)
            # 收集所有符合条件的三元组
            for i in range(left_start, left_end):
                if i < j:
                    for k in range(right_start, right_end):
                        if k > j:
                            list1.append((arr[i], arr[j], arr[k]))

print(list1)

这个方案的时间复杂度是O(n log n)(排序如果数组无序的话)加上O(n log n)的遍历和二分查找,整体效率比哈希表方案更稳定,尤其适合大规模有序数组。

方案三:直接遍历+哈希表查找(简化版)

如果只需要收集元素值而非索引,还可以更简化:遍历每个元素作为等差数列的第一个元素,然后直接查找后两个元素是否存在:

from collections import defaultdict

arr = [1, 2, 4, 5, 7, 8, 10]
d = 3
list1 = []
element_set = set(arr)
# 存储元素到索引的映射,用于验证顺序
element_indices = {num: idx for idx, num in enumerate(arr)}

for num in arr:
    mid_num = num + d
    end_num = mid_num + d
    if mid_num in element_set and end_num in element_set:
        # 验证索引顺序:num的索引 < mid_num的索引 < end_num的索引
        if element_indices[num] < element_indices[mid_num] < element_indices[end_num]:
            list1.append((num, mid_num, end_num))

print(list1)

这个方案更简洁,时间复杂度是O(n),但只适用于数组中元素不重复的情况(如果有重复元素,需要调整映射为索引列表)。

通用优化思路总结

当遇到多层嵌套循环且内层循环依赖外层迭代值时,你可以:

  • 重构问题条件:把循环需要验证的条件转化为“查找是否存在满足要求的元素”,减少嵌套层数;
  • 使用哈希表/集合:提前存储元素信息,将O(n)的遍历查找转化为O(1)的快速查找;
  • 利用有序特性:如果数组有序,用二分查找、双指针等方法进一步降低时间复杂度;
  • 减少不必要的遍历:只遍历可能符合条件的元素范围,而非整个数组。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:45:53