leetcode - 1679 - K 和数对的最大数目

文章目录

    • 题目描述
    • 题目剖析&信息挖掘
    • 解题思路
      • 方法一 哈希法
        • 思路
        • 注意
        • 知识点
        • 复杂度
        • 代码实现
      • 方法二 双指针法
        • 思路
        • 注意
        • 知识点
        • 复杂度
        • 参考
        • 代码实现
    • 相关题目

题目描述

[1679] K 和数对的最大数目

给你一个整数数组 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 <= 10^5
  • 1 <= nums[i] <= 10^9
  • 1 <= k <= 10^9
Related Topics
  • 数组
  • 哈希
  • 双指针

题目剖析&信息挖掘

题目是要找到和为k的数对,可以用哈希法和双指针法解决

解题思路

根据题意一个数字用完后会删除,所以一个数字最多只用一次。利用贪心原理,去遍历数组,找到另一个数字并从中删除。这就转化成从数组中找出和为k的对数。和之前的两数之和、三数之和、四数之和的题类似。有2种做法一种是直接哈希法,另一种是排序以后用双指针法。

方法一 哈希法

思路

  • 维护哈希表存储数字的个数
  • 遍历数组,对于遍历的数字n,查看前面有没与之加和为k的数
  • 如果有就删除k-n,并sum++,如果没有就把n加入到哈希表中。
func maxOperations(nums []int, k int) int {
  m:= make(map[int]int, len(nums)) //
	sum := 0
	for _, n:= range nums {
		if m[n]>0 {
			sum++
			m[n]--
		} else {
			m[k-n]++ // 这里存储的相减后的结果 
		}
	}
	return sum
}

注意

  • 哈希设计要用统计,不能用bool
  • 同种组合有多组的情况, 如[3,3,3,3] , 6

知识点

  • 数组
  • 哈希

复杂度

  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

代码实现

func maxOperations(nums []int, k int) int {
  m:= make(map[int]int, len(nums)) //
	sum := 0
	for _, n:= range nums {
		if m[n]>0 {
			sum++
			m[n]--
		} else {
			m[k-n]++ // 这里存储的相减后的结果 
		}
	}
	return sum
}

方法二 双指针法

思路

  • 先对数组排序
  • 用双指针对头尾进行遍历
func maxOperations(nums []int, k int) int {
  sort.Sort(nums)
	sum := 0
  left, right := 0, len(nums)-1
  // nums[left]
	for ;left<right; {
    if nums[left]+nums[right] == k {
      sum++
      left++
      right--
    } else if nums[left]+nums[right] < k { // 说明小的数字要增大
      left++
    } else { // 大的数字要减少
      right--
    }
	}
	return sum
}

注意

  • 一定要先排序
  • 同种组合有多组的情况, 如[3,3,3,3] , 6

知识点

  • 数组
  • 双指针
  • 排序

复杂度

  • 时间复杂度:O(nlog(n))
  • 空间复杂度:O(n)

参考

代码实现

func maxOperations(nums []int, k int) int {
	sort.Sort(sort.IntSlice(nums))
	sum := 0
	left, right := 0, len(nums)-1
	// nums[left]
	for ;left<right; {
		if nums[left]+nums[right] == k {
			sum++
			left++
			right--
		} else if nums[left]+nums[right] < k { // 说明小的数字要增大才有可能使和=k
			left++
		} else { // 大的数字要减少,同理。
			right--
		}
	}
	return sum
}

相关题目

https://leetcode-cn.com/problems/two-sum/

https://leetcode-cn.com/problems/3sum/

https://leetcode-cn.com/problems/4sum/
在这里插入图片描述

你可能感兴趣的:(leetcode,leetcode,算法,哈希,排序)