my_leetcode/rust/src/implements/q0069.rs

129 lines
3.7 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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);
}
}