• Leetcode刷题(四十二)


    美丽下标对的数目(Easy)

    给你一个下标从 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] 的最后一个数字是 525 互质,因此 gcd(2,5) == 1 。
    i = 0 和 j = 2 :nums[0] 的第一个数字是 2 ,nums[2] 的最后一个数字是 121 互质,因此 gcd(2,1) == 1 。
    i = 1 和 j = 2 :nums[1] 的第一个数字是 5 ,nums[2] 的最后一个数字是 151 互质,因此 gcd(5,1) == 1 。
    i = 1 和 j = 3 :nums[1] 的第一个数字是 5 ,nums[3] 的最后一个数字是 454 互质,因此 gcd(5,4) == 1 。
    i = 2 和 j = 3 :nums[2] 的第一个数字是 1 ,nums[3] 的最后一个数字是 414 互质,因此 gcd(1,4) == 1 。
    因此,返回 5 。
    示例 2:
    
    输入:nums = [11,21,12]
    输出:2
    解释:共有 2 组美丽下标对:
    i = 0 和 j = 1 :nums[0] 的第一个数字是 1 ,nums[1] 的最后一个数字是 1gcd(1,1) == 1 。
    i = 0 和 j = 2 :nums[0] 的第一个数字是 1 ,nums[2] 的最后一个数字是 2gcd(1,2) == 1 。
    因此,返回 2 。
    提示:
    
    2 <= nums.length <= 100
    1 <= nums[i] <= 9999
    nums[i] % 10 != 0
    Related Topics
    数组
    哈希表
    数学
    计数
    数论
    

    思路分析1

    首先想到的就是使用双循环的暴力解法,使用双循环逐个遍历数组,找到所有的美丽下标对。这里判断两个数是不是互质的函数写法是固定常用的GCD函数,如果返回值为1则代表两个数互质。

    代码实现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;
        }
    }
    

    思路分析2

    上面的方法就是简答粗暴地遍历,我就思考有没有可能优化一点速度,这里我可以选择把相同数字出现的次数记录下来,那么下面只要出现了互质的数字直接就增加对应的次数。比如说,前三个数字的第一位都是‘3’,那么后面只要有一个数字的最后一位是与‘3’互质的,最后的结果就可以直接增加3。这样就减少了一定的重复工作。

    代码实现2

    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,检查是否存在互质的数字对。

  • 相关阅读:
    有方N58CA和EA差异
    Python之正则表达式
    算法金 | LSTM 原作者带队,一个强大的算法模型杀回来了
    ::before 和 :after中双冒号和单冒号有什么区别?解释一下这2个伪元素的作用
    【QT】QT 按钮保持按下时的样式
    主从Reactor高并发服务器
    【仿牛客网笔记】 Redis,一站式高性能存储方案——Redis入门
    XTU-OJ 1295-Flawless Prime
    vscode代码拼写错误检测插件
    如何成为优秀的咖啡师?
  • 原文地址:https://blog.csdn.net/m0_56798535/article/details/139842664