2023 年第 1 周总结

发布于 2023-01-01  104 次阅读


本周学习情况

  • 周一至周三每天进行了两轮周赛模拟,其中有五次均在40分钟内完成了三题,一次在一个半小时内完成三题。
  • 周四把上次周赛的中等题过了一遍,并练习了枚举。
  • 周五、周六温习图的相关算法与代码模板,并做练习。
  • 周赛第一次 0 错误 AK 。

一点阶段性感想

过去两个月刷 LeetCode 的经历还是比较开心的,学到很多东西(也还有更多要学)。

差不多要进入下一个阶段的学习了。虽然不会停止算法练习,但就不每天专帖更新了。

再多立个flag,今年每日一题要全勤!(虽然12月每天都做题,但非每日一题不算……)

周赛情况

两道 M 题都涉及到质数,恰好这周刷到了质数题,对这类题目有基本了解,所以很快做出来了。

但最后能 AK 确实意料之外。算是2023年第一天的一个意外惊喜,新年新气象!

可能因为圣诞周赛太难了所以这次放放水

Problem 1 统计能整除数字的位数

思路

数字最大才9位,逐位检查即可。

代码

class Solution:
    def countDigits(self, num: int) -> int:
        value = num
        ans = 0
        while num:
            cur = num % 10
            num //= 10
            if value % cur == 0: ans += 1
        return ans

Problem 2 数组乘积中的不同质因数数目

思路

首先不能被举例迷惑,总共会有 10000 个数字,累积肯定会溢出。而显然每个因数的因数也一定是积的因数,所以检查所有数字的质因数即可。

先想分解每个数再统计,但估计会超时。然后看到数字范围,只有 1000 个,那么可以对这 1000 个数字逐个求质因数,放进单独的集合中,遍历数组时直接取用算好的质因数放到集合里即可。

最后返回集合大小。

代码

class Solution:
    def distinctPrimeFactors(self, nums: List[int]) -> int:
        def getContent(x: int) -> Set[int]:
            content = set()
            i = 2
            while i * i <= x:
                if (x % i == 0):
                    while x % i == 0:
                        content.add(i)
                        x = x // i
                i += 1
            if x > 1: content.add(x)
            return content
        mapping = [set() for _ in range(1001)]
        for num in range(2, 1001):
            mapping[num] = getContent(num)
        res = set()
        for num in nums:
            res = res.union(mapping[num])
        return len(res)

Problem 3 将字符串分割成值不超过 K 的子字符串

思路

贪心法,让当前数字尽可能大,如果超出 k ,就另起一个数字。如此可以推出全局最优:子串数目最少。

另外想到什么时候无法分割子串?在最坏的情况下,我们只能把每一位数字作为一个子串,那么当 k 小于 9 ,且字符串中有大于 k 的数字,此时一定分割不了,返回 -1 。

代码

class Solution:
    def minimumPartition(self, s: str, k: int) -> int:
        if k < 9:
            for ch in s:
                if int(ch) > k: return -1
        ans = 0
        cur = ""
        n = len(s)
        for idx in range(n):
            if int(cur + s[idx]) > k:
                cur = ""
                ans += 1
            cur += s[idx]
        return ans + 1

Problem 4 范围内最接近的两个质数

思路

看到数据范围最大到 10 的 6 次方,而上次计数质数是它的五倍,那么显然可以直接用了。

直接用埃氏筛法生成范围内质数,然后从小到大遍历找差最小的组合即可(显然组合一定相邻)。

如果生成的质数数目不足 2 ,返回 -1 。

代码

class Solution:
    def closestPrimes(self, left: int, right: int) -> List[int]:
        primes = []

        def getPrimes(n: int) -> None:
            if n < 2:  return
            nums = [1 for i in range(n + 1)]
            nums[0] = 0
            nums[1] = 0
            for num in range(2, int(sqrt(n)) + 1):
                if nums[num]:
                    for i in range(num * num, n + 1, num):
                        nums[i] = 0
            for num in range(n + 1):
                if nums[num] and left <= num <= right:
                    primes.append(num)
            return

        getPrimes(right)
        if len(primes) < 2: return [-1, -1]
        ans = [primes[0], primes[1]]
        n = len(primes)
        for i in range(1, n):
            if primes[i] - primes[i - 1] < ans[1] - ans[0]:
                ans = [primes[i - 1], primes[i]]
        return ans