题目
532. 数组中的 k-diff 数对
给定一个整数数组和一个整数 k,你需要在数组里找到 不同的 k-diff 数对,并返回不同的 k-diff 数对 的数目。
这里将 k-diff 数对定义为一个整数对 (nums[i], nums[j]),并满足下述全部条件:
0 <= i < j < nums.length
|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, 2, 3, 4, 5], k = 1
输出:4
解释:数组中有四个 1-diff 数对, (1, 2), (2, 3), (3, 4) 和 (4, 5)。
示例 3:
输入:nums = [1, 3, 1, 5, 4], k = 0
输出:1
解释:数组中只有一个 0-diff 数对,(1, 1)。
提示:
1 <= nums.length <= 104
-107 <= nums[i] <= 107
0 <= k <= 107
方法1:双指针
public int findPairs(int[] nums, int k) {
Arrays.sort(nums);
int res = 0, n = nums.length, i = 0, j = 1;
while (i <= j && j < n) {
//计算diff
int diff = nums[j] - nums[i];
if (diff == k) {
res++;
// System.out.printf("%diff %diff -> ", nums[i] , nums[j] );
//如果j重复出现,不再被统计
while (j < n - 1 && nums[j + 1] == nums[j]) j++;
j++;
} else if (diff > k) i++;
else if (diff < k) j++;
if (i == j) j++;//强制性岔开1个数,否则比较的是两个相同数本身
}
return res;
}
另
public int findPairs(int[] nums, int k) {
Arrays.sort(nums);
int n = nums.length, j = 0, res = 0;
for (int i = 0; i < n; i++) {//定左区间
//i==0 初始情况,进入
//i这个数和之前的数相同,跳过
if (i == 0 || nums[i] != nums[i - 1]) {
//选定j的边界
//[j]-[i]的 diff比 k小 要扩j
//i==j 说明i追上j了,错开1个位置
while (j < n && (nums[j] - nums[i] < k || j == i)) {
j++;
}
//统计
if (j < n && nums[j] - nums[i] == k) {
res++;
}
}
}
return res;
}
方法2:哈希
两个hash的做法,写法很好
//int nums[] = {3 1 4 1 5} k = 2;
// |
//i=0 vis:3
// res:
//i=1 vis:3 1
// res:1
//i=2 vis:3 1 4
// res:1
//i=3 vis:3 1 4 //这一步已经添加了元素1,两个set去重了
// res:1
//i=4 vis:3 1 4 5
// res:1 3
public int findPairs(int[] nums, int k) {
Set<Integer> vis = new HashSet<>(), res = new HashSet<>();
for (int x : nums) {
//以x为起点,找其上,即[x,x+k]
if (vis.contains(x + k)) {
res.add(x);//都是以下作为参考值
}
//以x为起点,找其下,即[x-k,x]
if (vis.contains(x - k)) {
res.add(x - k);//都是以下作为参考值
}
vis.add(x);//x已经被统计过
}
return res.size();
}