【LeetCode - 第316场周赛】【暴力 / 滑动窗口】2447. 最大公因数等于 K 的子数组数目 Java实现


题目链接

https://leetcode.cn/problems/number-of-subarrays-with-gcd-equal-to-k/

题目

在这里插入图片描述

思路

方案一 暴力枚举

g = gcd(g, nums[j])

class Solution {
    public int subarrayGCD(int[] nums, int k) {
        int res = 0;

        for (int i = 0; i < nums.length;  i++){
            int g = nums[i];
            for (int j = i; j < nums.length; j ++){
                g = gcd(g, nums[j]);
                if (g == k){
                    res++;
                }
            }
        }
        return res;
    }

    private int gcd(int a, int b) {
        while (b != 0) {
            int tmp = a % b;
            a = b;
            b = tmp;
        }
        return a;
    }
}

稍加改进,如果当前的最大公约数已经小于k,那么没必要继续循环下去

class Solution {
    public int subarrayGCD(int[] nums, int k) {
        int res = 0;

        for (int i = 0; i < nums.length; i++) {
            int g = nums[i];
            for (int j = i; j < nums.length; j++) {
                g = gcd(g, nums[j]);
                if (g == k) {
                    res++;
                } else if (g < k) {
                    break;
                }
            }
        }
        return res;
    }

    private int gcd(int a, int b) {
        while (b != 0) {
            int tmp = a % b;
            a = b;
            b = tmp;
        }
        return a;
    }
}

在这里插入图片描述

方案二 滑动窗口

满足最大公约数是k的子数组里的所有元素,要么是k,要么是2k,3k,4k…

  • 当进入窗口的数字不是k或者nk,数组被截断,窗口清空

  • 当进入窗口的数字是k时,以当前数字k为结尾的满足答案的子数组有i-left+1

  • 当进入窗口的数字是nk时

    • 窗口只有当前数字时,没有满足答案的子数组

    • 窗口内有别的元素时,以当前数字nk为结尾的满足答案的子数组通过倒序遍历求得

      • 例如:k=1,窗口内有[3,5,7,9],我们倒序判断[7,9],[5,7,9],[3,5,7,9]是否满足即可
        在这里插入图片描述
class Solution {
    public int subarrayGCD(int[] nums, int k) {
        int n = nums.length;
        int left = 0;
        int res = 0;
        for (int i = 0; i < n; i++) {
            if (nums[i] % k != 0) {
                left = i + 1;
            } else if (nums[i] == k) {//k
                res += (i - left + 1);
            } else {//nk
                res += getCount(nums, k, left, i);
            }
        }
        return res;
    }

    private int getCount(int[] nums, int k, int left, int right) {
        int res = 0;
        int g = nums[right];
        for (int i = right - 1; i >= left; i--) {
            g = gcd(g, nums[i]);
            if (g == k) {
                res++;
            } else if (g < k) {
                break;
            }
        }
        return res;
    }

    private int gcd(int a, int b) {
        while (b != 0) {
            int tmp = a % b;
            a = b;
            b = tmp;
        }
        return a;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java题目(仅供学习): 一、根据以下要求,比较两个字符串的大小,并返回比较结果: 1、比较两字符串的大小。 2、忽视大小写 3、 按字典序 如果第一个字符串大于第二个字符串 返回大于0,如果第一个字符串等于第二个字符串 返回等于0 ,如果第一个字符串小于第二个字符串返回小于0。 4、例 compareToIgnoreCase("HARD","hark")的比较结果返回小于0 。 二、给一个二维数组inArr[ ][ ],写一个方法获取每一列的最小值,输出到一个一维数组outArr[ ]中。 如:inArr[ ][ ]={{1,8,3},{6,5}},则输出outArr[ ] = {1,5,3} 三、判断一个字符串是否是首字母大写,其余字母都是小写。 例如 输入:True 输出: true 四、输入一个字符串,字符串是字母和数字的组合,编程实现输出一个新的字符串,要求字母在前面,数字在后面,顺序不变,例如:2s7ess83a 变成sessa2783 五、一个字符串,获取最长的一个单词,如有多个相同长度的单词返回第一个单词。入输入:"hello china"则返回 hello 六、将一个字符里出现最多的字母截取,如,addcbbs变为acs。 七、输入一个整型数组,arr=(1,2,5) 输出数组中数字对应英文字母表中对应的字母,如果不在字母表中用"?"表示 例如,输入arr=(1,2,30,3),输出:a b ? c 八、输入一数组,按照英文26个字母顺序,输出每个数字对应的字母,如果查不到,则输出?。如[1,3,30],输出ac?。 九、把数组中的1-26的数字映射成a-z的小写字母 如果输入其他数字,则在页面上打印"?" 如:int [] arr={1,2,3,4,30} 输出:a,b,c,d,? 十、输入A-Z26个字母,输入一个大写字母后,输出该字母之后第5个字母的小写。 如输入A,输出f,输入Z,则输出e,超出Z是,超过1个,则返回a,超过两个,则返回b,以此类推。 十一、一个维数组,求大于等于数组内的所有值的平均值的个数 例,{1、2、3、4、5、6、7、8、9、10} 输出 5 十二、给一个二维数组inArr[ ][ ],写一个方法获取每一列的最大值,输出到一个一维数组outArr[ ]中。 如:inArr[ ][ ]={{1,8,3},{6,5}},则输出outArr[ ] = {8,6} 选取一组一维数组,求出它的最大值和次大值,放入另一个一维数组中并返回。 十三、求两个数的最大公约数

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值