如何解决如何减少该程序的时间?
我有一个像这样的程序:给定一个整数序列,找到最大的素数和它的正数。
示例:
input:
9 // how many numbers
19 7 81 33 17 4 19 21 13
output:
19 // the biggest prime
1 7 // and its positon
所以首先我得到输入,将其存储在一个数组中,制作该数组的副本并对其进行排序(因为我使用了一个变量来跟踪最高级的素数,如果未排序则会发生疯狂的事情)用该数组的每个数字检查它是否为素数,再次遍历该数组以得到正数并打印结果。
但是时间太慢了,我可以改善吗?
我的代码:
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
int main()
{
int n;
cin >> n;
int numbersNotSorted[n];
int maxnum{0};
for (int i = 0; i < n; i++)
{
cin >> numbersNotSorted[i];
}
int numbeRSSorted[n];
for (int i = 0; i < n; i++)
{
numbeRSSorted[i] = numbersNotSorted[i];
}
sort(numbeRSSorted,numbeRSSorted + n);
for (int number = 0; number < n; number++)
{
int countNum{0};
for (int i = 2; i <= sqrt(numbeRSSorted[number]); i++)
{
if (numbeRSSorted[number] % i == 0)
countNum++;
}
if (countNum == 0)
{
maxnum = numbeRSSorted[number];
}
}
cout << maxnum << '\n';
for (int i = 0; i < n; i++)
{
if (numbersNotSorted[i] == maxnum)
cout << i + 1 << ' ';
}
}
解决方法
如果您需要最大的质数,则对数组进行排序不会带来任何好处,无论如何,您都需要检查存储在数组中的所有值。
即使您实现了the best averages you can hope for are O(N + k)
这种快速排序算法,所以对数组进行排序实际上比在未排序的数组中查找最大素数要昂贵得多。
该过程非常简单,请检查下一个值是否大于当前的最大素数,如果是,请检查其是否也为素数,存储位置和/或值(如果不是),则检查下一个值,重复直到数组结尾。
θ(N)
时间兼容性将是在特定条件下可能的最佳优化。
从基本的“输入的每个数字”循环开始:
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
int main() {
int n;
int newNumber;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> newNumber;
}
}
如果新数字小于当前的最大素数,则可以将其忽略。
int main() {
int n;
int newNumber;
int highestPrime;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> newNumber;
if(newNumber >= highestPrime) {
}
}
}
如果新数字等于最高质数,则只需将其位置存储在某处。我很懒,所以:
int main() {
int n;
int newNumber;
int highestPrime;
int maxPositions = 1234;
int positionList[maxPositions];
int nextPosition;
int currentPosition = 0;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> newNumber;
currentPosition++;
if(newNumber >= highestPrime) {
if(newNumber == highestPrime) {
if(nextPosition+1 >= maxPositions) {
// List of positions is too small (should've used malloc/realloc instead of being lazy)!
} else {
positionList[nextPosition++] = currentPosition;
}
}
}
}
}
如果新数字大于当前最大的质数,则需要确定它是否是质数,如果是,则需要重置列表并存储其位置,等等:
int main() {
int n;
int newNumber;
int highestPrime = 0;
int maxPositions = 1234;
int positionList[maxPositions];
int nextPosition;
int currentPosition = 0;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> newNumber;
currentPosition++;
if(newNumber >= highestPrime) {
if(newNumber == highestPrime) {
if(nextPosition+1 >= maxPositions) {
// List of positions is too small (should've used malloc/realloc instead of being lazy)!
} else {
positionList[nextPosition++] = currentPosition;
}
} else { // newNumber > highestPrime
if(isPrime(newNumber)) {
nextPosition = 0; // Reset the list
highestPrime = newNumber;
positionList[nextPosition++] = currentPosition;
}
}
}
}
}
您还需要一些东西来显示结果:
if(highestPrime > 0) {
for(nextPosition= 0; nextPosition < currentPosition; nextPosition++) {
cout << positionList[nextPosition];
}
}
现在;您唯一缺少的是isPrime(int n)
函数。最快的方法是预先计算“是/不是素数”位域。看起来可能像这样:
bool isPrime(int n) {
if(n & 1 != 0) {
n >>= 1;
if( primeNumberBitfield[n / 32] & (1 << (n % 32)) != 0) {
return true;
}
}
return false;
}
这里的问题是(对于32位带符号整数中的正值),您将需要10亿位(或128 MiB)。
为避免这种情况,您可以为数字最多sqrt(1 << 31)
(仅约4 KiB)使用更小的位域;那么如果该数字对于位域而言太大,则可以使用该位域查找质数并检查(取模)它们是否均匀地划分了原始数。
请注意,Eratosthenes(https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes)筛网是生成较小位域的有效方法(但对于数量较少的稀疏种群而言效率不高。)
如果操作正确,您可能会产生一种瞬时的错觉,因为几乎所有的工作都将在人类缓慢输入数字的同时完成(直到输入完所有数字后才进行) )。对于一个非常快的打字员,您在数字之间会有大约2毫秒的时间,而且(输入最后一个数字后)人类不会注意到小于10毫秒的延迟。
,但是时间太慢了,我可以改善吗?
下面的循环患有:
-
为什么要先检查最小值?首先检查最大值以找到最大素数更有意义。找到素数后,请尽早退出
for (... number..)
循环。这利用了sort()
完成的工作。 -
一旦候选值不是素数,请退出素性测试。
。
// (1) Start for other end rather than as below
for (int number = 0; number < n; number++) {
int countNum {0};
for (int i = 2; i <= sqrt(numbersSorted[number]); i++) {
if (numbersSorted[number] % i == 0)
// (2) No point in continuing prime testing,Value is composite.
countNum++;
}
if (countNum == 0) {
maxNum = numbersSorted[number];
}
}
OP可以实施更正。
- 高级:首要测试是一个很深的主题,并且存在许多比OP的方法更好的优化(琐碎和复杂)。但是我怀疑以上2种改进足以满足OP要求。
脆性:代码不能很好地处理列表或n <= 0
中没有质数的情况。
i <= sqrt(numbersSorted[number])
容易出现FP问题,从而导致错误的结果。推荐i <= numbersSorted[number]/i)
。
排序为O(n * log n)
。如此处所做的主要测试是O(n * sqrt(n[i]))
。当最大值的平方根小于O()
的log时,排序不会增加整个代码的n
。如果排序结果使用得当,则值得进行排序。
如果最大值为1,则代码失败,因为素数测试错误地将1标识为素数。
由于numbersSorted[number] < 0
,sqrt()
导致代码失败。
只需进行全范围int
主要测试:
bool isprime(int num) {
if (num % 2 == 0) return num == 2;
for (int divisor = 3; divisor <= num / divisor; divisor += 2) {
if (num % divisor == 0) return false;
}
return num > 1;
}
,
如果要查找素数,请不要进行排序。然后,您必须检查数组中存在的所有数字。
您可以尝试使用这种方法来做同样的事情,但都可以在更短的时间内完成:
步骤1::创建用于检测素数的全局函数。这是解决该问题的方法-
bool prime(int n)
{
int i,p=1;
for(i=2;i<=sqrt(n);i++) //note that I've iterated till the square root of n,to cut down on the computational time
{
if(n%i==0)
{
p=0;
break;
}
}
if(p==0)
return false;
else
return true;
}
步骤2:现在,您的主要功能开始了。您接受用户的输入:
int main()
{
int n,i,MAX;
cout<<"Enter the number of elements: ";
cin>>n;
int arr[n];
cout<<"Enter the array elements: ";
for(i=0;i<n;i++)
cin>>arr[i];
第3步:请注意,我已经声明了一个计数器变量MAX
。我将此变量初始化为数组的第一个元素:MAX=arr[0];
步骤4:现在是循环数组的循环。我所做的是,遍历数组,并在每个元素处检查了该值是否大于或等于前一个MAX
。这样可以确保程序不会检查小于MAX
的值,从而消除了数组的一部分并减少了时间。然后,我嵌套了另一个if语句,以检查该值是否为质数。如果这两个条件都满足,则将MAX
的值设置为数组的当前值:
for(i=0;i<n;i++)
{
if(arr[i]>=MAX) //this will check if the number is greater than the previous MAX number or not
{
if(prime(arr[i])) //if the previous condition satisfies,then only this block of code will run and check if it's a prime or not
MAX=arr[i];
}
}
这会发生什么-在每个循环之后,MAX
的值将更改为数组的最大素数 。
步骤5:然后,在最终遍历数组之后,当程序最终退出循环时,MAX
将具有存储在其中的最大素数。打印此值MAX
。现在获取位置MAX
的位置,只需遍历整个循环并检查与MAX
匹配的值并打印其位置:
for(i=0;i<n;i++)
{
if(arr[i]==MAX)
cout<<i+1<<" ";
}
我在Dev C++ 5.11
中运行了这段代码,编译时间为0.72s
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。