129 lines
3.7 KiB
Rust
129 lines
3.7 KiB
Rust
use crate::Solution;
|
||
|
||
|
||
impl Solution {
|
||
/// [69.Sqrt(x)](https://leetcode-cn.com/problems/sqrtx/)
|
||
///
|
||
/// 2021-11-11 11:00:34
|
||
///
|
||
/// 给你一个非负整数 `x` ,计算并返回 `x` 的 **算术平方根** 。
|
||
///
|
||
/// 由于返回类型是整数,结果只保留 **整数部分** ,小数部分将被 **舍去 。**
|
||
///
|
||
/// **注意:** 不允许使用任何内置指数函数和算符,例如 `pow(x, 0.5)` 或者 `x * 0.5` 。
|
||
///
|
||
/// * **示例 1:**
|
||
/// + **输入:** x = 4
|
||
/// + **输出:** 2
|
||
/// * **示例 2:**
|
||
/// + **输入:** x = 8
|
||
/// + **输出:** 2
|
||
/// + **解释:** 8 的算术平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去。
|
||
/// * **提示:**
|
||
/// * `0 <= x <= 2^31 - 1`
|
||
/// * Related Topics
|
||
/// + 数学
|
||
/// + 二分查找
|
||
///
|
||
/// * 👍 823
|
||
/// * 👎 0
|
||
/// # 方法1 内置函数
|
||
/// ```rust
|
||
/// pub fn my_sqrt(x: i32) -> i32 {
|
||
/// (x as f32).sqrt() as i32
|
||
/// }
|
||
/// ```
|
||
/// # 方法2 牛顿迭代法
|
||
/// f(x) = x^2 - c 的零点,令x0=c,取f(x)在点(x0, f(x0))处切线的与x轴交点的坐标x1,迭代上一步。
|
||
/// ## 源码
|
||
/// ```rust
|
||
/// pub fn my_sqrt(x: i32) -> i32 {
|
||
/// if x == 0 {
|
||
/// return 0;
|
||
/// }
|
||
/// let c = x as f64;
|
||
/// let mut x0 = x as f64;
|
||
/// loop {
|
||
/// let xi = 0.5 * (x0 + c / x0);
|
||
/// if (x0 - xi).abs() < 1e-7 {
|
||
/// break;
|
||
/// }
|
||
/// x0 = xi;
|
||
/// }
|
||
/// x0 as i32
|
||
/// }
|
||
/// ```
|
||
/// # 方法3 二分查找法
|
||
/// 实现见源码
|
||
/// ## 源码
|
||
/// ```rust
|
||
/// pub fn my_sqrt(x: i32) -> i32 {
|
||
/// let (mut l, mut r, mut ans) = (0, x, -1);
|
||
/// while l <= r {
|
||
/// let mid = l + (r - l) / 2;
|
||
/// if mid as i64 * mid as i64 <= x as i64 {
|
||
/// ans = mid;
|
||
/// l = mid + 1;
|
||
/// } else {
|
||
/// r = mid - 1;
|
||
/// }
|
||
/// }
|
||
/// ans
|
||
/// }
|
||
/// ```
|
||
/// # 方法4 袖珍计算器算法
|
||
/// 使用指数函数和对数函数替换平方根函数的方法
|
||
/// ## 源码
|
||
/// ```rust
|
||
/// pub fn my_sqrt(x: i32) -> i32 {
|
||
/// let ans = (0.5f64 * (x as f64).ln()).exp() as i32;
|
||
/// if (ans + 1) as i64 * (ans + 1) as i64 <= x as i64 {
|
||
/// ans + 1
|
||
/// } else {
|
||
/// ans
|
||
/// }
|
||
/// }
|
||
/// ```
|
||
/// # 方法5 卡马克快速平方根倒数
|
||
/// ```rust
|
||
/// pub fn my_sqrt(x: i32) -> i32 {
|
||
/// unsafe {
|
||
/// union X2f {
|
||
/// i: i64,
|
||
/// f: f64,
|
||
/// }
|
||
/// let x_half = 0.5f64 * x as f64;
|
||
/// let mut u = X2f { f: x as f64 };
|
||
/// u.i = 0x5FE6EC85E7DE30DA_i64 - (u.i >> 1);
|
||
/// u.f = u.f * (1.5f64 - x_half * u.f * u.f); // 牛顿迭代法
|
||
/// u.f = u.f * (1.5f64 - x_half * u.f * u.f);
|
||
/// u.f = u.f * (1.5f64 - x_half * u.f * u.f); // 三次迭代
|
||
/// return (1.0f64 / u.f) as i32;
|
||
/// }
|
||
/// }
|
||
/// ```
|
||
pub fn my_sqrt(x: i32) -> i32 {
|
||
let x_half = 0.5 * x as f64;
|
||
let mut i = (x as f64).to_bits();
|
||
i = 0x1FF7A3BEA91D9B1B + (i >> 1);
|
||
let mut f = f64::from_bits(i);
|
||
f = 0.5 * f + x_half / f;
|
||
f = 0.5 * f + x_half / f;
|
||
f = 0.5 * f + x_half / f;
|
||
f as i32
|
||
}
|
||
}
|
||
|
||
|
||
#[cfg(test)]
|
||
mod test {
|
||
use crate::Solution;
|
||
|
||
#[test]
|
||
fn test_q0069() {
|
||
let x = 2147395599;
|
||
let i = Solution::my_sqrt(x);
|
||
assert_eq!(i, 46339);
|
||
}
|
||
}
|