至少满足最小值差的列表元素的最大对数
Maximum number of pairs from list elements satisfying at least a minimum value difference
给定一个长度为 n
(例如 n=1000
)的列表 l
,其中(随机)整数元素在 0<l[i]<10^m
范围内(例如 m=5
) ,可以从此列表中提取的两个元素的最大对数是多少(一对中的任何元素都不能与另一对中的任何元素重叠),这样每个元素对的值至少有一个最小差异 0<=diff<10^k
与 0<k<=m
?
生成所有可能的分区并检查每个分区是否具有足够的值距离的最大对数的朴素方法效率非常低。我们怎样才能巧妙地做到这一点?
示例:
考虑列表 l
由以下人员给出:
l = {1, 2, 8, 9, 10, 15};
和允许对中元素之间的最小差异 diff=7
。那么我们可以构造如下满足元素距离要求的不相交对集合:
{ {1,8} , {2,9} }
{ {1,8} , {2,10} }
{ {1,8} , {2,15} }
{ {1,9} , {2,10} , {8,15} }
{ {1,9} , {2,15} }
{ {1,10} , {2,9} , {8,15} }
...etc
请注意,所有选择的对都包含 larger element
减去 smaller element
大于或等于所需的最小值 diff=7
的元素。在上面的例子中,一旦遇到可以构建最大对数(例如3
)的情况,我们就可以停止,因为我们发现答案是3
。但是可能会发生一个列表只允许最大数量的这样的对,其长度小于 l
长度的一半。列表 l
也可能有多个具有相同值的元素,在这种情况下,涉及一个的组合不等同于涉及另一个的数值相同的组合(但推测它们的对数将相同)。
如果每个元素可能出现在任意数量的对中
一共有(n选2)对,所以差值至少diff
的对数等于(n选2)减去差值小于[=10的对数=].
计算这些更容易:对数组进行排序,并使用双指针技术,其中 i < j
是可能对的索引,从 i = 0
和 j = 1
开始。当差异足够小时,递增j
;当差异太大时,则递增 i
,并将 j - i
添加到总数中以说明较小值位于索引 i
处的对。 (通过先递增,我们避免计算差异太大的对。)
由于每次迭代都会递增 i
或 j
,并且任何索引都不会因任何原因变小,因此“计数”阶段的操作总数为 O(n)。因此,首先对数组进行排序的整体时间复杂度为 O(n log n)。
如果每个元素只能出现一对
同样,排序对此有很大帮助。
- 如果
(a, b)
是一对,则任何元素 c < a
也出现在一对中,否则交换 a
和 c
仍然会产生有效对。
- 如果
(a, b)
是一对,则任何元素 d > b
也出现在一对中,否则交换 b
和 d
仍然会产生有效的对。
- 如果
(a, b)
和 (c, d)
都是对,那么 b >= c
,否则交换 b
和 c
仍然会得到两个有效对。
- 如果
(a, b)
和 (c, d)
都是对,并且 a <= c
也是 b <= d
,否则交换 b
和 d
仍然会产生两个有效对。
因此,如果存在 k
对的解决方案,则存在最小 k
元素与最大 k
元素以相同顺序配对的解决方案.所以我们只需要寻找这样的解决方案,通过找到最大的数字 k
使得所有差异都足够大。
请注意,找到最大的 k
并不像两指针技术那么简单,例如在具有最小差异 4
的数组 1, 4, 5, 6, 7, 9
中,给出的解决方案这个方法是(1, 7), (4, 9)
,但是(1, 6)
和(5, 9)
的区别都够大了。一个简单的方法就是检查每个 k
的所有差异,从而产生 O(n2) 算法,这对于 [=51= 应该完全没问题].
给定一个长度为 n
(例如 n=1000
)的列表 l
,其中(随机)整数元素在 0<l[i]<10^m
范围内(例如 m=5
) ,可以从此列表中提取的两个元素的最大对数是多少(一对中的任何元素都不能与另一对中的任何元素重叠),这样每个元素对的值至少有一个最小差异 0<=diff<10^k
与 0<k<=m
?
生成所有可能的分区并检查每个分区是否具有足够的值距离的最大对数的朴素方法效率非常低。我们怎样才能巧妙地做到这一点?
示例:
考虑列表 l
由以下人员给出:
l = {1, 2, 8, 9, 10, 15};
和允许对中元素之间的最小差异 diff=7
。那么我们可以构造如下满足元素距离要求的不相交对集合:
{ {1,8} , {2,9} }
{ {1,8} , {2,10} }
{ {1,8} , {2,15} }
{ {1,9} , {2,10} , {8,15} }
{ {1,9} , {2,15} }
{ {1,10} , {2,9} , {8,15} }
...etc
请注意,所有选择的对都包含 larger element
减去 smaller element
大于或等于所需的最小值 diff=7
的元素。在上面的例子中,一旦遇到可以构建最大对数(例如3
)的情况,我们就可以停止,因为我们发现答案是3
。但是可能会发生一个列表只允许最大数量的这样的对,其长度小于 l
长度的一半。列表 l
也可能有多个具有相同值的元素,在这种情况下,涉及一个的组合不等同于涉及另一个的数值相同的组合(但推测它们的对数将相同)。
如果每个元素可能出现在任意数量的对中
一共有(n选2)对,所以差值至少diff
的对数等于(n选2)减去差值小于[=10的对数=].
计算这些更容易:对数组进行排序,并使用双指针技术,其中 i < j
是可能对的索引,从 i = 0
和 j = 1
开始。当差异足够小时,递增j
;当差异太大时,则递增 i
,并将 j - i
添加到总数中以说明较小值位于索引 i
处的对。 (通过先递增,我们避免计算差异太大的对。)
由于每次迭代都会递增 i
或 j
,并且任何索引都不会因任何原因变小,因此“计数”阶段的操作总数为 O(n)。因此,首先对数组进行排序的整体时间复杂度为 O(n log n)。
如果每个元素只能出现一对
同样,排序对此有很大帮助。
- 如果
(a, b)
是一对,则任何元素c < a
也出现在一对中,否则交换a
和c
仍然会产生有效对。 - 如果
(a, b)
是一对,则任何元素d > b
也出现在一对中,否则交换b
和d
仍然会产生有效的对。 - 如果
(a, b)
和(c, d)
都是对,那么b >= c
,否则交换b
和c
仍然会得到两个有效对。 - 如果
(a, b)
和(c, d)
都是对,并且a <= c
也是b <= d
,否则交换b
和d
仍然会产生两个有效对。
因此,如果存在 k
对的解决方案,则存在最小 k
元素与最大 k
元素以相同顺序配对的解决方案.所以我们只需要寻找这样的解决方案,通过找到最大的数字 k
使得所有差异都足够大。
请注意,找到最大的 k
并不像两指针技术那么简单,例如在具有最小差异 4
的数组 1, 4, 5, 6, 7, 9
中,给出的解决方案这个方法是(1, 7), (4, 9)
,但是(1, 6)
和(5, 9)
的区别都够大了。一个简单的方法就是检查每个 k
的所有差异,从而产生 O(n2) 算法,这对于 [=51= 应该完全没问题].