📅  最后修改于: 2023-12-03 15:26:11.136000             🧑  作者: Mango
在给定的数组中,我们可以形成许多的对,每个对包含两个不同的元素。我们需要找到所有的对中,最小值的和最大的那个对,返回它们最小值的和。
例如,对于数组 [3, 5, 2, 6]
,存在以下的所有对:
(3, 5)
(3, 2)
(3, 6)
(5, 2)
(5, 6)
(2, 6)
它们的最小值依次为 3, 2, 3, 2, 5, 2
。其中,最小值为 2
的对有两个 (3, 2)
和 (5, 2)
。它们的最小值和为 2 + 2 = 4
,因此函数应该返回 4
。
其他的例子:
输入:[1, 2, 4, 5]
输出:4
输入:[2, 2, 2, 2, 2]
输出:4
可以使用贪心算法解决本题。对于任意的两个元素,它们可以组成一个对。我们需要找到所有的对中,最小值最大的那个对。
考虑假设最小值为 x
,那么我们需要找到数组中所有的对中,最小值大于等于 x
的那个对。在找到这个对之后,我们将它们的最小值累加到答案中。
那么关键问题就是如何快速找到一个最小值大于等于 x
的对。有一种简单的方法是使用双重循环,但是时间复杂度为 $O(n^2)$。事实上,我们可以使用一些更高效的算法。
首先,我们可以将数组排序,将时间复杂度降至 $O(n \log n)$。在排序之后,我们可以使用双指针的方法,从两端排除元素,以找到最小值大于等于 x
的对。具体来说,对于当前的最小值 x
,我们维护两个指针 i
和 j
,使得数组中 0 ~ i-1
和 j+1 ~ n-1
的元素都小于 x
,而 i
和 j
是最小值大于等于 x
的两个元素的下标,它们之间的所有元素都大于等于 x
。
这样,我们就可以用 $O(n \log n)$ 的时间复杂度解决本问题。
from typing import List
def getMinSum(nums: List[int]) -> int:
nums.sort()
n = len(nums)
ans = float('inf')
for i in range(n):
j = n - 1
while j > i and nums[i] + nums[j] >= ans:
j -= 1
if j > i:
ans = min(ans, nums[i] + nums[j])
return ans
时间复杂度:$O(n \log n)$
空间复杂度:$O(1)$
其中,空间复杂度为排序所用的栈空间,因此可以忽略。