LeetCode 第69题:x的平方根
题目描述
给你一个非负整数 x ,计算并返回 x 的 算术平方根 。
由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。
**注意:**不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。
难度
简单
题目链接
示例
示例 1:
输入:x = 4 输出:2 解释:4 的算术平方根是 2 ,因此返回 2 。
示例 2:
输入:x = 8 输出:2 解释:8 的算术平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去,所以返回 2 。
提示
0 <= x <= 2^31 - 1
解题思路
二分查找法
这道题可以使用二分查找来解决,因为平方根一定在0到x之间。
关键点:
- 使用二分查找缩小范围
- 注意整数溢出问题
- 处理边界情况
- 向下取整的处理
具体步骤:
- 处理特殊情况(0和1)
- 设定左右边界
- 使用二分查找逼近平方根
- 处理溢出和边界情况
图解思路
算法步骤分析表
| 步骤 | 操作 | 状态 | 说明 |
|---|---|---|---|
| 初始 | x=8, left=1, right=8 | mid=4 | 4*4>8,缩小右边界 |
| 第1步 | left=1, right=4 | mid=2 | 2*2<8,记录答案 |
| 第2步 | left=3, right=4 | mid=3 | 3*3>8,结束 |
| 结果 | 返回2 | - | 最后一个平方小于x的数 |
状态/情况分析表
| 情况 | 输入 | 输出 | 说明 |
|---|---|---|---|
| 完全平方数 | 16 | 4 | 结果正好是整数 |
| 非完全平方数 | 8 | 2 | 需要向下取整 |
| 特殊情况 | 0,1 | 0,1 | 边界情况 |
代码实现
C# 实现
public class Solution {
public int MySqrt(int x) {
if (x == 0) return 0;
if (x == 1) return 1;
int left = 1;
int right = x;
int 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;
}
}
Python 实现
class Solution:
def mySqrt(self, x: int) -> int:
if x <= 1:
return x
left = 1
right = x
ans = 0
while left <= right:
mid = left + (right - left) // 2
# 使用除法避免溢出
if mid <= x // mid:
ans = mid
left = mid + 1
else:
right = mid - 1
return ans
C++ 实现
class Solution {
public:
int mySqrt(int x) {
if (x <= 1) return x;
int left = 1;
int right = x;
int 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;
}
};
执行结果
- 执行用时:28 ms
- 内存消耗:26.5 MB
代码亮点
- 🎯 使用二分查找优化性能
- 💡 巧妙避免整数溢出
- 🔍 特殊情况处理完善
- 🎨 代码简洁易懂
常见错误分析
- 🚫 整数溢出问题
- 🚫 边界条件处理错误
- 🚫 二分查找边界设置错误
- 🚫 结果向下取整处理错误
解法对比
| 解法 | 时间复杂度 | 空间复杂度 | 优点 | 缺点 |
|---|---|---|---|---|
| 二分查找 | O(log n) | O(1) | 高效稳定 | 需要处理溢出 |
| 牛顿迭代 | O(log n) | O(1) | 收敛快 | 实现复杂 |
| 暴力遍历 | O(√n) | O(1) | 简单直观 | 效率低 |