🎈不知道大家对于算法的学习是一个怎样的心态呢?为了面试还是因为兴趣?不管是出于什么原因,算法学习需要持续保持。
校运动会上,所有参赛同学身上都贴有他的参赛号码。某班参赛同学的号码记于数组 nums 中。假定反转后的号码称为原数字的「镜像号码」。如果 两位同学 满足条件:镜像号码 A + 原号码 B = 镜像号码 B + 原号码 A,则这两位同学可以到广播站兑换一次读通讯稿的机会,为同班同学加油助威。请返回所有参赛同学可以组成的可以读通讯稿的组数,并将结果对10^9+7取余。
注意:
输入:nums = [17,28,39,71]
输出:3
解释:
共有三对同学,分别为 [17,28]、[17,39]、[28,39]。其中:
第一对同学:17 + 82 = 71 + 28;
第二对同学:17 + 93 = 71 + 39;
第三对同学:28 + 93 = 82 + 39。
示例 2:
输入:nums = [71, 60]
输出:1
解释:
共有一对同学,为 [71, 60]。
因为 71 + 6 = 17 + 60,此处 60 的镜像号码为 6,前导零被忽略。
提示:
首先我们要先理解一下题意,最主要的就是这个公式:镜像号码 A + 原号码 B = 镜像号码 B + 原号码 A
,我们需要在所有号码中找到所有符合这个公式的组合数。
首先数据的规模为:
因此我们不能直接暴力进行匹配,暴力的话我们需要进行双重遍历,时间复杂度为 10^6 * 10^6 = 10 ^ 12,这样很明显会超时,所以我们需要重新想想有没有其他更加简便的方法来解决这道题。
我们假设有两个数 a
和 b
,令镜像a = a + x
,镜像b = b + y
,将其代入公式镜像号码 A + 原号码 B = 镜像号码 B + 原号码 A
,我们可以得到:a + x + b = b + y + a
,化简可以得到x = y
,也就是说要想等式成立,只需要x = y
即可。
所以我们可以使用一个哈希表来记录每一个原号码与镜像号码之差x
的数量,后面再对每一个x
进行组合即可得出答案,具体步骤如下:
const getReverse = function(t){
let temp = '';
for(let j = t.length - 1; j >= 0; j--){
temp += t[j];
}
return temp
};
let map = new Map();
for(let i = 0; i < nums.length; i++){
let temp = getReverse(nums[i] + '');
temp = temp - nums[i];
map.set(temp,(map.get(temp) || 0) + 1);
}
let res = 0;
for(let key of map.keys()){
let ind = map.get(key);
res += ind * (ind - 1) / 2;
res %= 10 ** 9 + 7;
}
完整代码如下:
/**
* @param {number[]} nums
* @return {number}
*/
var numberOfPairs = function(nums) {
let map = new Map();
const getReverse = function(t){
let temp = '';
for(let j = t.length - 1; j >= 0; j--){
temp += t[j];
}
return temp
};
for(let i = 0; i < nums.length; i++){
let temp = getReverse(nums[i] + '');
temp = temp - nums[i];
map.set(temp,(map.get(temp) || 0) + 1);
}
let res = 0;
for(let key of map.keys()){
let ind = map.get(key);
res += ind * (ind - 1) / 2;
res %= 10 ** 9 + 7;
}
return res;
};
关注公众号『前端也能这么有趣
』,获取更多有趣内容。
🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,偶尔也会在自己的公众号『
前端也能这么有趣
』发一些比较有趣的文章,有兴趣的也可以关注下。在此谢谢大家的支持,我们下文再见 🙌。