问题:
Given an array of integers and an integer k, you need to find the number of unique k-diff pairs in the array. Here a k-diff pair is defined as an integer pair (i, j), where i and j are both numbers in the array and their absolute difference is k.
Example 1:
Input: [3, 1, 4, 1, 5], k = 2 Output: 2 Explanation: There are two 2-diff pairs in the array, (1, 3) and (3, 5). Although we have two 1s in the input, we should only return the number of unique pairs.
Example 2:
Input:[1, 2, 3, 4, 5], k = 1 Output: 4 Explanation: There are four 1-diff pairs in the array, (1, 2), (2, 3), (3, 4) and (4, 5).
Example 3:
Input: [1, 3, 1, 5, 4], k = 0 Output: 1 Explanation: There is one 0-diff pair in the array, (1, 1).
Note:
- The pairs (i, j) and (j, i) count as the same pair.
- The length of the array won't exceed 10,000.
- All the integers in the given input belong to the range: [-1e7, 1e7].
解决:
①我使用Set用来存储排序后的数组,可以方便的找到与nums[i]差值为k的数;另外,使用Map来存储满足条件的两个值,避免重复。耗时47 ms,因为使用了map和set,性能不是很好。
public class Solution {
public int findPairs(int[] nums, int k) {
if(k<0 || nums==null) return 0;
Arrays.sort(nums);
Map<Integer,Integer> map = new HashMap<>();
Set<Integer> set = new HashSet<>();
for (int i = 0;i < nums.length ;i ++ ) {
if (set.contains(nums[i] - k) && !map.containsKey(nums[i] - k)) {
map.put(nums[i] - k,nums[i]);
}
set.add(nums[i]);
}
return map.size();
}
}
②只用map实现:在map中保存数组中的值和它的个数,然后遍历map,查找满足条件的值即可。这样就不会有使用set时的重复了。耗时32ms.
public class Solution {
public int findPairs(int[] nums, int k) {
if(k < 0 || nums == null) return 0;//不要忘记判断边界
Map<Integer,Integer> map = new HashMap<>();
for (int i = 0;i < nums.length ;i ++ ) {
map.put(nums[i],map.getOrDefault(nums[i],0) + 1);//map(数组中的值,数组中值的个数)
}
int count = 0;
for(Map.Entry<Integer,Integer> entry:map.entrySet()){//遍历map
if(k == 0){
if (entry.getValue() >= 2) {//如果有个数大于2的值
count ++;
}
}else if(map.containsKey(entry.getKey() + k)){//查看是否存在与当前值差值为k的值
count ++;
}
}
return count;
}
}
③直接方法,使用两个指针,一个指向被减数,一个指向减数,向右移动指针,查找满足差值为k的数,count++,并且right要跳过重复,以避免重复使用同一对。(21ms)
public class Solution {
public int findPairs(int[] nums, int k) {
if(k < 0 || nums.length == 0) return 0;
Arrays.sort(nums);
int count = 0;
int left = 0; //指向被减数
int right = 1;//指向减数,并且不可以重复
int len = nums.length;
while(right < len){
if(nums[right] - nums[left] == k){
count ++;
left ++;
right ++;
while(right < len && nums[right] == nums[right - 1]) right ++;//跳过重复
}else if(nums[right] - nums[left] > k){
left ++;
}else{
right ++;
}
right = Math.max(left + 1,right);//保证right > left
}
return count;
}
}
-------------------------------------------------------------------------------------------------------------
【注】当数组值不是太大如<10000时,可以使用以下方法
public class Solution {
public int findPairs(int[] nums, int k) {//使用hash table存储数值的个数
int hash[] = new int[20001];
int count = 0;
for (int i = 0;i < nums.length;i ++) {
hash[nums[i] + 10000] ++;//数组下标越界,因为数值的范围是 [-1e7, 1e7]。不可以使用这种方法
}
for (int i = 0;i < 20001 ;i ++ ) {
if (hash[i] <= 0) {
continue;
}
if (k == 0) {
if(hash[i] >= 2)count ++;
}else{
if (hash[i + k] > 0) {
count ++;
hash[i] = 0;
}
}
}
return count;
}
}