找到一个数字是一个完美的正方形的优化方法

时间:2014-08-27 16:23:25

标签: algorithm optimization

我的作业中有一个问题,即查找数字是否为perfect square

  

完美正方形是代数结构的一个元素,等于   另一个元素的正方形。

例如:4,9,16等。

我的朋友所做的是,如果n是数字,他们会n - 1次计算n * n

// just a general gist
int is_square = 0;
for (int i = 2; i < n; i++)
{
  if ((i * i) == n)
  {
    std::cout << "Yes , it is";
    is_square = 1;
    break;
  }
}
if (is_square == 0)
{
  std::cout << "No, it is not";
}

我想出了一个解决方案,如下所示:

 if (ceil(sqrt(n)) == floor(sqrt(n)))
 {
   std::cout << "Yes , it is";
 }
 else
 {
   std::cout << "no , it is not";
 }

它运作正常。

可以将其称为 更优化的解决方案 吗?

7 个答案:

答案 0 :(得分:4)

久经考验的遗骸:

double sqrt(double x); // from lib

bool is_sqr(long n) {
    long root = sqrt(n);
    return root * root == n;
}

答案 1 :(得分:2)

您需要知道计算机上sqrt(x)函数的复杂性,以便将其与其他方法进行比较。顺便说一下,你要两次调用sqrt(n);考虑将其存储到变量中(即使编译器可能会为您执行此操作)。

如果使用类似Newton的方法,sqrt(x)的复杂度在O(M(d)),其中M(d)测量乘以两个d位数字所需的时间。 Wikipedia

你朋友的方法做了(n - 2)次乘法(最坏情况),因此它的复杂性就像O(n * M(x)),其中x是一个不断增长的数字。

您的版本仅使用sqrt()(ceil和floor可以忽略,因为它们的复杂程度不变),这使得O(M(n))

O(M(n)) < O(n * M(x)) - 您的版本比您的朋友更优化,但效率最高。看看interjay的链接以获得更好的方法。

答案 2 :(得分:1)

我不知道你有什么限制,但完美的方数定义很明显

  

另一种说法(非负数)是一个平方数,   它的平方根再次是整数   in wikipedia

IF SQRT(n) == FLOOR(SQRT(n)) THEN
    WRITE "Yes it is"
ELSE
    WRITE "No it isn't"

示例sqrt(9) == floor(sqrt(9))sqrt(10) == floor(sqrt(10))

答案 3 :(得分:0)

#include <iostream>
using namespace std;
void isPerfect(int n){
    int ctr=0,i=1;
    while(n>0){
        n-=i;
        i+=2;
        ctr++;
    }
    if(!n)cout<<"\nSquare root = "<<ctr;
    else cout<<"\nNot a perfect square";
}
int main() {
    isPerfect(3);
    isPerfect(2025);
    return 0;
}

答案 4 :(得分:0)

我推荐这个

if(((unsigned long long)sqrt(Number))%1==0) // sqrt() from math library
{
   //Code goes Here
}

它起作用,因为....所有整数(和只有正整数)是1的正倍数

因此解决方案.....

您也可以运行基准测试; 我在MSVC 2012中使用了以下代码

#include <iostream>
#include <conio.h>
#include <time.h>
#include <math.h>

using namespace std;

void IsPerfect(unsigned long long Number);

void main()
{
    clock_t Initial,Final;
    unsigned long long Counter=0;
    unsigned long long Start=Counter;
    Start--;
    cout<<Start<<endl;
    Initial=clock();
    for( Counter=0 ; Counter<=100000000 ; Counter++ )
    {
        IsPerfect( Counter );
    }
    Final=clock();
    float Time((float)Final-(float)Initial);
    cout<<"Calculations Done in "<< Time ;
    getch();
}

void IsPerfect( unsigned long long Number)
{
    if(ceil(sqrt(Number)) == floor(sqrt(Number)))
    //if(((unsigned long long)sqrt(Number))%1==0) // sqrt() from math library
    {
    }

}

您的代码需要13590个时间单位

仅挖掘10049个时间单位

此外,我使用了很少的额外步骤,即类型转换

(unsigned long long)sqrt(Number))

如果没有这个,它可以做得更好

我希望它有所帮助.....

度过愉快的一天......

答案 5 :(得分:0)

您的解决方案更加优化,但可能无效。由于sqrt(x)可能会返回真正的平方根+/- epsilon ,因此必须测试3个不同的根:

bool isPerfect(long x){
  double k = round( sqrt(x) );

  return (n==(k-1)*(k-1)) || (n==k*k) || (n==(k+1)*(k+1));

}

答案 6 :(得分:0)

这是一个简单的python代码,用于查找完美的方形r:

import math
n=(int)(input())
giv=(str)(math.sqrt(n))
if(len(giv.split('.')[1])==1):
    print  ("yes")
else:
    print ("No")