x 的平方根
782 字
4 分钟
x 的平方根
题目链接:69. x 的平方根 - 力扣(LeetCode)
- 难度:简单
- 标签:数学、二分查找
题目描述
Note
原题说明:
给你一个非负整数 x ,计算并返回 x 的 算术平方根 。
由于返回类型是整数,结果只保留 整数部分 ,小数部分将被舍去。不允许使用任何内置指数函数和算符(如 pow(x, 0.5))。
示例
- 输入:
x = 4-> 输出:2 - 输入:
x = 8-> 输出:2(8 的平方根约为 2.828,舍去小数后得 2)
方案一:线性扫描(初步尝试)
核心思路: 从小到大尝试每一个整数 ,直到发现其平方刚好大于 。此时 就是我们要找的整数平方根。
源码实现
class Solution {public: int mySqrt(int x) { if (x == 0) return 0; if (x == 1) return 1;
int i; // 注意:为避免 i * i 导致整型溢出,我们使用 x / i 来进行比较 for (i = 1; i < x; i++) { if (i <= x / i && (i + 1) > x / (i + 1)) { break; } } return i; }};复杂度分析
- 时间复杂度:。最坏情况下我们需要检查到 。
- 空间复杂度:。
方案二:二分查找(进阶解法)
核心思路: 由于 的平方根一定落在 之间,且函数 在该范围内是单调递增的,因此我们可以使用二分查找来极速定位。
源码实现
class Solution {public: int mySqrt(int x) { if (x == 0) return 0; int left = 1, right = x;
while (left < right) { // 取中点时 +1 是为了在只有两个元素时向上取整,配合 left = mid 避免死循环 int mid = left + (long)(right - left + 1) / 2;
if (mid <= x / mid) { left = mid; // mid 可能是答案,尝试向右侧逼近 } else { right = mid - 1; // mid 太大了,缩减右边界 } } return left; }};复杂度分析
- 时间复杂度:。对数级别的效率,即使是 级别的数据也能瞬秒。
- 空间复杂度:。
关键避坑指南
- 防止整型溢出:
在 32 位系统中,如果判断
mid * mid <= x,当mid较大时会直接溢出导致逻辑错误。- 对策 A:使用
mid <= x / mid(推荐,本项目采用)。 - 对策 B:将变量声明为
long long。
- 对策 A:使用
- 二分死循环:
当区间缩小到只剩两个元素(如
left=2, right=3)时,如果mid总是取下整(left),且代码逻辑中有left = mid,则会陷入死循环。- 对策:使用
left + (right - left + 1) / 2这种向上取整的计算方式。
- 对策:使用
总结
- 数学与搜索的结合:这道题是二分查找在数学数值逼近领域的经典应用。
- 工程细节:处理好“除以0”和“溢出”是体现代码健壮性的关键。
Tip
进阶思考:除了二分法,这道题还有一种更高级的解法——牛顿迭代法。它利用切线逼近,收敛速度极快,感兴趣的同学可以查阅相关资料。
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!
最后更新于 2025-10-18,距今已过 193 天
部分内容可能已过时
相关文章 智能推荐
1
爬楼梯
算法 力扣第70题:爬楼梯。从递归到动态规划(DP)的演进,深入理解斐波那契数列在算法中的美妙应用。
2
加一
算法 力扣第66题:加一。处理大整数数组的进位逻辑,从逐位检查到首位插入的技巧分析。
3
最后一个单词的长度
算法 力扣第58题:最后一个单词的长度。从反向遍历的直观思想到双指针的精准定位,掌握字符串处理的边界细节。
4
搜索插入位置
算法 力扣第35题:搜索插入位置。深入理解二分查找(Binary Search)的边界处理,实现 $O(\log n)$ 的极速搜索。
5
有效的括号
算法 力扣第20题:有效的括号。从“回文”误区到栈(Stack)的经典应用,深入理解括号匹配的 LIFO 逻辑。
随机文章 随机推荐