题目翻译:
实现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;
}
};
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