问题描述
小S在学习素数因子的分解,她希望在[1,n][1,n]的范围内,找到一些连续的自然数,这些数的乘积最多包含kk个不同的素因子。你的任务是帮助小S找到可以取的连续自然数的最大长度。
连续的自然数指的是不能重复且相邻数的差为1的一组正整数,例如 [2, 3, 4, 5] 和 [5, 6, 7] 都是连续的取数。
问题理解
我们需要在 [1, n] 的范围内找到一些连续的自然数,这些数的乘积最多包含 k 个不同的素因子。目标是找到可以取的连续自然数的最大长度。
关键点
- 素因子分解:我们需要对每个数进行素因子分解,并统计其素因子的数量。
- 滑动窗口:为了找到最大长度的连续自然数,我们可以使用滑动窗口技术来动态调整窗口的大小。
数据结构选择
- 素因子分解:可以使用一个字典来存储每个数的素因子及其数量。
- 滑动窗口:可以使用两个指针来表示窗口的左右边界。
算法步骤
-
初始化:
- 初始化一个字典来存储当前窗口内每个素因子的数量。
- 初始化两个指针
left和right表示窗口的左右边界,初始值均为1。 - 初始化一个变量
max_length来记录最大长度。
-
滑动窗口:
-
移动
right指针,将新的数加入窗口,并更新素因子字典。 -
检查当前窗口内的素因子数量是否超过
k:- 如果超过,移动
left指针,缩小窗口,直到素因子数量不超过k。
- 如果超过,移动
-
更新
max_length。
-
-
终止条件:
- 当
right指针超过n时,终止循环。
- 当
代码实现
### 时间复杂度分析
update_prime_factors 函数
- 这个函数用于分解
num的素因子,并更新prime_factors字典。 - 对于一个数
num,我们需要检查从2到sqrt(num)的所有数,看看它们是否是num的因子。 - 因此,
update_prime_factors的时间复杂度是O(sqrt(num))。
remove_prime_factors 函数
- 这个函数用于移除
num的素因子,并更新prime_factors字典。 - 类似于
update_prime_factors,它的时间复杂度也是O(sqrt(num))。
count_distinct_primes 函数
- 这个函数用于统计
prime_factors字典中不同素因子的数量。 - 它的时间复杂度是
O(1),因为只需要返回字典的长度。
solution 函数
- 在
solution函数中,我们使用滑动窗口技术来找到最大长度的连续自然数。 right指针从1遍历到n,因此外层循环的时间复杂度是O(n)。- 对于每个
right,我们调用update_prime_factors,其时间复杂度是O(sqrt(right))。 - 在每次移动
left指针时,我们调用remove_prime_factors,其时间复杂度是O(sqrt(left))。 - 因此,内层循环的总时间复杂度是
O(n * sqrt(n))。
综上所述,solution 函数的时间复杂度是 O(n * sqrt(n))。
空间复杂度分析
prime_factors 字典
prime_factors字典用于存储当前窗口内每个素因子的数量。- 在最坏情况下,
prime_factors字典的大小不会超过k,因为题目要求素因子数量不超过k。 - 因此,
prime_factors字典的空间复杂度是O(k)。
其他变量
- 其他变量(如
left、right、max_length等)的空间复杂度是O(1)。
综上所述,solution 函数的空间复杂度是 O(k)。
总结
- 时间复杂度:
O(n * sqrt(n)) - 空间复杂度:
O(k)