69. Sqrt(x)

69. Sqrt(x)

My Submissions
Question
Total Accepted: 79525  Total Submissions: 325488  Difficulty: Medium

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

Implement int sqrt(int x).

Compute and return the square root of x.

Subscribe to see which companies asked this question

Hide Tags
  Math Binary Search
Hide Similar Problems
  (M) Pow(x, n)


分析:

一个正整数的平方根,尽然要求返回一个整数?觉得别扭。
本题是一个典型的数值分析问题,还是比较简单的!控制精度以及两个变量二分迭代至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的函数,如图所示:

<LeetCode OJ> 69. Sqrt(x)_第1张图片


在Xn处的斜率为:

求得:


根据

得到递推公式:

<LeetCode OJ> 69. Sqrt(x)_第2张图片

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


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

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

题目描述:

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

输入:

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

<LeetCode OJ> 69. Sqrt(x)_第3张图片

输出:

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

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

分析:

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


<LeetCode OJ> 69. Sqrt(x)_第4张图片

我们得到上图的结果,得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


你可能感兴趣的:(LeetCode,数据结构,数学,牛顿迭代,二分迭代)