【leetcode】1512. 好数对的数目(简单)题解学习

7 篇文章 0 订阅
5 篇文章 0 订阅

题目描述:

给你一个整数数组 nums 。

如果一组数字 (i,j) 满足 nums[i] == nums[j] 且 i < j ,就可以认为这是一组 好数对 。

返回好数对的数目。

示例 1:

输入:nums = [1,2,3,1,1,3]
输出:4
解释:有 4 组好数对,分别是 (0,3), (0,4), (3,4), (2,5) ,下标从 0 开始

示例 2:

输入:nums = [1,1,1,1]
输出:6
解释:数组中的每组数字都是好数对

示例 3:

输入:nums = [1,2,3]
输出:0

提示:

  • 1 <= nums.length <= 100
  • 1 <= nums[i] <= 100

代码实现:

方法一:可以通过暴力枚举的方式来求解。可以使用两个嵌套的循环,外层循环枚举所有可能的位置 i,内层循环枚举 i 后面的位置 j,如果 nums[i] == nums[j],则说明找到了一组好数对,累加计数器即可

public int numIdenticalPairs(int[] nums) {
    int n = nums.length;
    int count = 0;
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            if (nums[i] == nums[j]) {
                count++;
            }
        }
    }
    return count;
}

该方法的时间复杂度为 O(n^2),空间复杂度为 O(1)。

方法二:可以利用哈希表来记录每个数字出现的次数

具体步骤如下:

  1. 创建一个哈希表 map,用于记录数组中每个数字出现的次数。
  2. 遍历数组 nums,对于每个数字 num,将其在哈希表中对应的计数器加一。
  3. 遍历哈希表 map,对于每个数字出现的次数 count,好数对的数量为 count * (count - 1) / 2,将其累加到结果 ans 中。
  4. 返回结果 ans
public int numIdenticalPairs(int[] nums) {
    Map<Integer, Integer> map = new HashMap<>();
    int count = 0;
    
    for (int num : nums) {
        map.put(num, map.getOrDefault(num, 0) + 1);
    }
    
    for (int num : map.keySet()) {
        int freq = map.get(num);
        count += freq * (freq - 1) / 2;
    }
    
    return count;
}

这种方法的时间复杂度为 O(n),其中 n 是数组 nums 的长度。需要遍历两次数组,第一次遍历统计每个数字出现的次数,第二次遍历计算好数对的数量。空间复杂度为 O(n),用于存储哈希表。相较于暴力枚举的方法,这种方法的效率更高。

(第二种方法不是很能理解O.o...),

count += freq * (freq - 1) / 2;

这句代码的作用是计算出当前数字 num 的好数对数量,并将其累加到变量 count 上。

具体来说,如果一个数字在数组中出现了 freq 次,那么它可以组成的好数对数量为 freq * (freq - 1) / 2。这个公式的解释如下:

假设这个数字出现在数组中的位置分别为 i1, i2, ..., ifreq,那么它可以和其他数字组成的好数对数量就是

C(freq, 2) = freq! / (2! * (freq - 2)!) = freq * (freq - 1) / 2

其中 C(n, m) 表示从 n 个元素中选取 m 个元素的组合数。

因为一个数字出现 freq 次,所以它可以和其他任意一个相同的数字组成一组好数对,因此它能够组成的好数对数量就是 C(freq, 2)

最后,我们遍历哈希表中的每个数字,将它们的好数对数量相加得到总的好数对数量,即为变量 count 的值。

总之,这句代码的作用是将当前数字能够组成的好数对数量累加到计数器上。

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值