[Leetcode Weekly Contest]326

链接:LeetCode

[Leetcode]2520. 统计能整除数字的位数

给你一个整数 num ,返回 num 中能整除 num 的数位的数目。
如果满足 nums % val == 0 ,则认为整数 val 可以整除 nums 。

遍历即可。

class Solution {
    public int countDigits(int num) {
        int raw = num;
        int res = 0;
        while(num > 0) {
            int val = num % 10;
            num = num / 10;
            if(raw % val == 0) res++;
        }
        return res;
    }
}

[Leetcode]2521. 数组乘积中的不同质因数数目

给你一个正整数数组 nums ,对 nums 所有元素求积之后,找出并返回乘积中 不同质因数 的数目。

注意:

  • 质数 是指大于 1 且仅能被 1 及自身整除的数字。
  • 如果 val2 / val1 是一个整数,则整数 val1 是另一个整数 val2 的一个因数。

本题思路比较直接,对nums数组的每个元素求出质因数,取他们的并集即可。主要难点在于如何求出每个元素的质因数。

class Solution {
    public int distinctPrimeFactors(int[] nums) {
        HashSet<Integer> set = new HashSet<>();
        for(var num:nums) {
            int i = 2;
            while(i*i <= num) {
                while(num % i == 0) {
                    set.add(i);
                    num = num / i;
                }
                i++;
            }
            if(num != 1) set.add(num);
        }
        return set.size();
    }
}

[Leetcode]2522. 将字符串分割成值不超过 K 的子字符串

给你一个字符串 s ,它每一位都是 1 到 9 之间的数字组成,同时给你一个整数 k 。
如果一个字符串 s 的分割满足以下条件,我们称它是一个 好 分割:

  • s 中每个数位 恰好 属于一个子字符串。
  • 每个子字符串的值都小于等于 k 。

请你返回 s 所有的 好 分割中,子字符串的 最少 数目。如果不存在 s 的 好 分割,返回 -1 。
注意:

  • 一个字符串的 值 是这个字符串对应的整数。比方说,"123" 的值为 123 ,"1" 的值是 1 。
  • 子字符串 是字符串中一段连续的字符序列。

贪心。

class Solution {
    public int minimumPartition(String s, int k) {
        int res = 0;
        int i = 0, n = s.length();
        while(i < n) {
            long val = s.charAt(i) - '0';
            if(val > k) return -1;
            int j = i+1;
            while(j < n && val*10+(s.charAt(j) - '0') <= k) {
                val = val * 10 + (s.charAt(j) - '0');
                j++;
            }
            i = j;
            res ++;
        }
        return res;
    }
}

[Leetcode]2523. 范围内最接近的两个质数

给你两个正整数 left 和 right ,请你找到两个整数 num1 和 num2 ,它们满足:

  • left <= nums1 < nums2 <= right 。
  • nums1 和 nums2 都是 质数 。
  • nums2 - nums1 是满足上述条件的质数对中的 最小值 。

请你返回正整数数组 ans = [nums1, nums2] 。如果有多个整数对满足上述条件,请你返回 nums1 最小的质数对。如果不存在符合题意的质数对,请你返回 [-1, -1] 。
如果一个整数大于 1 ,且只能被 1 和它自己整除,那么它是一个质数。

找到[left, right]中的所有素数,然后遍历作差
一般有两种筛素数的方法

  • 埃氏筛:遍历到数i时,筛掉range(i*i, right, i)中的数
  • 线性筛:遍历到数i时,筛掉primes[j]*i的数。另外,线性筛的核心在于用最小的素因子筛掉合数,所以当遍历到ii % primes[j] == 0i时就需要退出循环。因为i乘上primes[j]后面的质数的结果一定会被primes[j]的倍数筛掉,就不需要在i这里先筛一次。举个例子,12应该被\(2∗6(i=6)\)筛掉,而不是被\(3∗4(i=4)\)筛掉
    二者的区别在于埃氏筛会有重复(比如6会同时被2和3筛掉),而线性筛不会重复
class Solution {
    boolean[] isPrimes;

    public int[] closestPrimes(int left, int right) {
        isPrimes = new boolean[right-left+1];
        Arrays.fill(isPrimes, true);
        if(left<=1) isPrimes[1-left] = false;
        filter(left, right);
        int[] res = new int[2];
        int num1 = -1, num2 = -1, diff = Integer.MAX_VALUE;
        int pre = -1;
        for(int n=0; n<right-left+1; ++n) {
            int cur = left + n;
            if(isPrimes[n]) {
                if(pre == -1) pre = cur;
                else {
                    if(cur-pre < diff) {
                        num1 = pre;
                        num2 = cur;
                        diff = cur-pre;
                    }
                    pre = cur;
                }
            }
        }

        res[0] = num1;
        res[1] = num2;
        return res;
    }

    public void filter(int left, int right) {
        for(int i=2;i<left;++i) {
            for(int j=2;i*j<=right;++j) {
                if(i*j>=left) isPrimes[i*j-left] = false;
            }
        }
    }
}

参考:LeetCode

posted @ 2023-01-03 20:24  Jamest  阅读(25)  评论(0编辑  收藏  举报