二分与平方根求法

本文详细介绍了如何优化求解完全平方数问题的算法,从基本循环优化到二分查找,再到牛顿迭代法。讨论了不同方法的时间复杂度和实际运行效率,包括Carmack在QUAKE3中使用的神奇算法,并对比了内置的sqrt函数。通过测试,揭示了不同方法在时钟周期数上的差异。
摘要由CSDN通过智能技术生成

此博客原文地址:https://www.cnblogs.com/BobHuang/p/12654026.html
Bob老师遇到了3439: 完全平方数这个题目,他现在没啥想法。他选择去循环变量i从0到n看看是不是可以得到答案,于是写下了如下代码:

#include <bits/stdc++.h>
using namespace std;

int main()
{
   
    int n;
    //读入n
    while (cin >> n)
    {
   
        //如果n为-1,结束循环
        if (n == -1)
            break;
        //定义一个旗子,初始未插上。即n不是完全平方数
        int flag = 0;
        for (int i = 0; i <= n; i++)
        {
   
            //枚举的i等于n了结束循环
            if (i * i == n)
            {
   
                //插上旗子,表示n是完全平方数
                flag = 1;
                break;
            }
        }
        //分存在和不存在的情况
        if (flag == 0)
            cout << "No\n";
        else
            cout << "Yes\n";
    }
    return 0;
}

但是他悲伤得获得了TLE(Time Limit Exceeded),因为如果一个数不是完全平方数循环就要执行n+1次,如果是109那么就要执行09+1次,太慢了不能满足这个题目的要求。我们可以用大写字母O来表示时间复杂度,可以粗略的理解就是循环的次数,上述做法的算法复杂度是O(n),即线性阶(1和n比起来很小,被我们舍去了)。还有T组,那么总复杂度为O(T*n),接下来我们将优化这个做法。

一、做一些微小的优化

Alice和Bob说,你这也太傻了,有些循环完全不用运行,既然你知道i * i == n可以结束循环,那不是的时候什么时候可以循环呢。
如果是8,1 * 1 = 1 ;2 * 2 = 4;3 * 3 = 9。9已经比8大了,在找下去肯定也没有啊。Bob把下面的程序添了一个if,就通过了题目。现在我们的算法复杂度是O(T*sqrt(n)),也就是109的循环我只需要31624次,因为31623 * 31623 > 109

#include <bits/stdc++.h>
using namespace std;

int main()
{
   
    int n;
    //读入n
    while (cin >> n)
    {
   
        //如果n为-1,结束循环
        if (n == -1)
            break;
        //定义一个旗子,初始未插上。即n不是完全平方数
        int flag = 0;
        for (int i = 0; i <= n; i++)
        {
   
            //枚举的i等于n了结束循环
            if (i * i == n)
            {
   
                //插上旗子,表示n是完全平方数
                flag = 1;
                break;
            }
            //肯定不存在了,也要结束循环
            if (i * i > n)
            {
   
                break;
            }
        }
        //分存在和不存在的情况
        if (flag == 0)
            cout << "No\n";
        else
            cout << "Yes\n";
    }
    return 0;
}

哎呦,不错哦。如果让你求i*i<=n的i最大值呢,那我循环的时候统计ans不就好了。

#include <bits/stdc++.h>
using namespace std;

int main()
{
   
    int n;
    //读入n
    while (cin >> n)
    {
   
        //如果n为-1,结束循环
        if (n == -1)
            break;
        //定义答案,如果不存在为-1
        int ans = -1;
        for (int i = 0; i <= n; i++)
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值