69. x 的平方根(简单)

69. x 的平方根

1. 题目描述

题目中转:69. x 的平方根

2.详细题解

不能使用系统内置的函数,寻找某个数(假定为x)的算术平方根,并返回算术平方根的整数部分,最直观的方法是从0依次开始尝试所有小于等于x的数(假定为y),当y*y的积小于等于x时,继续遍历下一个数,直至y*y的积首次大于x时,此时y-1即为x的算术平方根的整数部分,如Python方法一逐个遍历实现。

上述方法遍历的过程中,每次仅能排除判断一个数字是否满足,有没有办法一次性判断或者排除多个数字呢?这就是二分查找算法,简单的说,即待查数据需有序,每次判断时折中取中间值进行对比,以判断目标值可能存在的那一半,从而快速定位目标值,每次判断可以排除一半的空间大小。具体算法如下:

  • Step1:前置条件:个已排序的数组 arr 和待查找的元素 target。;
  • Step2:初始化:两个指针 left 和 right,分别指向数组的起始和结束位置;
  • Step3:计算中间元素的索引: mid = (left + right) / 2;
  • Step4:比较中间元素 arr[mid] 与 target;
  • 如果 arr[mid] == target,则找到目标值,返回 mid,程序结束;
  • 如果 arr[mid] < target,则目标值可能在 mid 的右侧,更新 left = mid + 1;
  • 如果 arr[mid] > target,则目标值可能在 mid 的左侧,更新 right = mid - 1;
  • Step5:当 left <= right 时,循环执行Step3_Step4.

对于此题,是计算算术平方根的整数部分,因此等价于寻找首次平方之和大于x的数,该数减1即为x的算术平方根(假定x的算术平方根为y.z,其中y为整数部分,z为小数部分,y*y的结果是小于x,而(y+1)*(y+1)是大于x的)。因此,针对此题,二分查找算法在返回值方面有一点点不同,应当返回最后的右指针指向的值,为什么呢?因为right为最后一次mid值大于x时减1的值,其它的mid值均小于x,故最后一次大于x的mid值减1即为目标整数,即right。实现详见Python方法二Java实现

3.代码实现

3.1 Python

方法一:逐个遍历

python 复制代码
class Solution:
    def mySqrt(self, x: int) -> int:
        left = 0
        while left * left <= x:
            left += 1
        return left-1

方法二:二分查找

python 复制代码
class Solution:
    def mySqrt(self, x: int) -> int:
        left, right = 0, x//2
        while left <= right:
            mid = (left + right) // 2
            mul = mid * mid
            if mul == x:
                return mid
            elif mul < x:
                left = mid + 1
            else:
                right = mid - 1
        return right

此时未通过x=1的测试用例,此时预期结果为1但返回0,仔细观察代码,right初始值为2整数x,对于1,结果为0,因此初始化出现了问题,优化如下:

python 复制代码
class Solution:
    def mySqrt(self, x: int) -> int:
        left, right = 0, x//2+1
        while left <= right:
            mid = (left + right) // 2
            mul = mid * mid
            if mul == x:
                return mid
            elif mul < x:
                left = mid + 1
            else:
                right = mid - 1
        return right

3.2 Java

java 复制代码
class Solution {
    public int mySqrt(int x) {
        int left = 0, right = x / 2 + 1;
        while (left <= right){
            int mid = (left + right) / 2;
            int mul = mid * mid;
            if (mul == x){return mid;}
            else if (mul < x){left = mid +1;}
            else{right = mid - 1;}
        }
        return right;
    }
}

对于测试案例x=2147395599运行错误,直接返回了right初始值的结果,说明一直触发的是中间值平方小于x,这明显是错误的,考虑到Java是严格声明和定义数据类型的,因此错误在于内存溢出,超出Java的int类型的取值范围,故中间值使用long整型,优化如下:

java 复制代码
class Solution {
    public int mySqrt(int x) {
        int left = 0, right = (int)(x / 2 + 1);
        while (left <= right){
            int mid = (int) (left + right) / 2;
            long mul = (long)mid * mid;
            if (mul == x){
                return mid;
            }else if (mul < x){
                left = mid + 1;
            }else{
                right = mid - 1;
            }
        }
        return right;
    }
}

执行用时不必过于纠结,对比可以发现,对于python和java完全相同的编写,java的时间一般是优于python的;至于编写的代码的执行用时击败多少对手,执行用时和网络环境、当前提交代码人数等均有关系,可以尝试完全相同的代码多次执行用时也不是完全相同,只要确保自己代码的算法时间复杂度满足相应要求即可,也可以通过点击分布图查看其它coder的code。

相关推荐
A懿轩A1 小时前
C/C++ 数据结构与算法【数组】 数组详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·数组
古希腊掌管学习的神1 小时前
[搜广推]王树森推荐系统——矩阵补充&最近邻查找
python·算法·机器学习·矩阵
云边有个稻草人1 小时前
【优选算法】—复写零(双指针算法)
笔记·算法·双指针算法
半盏茶香1 小时前
在21世纪的我用C语言探寻世界本质 ——编译和链接(编译环境和运行环境)
c语言·开发语言·c++·算法
忘梓.2 小时前
解锁动态规划的奥秘:从零到精通的创新思维解析(3)
算法·动态规划
LucianaiB2 小时前
探索CSDN博客数据:使用Python爬虫技术
开发语言·爬虫·python
suweijie7683 小时前
SpringCloudAlibaba | Sentinel从基础到进阶
java·大数据·sentinel
公贵买其鹿4 小时前
List深拷贝后,数据还是被串改
java
PieroPc4 小时前
Python 写的 智慧记 进销存 辅助 程序 导入导出 excel 可打印
开发语言·python·excel
tinker在coding4 小时前
Coding Caprice - Linked-List 1
算法·leetcode