📌  相关文章
📜  需要删除的最少对,以便数组不包含任何总和为 K 的对(1)

📅  最后修改于: 2023-12-03 15:42:25.911000             🧑  作者: Mango

需要删除的最少对,使数组不包含任何总和为 K 的对

问题描述

给定一个含有 n 个整数的数组 nums 和一个整数 k ,请找出需要删除的最小对数,使得数组中不包含任何总和为 k 的对。

解决方案
思路

本问题可以转化为:将 nums 中满足 num_a + num_b = k 的所有数对(num_a, num_b) 删除,问至少需要删除多少对数对。

既然我们需要删除的数对数量最少,那么我们必须尝试保留尽可能多的数对。因此我们采用贪心策略:

  • 对原数组进行排序,由小到大排列;

  • 使用双指针 left 和 right,分别指向数组的首尾两个元素;

  • 如果 nums[left] + nums[right] > k,则只能将 right 左移减小数对总数;

  • 如果 nums[left] + nums[right] < k,则只能将 left 右移减小数对总数;

  • 如果 nums[left] + nums[right] == k,则说明当前数对符合要求,则 left 和 right 都左右移,继续寻找下一对数对。

由此可以发现,按照从小到大的顺序排列,左指针 left 能取到的最小值只能是数组的首元素,右指针 right 能取到的最大值只能是数组的尾元素,所以用双指针实现的复杂度为 O(n)。

代码
def min_delete_nums(nums: List[int], k: int) -> int:
    nums.sort()
    left, right = 0, len(nums) - 1
    count = 0
    
    while left < right:
        if nums[left] + nums[right] == k:
            count += 1
            left += 1
            right -= 1
        elif nums[left] + nums[right] > k:
            right -= 1
        elif nums[left] + nums[right] < k:
            left += 1
    
    return count
复杂度
  • 时间复杂度:O(nlogn),主要是对 nums 进行排序;

  • 空间复杂度:O(1),只需常数级别的空间存储。

总结

本问题是典型的贪心问题,利用双指针的思路可以在 O(n) 的时间内找到最小的数对总数。