leetcode 69. x 的平方根

可以使用二分查找法或牛顿迭代法来实现 LeetCode 问题 69. x 的平方根。下面是使用二分查找法和牛顿迭代法的 C++ 实现。

二分查找法

cpp 复制代码
#include <iostream>

class Solution {
public:
    int mySqrt(int x) {
        if (x == 0) return 0;
        int left = 1, right = x, ans = 0;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (mid <= x / mid) {
                ans = mid;
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return ans;
    }
};

int main() {
    Solution solution;
    int x = 8;
    std::cout << "The square root of " << x << " is " << solution.mySqrt(x) << std::endl;
    return 0;
}

牛顿迭代法

cpp 复制代码
#include <iostream>

class Solution {
public:
    int mySqrt(int x) {
        if (x == 0) return 0;
        double x0 = x;
        while (true) {
            double xi = 0.5 * (x0 + x / x0);
            if (abs(x0 - xi) < 1e-7) break;
            x0 = xi;
        }
        return static_cast<int>(x0);
    }
};

int main() {
    Solution solution;
    int x = 8;
    std::cout << "The square root of " << x << " is " << solution.mySqrt(x) << std::endl;
    return 0;
}

解释

二分查找法
  1. 初始化 :定义 left 为 1,right 为 x,并初始化 ans 为 0。
  2. 循环 :当 left 小于等于 right 时,计算 mid 作为中间值。
  3. 判断 :如果 mid 的平方小于等于 x,说明 mid 可能是平方根的一部分,更新 ans 为 mid,并移动 left 到 mid + 1。否则,移动 right 到 mid - 1。
  4. 返回 :循环结束后,返回 ans。
牛顿迭代法
  1. 初始化 :定义 x0 为 x。
  2. 迭代 :计算 xi,它是 x0 和 x / x0 的平均值。如果 x0 和 xi 的差异小于一个很小的值(如 1e-7),则停止迭代。
  3. 更新 :将 x0 更新为 xi。
  4. 返回 :将 x0 转换为整数并返回。

这两种方法都能有效地计算 x 的平方根,并且二分查找法的时间复杂度为 O(log x),牛顿迭代法的时间复杂度为 O(log x)。你可以根据需要选择其中一种方法。

当然,使用图示和例子可以更直观地理解二分查找算法在计算平方根整数部分的过程。

例子:计算 10 的平方根的整数部分

我们以计算 10 的平方根为例,来展示整个过程。

步骤 1:初始化
  • left = 1
  • right = 10
  • ans = 0
步骤 2:开始二分查找
  1. 第一次迭代:

    • 计算中点 mid = left + (right - left) / 2 = 1 + (10 - 1) / 2 = 5

    • 检查 mid * mid 和 x 的关系:5 * 5 = 25,25 > 10,因此更新 right 为 mid - 1,即 right = 4

    • 图示:

      复制代码
      搜索区间: [1, 10]
      mid = 5, 5*5 > 10, 更新right = 4
  2. 第二次迭代:

    • 计算中点 mid = left + (right - left) / 2 = 1 + (4 - 1) / 2 = 2

    • 检查 mid * mid 和 x 的关系:2 * 2 = 4,4 < 10,因此更新 ans 为 mid,并更新 left 为 mid + 1,即 left = 3

    • 图示:

      复制代码
      搜索区间: [1, 4]
      mid = 2, 2*2 < 10, 更新left = 3, ans = 2
  3. 第三次迭代:

    • 计算中点 mid = left + (right - left) / 2 = 3 + (4 - 3) / 2 = 3

    • 检查 mid * mid 和 x 的关系:3 * 3 = 9,9 < 10,因此更新 ans 为 mid,并更新 left 为 mid + 1,即 left = 4

    • 图示:

      复制代码
      搜索区间: [3, 4]
      mid = 3, 3*3 < 10, 更新left = 4, ans = 3
  4. 第四次迭代:

    • 计算中点 mid = left + (right - left) / 2 = 4 + (4 - 4) / 2 = 4

    • 检查 mid * mid 和 x 的关系:4 * 4 = 16,16 > 10,因此更新 right 为 mid - 1,即 right = 3

    • 图示:

      复制代码
      搜索区间: [4, 4]
      mid = 4, 4*4 > 10, 更新right = 3
结束循环

当 left > right 时,退出循环,此时 ans 保存的就是最大的满足条件的整数。最终结果为 ans = 3,所以 10 的平方根的整数部分是 3。

代码对应的流程

  1. 初始化 left、right 和 ans
  2. 在每次迭代中计算 mid 并比较 mid * mid 和 x
    • 如果 mid * mid 小于等于 x,则更新 ans 并右移 left
    • 如果 mid * mid 大于 x,则左移 right
  3. 循环结束后,返回 ans

图示

复制代码
初始区间: [1, 10]

第一次迭代:
mid = 5, 5*5 > 10, 更新right = 4
搜索区间变为: [1, 4]

第二次迭代:
mid = 2, 2*2 < 10, 更新left = 3, ans = 2
搜索区间变为: [3, 4]

第三次迭代:
mid = 3, 3*3 < 10, 更新left = 4, ans = 3
搜索区间变为: [4, 4]

第四次迭代:
mid = 4, 4*4 > 10, 更新right = 3
搜索区间变为: [4, 3]

循环结束,返回 ans = 3

这样,通过二分查找,我们成功找到并返回了 10 的平方根的整数部分 3。

相关推荐
y1su2 小时前
Leetcode 字符串模板
java·数据结构·算法·leetcode·职场和发展·动态规划
residual_fan3 小时前
船用柴油机动态机动工况故障诊断:控制感知仿射网络(CAAN)的技术实现
人工智能·算法·数据挖掘·数据分析
其实防守也摸鱼3 小时前
Cylab在线靶场——CTF中的通用技能
linux·数据库·学习·算法·靶场·ctf·学习网络安全
蓝悦无人机4 小时前
《Planning algorithms》读书笔记——第8章 反馈运动规划
算法·读书笔记·反馈运动规划
RaaS1004 小时前
Agent Skills 进了 Linux Foundation:2.8 亿次安装,但装 skill 还没有安全规范
人工智能·算法·架构
CV爱数码4 小时前
CT 重建从零开始(五):ASTRA Toolbox 上手——几何、投影器与算法
图像处理·算法·计算机视觉·ct
TunerT_TQ4 小时前
超立方体Ramsey(openai/math 家族171)H11攻坚日志|D60–D69:Star分组重数、二幂坐标群、奇偶入射语义与Site‑Level候选计数形式化闭环
算法
Rabitebla5 小时前
【系统性学习笔记】Linux 权限篇(二):文件属性、权限修改与目录权限的底层逻辑
linux·c++·笔记·学习·算法
远离UE45 小时前
半拉格朗日学习笔记 动力学 实时渲染
人工智能·算法
小郎君6585 小时前
MPTT 不是万能编号:一棵百万节点树的增删改与批量事务
算法