美团二面 - 求数的平方根,不使用Math.sqrt

简介: 题目,给一个整数,求它的平方根,不能使用java自带的Math.sqrt();说来尴尬,我都不知道平方根是啥 0.0

题目,给一个整数,求它的平方根,不能使用java自带的Math.sqrt();


说来尴尬,我都不知道平方根是啥 0.0


贴心的面试官老哥告诉我就是开平方,比如4的平方根是2,100的平方根是10;


刚开始懵了,又是现场编程,本来就紧张,还不知道啥是平方根,严重影响发挥;


题解:

public class MySqrtDemo {
    public static void main(String[] args) {
        System.out.println(sqrt(100));//10
    }
    public static int sqrt(int i) {
        if (i <= 0) return i;
        int result;
        //从1开始疯狂试探
        for (int j = 1; true; j++) {
            if ((j * j <= i) && ((j + 1) * (j + 1) > i)) {
                result = j;
                //记得跳出循环
                break;
            }
        }
        return result;
    }
}

思路:

我这个方法没啥特点,就是从1开始疯狂试探,直到有一个数 i 满足i * i<=x&&((i+1)*(i+1)>x),这个 i 就是x的平方根;


优化

上面这个临时想出来的算法显然太鲁莽,优化优化

基于上面的算法,大体思路不会变,我们在 j * j 不等于入参的时候,对结果进行二分后再返回,无限二分,直到不能再细分,这样的值会更接近真实平方根;

public class MySqrtDemo {
    public static void main(String[] args) {
        System.out.println(sqrt(10));// 3.1622772216796875
        System.out.println(Math.sqrt(10));// 3.1622776601683795
    }
    public static double sqrt(int i) {
        if (i <= 0) return i;
        double result;
        //从1开始疯狂试探
        for (int j = 1; true; j++) {
            if (j * j == i) {
                result = j;
                //记得跳出循环
                break;
            } else if ((j * j < i) && ((j + 1) * (j + 1) > i)) {
                result = half(i, j, j + 1);
                //记得跳出循环
                break;
            }
        }
        return result;
    }
    public static double half(int i, double small, double big) {
        double average = (small + big) / 2;
        double result = average * average;
        if (result == i) {
          //如果平均值*平均值等于入参,直接返回
            return average;
        } else if (result > i) {
          //大于,则在前一个数和平均值之间递归二分
            if (String.valueOf(average).length() >= 18) return average;
            return half(i, small, average);
        } else {
          //小于,则在平均值后一个数之间递归二分
            if (String.valueOf(average).length() >= 18) return average;
            return half(i, average, big);
        }
    }
}

再次优化

利用牛顿法求解,这个解法对于我们这种学渣理解起来还是很有难度的,毕竟二次方程求导那些知识点早忘了

private static double mySqrt(int num) {
    double result = num;
    //精度控制,精确到多少位,但并不是截取到多少位,只是超过这个位数后面的值不精确了
    double accuracy = 0.001;
    //精度越高,循环次数越多
    while (result * result - num > accuracy) {
      //牛顿法,由切线方程求导转换而来,具体原理我还没搞懂 0.0
        result = (result * result + num) / (2 * result);
    }
    return result;
}


相关文章
|
前端开发 JavaScript Java
springboot实现用户统一认证、管理(单点登录)
springboot实现用户统一认证、管理(单点登录)
|
Java Maven 索引
idea更新maven索引失败
idea更新maven索引失败
|
人工智能 大数据 网络虚拟化
引领开放 阿里云持续推动开源生态发展
阿里云基础设施网络承办了“SONiC技术与应用分论坛“暨”第二届SONiC社区中国区分论坛“,携手国内外行业精英,分享了围绕SONiC的实践和创新
|
存储 人工智能 搜索推荐
RAG系统的7个检索指标:信息检索任务准确性评估指南
大型语言模型(LLMs)在生成式AI领域备受关注,但其知识局限性和幻觉问题仍具挑战。检索增强生成(RAG)通过引入外部知识和上下文,有效解决了这些问题,并成为2024年最具影响力的AI技术之一。RAG评估需超越简单的实现方式,建立有效的性能度量标准。本文重点讨论了七个核心检索指标,包括准确率、精确率、召回率、F1分数、平均倒数排名(MRR)、平均精确率均值(MAP)和归一化折损累积增益(nDCG),为评估和优化RAG系统提供了重要依据。这些指标不仅在RAG中发挥作用,还广泛应用于搜索引擎、电子商务、推荐系统等领域。
6273 2
RAG系统的7个检索指标:信息检索任务准确性评估指南
|
Docker Windows 容器
手把手教您在 Windows Server 2019 上使用 Docker
现在,您可以直接用 Windows Server 来运行“纯”Docker 容器,其中所有的容器进程都可以直接在主机操作系统上运行。
26662 1
|
消息中间件 算法 Kafka
从零开始掌握Kafka Rebalance和分区分配
**Kafka Rebalance详解:**当消费者组成员、订阅主题或分区变化时,集群需重新分配任务。涉及关键点:成员增减、主题数量及分区数变更。Rebalance包括Leader选举、RangeAssignor算法的分区分配,以及创建、删除、修改和查询Topic的基本操作。了解这些有助于优化Kafka集群管理。关注“软件求生”获取更多技术内容!
799 0
安装OpenCV-Python
安装OpenCV-Python
574 1
|
文字识别 开发工具 C++
PyMuPDF 1.24.4 中文文档(一)(2)
PyMuPDF 1.24.4 中文文档(一)
1332 0