持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第21天,点击查看活动详情
一、题目
LeetCode 数组中的 k-diff 数对
给你一个整数数组 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, 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
二、题解
k-diff数对表示为两个整数对(x, y),而这两个整数的差值的绝对值等于k,要在数组中找到所有不同的k-diff数对,数对的两个整数都相同则为重复的数对。
方法一
首先可以先遍历数组元素来寻找数对,根据每一个元素,判断是否存在另外一个符号条件的元素,对于当前元素num,如果num是数对中的一个元素,那么另一个元素值就应该为num - k或者num + k,所以就可以找数组中其余元素值是否符号,对此为了快速避免重复的操作,在遍历数组元素的时候可以将遍历过的元素存储到哈希表,然后对于当前元素num,就直接到哈希表中找寻num - k或者num + k。同时需要的是不重复的数对,所以还需要一个哈希表来存储数对,如果是存在num - k,那么就将num - k存入哈希表;如果是存在num + k,那么就将num存入哈希表,这样就不会重复了。最后遍历结束后的哈希表内元素数量就是数对的数量。
方法二
或者可以用双指针来解决,先将数组进行排序,初始的left为0、right为1,然后移动left遍历数组元素,当left等于0或者nums[left]不等于nums[left - 1]时去查询,如果nums[right]等于nums[left] + k记录个数。
三、代码
方法一 Java代码
class Solution {
public int findPairs(int[] nums, int k) {
Set<Integer> numSet = new HashSet<Integer>();
Set<Integer> pairs = new HashSet<Integer>();
for (int num : nums) {
if (numSet.contains(num - k)) {
pairs.add(num - k);
}
if (numSet.contains(num + k)) {
pairs.add(num);
}
numSet.add(num);
}
return pairs.size();
}
}
时间复杂度:O(n),需要遍历一次数组元素。
空间复杂度:O(n),需要两个哈希表来记录判断数对。
方法二 Java代码
class Solution {
public int findPairs(int[] nums, int k) {
Arrays.sort(nums);
int pairs = 0;
int right = 1;
for (int left = 0; left < nums.length - 1; left++) {
if (left == 0 || nums[left] != nums[left - 1]) {
while (right < nums.length - 1 && (right <= left || nums[right] < nums[left] + k)) {
right++;
}
if (nums[right] == nums[left] + k) {
pairs++;
}
}
}
return pairs;
}
}
时间复杂度:O(nlogn)
空间复杂度:O(nlogn)