返回
巧用哈希表、离散化:高效解决 532. 数组中的 k-diff 数对
后端
2023-12-30 05:24:37
在编程中,数组的处理可谓是家常便饭。数组中数对的差异对比,更是算法领域常见的操作。今天,我们走进 LeetCode 上的 532. 数组中的 k-diff 数对,一探究竟。
问题
给定一个整数数组 nums 和一个整数 k,请找出并返回数组中相差为 k 的数对数目。
解题思路
面对此题,我们有以下三种巧妙的解法:
1. 哈希表法
利用哈希表存储数组中每个元素的出现次数。对于每个元素 nums[i],查找哈希表中是否存在 nums[i] + k 和 nums[i] - k。若存在,则更新计数器。哈希表能有效避免重复查找,提升效率。
2. 离散化 + 二分法
首先将数组中的元素离散化,将它们映射到一个连续整数集合。然后,对于每个元素,我们可以使用二分查找在离散化数组中查找是否存在 nums[i] + k 和 nums[i] - k。二分查找的时间复杂度为 O(log n),使得该方法整体复杂度为 O(n log n)。
3. 离散化 + 双指针法
与第二种方法类似,我们先离散化数组。然后,使用双指针遍历离散化数组。当指针间距为 k 时,说明找到一对符合条件的数对。双指针法的时间复杂度为 O(n),效率更高。
代码实现
哈希表法:
import java.util.HashMap;
import java.util.Map;
class Solution {
public int findPairs(int[] nums, int k) {
if (nums == null || nums.length < 2 || k < 0) {
return 0;
}
Map<Integer, Integer> map = new HashMap<>();
for (int num : nums) {
map.put(num, map.getOrDefault(num, 0) + 1);
}
int count = 0;
for (int num : map.keySet()) {
if (k == 0) {
if (map.get(num) > 1) {
count++;
}
} else {
if (map.containsKey(num + k)) {
count++;
}
}
}
return count;
}
}
离散化 + 二分法:
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
class Solution {
public int findPairs(int[] nums, int k) {
if (nums == null || nums.length < 2 || k < 0) {
return 0;
}
// 离散化
Map<Integer, Integer> map = new HashMap<>();
for (int num : nums) {
map.put(num, map.getOrDefault(num, 0) + 1);
}
int[] numsDiscrete = new int[map.size()];
int index = 0;
for (int num : map.keySet()) {
numsDiscrete[index++] = num;
}
// 二分查找
int count = 0;
for (int i = 0; i < numsDiscrete.length; i++) {
if (binarySearch(numsDiscrete, i + 1, numsDiscrete.length - 1, numsDiscrete[i] + k)) {
count++;
}
}
return count;
}
private boolean binarySearch(int[] nums, int low, int high, int target) {
while (low <= high) {
int mid = (low + high) / 2;
if (nums[mid] == target) {
return true;
} else if (nums[mid] < target) {
low = mid + 1;
} else {
high = mid - 1;
}
}
return false;
}
}
离散化 + 双指针法:
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
class Solution {
public int findPairs(int[] nums, int k) {
if (nums == null || nums.length < 2 || k < 0) {
return 0;
}
// 离散化
Map<Integer, Integer> map = new HashMap<>();
for (int num : nums) {
map.put(num, map.getOrDefault(num, 0) + 1);
}
int[] numsDiscrete = new int[map.size()];
int index = 0;
for (int num : map.keySet()) {
numsDiscrete[index++] = num;
}
// 双指针
Arrays.sort(numsDiscrete);
int left = 0, right = 0, count = 0;
while (right < numsDiscrete.length) {
if (numsDiscrete[right] - numsDiscrete[left] < k) {
right++;
} else if (numsDiscrete[right] - numsDiscrete[left] > k) {
left++;
} else {
count++;
left++;
while (left < numsDiscrete.length && numsDiscrete[left] == numsDiscrete[left - 1]) {
left++;
}
}
}
return count;
}
}
总结
- 数组中的 k-diff 数对 考察了我们的数据结构和算法应用能力。通过哈希表、离散化和二分或双指针法,我们可以高效地解决此类问题。在实际编程中,根据数组规模和目标效率选择合适的方法至关重要。
希望这篇文章能帮助你加深对 LeetCode 532 题的理解,并提升你的算法解决能力!