【力扣刷题】1512. 好数对的数目【数学推导】

236 阅读1分钟

「这是我参与11月更文挑战的第 26 天,活动详情查看:2021最后一次更文挑战

原题链接

1512. 好数对的数目 - 力扣(LeetCode) (leetcode-cn.com)

题目描述

给你一个整数数组 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
解释:数组中的每组数字都是好数对

参数限制

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

分析

有题目得知好数对的特点为:两个数相同且为不同的下标,则为一对好数;所以,当一个数有多个下标时,每两个下标可以组成一对好数

假如一个数出现了 3 次,他的下标对应为 a, b, c,根据好数的定义,ab, ac, bc 3 种下标组合都能算一对好数,ba 的组合等效于 ab

根据上一步的分析进一步的推导,当一个数重复出现了 n 次时,第 1 下标可以和 后面的 n-1 个下标的数组合成好数,第 2 个坐标与后面的 n-2 个坐标组成了不重复的好数对。。。第 n-1 个与第 n 个组合成最后一对不重复的好数,由此可以推导出公式: (n-1)*(n-1+1)/2 => n*(n-1)/2

经过上述的分析,发现题目的目的其实是让我们统计数组中,各个元素出现的次数,最后需要再合计出重复次数超过 1 的元素的好数对的全部和

代码

var numIdenticalPairs = function(nums) {
    let obj = {};
    nums.forEach(n => obj[n] = (obj[n] || 0) + 1);
    let sum = n => n * (n - 1) / 2;
    return Object.keys(obj).map(k => sum(obj[k])).reduce((a, b) => a + b, 0);
};

在实际的编码过程中,发现我们不需要对出现次数为 1 的数做特殊处理,因为上述推导的统计公式再代入 1 去计算后返回 0,不影响我们的结果

image.png


今天的力扣刷题就分享到这里,感谢大家的阅读~