壹 ❀ 引

这几天心情复杂,也不知道形容。做道题吧,其实是上周的题,一直没整理,比较巧的是,这也是我同学17年去PPTV面试时遇到的一题,题目来自leetcode69. x 的平方根,题目描述如下:

实现 int sqrt(int x) 函数。

计算并返回 x 的平方根,其中 x 是非负整数。

由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。

示例 1:

输入: 4
输出: 2

示例 2:

输入: 8
输出: 2

说明: 8 的平方根是 2.82842...,

由于返回类型是整数,小数部分将被舍去。

站在JavaScript角度,其实就是让我们自己实现Math.sqrt方法,题目也不用分析了,唯一需要注意的是,比如8这样的数字平方根为2.82842...,因此取2,而非取3,让我们来实现它。

贰 ❀ 解题思路

Math中除了有求平方根的sqrt方法以外,其实还有求幂的pow,因此我们可以利用pow直接解题:

/**
* @param {number} x
* @return {number}
*/
var mySqrt = function (x) {
return Math.floor(Math.pow(x, 0.5));
};

当然,我们也可以使用笨一点的方法,由于0和1的平方根等于自己,所以从2开始,只要当第一个数字的平方比x还大,那么我们返回此数字减一位即可,像这样:

/**
* @param {number} x
* @return {number}
*/
var mySqrt = function (x) {
// 考虑0和1
if(x<2){
return x;
};
// 从2开始查找
let a = 2;
while (a * a <= x) {
a++;
};
return a - 1;
};

很明显,虽然这样做能实现,但是查找起来很慢,如果x的平方根越大,我们需要遇到它耗时就越久。而官方对于此题推荐的做法是使用二分查找。

举个例子,假设输入的是100,我们要找的就是10,由于上面的答案也分析了,0与1可以直接返回,所以left起点可以从2开始,那么右边边界怎么定呢?其实我们可以将右边起点定为Math.floor(x/2),为啥?0,1不用考虑,紧接着是数字2,2也是唯一一个的2次方后再除以2与自己相等的数,再往上走的任意数字,比如3的2次方为9,9除以2为4.5,显而易见4.5的二次方要比3的二次方大,直接将x除以2求floor的数完全没问题。

这里有个小技巧,当我们想让9/2为4时,一般的做法是前面说的结合Math.floor,其实还可以使用位运算符,这个跟二进制有关,大家先知道是这么回事就行。

9>>1 //4
8>>1 //4
6>>1 //3

也就是说,将数字除以2,如果能整除得到的就是这个整数,如果不能,则用floor向下取整,比如9>>1就是因为为4.5经过向下取整得到的结果。

我们先上代码:

/**
* @param {number} x
* @return {number}
*/
var mySqrt = function (x) {
if (x < 2) {
return x
};
let left = 2,
right = x >> 1;//这里等同于Math.floor(x/2)
while (left <= right) {
// 同理,这里也是用了位运算符,保证mid是个整数
let mid = left + ((right - left) >> 1);
//使用x/mid而非mid*mid是怕数字越界
if (mid === x / mid) {
return mid
} else if (mid < x / mid) {
left = mid + 1
} else {
right = mid - 1
};
};
// 最后直接用right和x/right相比较,如果大肯定取left,反之取right
return right > x / right ? left : right
};

唯一需要注意的是,二分法中取mid我在之前的文章中用的是Math.floor((low + high) / 2),但是网友说这样容易越界,也就是假设hight很大了,偏偏加了low已经越界,就无法参与计算了。所以另外一种求中间的做法就是left + Math.floor((right-left)/2),由于使用了位运算,所以就简写成left + ((right - left) >> 1)了,至于后面的判断也就是用x/mid与mid比较的问题,也不用过多解释。

最后我们总是会得到left与right两个数,再做最后一次比较即可。

那么本文就到这里了。

JS leetcode x 的平方根 题解分析的更多相关文章

  1. Leetcode 10. 正则表达式匹配 - 题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...

  2. node.js基础模块http、网页分析工具cherrio实现爬虫

    node.js基础模块http.网页分析工具cherrio实现爬虫 一.前言      说是爬虫初探,其实并没有用到爬虫相关第三方类库,主要用了node.js基础模块http.网页分析工具cherri ...

  3. diff.js 列表对比算法 源码分析

    diff.js列表对比算法 源码分析 npm上的代码可以查看 (https://www.npmjs.com/package/list-diff2) 源码如下: /** * * @param {Arra ...

  4. C#版 - Leetcode 306. 累加数 - 题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...

  5. C#版(击败100.00%的提交) - Leetcode 372. 超级次方 - 题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. Leetcod ...

  6. C#版(打败97.89%的提交) - Leetcode 202. 快乐数 - 题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...

  7. LeetCode All in One题解汇总(持续更新中...)

    突然很想刷刷题,LeetCode是一个不错的选择,忽略了输入输出,更好的突出了算法,省去了不少时间. dalao们发现了任何错误,或是代码无法通过,或是有更好的解法,或是有任何疑问和建议的话,可以在对 ...

  8. 病毒木马查杀实战第025篇:JS下载者脚本木马的分析与防御

    前言 这次我与大家分享的是我所总结的关于JS下载者脚本木马的分析与防御技术.之所以要选择这样的一个题目,是因为在日常的病毒分析工作中,每天都会遇到这类病毒样本,少则几个,多则几十个(当然了,更多的样本 ...

  9. LeetCode-343. 整数拆分 - 题解分析

    题目来源 343. 整数拆分 题目详情 给定一个正整数 n ,将其拆分为 k 个 正整数 的和( k >= 2 ),并使这些整数的乘积最大化. 返回 你可以获得的最大乘积 . 示例 1: 输入: ...

  10. js网页滚动条滚动事件实例分析

    本文实例讲述了js网页滚动条滚动事件用法.分享给大家供大家参考.具体分析如下: 在做js返回顶部的效果时,要监听网页滚动条滚动事件,这个事件就是:window.onscroll.当onscroll事件 ...

随机推荐

  1. node pressure and pod eviction

    0. overview There are too many guides about node pressure and pod eviction, most of them are specifi ...

  2. 搭建 spring boot + mybatis plus 项目框架并进行调试

    本文为博主原创,未经允许不得转载: 1.创建一个spring boot的工程应用: File ---- > New ----->Project ----> 然后选中Spring In ...

  3. Oracle索引&约束

    Oracle索引&约束 1索引的原理 索引是一种允许直接访问数据表某一数据行的树形结构,为了提高查询效率而引入,是独立于表的对象,可以存放在与表不同的表空间(TABLESPACE)中 索引记录 ...

  4. Spring——AOP练习

    模仿前面的例子,完成模拟JDBC操作 1.UserDAO接口,具有insert(String name)方法,UserDAOImpl实现它 2. 用前置增强,在插入之前,完成数据库连接.事务创建工作 ...

  5. Go-竞态条件-锁

    1. 产生环境 多个进程(process).线程(threading)或协程(routine)存在对同一个资源访问顺序敏感(时间上的错误) 2. 概念 临界区 -- 时间上对同一资源的读写产生的数据不 ...

  6. Go-基本类型-int-float-bool-byte-rune

  7. mysq-DQL-过滤条件-where

  8. blender 3D 汽车模型下载

    前言 因为之前需要模拟摄像头拍摄汽车车牌,从各种途径下载了一些blender 3D 汽车模型,现将模型分享出来,如有需要,直接去最后面下载地址下载即可 目前已经车型40多款 车型图 70年代Porsc ...

  9. Nginx的日志处理

    Nginx的日志处理 背景 之前一直被各种咨询nginx的使用问题. 大部分都是性能, 加模块, 以及一些tcp端口等的问题. 其实这些都还好, 还有一个比较麻烦的问题时日志相关的. nginx的日志 ...

  10. Kafka的部分初始化参数的学习与整理

    Kafka的部分初始化参数的学习与整理 背景 前段时间跟同事一起处理过kafka的topic offset的retention 时间与 log 的retention时间不一致. 导致消息还有, 但是o ...