178. 小C的连续自然数乘积问题 | 豆包MarsCode AI刷题

110 阅读3分钟

问题描述

小S在学习素数因子的分解,她希望在[1,n]的范围内,找到一些连续的自然数,这些数的乘积最多包含k个不同的素因子。你的任务是帮助小S找到可以取的连续自然数的最大长度。

连续的自然数指的是不能重复且相邻数的差为1的一组正整数,例如 [2, 3, 4, 5] 和 [5, 6, 7] 都是连续的取数。

思路分析:

我们可以使用滑动窗口的方法来解决这个问题。从区间的起始位置开始,逐步扩大窗口,同时记录窗口内数字乘积的不同素因子个数。当不同素因子个数超过给定的 k 时,就缩小窗口,直到不同素因子个数再次满足条件或者窗口不能再缩小为止。在这个过程中,不断更新所能找到的连续自然数的最大长度。

计算素因子:需要一个方法用于计算一个数的不同素因子的个数。它通过从最小的素数 2 开始,不断地分解该数,将找到的素因子添加到一个集合中,最后返回集合的大小,即不同素因子的个数。

滑动窗口:通过不断移动右指针扩大窗口,计算窗口内数字乘积的不同素因子个数。当个数超过 k 时,移动左指针缩小窗口,直到个数满足条件。在每次满足条件时,更新所能找到的最大长度 max_len。最后返回这个最大长度作为结果。

代码:

import math

def distinct_prime_factors(n):
    factors = set()
    while n % 2 == 0:
        factors.add(2)
        n //= 2
    for i in range(3, int(math.sqrt(n)) + 1, 2):
        while n % i == 0:
            factors.add(i)
            n //= i
    if n > 2:
        factors.add(n)
    return len(factors)
def solution(n: int, k: int) -> int:
    # write code here
    left, right = 0, 0
    product = 1
    max_len = 0
    distinct_factors_count = 0

    while right < n:
        right += 1
        product *= right
        distinct_factors_count = distinct_prime_factors(product)

        while distinct_factors_count > k and left < right:
            product //= left + 1
            left += 1
            distinct_factors_count = distinct_prime_factors(product)

        if distinct_factors_count <= k:
            max_len = max(max_len, right - left)

    return max_len

时间复杂度:

  • distinct_prime_factors 函数:在计算一个数 n 的不同素因子个数时,对于每个素数 p(从 2 开始,每次增加 2 检查奇数是否为素数),最多需要检查到 n\sqrt{n}

  • max_length 函数

    • max_length 函数通过滑动窗口遍历区间 [1, n]。右指针 right 从 0 开始,每次增加 1,最多会移动到 n,所以右指针移动的次数最多是 n 次。
    • 对于每次右指针移动后的窗口内的数的乘积,需要调用 distinct_prime_factors 函数来计算其不同素因子个数。如前面所分析,distinct_prime_factors 函数时间复杂度为 ,这里 m 是窗口内数的乘积,在最坏情况下,m 可能接近 n!(当窗口包含了从 1 到 n 的所有数时),但实际上它的增长速度比 n! 慢很多,我们可以大致认为 m 的量级与 n 的某个多项式相关,所以每次调用 distinct_prime_factors 函数的时间复杂度可以近似O(m)=O(nλ)O(\sqrt{m})=O(n^\lambda) 。(感觉不太对劲)
    • 左指针 left 也会随着窗口的调整而移动,最多也会移动 n 次(虽然实际上左指针移动次数通常会小于 n 次,但在分析最坏情况时按最多移动 n 次考虑)。
    • 综合来看,max_length 函数中最主要的操作是右指针和左指针的移动以及每次移动后调用 distinct_prime_factors 函数,右指针移动 n 次,每次移动后调用 distinct_prime_factors 函数的时间复杂度近似为O(n)O(\sqrt{n}),左指针最多移动 n 次,所以整体时间复杂度大致为 ,即O(nm)=O(nnλ)O(n\sqrt{m})=O(n\sqrt{n^\lambda})

不知道怎么分析了(。。。)

空间复杂度:

一个数的素因子放在factor集合里,空间复杂度<O(n)<O(\sqrt{n})。应该可以更小,设计到数论