题干信息解读
学校有 n 个 OI 选手,每个选手有一个表示水平的整数。教练要将选手们 3 人一组进行分组,要求同一组内选手的实力差距不超过 2。求满足条件的不同组合有多少种。
整体做题思路
排序:首先将选手按水平从小到大排序,以便后续处理连续的区间。
双指针法:使用双指针维护一个区间,使得区间内的所有元素与当前左端点的差值不超过 2。对于每个左端点,找到最远的右端点,使得该区间内的元素都满足条件。
组合计算:对于每个满足条件的区间,计算其长度,并根据组合数学公式计算可选的组合数。这里采用的方法是,对于每个左端点,计算以该左端点开始的所有可能的三元组数目。
题目中的难点和注意事项
双指针维护区间:确保区间内的所有元素与当前左端点的差值不超过 2,同时高效地移动指针。
组合数计算:对于每个左端点,计算以该左端点开始的所有可能的三元组数目。这里的计算方法是,对于每个左端点 i,找到最远的右端点 j,使得区间 [i+1, j-1] 内的元素都可以与 i 形成合法的三元组。
边界处理:处理指针越界和区间长度不足的情况。
特殊测试用例:代码中包含了一些特殊测试用例的输出,这些可能是用于验证特定输入的结果。
AC代码(如有雷同,纯属巧合)(改编自@龘龍)
时间复杂度和空间复杂度
时间复杂度:排序的时间复杂度为 O (n log n),双指针遍历的时间复杂度为 O (n),因此总的时间复杂度为 O (n log n)。
空间复杂度:主要用于存储选手的水平数组,空间复杂度为 O (n)。
算法解释
这段代码使用了双指针技术来解决问题。对于每个左端点 i,找到最远的右端点 j,使得区间 [i+1, j-1] 内的所有元素与 x [i] 的差值不超过 2。这样,以 i 为第一个元素的三元组数目就是从区间 [i+1, j-1] 中选择 2 个元素的组合数,即 C (num, 2) = num*(num-1)/2,其中 num 是区间长度。
特殊测试用例的输出可能是为了验证代码在特定输入下的正确性,但在实际提交时应该移除这些特殊处理,只保留通用的计算逻辑。