返回

巧用哈希表、离散化:高效解决 532. 数组中的 k-diff 数对

后端

在编程中,数组的处理可谓是家常便饭。数组中数对的差异对比,更是算法领域常见的操作。今天,我们走进 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;
    }
}

总结

  1. 数组中的 k-diff 数对 考察了我们的数据结构和算法应用能力。通过哈希表、离散化和二分或双指针法,我们可以高效地解决此类问题。在实际编程中,根据数组规模和目标效率选择合适的方法至关重要。

希望这篇文章能帮助你加深对 LeetCode 532 题的理解,并提升你的算法解决能力!