「这是我参与2022首次更文挑战的第20天,活动详情查看:2022首次更文挑战」。
每日刷题第42天 2021.02.09
2006.差的绝对值为K的数对数目
- leetcode原题链接:leetcode-cn.com/problems/co…
- 难度:简单
- 方法:哈希表
主要思想
- 思想上的转变,有些正向不太好做的题目,可以倒过来试试。
- 基于自身的位置,➕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 <= 2001 <= nums[i] <= 1001 <= 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,即两个位置都有值,找到一组解。 - 统计解的个数