K 和数对的最大数目

标签: 数组 哈希表 双指针 排序

难度: Medium

给你一个整数数组 nums 和一个整数 k

每一步操作中,你需要从数组中选出和为 k 的两个整数,并将它们移出数组。

返回你可以对数组执行的最大操作数。

 

示例 1:

输入:nums = [1,2,3,4], k = 5
输出:2
解释:开始时 nums = [1,2,3,4]:
- 移出 1 和 4 ,之后 nums = [2,3]
- 移出 2 和 3 ,之后 nums = []
不再有和为 5 的数对,因此最多执行 2 次操作。

示例 2:

输入:nums = [3,1,3,4,3], k = 6
输出:1
解释:开始时 nums = [3,1,3,4,3]:
- 移出前两个 3 ,之后nums = [1,4,3]
不再有和为 6 的数对,因此最多执行 1 次操作。

 

提示:

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 109
  • 1 <= k <= 109

Submission

运行时间: 62 ms

内存: 28.2 MB

class Solution:
    def maxOperations(self, nums: List[int], k: int) -> int:
        tmp = Counter(nums)
        ans = 0
        for num in tmp:
            if num * 2 < k:
                ans += min(tmp[num], tmp.get(k-num, 0))
            elif num * 2 == k:
                ans += tmp[num] // 2
        return ans

Explain

本题解使用哈希表来存储数组中每个数字的出现次数,然后遍历哈希表的键(即数组中的不同数字),检查每个数字与其配对构成和为k的另一个数字是否存在于哈希表中。对于每个数字num,如果num的两倍小于k,则检查与之相加等于k的数字(即k-num)是否存在,并将它们的出现次数的最小值累加到答案中。如果num的两倍恰好等于k,说明需要将num与自身配对,只能将其出现次数除以2(向下取整)来计算配对的次数。遍历完成后,得到的答案即为最大操作数。

时间复杂度: O(n)

空间复杂度: O(n)

class Solution:
    def maxOperations(self, nums: List[int], k: int) -> int:
        tmp = Counter(nums)  # 使用Counter来统计数组nums中每个数字的出现次数
        ans = 0  # 初始化答案为0
        for num in tmp:  # 遍历哈希表中的每一个数
            if num * 2 < k:  # 如果当前数字的两倍小于k,需要找到配对的数字
                ans += min(tmp[num], tmp.get(k-num, 0))  # 增加可以配对的次数,取两个数字出现次数的最小值
            elif num * 2 == k:  # 如果当前数字的两倍正好为k,它只能与自己配对
                ans += tmp[num] // 2  # 增加配对次数,每对需要两个相同的数字
        return ans  # 返回最大操作数

Explore

在算法实现中,我们通过确保每次处理数字num时,只考虑其配对数字k-num,且仅当num小于k-num时才进行配对操作,以避免重复计数。这意味着,对于每一对有效的配对数字,它们只会被计算一次。例如,当num等于k-num时,如num * 2 = k,我们通过直接将num的数量除以2来处理配对,确保每个数字只与自己配对一次,不会与其他数字重复配对。

当num * 2等于k时,这意味着num只能与自身形成有效配对,因为其他任何数字加上num都将超过k或小于k,无法形成有效的k-sum配对。因此,在这种特定情况下,只考虑将num的数量除以2来计算配对次数,每两个相同的num可以形成一次有效操作。这种方法确保了算法的准确性和效率。

在Python中,使用tmp.get(k-num, 0)可以安全地尝试访问哈希表中的元素,即使该元素不存在也不会引发错误。如果使用tmp[k-num],当k-num不在哈希表中时,将引发KeyError异常。使用get方法允许我们为不存在的键提供一个默认值(在本例中为0),这使得代码更加健壮,能够处理数组中不存在的数字,简化了配对逻辑。

为了确保每对数字只被计算一次,算法在遍历哈希表时采取了特殊策略:只考虑那些num小于k-num的情况进行计数。这样做确保了每一对数字(num和k-num)只在num的迭代时被计算一次,避免在k-num的迭代时重复计算。此外,当num恰好等于k-num时,我们通过将num的数量除以2来处理,确保这种情况下的配对也只计算一次。这种策略避免了重复和冗余的计算,提高了算法的效率和准确性。