leetcode
leetcode 451 ~ 500
数组中的 k-diff 数对

数组中的 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

代码结果

运行时间: 24 ms, 内存: 17.7 MB


/*
 * 题目思路:
 * 1. 使用Java Stream API进行数据处理。
 * 2. 创建一个哈希集合来存储数组中的数字。
 * 3. 使用stream遍历数组,对于每个数字检查它的加上k或减去k的值是否在哈希集合中。
 * 4. 将符合条件的数对加入到已找到的数对集合中。
 * 5. 最后返回已找到的数对集合的大小。
 */
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
 
public class KDiffPairsStream {
    public int findPairs(int[] nums, int k) {
        if (k < 0) return 0;
        Set<Integer> numSet = new HashSet<>();
        Set<Integer> foundPairs = IntStream.of(nums)
                .filter(num -> {
                    boolean found = numSet.contains(num - k) || numSet.contains(num + k);
                    numSet.add(num);
                    return found;
                })
                .mapToObj(num -> num - k)
                .collect(Collectors.toSet());
        return foundPairs.size();
    }
}
 

解释

方法:

该题解的思路是首先判断k是否为0,如果k为0,则直接统计nums中出现次数大于1的元素个数并返回。如果k不为0,则先将nums去重,然后遍历nums中的每个元素x,判断x+k是否也在nums中,如果在则将count加1,最后返回count的值。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
为什么在k为0的情况下,选择使用Counter来统计元素出现次数而不是其他方法?
在k为0的条件下,需要统计数组中相同元素的出现次数,并且只有当某个元素出现至少两次时,这个元素才能形成k-diff数对(其中两个数相同)。Counter类是一个专门用来计数的数据结构,它可以直接统计数组中每个元素的出现次数,从而方便地找出出现次数大于1的元素。使用Counter可以非常简洁和直观地实现这一功能,而其他方法(如使用普通字典手动计数或使用多次遍历数组)可能会更加繁琐且容易出错。
🦆
在处理k不为0的情况时,将nums转换为set来去重,这一做法是否会影响最终结果中数对的唯一性判断?
将nums转换为set进行去重是为了确保每个数字在判断时只被计算一次,从而确保数对的唯一性。在k不为0的情况下,如果数组中有重复元素,不去重可能会导致某些数对被重复计算。例如,对于数组[1, 1, 2, 3]和k=1,如果不去重,数字1可能会重复计算数对(1,2)。而使用set去重后,每个元素只保留一次,可以保证每个数对只被计算一次,从而保持数对的唯一性。
🦆
题解中提到的`x+k是否也在nums中`的判断逻辑,是否考虑了k为负数的情况,这会如何影响算法的输出?
题解中提到的逻辑确实考虑了k为负数的情况,因为无论k是正数还是负数,计算x+k的结果只要在nums中即可计为有效的数对。例如,对于数组[1, 2, 3, 4]和k=-1,数对(2,1)和(3,2)等都是有效的。因此,k的正负不影响算法的有效性,只是改变了数对的组成方式(对于正k是(x, x+k),对于负k是(x, x-k))。
🦆
算法中使用`lambda`函数和`map`来创建t列表,这种方法与直接使用循环有何优缺点?
使用`lambda`函数和`map`可以使代码更加简洁和函数式编程风格,有助于减少代码量并可能提高代码的可读性。然而,这种方法可能会比直接使用循环在性能上略有不足,因为`map`和`lambda`会创建额外的函数调用开销,并且生成的是一个列表而不是一个迭代器,这在处理非常大的数据集时可能会增加内存消耗。直接使用循环则更直接,可能在性能上更优,特别是在需要最佳性能或处理大数据时。

相关问题

二叉搜索树的最小绝对差

给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值

差值是一个正数,其数值等于两值之差的绝对值。

 

示例 1:

输入:root = [4,2,6,1,3]
输出:1

示例 2:

输入:root = [1,0,48,null,null,12,49]
输出:1

 

提示:

  • 树中节点的数目范围是 [2, 104]
  • 0 <= Node.val <= 105

 

注意:本题与 783 https://leetcode-cn.com/problems/minimum-distance-between-bst-nodes/ 相同