• 二分法-数据类型定义导致的内存超限


    力扣心得1 整数溢出导致的内存超限 —Q-69.x 的平方根

    1、问题描述:一直显示【内存超限】


    博主在学习二分法,做力扣69. x 的平方根这一题的时候,遇到一个内存超限的问题,抓耳挠腮了好久,都没有找到原因在哪:
    在这里插入图片描述

    题目要求不使用 pow(x, 0.5) 或者 x ** 0.5等自带功能,求出一个非负整数的算术平方根。使用二分法的思想本身倒是很简单,通过左右两个指针不断去接近其算术平方根即可
    在检查了几遍自己大体思路没问题后,我开始针对这个测试案例进行思考,最终发现了问题~

    先上干货,debug后的正确代码:

    class Solution {
        public int mySqrt(int x) {
            int left=0;
            int right=x;
            int res=-1;
            while(left<=right){
                int mid=(left+right)/2;
                if((long)mid*mid>x){//在判断条件中,中间指针mid前加上(long),避免mid^2超出int类型上限
                    right=mid-1;
                }else if(mid*mid<=x){
                    res=mid;
                    left=mid+1;
                }
            }
            return res;
        }
    }
    

    2、原因与解决办法

    我对测试案例进行观察,发现2147395599这个数字好像比较特别,好像是int类型数组的上限也是2147开头的数字,于是去查询了一下:
    在这里插入图片描述
    这里我就发现似乎找到了问题所在了 ,于是写了个脚本测试了一下,到底mid是在哪个地方出问题了:

    public static void main(String[] args) {
            int a1 = 46341;
            int square1 = a1 * a1;
            int a2 = 46340;
            int square2 = a2 * a2;
            System.out.println(square1);
            System.out.println(square2);
    }
    

    输出:

    -2147479015//square1  实际46341^2=2147488281
    2147395600//square2
    

    这里由于square被定义为int类型,因此出现了整数溢出,应该输出输出为2147488281的结果,最后变成了:-2147479015。而本题报错的测试用例2147395599处于2147395600~2147488281

    超限过程

    下面我们快来看一下这个内存超限的过程:
    我们可以看一下第一次进入这个while循环的时候,mid就变成了107369780,这时候整型溢出就已经开始了,实际上107369780^2>>x,然而却因为整型溢出,被赋值成负数,从而错误的执行
    else if(mid*mid<=x)这条语句,将left指针变成107369781。
    在这里插入图片描述
    但是如果仅仅是一直进入这个循环,只是left一直往右移动,顶多只是计算结果错误,还不至于内存超限
    坏就坏在mid往右移动的时候,有的计算结果在内存超限后,不光会错误地把mid*mid的结果变成-2147479015这样的负数,还会因为溢出变成一些错误的正数,因此,还可能会进入if(mid*mid>x)这个循环,所以,leftright指针会像在上图中这样反复横跳,从而导致内存超限。

    博主用编译器打印了一下,样最后leftright会在哪两个值上一直反复横跳,这是最后输出的结果:

    mid			-715915930
    left		-715915929
    mid			715739835
    left		715739836
    mid			-715915930
    left		-715915929
    mid			715739835
    left		715739836
    mid			-715915930
    left		-715915929
    

    结果显示,mid最终在-715915930715739835之间反复横跳,导致内存超限

    最后,在判断前加个long定义一下数据类型就可以了~

    这是个小问题,希望大家有则改之,无则加勉,永远都不会受到bug困扰,我们下期再见!

  • 相关阅读:
    狂飙10年后,电动两轮车终究要回归理性
    SAP:增强中用commit和wait up会导致操作异常
    【组件封装】基于neo4jD3封装关系图、关联图谱
    Unity API详解——Mathf类
    普通web整合quartz跑定时任务
    免费word转换pdf的软件
    ExecutorService、Callable、Future实现有返回结果的多线程原理解析
    算法总结--ST表
    产生自卑心理的原因是什么?
    内外统一的边缘原生云基础设施架构——火山引擎边缘云
  • 原文地址:https://blog.csdn.net/esmager/article/details/139630865