<LeetCode OJ> 69 / 367 Sqrt(x) / Valid Perfect Square

题目翻译:

实现sqrt函数,即平方根函数


分析:

一个正整数的平方根,尽然要求返回一个整数?觉得别扭。
本题是一个典型的数值分析问题,还是比较简单的!控制精度以及两个变量二分迭代至n即可。
具体:
首先根号n这个值一定在n以内,令low=0,high=n
控制精度为0.01,使x-((low+high)/2)*((low+high)/2)之差<0.01(微小的数即可,说明基本相等了)
可得int((low+high)/2)

class Solution {
public:
    int mySqrt(int x) {
        if(x==1 || x==0)
            return x;
        double xx=double(x);
        double low=0.0,high=xx,mid=(low+high)/2.0;
        while(abs(mid*mid-xx)>0.01)
        {
            if(mid*mid-xx > 0)//mid需要减小
                high=mid;
            if(mid*mid-xx < 0)//mid需要增大
                low=mid;
            mid=(low+high)/2.0;    
        }
        return int(mid);
    }
};


别人的答案,怪不得要求返回整数,看来我想偏了,这道问题或许不算数值分析问题,下一道“切蛋糕”才是:

class Solution {
public:
    int mySqrt(int x) {
        long r = x;
        while (r*r > x)
            r = (r + x/r) / 2;//刚好小于x时的r即为所求,这个迭代式子不明白.......
        return r;
    }
};

看了一下网上的分析,猛地回忆起了牛顿迭代法,实际上我们就是在解方程x^2-n=0,而根据牛顿迭代式就成了上述式子。
既然牛顿迭法可以做,那么雅特肯迭代法等也可以做;
牛顿迭代法求开方,具体推到如下:

假设f(x)是关于x的函数,如图所示:



在Xn处的斜率为:

求得:


根据

得到递推公式:

当Xn+1和Xn差距极其小时,Xn即为所求



别人的解法:

class Solution {
public:
    int mySqrt(int x) {
        if(x == 0 || x == 1) 
            return x;
        int beg = 1;
        int end = x;
        long mid = 0;   //这里用long,否则会溢出
        while(beg <= end){
            mid = beg + (end - beg)/2;
            if(mid * mid < x)
                beg = mid + 1;
            else if(mid * mid > x)
                end = mid - 1;
            else
                return mid;
        }
        return end;
    }
};






Total Accepted: 1047  Total Submissions: 2801  Difficulty: Medium

Given a positive integer num, write a function which returns True if num is a perfect square else False.

Note: Do not use any built-in library function such as sqrt.

Example 1:

Input: 16
Returns: True

Example 2:

Input: 14
Returns: False

分析:

本题是上面题目的变形!

class Solution {
public:
    bool isPerfectSquare(int x) {
        if(x == 0 || x == 1)   
            return true;  
        int beg = 1;  
        int end = x;  
        long mid = 0;   //这里用long,否则会溢出  
        while(beg <= end){  
            mid = beg + (end - beg)/2;  
            if(mid * mid < x)  
                beg = mid + 1;  
            else if(mid * mid > x)  
                end = mid - 1;  
            else  
                return true;  
        }  
        return false;  
    }
};






/**********************************************来自九度的华丽分割线**********************************************/

联动一道在九度玩过的一道题:
题目1551:切蛋糕

题目描述:

有如下图半价为R的圆形蛋糕,被切一刀后(图中红色直线),分成两个部分(黄色和绿色),已知其比例为r,求刀痕长度(图中红色直线)。

输入:

输入包括多组测试数据,包括一个整数R(1<=R<=1000),和一个浮点数r(0<r<1),精确到第四位小数。

输出:

对于每组测试用例,输出一个浮点数,代表刀痕的长度,保留二位小数。

样例输入:
1000 0.5000
500 0.6183
样例输出:
1928.53
982.49

分析:

这个题目的主要难度在于分析题目如何解决。



我们得到上图的结果,得S1/S2=r,即S1=r*S2;

又S1+S2=PI*R*R(整个圆的面积)

得到S1=(PI*R*R)*r/(1+r);

假设刀痕的长度为2L,则其一半为L,且sin(a)=l/R

则a=arcsin(l/R)

扇形面积为S3=R*R*(2*a)/2

三角形的面积为S4=L*sqrt(R*R-L*L)/2

所以S1new=S3-2*S4

由于这个L是未知的我们可以初始化其值,让S1new和S1的差精确到0.00000001(甚至更小)

#include <iomanip>//小数点精确
#include <cstdio>  
#include <cstdlib>  
#include "queue"
#include "vector"
#include "string"
#include "algorithm"
#include <iostream>
#include "stack"
#include <cmath>
#include <set>
 
using namespace std;
 
const double Pi = 3.1415926;
int main()
{
    int R = 0;
    double r = 0.0;
    while (cin >> R >> r)
    {
        if (r > 1)
            r = 1.0 / r;
        double low = 0.0, high = R*1.0;
        double s1 = Pi*R*R*r / (1 + r);//将s1的面积已知,用来控制精度(s1+s2=Pi*R*R)
        double l=0.0, result=0.0;
        while (true)
        {
            l = (low + high) / 2;//初始化
            result = R*R*asin(l / R) - sqrt(R*R - l*l)*l;//根据公式求出s1的面积
            if (abs(result - s1)<0.0000001)//控制精度
                break;
            if (result>s1)//慢慢缩减到准确值
                high = l;
            if (result<s1)
                low = l;
        }
        cout <<fixed<<setprecision(2)<< 2 * l << endl;
    }
    return 0;
}
/**************************************************************
    Problem: 1551
    User: EbowTang
    Language: C++
    Result: Accepted
    Time:50 ms
    Memory:1600 kb
****************************************************************/



注:本博文为EbowTang原创,后续可能继续更新本文。如果转载,请务必复制本条信息!

原文地址:http://blog.csdn.net/ebowtang/article/details/50520553

原作者博客:http://blog.csdn.net/ebowtang


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值