给你一个下标从 0 开始的整数数组 nums 。如果下标对 i、j 满足 0 ≤ i < j < nums.length ,如果 nums[i] 的 第一个数字 和 nums[j] 的 最后一个数字 互质 ,则认为 nums[i] 和 nums[j] 是一组 美丽下标对 。
返回 nums 中 美丽下标对 的总数目。
对于两个整数 x 和 y ,如果不存在大于 1 的整数可以整除它们,则认为 x 和 y 互质 。换而言之,如果 gcd(x, y) == 1 ,则认为 x 和 y 互质,其中 gcd(x, y) 是 x 和 y 的 最大公因数 。
示例 1:
输入:nums = [2,5,1,4]
输出:5
解释:nums 中共有 5 组美丽下标对:
i = 0 和 j = 1 :nums[0] 的第一个数字是 2 ,nums[1] 的最后一个数字是 5 。2 和 5 互质,因此 gcd(2,5) == 1 。
i = 0 和 j = 2 :nums[0] 的第一个数字是 2 ,nums[2] 的最后一个数字是 1 。2 和 1 互质,因此 gcd(2,1) == 1 。
i = 1 和 j = 2 :nums[1] 的第一个数字是 5 ,nums[2] 的最后一个数字是 1 。5 和 1 互质,因此 gcd(5,1) == 1 。
i = 1 和 j = 3 :nums[1] 的第一个数字是 5 ,nums[3] 的最后一个数字是 4 。5 和 4 互质,因此 gcd(5,4) == 1 。
i = 2 和 j = 3 :nums[2] 的第一个数字是 1 ,nums[3] 的最后一个数字是 4 。1 和 4 互质,因此 gcd(1,4) == 1 。
因此,返回 5 。
示例 2:
输入:nums = [11,21,12]
输出:2
解释:共有 2 组美丽下标对:
i = 0 和 j = 1 :nums[0] 的第一个数字是 1 ,nums[1] 的最后一个数字是 1 。gcd(1,1) == 1 。
i = 0 和 j = 2 :nums[0] 的第一个数字是 1 ,nums[2] 的最后一个数字是 2 。gcd(1,2) == 1 。
因此,返回 2 。
提示:
2 <= nums.length <= 100
1 <= nums[i] <= 9999
nums[i] % 10 != 0
Related Topics
数组
哈希表
数学
计数
数论
首先想到的就是使用双循环的暴力解法,使用双循环逐个遍历数组,找到所有的美丽下标对。这里判断两个数是不是互质的函数写法是固定常用的GCD函数,如果返回值为1则代表两个数互质。
class Solution {
public int countBeautifulPairs(int[] nums) {
int result = 0;
for (int i = 0; i < nums.length; i++){
for (int j = i + 1;j < nums.length; j++){
int a = nums[i];
while (a >= 10){
a = a / 10;
}
int b = nums[j] % 10;
if (gcd(a, b)==1){
result++;
}
}
}
return result;
}
public int gcd(int a, int b){
while (b != 0){
int temp = b;
b = a % b;
a = temp;
}
return a;
}
}
上面的方法就是简答粗暴地遍历,我就思考有没有可能优化一点速度,这里我可以选择把相同数字出现的次数记录下来,那么下面只要出现了互质的数字直接就增加对应的次数。比如说,前三个数字的第一位都是‘3’,那么后面只要有一个数字的最后一位是与‘3’互质的,最后的结果就可以直接增加3。这样就减少了一定的重复工作。
class Solution {
// 求两个数的最大公约数
private int gcd(int a, int b) {
while (b != 0) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}
public int countBeautifulPairs(int[] nums) {
int[] cnt = new int[10]; // 已遍历 第一位数的计数
int ans = 0;
for (int x : nums) {
// 获取第一个数字
int first = 0;
for (int tx = x; tx != 0; tx /= 10) {
first = tx % 10;
}
// 获取最后一个数字
int last = x % 10;
// 遍历找之前是否有互质的
for (int fir = 1; fir <= 9; fir++) {
if (cnt[fir] != 0 && gcd(fir, last) == 1) {
ans += cnt[fir];
}
}
cnt[first]++; // 维护计数器
}
return ans;
}
}
在这段代码中:
1.gcd 方法用于计算两个数的最大公约数。
2.countBeautifulPairs 方法计算美丽下标对的总数目。它遍历数组 nums,提取每个数的第一个和最后一个数字,并检查是否存在之前遍历过的数字与当前数的最后一个数字互质。
3.维护一个计数器 cnt,记录每个数字的第一个数字出现的次数。通过遍历 cnt,检查是否存在互质的数字对。