Sqrt(x)——二分法,防越界
Implement int sqrt(int x).
Compute and return the square root of x.
转自:http://blog.csdn.net/doc_sgl/article/details/12404971
实际面试遇到的题目可能不是对一个整数开方,而是对一个实数。方法和整数其实是一致的,只是结束条件换成左界和右界的差的绝对值小于某一个epsilon(极小值)即可。在C++中我们需要通过两个数的绝对值差小于某个极小值来判断两个double的相等性。实际上两个double因为精度问题往往是不可能每一位完全相等的。
1. 二分法:
这道题一看到函数的定义int sqrt(int x)都是int就高兴了,直接二分吧。但是要注意,即使用long long都TM越界,还要用unsigned long long。最后返回值还要再检查一下。
int sqrt(int x) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
unsigned long long begin = ;
unsigned long long end = (x+)/;
unsigned long long mid;
unsigned long long tmp;
while(begin < end)
{
mid = begin + (end-begin)/;
tmp = mid*mid;
if(tmp==x)return mid;
else if(tmp<x) begin = mid+;
else end = mid-;
}
tmp = end*end;
if(tmp > x)
return end-;
else
return end;
}
2. 牛顿迭代法
为了方便理解,就先以本题为例:
计算x2 = n的解,令f(x)=x2-n,相当于求解f(x)=0的解,如左图所示。
首先取x0,如果x0不是解,做一个经过(x0,f(x0))这个点的切线,与x轴的交点为x1。
同样的道理,如果x1不是解,做一个经过(x1,f(x1))这个点的切线,与x轴的交点为x2。
以此类推。
以这样的方式得到的xi会无限趋近于f(x)=0的解。
判断xi是否是f(x)=0的解有两种方法:
一是直接计算f(xi)的值判断是否为0,二是判断前后两个解xi和xi-1是否无限接近。
经过(xi, f(xi))这个点的切线方程为f(x) = f(xi) + f’(xi)(x - xi),其中f'(x)为f(x)的导数,本题中为2x。令切线方程等于0,即可求出xi+1=xi - f(xi) / f'(xi)。
继续化简,xi+1=xi - (xi2 - n) / (2xi) = xi - xi / 2 + n / (2xi) = xi / 2 + n / 2xi = (xi + n/xi) / 2。
有了迭代公式xi+1= (xi + n/xi) / 2,程序就好写了。关于牛顿迭代法,可以参考wikipedia以及百度百科。
class Solution {
public:
int mySqrt(int x) {
if (x ==)
return ;
double pre;
double cur = ;
do
{
pre = cur;
cur = x / ( * pre) + pre / 2.0;
} while (abs(cur - pre) > 0.00001);
return int(cur);
}
};
float InvSqrt(float x)
{
float xhalf = 0.5f*x;
int i = *(int*)&x; // get bits for floating VALUE
i = 0x5f375a86- (i>>); // gives initial guess y0
x = *(float*)&i; // convert bits BACK to float
x = x*(1.5f-xhalf*x*x); // Newton step, repeating increases accuracy
return x;
}
Sqrt(x)——二分法,防越界的更多相关文章
- saturate_cast防越界函数
CV_IMAGE_ELEM(img2,uchar,i,j*3+c)=saturate_cast<uchar>(alpha*( CV_IMAGE_ELEM(img,uchar,i,j*3+c ...
- 【经典面试题】实现平方根函数sqrt
本文将从一道经典的面试题说起:实现平方根函数,不得调用其它库函数. 函数原型声明例如以下: double Sqrt(double A); 二分法 二分法的概念 求,等价于求方程的非负根(解).求解方程 ...
- 开博第一篇:DHT 爬虫的学习记录
经过一段时间的研究和学习,大致了解了DHT网络的一些信息,大部分还是参会别人的相关代码,一方面主要对DHT爬虫原理感兴趣,最主要的是为了学习python,大部分是别人的东西原理还是引用别人的吧 DHT ...
- CODEVS 2055 集合划分
[题目描述] 对于从1到N(1<=N<=39)的连续整数集合,划分成两个子集合,使得每个集合的数字之和相等. 举个例子,如果N=3,对于{1,2,3}能划分成两个子集合,他们每个的所有数字 ...
- C++Primer第5版学习笔记(一)
C++Primer第5版学习笔记(一) 第一.二章的重难点内容 这个笔记本主要记录了我在学习C++Primer(第5版,中文版)的过程中遇到的重难点及其分析.因为第一.二章都比较简单,因 ...
- 快速排序 partition函数的所有版本比较
partition函数是快排的核心部分 它的目的就是将数组划分为<=pivot和>pivot两部分,或者是<pivot和>=pivot 其实现方法大体有两种,单向扫描版本和双向 ...
- FJUT寒假作业涨姿势题解
题意非常简单易懂,对于涨姿势0,数据非常小,比较容易想到的是直接循环暴力解题完成任务.把数据放入数组arr,循环i,j控制所有区间算和.结果记入vis. 到了涨姿势1,2,3,我们观察数据变化,发现数 ...
- 洛谷P2569 股票交易
题目传送门https://www.luogu.org/problemnew/show/P2569 第一眼看题就觉得是个dp ,然后看到2000的范围,hmm大概是个n^2的2维dp 开始设状态,第一维 ...
- P1282 多米诺骨牌
P1282 多米诺骨牌 题目描述 多米诺骨牌有上下2个方块组成,每个方块中有1~6个点.现有排成行的 上方块中点数之和记为S1,下方块中点数之和记为S2,它们的差为|S1-S2|.例如在图8-1中,S ...
随机推荐
- sass的颜色函数
sass中有些非常实用的颜色处理函数,总结如下 1.颜色加深或变浅 lighten($color,$amount) //颜色变浅 darken($color,$amount) //颜色加深 例如: l ...
- ywy_c_asm题
未知出处 题意: 定义一个无穷长的数列,满足以下性质:$1.X_{2n}=-{X_{n}}$ $2.X_{2n}=(-1)^{(n+1)}*X_{n}$ $3.X_{2n-1}=(-1)^{(n+1) ...
- 【图论】tarjan的离线LCA算法
百度百科 Definition&Solution 对于求树上\(u\)和\(v\)两点的LCA,使用在线倍增可以做到\(O(nlogn)\)的复杂度.在NOIP这种毒瘤卡常比赛中,为了代码的效 ...
- 解决无法安装cnpm,cnpm卡顿问题
# 注册模块镜像 npm set registry https://registry.npm.taobao.org # node-gyp 编译依赖的 node 源码镜像 npm set disturl ...
- selenium - 获取断言信息
断言:通过脚本提取相应元素的数值,将实际结果与预期结果进行比较.通常获取title,URL,text等信息进行断言. from selenium import webdriver from time ...
- Indexing GROUP BY
SQL databases use two entirely different group by algorithms. The first one, the hash algorithm, agg ...
- Linux系统iptables查看、设置、保存、备份和恢复
不同linux系统,相关软件是否安装,会让iptables的某些命令不能执行,这里收集了大多数iptables命令,不管是Ubuntu还是Centos,都能找到相关的修改.查询.保存命令. 仅允许某些 ...
- RabbitMQ 命令
1.RabbitMQ 服务启动与关闭 同时启动RabbitMQ 节点和erlang服务 普通方式启动./rabbitmq-server守护线程方式启动./rabbitmq-server –detach ...
- [技巧篇]19.InputStream与String,Byte之间互转[转载]
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOExceptio ...
- springboot以jar包方式启动、关闭、重启脚本
springboot以jar包方式启动.关闭.重启脚本 启动 编写启动脚本startup.sh #!/bin/bash echo Starting application nohup java -ja ...