[set、二分、map] 532. 数组中的 k-diff 数对

112 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第18天,点击查看活动详情

每日刷题 2022.06.16

题目

  • 给你一个整数数组 nums 和一个整数 k,请你在数组中找出 不同的 k-diff 数对,并返回不同的 k-diff 数对的数目。
  • k-diff 数对定义为一个整数对 (nums[i], nums[j]) ,并满足下述全部条件:
    • 0 <= i, j < nums.length
    • i != j
    • nums[i] - nums[j] == k
  • 注意,|val| 表示 val 的绝对值。

示例

  • 示例1
输入:nums = [3, 1, 4, 1, 5], k = 2
输出:2
解释:数组中有两个 2-diff 数对, (1, 3) 和 (3, 5)。
尽管数组中有两个 1 ,但我们只应返回不同的数对的数量。
  • 示例2
输入: nums = [1, 3, 1, 5, 4], k = 0
输出: 1
解释: 数组中只有一个 0-diff 数对,(1, 1) 。

提示

  • 1 <= nums.length <= 10^4
  • -10^7 <= nums[i] <= 10^7
  • 0 <= k <= 10^7

解题思路

去重+map集合

  • 首先数组去重,可以避免出现相同的数对(例:(1,3)和(3,1),虽然下标是不同的,但是会被认定为重复的数对),对结果进行重复的计算。
  • 去重后的数组记为arr,对arr数组中的每一个元素,从其当前所在的位置往后找,直到找到数组的最后一个元素结束,在每次查找的过程中,记录当前位置i,可以加k得到的j,找到符合的数对就将结果++。
    • 这样的话,还有一种情况会漏掉。k = 0的时候,也就是(1,1),即:nums[i]和nums[j]相等的情况下,就会因为数组去重而没有计算上。 因此,需要在k = 0的时候,使用map集合统计没有去重前的数组中每个元素出现的次数,当某个元素出现的次数大于1的时候,就表示其可以形成一个k = 0的数对,因此就需要给结果++。

二分查找(两数之和的做法类似)+ 排序

  • 两数之和的总结,可以查看这篇文章两数之和
  • 相应的转换:两数之和对于数组中的每一位,都可以使用target减去当前的元素值,然后在数组中再去查找符合的值
  • 而本题就是,需要对于数组中的每一个元素去查找,当前元素+k之后的数值。通过观察可以知道查找可以使用二分,因为其具有二段性。

map集合

  • 重点:去重的手法
  • 同样是遍历数组中的每一个元素,这次使用map集合来记录当前位置之前的元素,因为不能存在相同的数对,因此我们可以保证数对的前面元素是最小值,这样就不会出现(1,3)和(3,1)这种重复的情况,因为每次都是将最小的放在前面才进行记录。
  • 又因为题目中所给的k值是唯一的,那么对于每个数对的前一个元素来说,一定会有一个唯一的后一个元素与之匹配,因为是唯一的,所以可以使用数对中的前一个元素来代表整个数对。
  • 使用map匹配的时候,应该匹配i + k 和 i - k两个都应该遍历到。
  • 最终输出存储的所有的数对前一个元素的数组的长度即可(答案)。

AC代码

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
var findPairs = function(nums, k) {
  // 首先先去重
  // 然后计算数对
  let map = new Map(), ans = 0;
  // 需要特判k=0
  if(k == 0) {
    nums.forEach(value => {
      map.set(value, (map.get(value) || 0) + 1);
    });
    map.forEach(value => {
      if(value >= 2) ans++;
    });
  }
  // 对数组进行去重,并存储在set中
  const set = new Set(nums);
  const arr = [...set], n = arr.length;
  for(let i = 0; i < n; i++) {
    for(let j = i + 1; j < n; j++) {
      // 查找两数之差是否等于k,可以优化,使用二分
      // 常规的做题方法,挨个测试,计算两数之差是否等于k
      if(Math.abs(arr[i] - arr[j]) == k){
        ans++;
      }
    }
  }
  return ans;
};