2006.差的绝对值为K的数对数目(哈希表)

290 阅读3分钟

「这是我参与2022首次更文挑战的第20天,活动详情查看:2022首次更文挑战」。

每日刷题第42天 2021.02.09

2006.差的绝对值为K的数对数目

主要思想

  • 思想上的转变,有些正向不太好做的题目,可以倒过来试试。
  • 基于自身的位置,➕k,判断前面有多少个这样的数。

题目

  • 给你一个整数数组 nums 和一个整数 k ,请你返回数对 (i, j) 的数目,满足 i < j 且 |nums[i] - nums[j]| == k 。

  • |x| 的值定义为:

    • 如果 x >= 0 ,那么值为 x 。
    • 如果 x < 0 ,那么值为 -x 。

示例

  • 示例1
输入:nums = [1,2,2,1], k = 1
输出:4
  • 示例2
输入: nums = [1,3], k = 3
输出: 0
解释: 没有任何数对差的绝对值为 3 。
  • 示例3
输入:nums = [3,2,1,5,4], k = 2
输出:3

提示

  • 1 <= nums.length <= 200
  • 1 <= nums[i] <= 100
  • 1 <= k <= 99

解法

暴力解法

  • 使用双层循环,一层遍历i,一层遍历j,判断数组中相邻的两个数计算差值的绝对值是否为k,统计所有符合条件的数对。

复杂度分析

  • 时间复杂度:O(n^2),其中 n 为数组nums的长度。我们使用了两层循环来寻找所有符合条件的数对。
  • 空间复杂度:O(1)。仅使用常数空间
var countKDifference = function(nums, k) {
  let ans = 0;
  for(let i = 0; i < nums.length; i++) {
    for(let j = i + 1; j < nums.length; j++) {
      if(Math.abs(nums[i] - nums[j]) == k) ans++;
    }
  }
  return ans;
};

哈希表+一次遍历(单层)

  • |nums[i] - nums[j]| = k可以转换为nums[i] = nums[j] + k或者nums[i] = nums[j] - k
  • 这样一来,就将问题转换为:在当前位置上,查找基于当前数值加上k后,前面包含多少个这样的数,因此在遍历的过程中,使用map集合记录下来出现的次数,通过o(1)的时间复杂度拿到自己想要的数据。

复杂度分析

  • 时间复杂度:O(n),其中 n为数组 nums 的长度。我们仅使用了一次遍历来寻找所有符合条件的数对。
  • 空间复杂度:O(n)。哈希表消耗了 O(n) 的空间
var countKDifference = function(nums, k) {
  // 哈希表解法
  let map = new Map();
  let num = 0;
  for(let i = 0; i < nums.length; i++) {
    // j + k = i || j - k = i
    num += (map.get(nums[i] + k) || 0) + (map.get(nums[i] - k) || 0);
    // console.log('num',nums[i] + k);
    map.set(nums[i], map.get(nums[i]) + 1 || 1);
    // console.log('map',map);
  }
  return num;
};

其他(题解学习)

  • 首先暴力枚举是肯定可以实现的,但是如何把时间复杂度提升到O(n)
  • 可以采用计数的思想。
  • 因为题目给了范围,我们可以用一个长度为101的数组。可以理解为101个洞
  • 数的值对应下标的位置,如果该位置有值,洞的值+1。没有值就是0
  • 依次将相隔为k的两个值相乘,如果为1,说明是1*1,即两个位置都有值,找到一组解。
  • 统计解的个数