实践出真知,刷题体验
当我们要了解说一个东西的效果如何,最简单的方法就是试着用一下。实践出真知这句话到现在都是亘古不变的真理。 下面是官方介绍 豆包 MarsCode 编程助手是豆包旗下的 AI 编程助手,提供以智能代码补全为代表的 AI 功能。它支持主流的编程语言和 IDE,在开发过程中提供单行代码或整个函数的编写建议。此外,它还支持代码解释、单测生成和问题修复等功能,提高了开发效率和质量。
今天我在写一道hard题目的时候,在写完了让豆包给我解答内容。让我们来看看怎么样。 题目是小C的自然连续数乘积。
问题描述
小S在学习素数因子的分解,她希望在[1,n]的范围内,找到一些连续的自然数,这些数的乘积最多包含k个不同的素因子。你的任务是帮助小S找到可以取的连续自然数的最大长度。
连续的自然数指的是不能重复且相邻数的差为1的一组正整数,例如 [2, 3, 4, 5]
和 [5, 6, 7]
都是连续的取数。
测试样例
样例1:
输入:
n = 10,k = 3
输出:6
样例2:
输入:
n = 20,k = 5
输出:12
样例3:
输入:
n = 100,k = 4
输出:10
解题思路
-
理解问题:
- 我们需要在[1,n]的范围内找到一组连续的自然数,使得这些数的乘积最多包含k个不同的素因子。
- 目标是找到这组连续自然数的最大长度。
-
数据结构选择:
- 使用
unordered_map
来记录每个素因子的出现次数。 - 使用
vector
来存储每个数的素因子。
- 使用
-
算法步骤:
- 遍历从1到n的所有可能的起始点
start
。 - 对于每个起始点,使用滑动窗口技术,从
start
开始向右扩展,直到素因子的数量超过k
。 - 在扩展过程中,记录当前窗口的长度,并更新最大长度。
- 如果当前窗口的素因子数量超过
k
,则从窗口中移除最左边的数,并更新素因子计数。
- 遍历从1到n的所有可能的起始点
-
优化:
- 预处理每个数的素因子,避免重复计算。
- 使用滑动窗口技术减少不必要的计算。
代码实现
#include <iostream>
#include <vector>
#include <unordered_map>
#include <cmath>
using namespace std;
// 判断一个数是否为素数
bool isPrime(int num) {
if (num <= 1) return false;
for (int i = 2; i <= sqrt(num); ++i) {
if (num % i == 0) return false;
}
return true;
}
// 获取一个数的所有素因子
vector<int> getPrimeFactors(int num) {
vector<int> factors;
for (int i = 2; i <= num; ++i) {
if (num % i == 0 && isPrime(i)) {
factors.push_back(i);
}
}
return factors;
}
int solution(int n, int k) {
int maxLength = 0;
for (int start = 1; start <= n; ++start) {
unordered_map<int, int> factorCount;
int distinctFactors = 0;
int currentLength = 0;
for (int end = start; end <= n;
++end) {
vector<int> factors =
getPrimeFactors(end);
for (int factor : factors) {
if (factorCount[factor] == 0)
{
distinctFactors++;
}
factorCount[factor]++;
}
currentLength++;
if (distinctFactors > k) {
break;
}
if (distinctFactors <= k) {
maxLength = max(maxLength,
currentLength);
}
}
}
return maxLength;
}
int main() {
std::cout << (solution(10, 3) == 6) <<
std::endl;
std::cout << (solution(20, 5) == 12) <<
std::endl;
std::cout << (solution(100, 4) == 10) <<
std::endl;
return 0;
}
代码解释
-
isPrime函数:
- 判断一个数是否为素数。
-
getPrimeFactors函数:
- 获取一个数的所有素因子。
-
solution函数:
- 使用滑动窗口技术,从每个可能的起始点
start
开始,向右扩展,直到素因子的数量超过k
。 - 记录当前窗口的长度,并更新最大长度。
- 使用滑动窗口技术,从每个可能的起始点
-
main函数:
- 测试样例,验证代码的正确性。
总结
通过使用滑动窗口技术和预处理素因子,我们可以在[1,n]的范围内找到一组连续的自然数,使得这些数的乘积最多包含k个不同的素因子,并找到这组连续自然数的最大长度。
感受
可以看得出来还是非常完备的,不过有时候题目的答案无法通过测试,而且比较明显多次出现这个问题,还是需要多个版本进行迭代。