leeCode69_x的平方根

一、题目内容

实现int sqrt(int x)函数。
计算并返回x的平方根,其中x是非负整数。
由于返回类型是整数,结果只保留整数部分,小数部分将被舍去。

示例1
输入:4

输出:2

示例2
输入:8

输出:2

说明:8的平方根是2.82842…由于返回类型是整数,小数部分将被舍去。

二、题目分析

使用二分法来完成平方根还是比较容易被想到的,在有限的“区间”中,每次通过筛选一半的元
素,到最终只剩下一个数(收敛),这个数就是题目要求的取整的平方根整数。

根据之前说过的二分法模板,要使用二分法,我们当然要找到Left,Right,Mid,那在这里,Mid 自然被作为最终我们要找的平方根的值(不像上一道题,Mid是作为速度,不太容易被想到),而 Left 和Right,我们采用 1 和x/2。

Left 设置为 1 比较容易理解,因为我们可以直接处理掉 x 为 0 的情况(当然,也可以把 Left 初始化为2,然后我们额外处理 0 和 1 的情况,我之前说过,二分法一万个人有一万种写法,只要能解释清楚,那就是你自己的)。但是为什么 Right 是 x/2 呢?

我们看一下下面这些数的值:
在这里插入图片描述
很容易观察出,当 x>2 时,它的整数平方根一定小于等于 x/2 。即有 0 < 整数平方根 <= x/2。所以我们的问题转化为在 [0,x/2] 中找一个特定值,满足二分查找的条件。(当然,如果没有想到使用 x/2 作为Right 而 直接使用 x ,其实也是可以的)

剩下的逻辑就很简单了,我们不停缩小mid的范围,如果最终平方大于x就放回它前面一个值,否则就正常返回,直到两边的边界完全收敛。

三、代码实现

public class Solution {
	public int mysqrt(int x) {
		if(x == 0) return 0;
		long left = 1;
		long right = x / 2;
		while(left < right) {
			long mid = (right + left) / 2 + 1;
			if(mid > x / mid) {
				right = mid - 1;
			} else {
				left = mid;
			}
		}
		return (int)left;
	}
}

上面的代码,有三处需要进行讲解:

  1. 第一,就是这里将 left 和 right 都设置为了 long,这是因为担心超出界限。同时,也正是因为设置为了 long,所以后面我可以直接使用 right left,而不用担心报错。
  2. 第二,还是这行代码,大家肯定会疑惑,为什么我要在 (right left)/ 2 后面再加1。这其实是一种技巧,一般人我不告诉他。因为在面试的时候,我们往往需要快速写出freebug 的代码,但是如果遇到二分的题目,你很可能会不停的纠结 mid 到底如何设置,是左边界还是右边界。其实,面试官大多时候,并不需要你写出一个非常非常标准的二分,找到绝对的中值。
  3. 第三,这点本来不需要额外说明的,正是在第二的基础上,我们通过不停的缩小搜索空间,最终left 就变成我们要找的 mid 值,所以直接返回 left 就可以了。
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Shansec~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值