Leetcode 69.x的平方根

news2025/7/4 21:54:51

给你一个非负整数 x ,计算并返回 x 的 算术平方根 。

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

注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。

示例 1:

输入:x = 4
输出:2

示例 2:

输入:x = 8
输出:2
解释:8 的算术平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去。

提示:

  • 0 <= x <= 231 - 1

一、信息

1.给我的是非负整数x

2.计算x的算术平方根

3.返回类型是整型

二、分析

条件1:告诉我不用考虑输入为负数

条件2:告诉我两点。第一点就是告诉我是算术平方根如果只是普通的平方根输出的时候还要输出正负两个答案。第二点就是告诉我此次的目的。

条件3 告诉我函数的返回值类型。

三、算法步骤:

流程图:

 

四、问题出现

问题1.该如何实现开方呢?

我的思路:

我看到了在我面前有两条路。

第一条:遍历

我们设x为目标y为被开方的数,我们假设存在0<x<y使得x*x=y,我们只需要再y中一遍一遍试就行。这样的话时间复杂度应该为O(n).

第二条:遍历后用二分法提高查找效率。


更正后的思考过程

一、信息


我们要实现一个函数,这个函数接收一个非负整数 `x` ,计算并返回 `x` 的算术平方根的整数部分。我们不能使用内置的指数函数和算符,例如 `pow(x, 0.5)` 或者 `x ** 0.5`。

二、分析


初始思考:
一开始,我思考的是如何在没有使用平方根函数的情况下得到一个数的平方根。考虑到平方根的定义是,对于一个非负数 `x` ,其平方根是另一个非负数,这个数的平方等于 `x`。于是我们需要找到一个数,使其平方最接近且不大于 `x`。

#### 遇到的问题:
1. 我们不能直接计算平方根,所以我们需要使用一些间接的方法来找到这个数。
2. 我们需要考虑效率问题。例如,我们可以从 `0` 开始,一点一点地增加,直到我们找到这个数。但是这种方法效率很低,特别是当 `x` 很大时。

#### 解决方案:
考虑到效率问题,我们可以使用二分查找法。我们知道,对于一个非负整数 `x` ,其平方根不会大于 `x/2 + 1`。所以我们可以在 `0` 到 `x/2 + 1` 之间进行二分查找。这将大大减少我们需要检查的数字的数量,从而提高效率。

三、算法步骤


1. **边界条件处理**:如果 `x` 等于 `0` 或 `1`,直接返回 `x`。
2. **初始化**:将 `start` 初始化为 `0`,将 `end` 初始化为 `x`。
3. **二分查找**:
   a. 计算中点 `mid = start + (end - start) / 2`。
   b. 检查 `mid` 的平方与 `x` 的关系。如果 `mid` 的平方等于 `x`,则直接返回 `mid`。
   c. 如果 `mid` 的平方小于 `x`,更新 `start = mid + 1`。
   d. 如果 `mid` 的平方大于 `x`,更新 `end = mid - 1`。
4. **返回结果**:二分查找结束时,`start` 将会大于 `end`,我们返回 `end`,因为我们要找的是不大于 `x` 的最大整数平方根。

通过这个方法,我们可以高效地找到一个数的平方根的整数部分,而无需使用任何内置的平方根函数或算符。

 


五、实现

我的答案:

C语言版本:

#include <stdio.h>

int mySqrt(int x) {
    if (x == 0 || x == 1) return x;
    
    long long start = 0;
    long long end = x;
    while (start <= end) {
        long long mid = start + (end - start) / 2;
        
        if (mid * mid == x) return mid; // 找到了精确的平方根
        
        if (mid * mid < x) {
            start = mid + 1;
        } else {
            end = mid - 1;
        }
    }
    
    // 由于题目要求返回整数部分,所以返回end
    return end;
}

int main() {
    int x1 = 4;
    int x2 = 8;
    
    printf("The square root of %d is %d\n", x1, mySqrt(x1)); // 输出:2
    printf("The square root of %d is %d\n", x2, mySqrt(x2)); // 输出:2
    
    return 0;
}

C++版本:

#include <iostream>

class Solution {
public:
    int mySqrt(int x) {
        if (x == 0 || x == 1) return x;
        
        long long start = 0, end = x;
        while (start <= end) {
            long long mid = start + (end - start) / 2;
            
            if (mid * mid == x) return mid; // 找到了精确的平方根
            
            if (mid * mid < x) start = mid + 1;
            else end = mid - 1;
        }
        
        // 返回end,因为我们要返回的是不大于x的最大整数平方根
        return end;
    }
};

int main() {
    Solution solution;
    std::cout << "The square root of 4 is " << solution.mySqrt(4) << std::endl; // 输出:2
    std::cout << "The square root of 8 is " << solution.mySqrt(8) << std::endl; // 输出:2
    return 0;
}

JAVA:

public class Solution {
    
    public int mySqrt(int x) {
        if (x == 0 || x == 1) return x;
        
        long start = 0, end = x;
        while (start <= end) {
            long mid = start + (end - start) / 2;
            
            if (mid * mid == x) return (int) mid; // 找到了精确的平方根
            
            if (mid * mid < x) start = mid + 1;
            else end = mid - 1;
        }
        
        // 返回end,因为我们要返回的是不大于x的最大整数平方根
        return (int) end;
    }
    
    public static void main(String[] args) {
        Solution solution = new Solution();
        System.out.println("The square root of 4 is " + solution.mySqrt(4)); // 输出:2
        System.out.println("The square root of 8 is " + solution.mySqrt(8)); // 输出:2
    }
}

Leetcode 题解:

方法三:牛顿迭代

 

 

源代码:

 

class Solution {
public:
    int mySqrt(int x) {
        if (x == 0) {
            return 0;
        }

        double C = x, x0 = x;
        while (true) {
            double xi = 0.5 * (x0 + C / x0);
            if (fabs(x0 - xi) < 1e-7) {
                break;
            }
            x0 = xi;
        }
        return int(x0);
    }
};

我的答案和Leetcode的答案的各自的优劣

二分查找法和牛顿迭代法都是有效的数值方法,用于求解平方根,它们各自有一些优劣势:

### 1. **二分查找法**:
#### 优势:
- **直观易懂**:二分查找法是一种非常直观且易于理解和实现的算法。
- **稳定性高**:由于算法逻辑简单,因此其在各种情况下都表现得很稳定。
- **适用性广**:二分查找法可以应用于任何有序序列,不仅仅局限于求平方根。
  
#### 劣势:
- **收敛速度**:相较于牛顿迭代法,二分查找法的收敛速度较慢,尤其是在求解较大的数的平方根时。

### 2. **牛顿迭代法**:
#### 优势:
- **收敛速度快**:牛顿迭代法是一种二次收敛的方法,每一次迭代都会使得结果的有效数字大约翻倍,因此通常会比二分查找法更快地收敛到实际的平方根。
- **适用性强**:牛顿迭代法可以用来求解各种非线性方程的根,适用性非常广泛。

#### 劣势:
- **实现复杂度**:相较于二分查找法,牛顿迭代法的实现略显复杂。
- **初始值选择**:牛顿迭代法的收敛性会受到初始值选择的影响,而选择合适的初始值有时并非易事。

### 综合比较:
对于求平方根这一特定问题而言,如果追求算法的简单和稳定,二分查找是一个很好的选择。而如果追求更高的收敛速度,尤其是在处理较大的数时,牛顿迭代法会是更优的选择。在实际应用中,可以根据问题的具体要求和约束来选择最合适的方法。

总结:

从这道题目中,我们能学到多方面的知识和技能:

### 1. **算法基础**
- **二分查找**:学会使用二分查找来求解有序序列中的问题,理解其工作原理和实现方法。
- **牛顿迭代**:学会使用牛顿迭代法来快速求解非线性方程的根,理解其收敛性和收敛速度。

### 2. **编程实践**
- **实现方法**:学会如何将算法用代码实现,例如C++或Java中如何实现二分查找和牛顿迭代法。
- **调试和优化**:通过实践,学会如何调试代码,优化算法性能,如何选择合适的初始值和终止条件等。

### 3. **数学知识**
- **函数和图像理解**:通过牛顿迭代法,加深对函数、导数和图像的理解,学习如何通过图像直观理解算法过程。
- **收敛性理解**:通过对比不同方法,理解算法的收敛性和收敛速度,学会如何评估算法的性能。

### 4. **问题解决技能**
- **多种解决方案**:学会对同一问题采用不同的解决方案,并能够分析各种方案的优劣,从而选择最合适的一种。
- **分析和评估**:学会分析问题的需求和限制,评估不同方案的适用性,做出合理的决策。

### 5. **实际应用**
- **实际问题中的应用**:学会如何将学到的算法和知识应用到实际问题中,例如在没有开方运算的环境中求解平方根。
- **性能优化**:了解在实际应用中如何优化算法,提高算法的运行效率,满足实际需求。

总之,这道题目不仅可以加深对基础算法和编程的理解,而且可以提高数学理论和问题解决能力,具有很高的学习价值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1055211.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微服务moleculer01

1.官网地址&#xff1a; Moleculer - Progressive microservices framework for Node.js 2. github代码地址&#xff1a; GitHub - moleculerjs/moleculer: :rocket: Progressive microservices framework for Node.js Moleculer是基于Node.js的一款快速、多功能的微服务框…

docker 安装本地starrocks测试环境

安装文档 Quick start: Deploy StarRocks with Docker deploy_in_docker StarRocks Docs Quick start: Deploy StarRocks with Docker deploy_in_docker StarRocks Docs 镜像版本 https://hub.docker.com/r/starrocks/allin1-ubuntu/tags?page1 docker安装starrocks

【软件工程_UML—StartUML作图工具】startUML怎么画interface接口

StartUML作图工具怎么画interface接口 初试为圆形 &#xff0c;点击该接口在右下角的设置中->Format->Stereotype Display->Label&#xff0c;即可切换到想要的样式 其他方式 在class diagram下&#xff0c;左侧有interface图标&#xff0c;先鼠标左键选择&#xff0…

【多线程进阶】常见的锁策略

文章目录 前言1. 乐观锁 vs 悲观锁2. 轻量级锁 vs 重量级锁3. 自旋锁 vs 挂起等待锁4. 读写锁 vs 互斥锁5. 公平锁 vs 非公平锁6. 可重入锁 vs 不可重入锁总结 前言 本章节所讲解的锁策略不仅仅是局限于 Java . 任何和 “锁” 相关的话题, 都可能会涉及到以下内容. 这些特性主…

windows系统一键开启和关闭虚拟化

说明 跟虚拟化相关的三个程序 一键开启脚本 REM 开启 Hyper-V 服务 pushd "%~dp0"dir /b %SystemRoot%\servicing\Packages\*Hyper-V*.mum >hyper-v.txtfor /f %%i in (findstr /i . hyper-v.txt 2^>nul) do dism /online /norestart /add-package:"%Sy…

一步一招,教你如何制作出成功的优惠促销微传单

在当今的数字化时代&#xff0c;几乎所有的事情都可以在互联网上完成&#xff0c;包括制作宣传单。有很多在线工具可以帮助我们轻松制作出精美的商场促销宣传单。下面就以乔拓云为例&#xff0c;详细介绍如何简单几步制作出让人眼前一亮的商场促销宣传单。 1. 注册并登录乔拓云…

WPS Office for Linux即将面临开源

WPS Office 是一款免费&#xff08;但不开源&#xff09;的办公套件&#xff0c;目前已经在 Windows、macOS、Android、iOS 和 Linux 设备上线&#xff0c;由于在界面和功能上模仿了微软 Office 的部分特性&#xff0c;对于那些轻量办公的用户来说已经能够完全驾驭大部分需求。…

三、飞行和射击

目录 1.飞行的实现 2.限制玩家视角 3.射击的实现 4.附录 1.飞行的实现 &#xff08;1&#xff09;在Player预制体上挂载Configuration Joint组件&#xff0c;并修改其Y Drive属性 &#xff08;2&#xff09; 修改PlayerInput.cs和PlayerController.cs以实现飞行 PlayerIn…

【刷题笔记10.2】LeetCode: 罗马数字转整数

LeetCode: 罗马数字转整数 一、题目描述 二、分析 方法一&#xff1a; 将给定字符串s中的"IV", “IX”, “XL”, “XC”, “CD”, “CM” 全部替换为其他字符如&#xff1a;a, b, c, d, e, f 这种&#xff0c;然后就可以遍历累加了。 s s.replace("IV",…

【数据代理+事件处理+计算属性与监视+绑定样式+条件渲染】

数据代理事件处理计算属性与监视绑定样式条件渲染 1 数据代理1.1 回顾Object.defineProperty方法1.2 数据代理 2 事件处理2.1 绑定监听2.2 事件修饰符2.3 键盘事件 3 计算属性与监视3.1 计算属性3.2 监视属性(侦视属性)3.3 watch对比computed 4 绑定样式4.1 绑定class样式4.2 绑…

Linux命令(一)(目录相关)

目录可以更快找到你想要的命令 1. 命令入门2. 常用目录命令(cd、pwd、ls、cp、rm、mkdir)*cd&#xff1a;用来进入到指定的文件夹*常见操作关于绝对路径和相对路径的说明&#xff1a; *pwd&#xff1a;显示当前工作目录的路径*选项用例 *ls&#xff1a;显示目录中文件及其属性信…

数据结构与算法-(7)---栈的应用-(3)表达式转换

&#x1f308;write in front&#x1f308; &#x1f9f8;大家好&#xff0c;我是Aileen&#x1f9f8;.希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流. &#x1f194;本文由Aileen_0v0&#x1f9f8; 原创 CSDN首发&#x1f412; 如…

区块链(8):p2p去中心化之websoket服务端实现业务逻辑

1 业务逻辑 例如 peer1和peer2之间相互通信 peer1通过onopen{ write(Mesage(QUERY_LATEST))} 向peer2发送消息“我要最新的区块”。 peer2通过onMessage收到消息,通过handleMessage方法对消息进行处理。 handleMessage根据消息类型进行处理 RESPONSE_BLOCKCHAIN:返回区块链…

WSL2和ubuntu的安装过程

目录 1.WSL2的安装 2.Ubuntu的安装 3.安装完成后的打开方式 1.WSL2的安装 按下WINX键&#xff0c;选择Windows PowerShell (管理员) 1.1执行以下命令&#xff0c;该命令的作用是&#xff1a;启用适用于 Linux 的 Windows 子系统 dism.exe /online /enable-feature /featur…

BI神器Power Query(25)-- 使用PQ实现表格多列转换(1/3)

实例需求&#xff1a;原始表格包含多列属性数据,现在需要将不同属性分列展示在不同的行中&#xff0c;att1、att3、att5为一组&#xff0c;att2、att3、att6为另一组&#xff0c;数据如下所示。 更新表格数据 原始数据表&#xff1a; Col1Col2Att1Att2Att3Att4Att5Att6AAADD…

经典网络解析(四) transformer | 自注意力、多头、发展

文章目录 1 背景1.1 困境1.2 基本架构 2 嵌入层3 编码器部分3.1 自注意力层3.2 多头注意力机制3.3 LayerNorm归一化层 4 解码器5 transformer的发展6 代码 1 背景 1.1 困境 transformer可以并行训练&#xff0c;也是用来实现attention注意力机制 之前RNN的困境 &#xff08…

【PostgreSQL】【存储管理】表和元组的组织方式

外存管理负责处理数据库与外存介质(PostgreSQL8.4.1版本中只支持磁盘的管理操作)的交互过程。在PostgreSQL中&#xff0c;外存管理由SMGR(主要代码在smgr.c中)提供了对外存的统一接口。SMGR负责统管各种介质管理器&#xff0c;会根据上层的请求选择一个具体的介质管理器进行操作…

【最优化理论】线性规划标准模型的基本概念与性质

我们在中学阶段就遇到过线性规划问题&#xff0c;主要是二维的情况&#xff0c;而求解的方法一般是非常直观、高效的图解法。根据过往的经验&#xff0c;线性规划问题的最优目标值一般在可行域的顶点处取得&#xff0c;那么本文就对这个问题进行更深入的探讨&#xff0c;维度也…

找不到msvcp140.dll解决方法的5个解决方法以及msvcp140.dll丢失原因分析

msvcp140.dll 是 Microsoft Visual C 2017 Redistributable 的一部分&#xff0c;许多应用程序和游戏都需要这个动态链接库&#xff08;DLL&#xff09;才能正常运行。如果您的系统中找不到 msvcp140.dll&#xff0c;您可能会遇到无法打开某些应用程序或游戏的困境。小编将讨论…

运用动态内存实现通讯录(增删查改+排序)

目录 前言&#xff1a; 实现通讯录&#xff1a; 1.创建和调用菜单&#xff1a; 2.创建联系人信息和通讯录&#xff1a; 3.初始化通讯录&#xff1a; 4.增加联系人&#xff1a; 5.显示联系人&#xff1a; 6.删除联系人&#xff1a; ​编辑 7.查找联系人&#xff1a; ​…