69. x 的平方根
实现
int sqrt(int x)函数。 计算并返回 x 的平方根,其中 x 是非负整数。 由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。 示例 1:
输入: 4输出: 2
示例 2:
输入: 8输出: 2说明: 8 的平方根是 2.82842...,由于返回类型是整数,小数部分将被舍去。
解题思路1
拿到本题时,我首先想到的是从1开始枚举,每次通过计算 i*i <= x && (i+1)*(i+1) > x 判断是否是x的平方根,但是对于一个很大的数,每次枚举都有两次乘法操作和两次判断,总体来说太耗时了。
代码实现1
int mySqrt(int x){int i;long long next;for(i=0;i<=x;i++){next = (long long )(i+1)*(i+1);if( i*i <= x && next > x )break;}return i;}
解题思路2
自己没想到更好的办法,看了 Leetcode官方题解
题目不让使用平方根的函数,但是可以利用其他数学公式转化为平方根得到结果
这里还有个问题需要注意,因为指数函数和对数函数的参数和返回值均为浮点数,而计算机对浮点数的存储是有限的,无法很精确,就会产生误差。因此在得到结果的整数部分 ans 后,我们应当找出ans 与 ans+1 中哪一个是真正的答案。
代码实现2
/*sqrt(x) = e^( (1/2)*lnx )*/int mySqrt(int x){if(x == 0)return 0;int sqrt1 = exp( 0.5 * log(x) );int sqrt2 = sqrt1 + 1;if( sqrt1*sqrt1 <= x && (long long) sqrt2*sqrt2 > x )return sqrt1;elsereturn sqrt2;}
解题思路3
用二分查找
代码实现3
/*用二分查找 ,初始时范围为 [0,x]注意结束条件if(left > right)return right实际上是最后几步left和right已经很接近了。前前一步,left1 + 1 = right1 ,mid1 = left1,而此时mid1*mid1 <= x,进入下一次调用left2 = left1 + 1 = right1前一步,由上次之后,left2 = right1 ,mid2 = left2 = right1 , mid2*mid2 > x ,进入下一次调用 right3 = mid2 -1这步,发现 left2 > right3 ,返回结果实right3,而 right3 = mid2 - 1 = left2 - 1 = left1 = mid1举个例子,求 8的平方根。[0,8 ] 8/2 = 4 , 4*4 = 16 > 8 ->[0,3], 3/2 = 1,1*1 = 1<8 ->[2,3],(2+3)/2 = 2, 2*2 = 4 < 8 ->[3,3],(3+3)/2 = 3, 3*3 = 9 >8 ->[3,2], 3>2 return 2;*///递归版的二分查找int findSqrt(int left,int right,int x){int mid = (left+right)/2;if(left > right)return right;if((long long)mid*mid <= x){return findSqrt(mid+1,right,x);}elsereturn findSqrt(left,mid-1,x);}int mySqrt(int x){return findSqrt(0,x,x);}
