一、题目
给你一个整数数组 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
解释:差的绝对值为 1 的数对为:
- [1,2,2,1]
- [1,2,2,1]
- [1,2,2,1]
- [1,2,2,1]
示例 2:输入:nums = [1,3], k = 3
输出:0
解释:没有任何数对差的绝对值为 3 。
示例 3:输入:nums = [3,2,1,5,4], k = 2
输出:3
解释:差的绝对值为 2 的数对为:
- [3,2,1,5,4]
- [3,2,1,5,4]
- [3,2,1,5,4]
提示:
1 <= nums.length <= 200
1 <= nums[i] <= 100
1 <= k <= 99来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/count-number-of-pairs-with-absolute-difference-k
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二、代码
思路1:暴力
第一重遍历选取第一个数a,
第二重遍历选取第二个数b,
求|a-b|==k?
如果是,则count++。
时间复杂度:O(n^2)
空间复杂度:O(1)
#include <math.h>
int countKDifference(int* nums, int numsSize, int k){
int count = 0;
for(int i = 0 ; i < numsSize; i++){
for(int j = i + 1 ; j < numsSize; j++){
if(abs(nums[i] - nums[j]) == k){
count++;
}
}
}
return count
}
思路2:哈希表+遍历计算差值为k的对数
- 哈希表记录nums数组中每个元素出现的次数
- 差值为k的两个元素a,b,他们各自出现次数的乘积a*b,为差值k的次数,也就是(a,b)和(b,a)出现次数
例如:[3,5,3,2,1,4,1,2,2],设k = 2
其中:
3:2次
5:1次
2:3次
1:2次
4:1次
|3 - 5| = k, 那么(3,5)和(5,3)的数对有 2次 * 1次 = 2次
|3 - 1| = k, 那么(3,1)和(1,3)的数对有 2次 * 2次 = 4次
|2 - 4| = k, 那么(2,4)和(4,2)的数对有 3次 * 1次 = 3次
共计有 2 + 4 + 3 = 9(对);
时间复杂度:O(n)
空间复杂度:O(n)
//利用数组模拟hash表,key = 数组下标 , value = 下标对应的元素
int hashmap[101];
//初始化hashmap数组
for(int i = 0 ; i < 101 ;i++){
hashmap[i] = 0;
}
//统计nums[]中各个元素的次数
for(int i = 0; i < numsSize; i++){
int n = nums[i];
hashmap[n]++;//元素出现次数+1
}
int count = 0;
//统计差值为k的数对个数
//遍历hashmap,找到相差k的两个数,次数相乘即为对数
//由于n + k ,n - k会重复统计,这里采用n - k方式,向前找差值为k的key。
for(int j = k ; j < 101; j++){//为什么从k开始,因为向前找需要 j - k,如果j从0开始,则j-k=-k,数组溢出。
count += hashmap[j] * hashmap[j - k];
}
//同样也可以采用n + k方式,如下:
// for(int j = 0; j < 101 - k;j++){
// count += hashmap[j] * hashmap[j + k];
// }
return count;
三、总结
1.哈希表
哈希表又称为散列表,散列查找技术不是挨个比较记录a[i]与key是”==“还是”!=“,也不是有序表查找那样可以利用a[i]与key的”<"或">"来折半查找。
哈希表不能采取“比较”的手段来找到元素,而是在记录的存储位置和它的关键字之间建立一个确定的对应关系f,使得每个关键字key对应一个存储位置f(key)。查找时,根据这个确定的对应关系找到对应值key的映射f(key),若查找集合中存在这个记录,则必定在f(key)的位置上。这种对应关系f称为散列函数,又称哈希函数。
按照这个思想,采用散列技术将记录存储在一块连续的存储空间中,这块连续存储空间称为散列表或哈希表(Hash table)。关键字对应的记录存储位置称为散列地址。
2.感悟
第二种思路不是我想出来的,是看题解的。看完完,我突然有一种感叹,这些思路想不到,并不是其有多难、复杂,而是想不到这个题目各个条件背后隐藏的一些数学关系。就如同这个计算差值为k的数对,我很难想到可以通过计算“差值为k的两个元素其各自次数的乘积”得到。不禁感叹数学逻辑的奇妙和自己的弱小。加油!加油!加油!