题目
给你一个整数数组 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]
,如果 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
)的排列数求出来:
然后把所有得出的排列数求和即为好数对的个数。
代码
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;
}
}
这里可以优化一下,把计算排列数的方式改成:
就可以边求排列数边累加排列数了。
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;
}
}
评论区