leetcode 69. x 的平方根

文章目录

69. x 的平方根

难度:简单

题库地址:https://leetcode-cn.com/problems/sqrtx/

1. 题目描述

实现 int sqrt(int x) 函数。

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

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

示例 1:

输入: 4
输出: 2

示例 2:

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

2. 解题思路

计算x的平方根,这里暂不考虑各种求平方根的计算公式。

最简单的方法就是i从0开始以步长1递增,当遇到第一个数i,使得i * i > x,那么i - 1就是要找的数。当然这里有个问题,i * i可能导致计算结果溢出变成死循环。正确的退出条件是当i > x / i,这样变化后需要注意i不能为0。

Java实现:

public int mySqrt(int x) {
    if (x < 2) {
        return 0;
    }
    int i = 1;
    while (i <= x / i) {
        i++;
    }
    return i - 1;
}

以上算法可以理解为在[1, x]中找数i,因为这里的[1, x]已经按升序排好顺序,所以可以使用二分查找法减少查找次数。
这里比较麻烦的地方是如何调整查找区间和找到循环终止条件。和在排好序的数组中查找一个数的位置不同的是:这里要查找数x的平方根整数部分。刚开始把问题想的很复杂,比如:

  • 当“中间值”不是要查找的对象时该如何确定下一个查找范围
  • 应该在什么情况下退出查找
  • 退出查找后,怎么确定是在刚刚好的位置(比如 4 -> 2),还是整数部分(8 -> 2)

实时证明这些考虑只是在给自己挖坑,在Mr__Kim的评论里说明了一种简单明了的解决办法,对于这个算法有如下优点:

  • 兼容 x = 0 的情况
  • 退出循环后不用考虑是在什么情况下退出的,因为程序实时的保存了解,只要程序退出了,当前保存的就是最终解
  • 对于如何调整查找分区清晰明了

Java代码如下:

public int mySqrt(int x) {
    int l = 1;
    int r = x;
    // 默认结果为0,如果x = 0,不会进入循环,直接退出
    int ans = 0;
    while (l <= r) {
        int mid = l + (r - l) / 2;
        // 要找的结果是真正平方根的向下取整值,
        // 所以 mid <= x / mid 时,随着查找分区的调整,这个 mid 就无限逼近于最后要找的值
        // 最后当退出循环时,这个 ans 就保存了最接近于真正的平方根的值,如 4 -> 2,8 -> 2
        if (mid <= x / mid) {
            // 实时保存最接近于平方根的结果
            ans = mid;
            // 由于当 mid == x / mid 时,已经将当前 mid 值保留了下来,所以下一次调整分区不必包含 mid
            l = mid + 1;
        } else {
            r = mid - 1;
        }
    }
    return ans;
}

运行结果:

leetcode 69. x 的平方根

上一篇:(69)zabbix监控惠普打印机


下一篇:Python基础项目实战:69行代码编写记忆数独游戏