每日一道 LeetCode (16):求 x 的平方根
每天 3 分钟,走上算法的逆袭之路。
前文合集
每日一道 LeetCode 前文合集
代码仓库
GitHub: https://github.com/meteor1993/LeetCode
Gitee: https://gitee.com/inwsy/LeetCode
题目:求 x 的平方根
题目来源:https://leetcode-cn.com/problems/sqrtx/
实现 int sqrt(int x) 函数。
计算并返回 x 的平方根,其中 x 是非负整数。
由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。
示例 1:
输入: 4
输出: 2
示例 2:
输入: 8
输出: 2
说明: 8 的平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去。
解题过程
看到这道题,嗯,实际上我是完全不会做的,只能说有一个初步的想法,但是感觉太二了,也就没写代码,直接去翻答案了。
看到答案以后,悄悄的讲,理解起来稍微还有点难度。
讲老实话,这道题,如果没点高中数学的知识,还真的是做不出来。
但是如果把高中数学的知识给各位普及一下,我感觉应该还不算是难做的。
问题的关键就是,高中数学老师的棺材板都要压不住了。
官方解法一:袖珍计算器算法
这种解法官方还给了一个看起来很高大上的名字 「袖珍计算器算法」 ,实际上我看下来感觉就是使用数学公式偷换概念。
这种方案并不介意各位同学在面试的时候拿出来用,否则被面试官按在地上摩擦就不好了。
目标是要求根号 x ,然后在公式上做了一个骚操作。
x=x1/2=(elnx)1/2=e12lnx\sqrt{x} = x ^ {1/2} = (e ^ {\ln x}) ^ {1/2} = e ^ { \frac{1}{2} \ln x} x=x1/2=(elnx)1/2=e21lnx
看不懂的同学去面壁,这个我记得不错的话应该是初中数学。
总体思路就是用自然对数 e 进行换底,讲道理,这题我上初中的时候应该能想到,现在已经完全没有任何想法了。
公式给了代码实际上就很简单了:
public int mySqrt(int x) {if (x == 0) return 0;int ans = (int) Math.exp(0.5 * Math.log(x));return (long)(ans + 1) * (ans + 1) <= x ? ans + 1 : ans;
}
直接用数学公式解答,果然是最快的方案。
官方解法二:二分法
二分法其实就是我一开始想到的方案,用 n * n
不停的去试,直到试到 n * n < x && (n + 1) * (n + 1) > x
或者正好 n * n = x
。
然后接下来就是使用二分查找找到这个数 n ,首先定义最左边的书是 0 ,最右边的数是 x 。
因为 x 开平方肯定是小于等于自己的,然后用二分法一步一步查找下去,直到找到那个数,代码如下:
public int mySqrt_1(int x) {if (x == 0) return 0;int left = 0, right = x, ans = -1;while (left <= right) {int mid = left + (right - left) / 2;if ((long) mid * mid <= x) {ans = mid;left = mid + 1;} else {right = mid - 1;}}return ans;
}
这里的 (long) mid * mid
这一段代码要注意,因为 mid 本身是 int ,做乘法以后,如果够大和容易超出上限的,所以这里做了类型强转,转成了 long 类型。
二分查找次数稍微有点多,毕竟很多数开平方后差距都是会少很多数量级的(越大的数少的越多),即使使用二分法要找到也需要循环更多的次数。
官方解法三:牛顿迭代
这个名词我是第一次听,不过从名字上就可以看出来,这个方法又是我们伟大的牛顿老师发明的。
顺便说一句,我在学微积分的时候就已经恨死他了。
牛顿迭代的思想是借助泰勒级数,从初始值开始快速向零点逼近。
任取一个 x0x_0x0 作为初始值,在每一步的迭代中,我们找到函数图像上的点 (xi,f(xi))(x_i, f(x_i))(xi,f(xi)) ,过该点作一条斜率为该点导数 f′(xi)f^′(x_i)f′(xi) 的直线,与横轴的交点记为 xi+1x_{i+1}xi+1 。xi+1x_{i+1}xi+1 相较于 xix_ixi 而言距离零点更近。在经过多次迭代后,我们就可以得到一个距离零点非常接近的交点。
算法
我们选择 x0=Cx_0 = Cx0=C 作为初始值。
在每一步迭代中,我们找到 xix_ixi 在图像上对应的点 (xi,xi2−C)(x_i, x_i^2 - C)(xi,xi2−C) 作一条斜率为 f′(xi)=2xif^′(x_i) = 2x_if′(xi)=2xi 的直线,直线的方程为:
y=2xi(x−xi)+xi2−C=2xix−(xi2−C)y = 2x_i(x - x_i) + x_i^2 - C = 2x_ix - (x_i^2 - C) y=2xi(x−xi)+xi2−C=2xix−(xi2−C)
与横轴的交点实际上就是上面那个方程 y = 0 的解,即为新的迭代结果 xi+1x_{i + 1}xi+1 :
xi+1=12(xi+Cxi)x_{i + 1} = \frac{1}{2}(x_i + \frac{C}{x_i}) xi+1=21(xi+xiC)
在进行 k 次迭代后, xkx_kxk 的值与真实的零点 x\sqrt{x}x 足够接近,即可作为答案。
上面这段内容好好理解一下,我也是看了很久才看懂几个公式的推导,真的是全都忘光了。
代码我还是抄一下官方的代码吧,做一个参考:
public int mySqrt_2(int x) {if (x == 0) return 0;double C = x, x0 = x;while (true) {double xi = 0.5 * (x0 + C / x0);if (Math.abs(x0 - xi) < 1e-7) {break;}x0 = xi;}return (int) x0;
}
可以看到,牛顿迭代的效率也是极高的,几乎可以媲美我们直接由数学公式推导。
这里有个小问题需要注意下,我们迭代到什么程度可以结束?一般是选取一个极小值,一般取到 10−610^{-6}10−6 或者 10−710^{-7}10−7 。
参考
https://leetcode-cn.com/
您的扫码关注,是对小编坚持原创的最大鼓励:)
每日一道 LeetCode (16):求 x 的平方根相关推荐
- leetcode最小面积_每日一道 LeetCode (51):盛最多水的容器
❝ 每天 3 分钟,走上算法的逆袭之路. ❞ 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub:https://github.com/meteor1993/LeetCode Gi ...
- 每日一道leetcode(python)876. 链表的中间结点
每日一道leetcode(python)876. 链表的中间结点 2021-08-19 给定一个头结点为 head 的非空单链表,返回链表的中间结点.如果有两个中间结点,则返回第二个中间结点.示例 1 ...
- 每日一道leetcode(python)48. 旋转图像
每日一道leetcode(python)48. 旋转图像 2021-07-27 给定一个 n × n 的二维矩阵 matrix 表示一个图像.请你将图像顺时针旋转 90 度. 你必须在 原地 旋转图像 ...
- 每日一道 LeetCode (51):盛最多水的容器
每天 3 分钟,走上算法的逆袭之路. 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub: https://github.com/meteor1993/LeetCode Gitee ...
- atoi函数_每日一道 LeetCode (50):字符串转换整数 (atoi)
❝ 每天 3 分钟,走上算法的逆袭之路. ❞ 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub:https://github.com/meteor1993/LeetCode Gi ...
- 二叉树层次遍历c语言_每日一道 LeetCode (23):二叉树的层次遍历 II
❝ 每天 3 分钟,走上算法的逆袭之路. ❞ 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub:https://github.com/meteor1993/LeetCode Gi ...
- c++两个数组对比去掉重复的元素_每日一道 LeetCode (8):删除排序数组中的重复项和移除元素...
❝ 每天 3 分钟,走上算法的逆袭之路. ❞ 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub:https://github.com/meteor1993/LeetCode Gi ...
- 每日一道leetcode(python)1823. 找出游戏的获胜者
每日一道leetcode(python)1823. 找出游戏的获胜者 2021-08-07 共有 n 名小伙伴一起做游戏.小伙伴们围成一圈,按 顺时针顺序 从 1 到 n 编号.确切地说,从第 i 名 ...
- 每日一道leetcode(python)844. 比较含退格的字符串
每日一道leetcode(python)844. 比较含退格的字符串 2021-09-05 给定 S 和 T 两个字符串,当它们分别被输入到空白的文本编辑器后,判断二者是否相等,并返回结果. # 代表 ...
最新文章
- 2021年大数据常用语言Scala(二十三):函数式编程 扁平化映射 flatMap
- 图像分割 c语言程序,OpenCV实现图像切割功能
- MATLAB灰色预测
- RequestDispatcher提供两个方法:forward,include有什么区别
- python的多线程threading_Python中多线程thread与threading的实现方法,pythonthreading
- 10种经典机器学习算法——Python版
- 解决比较Oracle中CLOB字段问题
- word打出计算机图形符号,word显示所有格式标记
- H5 小程序直播教程,一看就会!
- 定个理财小目标:8w到100w实盘
- 从零开始写高性能的人脸识别服务器(二)
- TCP粘包问题以及解决方法
- 进入BeOS的花花世界 系列九
- Element Dialog
- AIGC发展路径思考:大模型工具化普及迎来新机遇
- mssql查询分页存储过程SpPageOrder/proc_wuhan_getpages )
- 推荐给大家推荐一款可以修改图片的工具iSee
- Servlet下载文件迅雷不支持问题真相之一
- Quartus计算机组成与设计实验原理图整理(十)——二进制补码加法器实验
- 【调剂】浙江理工大学【杭州】欢迎凝聚态物理、电子信息等专业优秀学子调剂深造...
热门文章
- 钟南山腾讯团队用ML算法验证:这三种防疫措施效果最显著,严格防控要趁早,7至14天起效...
- SIMT ( Single Instruction Multiple Threads)
- 已经配置javahome了的,还出现A Java Runtime Environment (JRE) or Java Development
- [激光原理与应用-43]:《光电检测技术-10》- 激光测距原理、方案与案例分析:TOF VL53L0X模块
- JavaScript的字符串去空格
- (题解)《算法零基础100讲》(第38讲) 排序进阶 - 希尔排序
- 携程福利变噩梦 上海妇联:严肃处理旗下杂志
- 消息中间件MQ及ActiveMQ介绍
- npm install安装报错 npm ERR! code Z_BUF_ERROR 问题解决
- 保存地理坐标信息的SLIC分割结果