【哈希表】自己做的方法比较菜,先把所有的点都放进哈希表,然后枚举每一个元素,寻找比他大的元素是否在哈希表中。k=0这种情况需要单独考虑。
class Solution {
public int findPairs(int[] nums, int k) {
int ans = 0;
if(k == 0){
Map<Integer, Integer> map = new HashMap();
for(var x: nums){
map.put(x, map.getOrDefault(x, 0) + 1);
}
for(var key: map.keySet()){
if(map.get(key) > 1) ans++;
}
return ans;
}
Set<Integer> set = new HashSet(){{
for(var x: nums) add(x);
}};
for(var x: set){
if(set.contains(x + k)){
ans++;
}
}
return ans;
}
}
【改进哈希表】因为k是固定的,所以对于任何一个元组,我们只需要存较小值即可,具体做法为:
1.开两个哈希表,一个用来存枚举过的元素
2.另一个用来存符合条件的较小值
class Solution {
// 2:40 hash
public int findPairs(int[] nums, int k) {
Set<Integer> visit = new HashSet();
Set<Integer> ans = new HashSet();
for(var x: nums){
if(visit.contains(x - k)){
ans.add(x - k);
}
if(visit.contains(x + k)){
ans.add(x);
}
visit.add(x);
}
return ans.size();
}
}
【排序+二分】先对数组排序,然后对于每个元素,寻找从下一个坐标开始有没有比这个元素大k的值。需要注意对于已经计算过的元素要跳过,因为已经排好序了,重复元素都在一起,所以判一下和上个元素是否相同即可。
class Solution {
// 排序+二分 2:50 7
public int binarySearch(int[] nums, int target, int left){
int right = nums.length - 1;
while(left <= right){
int mid = (left + right) >>> 1;
if(nums[mid] == target) return mid;
else if(nums[mid] > target) right = mid - 1;
else left = mid + 1;
}
return -1;
}
public int findPairs(int[] nums, int k) {
Arrays.sort(nums);
int ans = 0;
for(var i = 0; i < nums.length; i++){
if(i != 0 && nums[i] == nums[i - 1]) continue;
if(binarySearch(nums, nums[i] + k, i + 1) != -1) ans++;
}
return ans;
}
}
【排序+双指针】 我们发现排序后的数组,某个元素nums[i]和比他大的元素nums[j],j是随着i向后移动而移动的。这样就具备了双指针的特性了。
class Solution {
// 排序+双指针 3:07
public int findPairs(int[] nums, int k) {
Arrays.sort(nums);
int ans = 0, j = 1;
for(var i = 0; i < nums.length; i++){
if(i != 0 && nums[i] == nums[i - 1]) continue;
while(j < nums.length && nums[j] <= nums[i] + k) j++;
if(j - 1 != i && nums[j - 1] == nums[i] + k) ans++;
}
return ans;
}
}