📅  最后修改于: 2023-12-03 14:54:58.216000             🧑  作者: Mango
在一个数字数组中,找出所有符合条件的三元组的个数,条件为:i < j < k 且 a[k] < a[i] < a[j]。
寻找符合条件的三元组,我们需要找到一个数对 $(i, j)$,其中 $i < j$,然后分别扫描左边和右边的元素,计算符合条件的三元组个数。
我们可以使用两个数组 $left$ 和 $right$ 来记录当前位置左右两侧的元素中,符合条件的最小、最大值。其中 $left_i$ 记录 $i$ 左侧的最小元素,即:
$$ left_i=\min_{j<i}a_j $$
同理,$right_i$ 记录 $i$ 右侧的最大元素,即:
$$ right_i=\max_{j>i}a_j $$
然后我们将数组 $a$ 从左到右扫描一遍,同时计算符合条件的三元组总数 $ans$,具体方法如下:
$$ ans+=\sum_{i=0}^{j-1}[a_i< a[j]\cdot min_i< a[j]\cdot max_i<a[j]] $$
上述公式中,$min_i$ 和 $max_i$ 分别是元素 $a_0\sim a_{j-1}$ 中,最小和最大的元素值,符合条件的 $i$ 的数量即为计算结果。
def count_triplets(arr: list) -> int:
n = len(arr)
left, right = [0] * n, [0] * n
left[0] = float('inf')
right[n-1] = float('-inf')
ans = 0
# 预处理 left 数组,记录从左边开始,每个位置的最小元素
for i in range(1, n):
left[i] = min(left[i-1], arr[i-1])
# 预处理 right 数组,记录从右边开始,每个位置的最大元素
for i in range(n-2, -1, -1):
right[i] = max(right[i+1], arr[i+1])
# 计算符合条件的三元组数量
for i in range(1, n-1):
if left[i] < arr[i] < right[i]:
cnt = sum([1 for j in range(i) if arr[j] < arr[i] < right[j]])
ans += cnt
return ans
预处理 left 和 right 数组的时间复杂度均为 $O(n)$,算法的总时间复杂度为 $O(n^2)$。