侧边栏壁纸
博主头像
GabrielxD

列車は必ず次の駅へ。では舞台は?私たちは?

  • 累计撰写 674 篇文章
  • 累计创建 128 个标签
  • 累计收到 20 条评论

目 录CONTENT

文章目录

【数学, 哈希表, 计数】好数对的数目

GabrielxD
2022-08-09 / 0 评论 / 0 点赞 / 201 阅读 / 808 字
温馨提示:
本文最后更新于 2022-09-02,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

题目

1512. 好数对的数目


给你一个整数数组 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

解题

方法一:暴力 计数

思路

对于每个 nums[i],枚举所有 nums[j](i>j)(i > j) ,如果 nums[i] = nums[j] 就把计数自增,最后返回计数。

代码

class Solution {
public:
    int numIdenticalPairs(vector<int>& nums) {
        int n = nums.size(), 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;
    }
};
class Solution {
    public int numIdenticalPairs(int[] nums) {
        int n = nums.length, 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;
    }
}

方法二:数学

思路

假设 nums = [1, 2, 3, 1, 1, 3],那么它有 4 组好数对,分别是 (0, 3), (0, 4), (3, 4), (2, 5)。我们按照下标对应的元素来分类就是:

  • 1 : (0, 3), (0, 4), (3, 4)
  • 2 : 无
  • 3 : (2, 5)

为了方便描述,我们定义相同元素的下标组成的集合为一个下标组,比如 1 的下标组是 0, 3, 4

于是我们发现,其实要求的就是元素相等的下标组两个为一组组合数(关于排列组合,可以参考这篇大佬的博客:排列组合的一些公式及推导(非常详细易懂) - 樱花赞)。

那么我们可以遍历整个数组,把每个元素的出现次数记录在哈希表中(这里由于数据量较小,使用数组代替)。然后遍历哈希表,把每个元素的计数(count)的排列数求出来:

An2=n(n1)2A^{2}_{n}=\frac{n(n-1)}{2}

然后把所有得出的排列数求和即为好数对的个数。

代码

class Solution {
public:
    int numIdenticalPairs(vector<int>& nums) {
        int counts[101] = {0};
        for (int& num : nums) ++counts[num];
        int ans = 0;
        for (int& count : counts) ans += count * (count - 1) / 2;
        return ans;
    }
};
class Solution {
    public int numIdenticalPairs(int[] nums) {
        int[] counts = new int[101];
        for (int num : nums) ++counts[num];
        int ans = 0;
        for (int count : counts) ans += count * (count - 1) / 2;
        return ans;
    }
}

这里可以优化一下,把计算排列数的方式改成:

An2=1+2+3+...+(n1)=i=1n1iA^{2}_{n}=1+2+3+...+(n-1)=\sum\limits_{i=1}^{n-1}i

就可以边求排列数边累加排列数了。

class Solution {
public:
    int numIdenticalPairs(vector<int>& nums) {
        int ans = 0, counts[101] = {0};
        for (int& num : nums) ans += counts[num]++;
        return ans;
    }
};
class Solution {
    public int numIdenticalPairs(int[] nums) {
        int ans = 0;
        int[] counts = new int[101];
        for (int num : nums) ans += counts[num]++;
        return ans;
    }
}
0

评论区