From 70fbfabb95a9006c8fe4c157792e322bf6b189a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B8=B8=E7=94=B1?= Date: Thu, 11 Nov 2021 14:47:41 +0800 Subject: [PATCH] =?UTF-8?q?69.Sqrt(x)=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- JavaScript/my_leetcode.js | 10 +- c_sharp/my_leetcode/Solution.cs | 17 ++++ cpp/src/Solution.cpp | 10 +- go/leetcode.go | 14 +++ java/src/com/iqiaoxu/code/Solution.java | 10 +- python/Solution.py | 16 +++ rust/src/implements/mod.rs | 1 + rust/src/implements/q0069.rs | 128 ++++++++++++++++++++++++ rust/src/leet_code.rs | 97 ------------------ 9 files changed, 191 insertions(+), 112 deletions(-) create mode 100644 rust/src/implements/q0069.rs diff --git a/JavaScript/my_leetcode.js b/JavaScript/my_leetcode.js index ce0d1de..26af87f 100644 --- a/JavaScript/my_leetcode.js +++ b/JavaScript/my_leetcode.js @@ -18,12 +18,12 @@ var xorOperation = function (n, start) { var mySqrt = function (x) { const xHalf = 0.5 * x; let i = new BigInt64Array(new Float64Array([x]).buffer)[0]; - i = 0x5FE6EC85E7DE30DAn - (i >> 1n); + i = 0x1FF7A3BEA91D9B1Bn + (i >> 1n); let f = new Float64Array(new BigInt64Array([i]).buffer)[0]; - f = f * (1.5 - xHalf * f * f); - f = f * (1.5 - xHalf * f * f); - f = f * (1.5 - xHalf * f * f); - return Math.floor(1.0 / f); + f = f * 0.5 + xHalf / f; + f = f * 0.5 + xHalf / f; + f = f * 0.5 + xHalf / f; + return Math.floor(f); }; /** diff --git a/c_sharp/my_leetcode/Solution.cs b/c_sharp/my_leetcode/Solution.cs index 600f7d9..14c4907 100644 --- a/c_sharp/my_leetcode/Solution.cs +++ b/c_sharp/my_leetcode/Solution.cs @@ -17,5 +17,22 @@ namespace my_leetcode { return new int[4] { nums.Length, 1, nums.Length + 1, 0 }[nums.Length & 3] ^ nums.Aggregate(0, (o, n) => o ^ n); } + + /// + /// 69.Sqrt(x) + /// + /// x + /// 平方根 + public int MySqrt(int x) + { + double xHalf = 0.5 * x; + long i = BitConverter.DoubleToInt64Bits(x); + i = 0x1FF7A3BEA91D9B1B + (i >> 1); + double f = BitConverter.Int64BitsToDouble(i); + f = f * 0.5 + xHalf / f; + f = f * 0.5 + xHalf / f; + f = f * 0.5 + xHalf / f; + return (int)f; + } } } diff --git a/cpp/src/Solution.cpp b/cpp/src/Solution.cpp index 9df2ab2..d72bc74 100644 --- a/cpp/src/Solution.cpp +++ b/cpp/src/Solution.cpp @@ -39,11 +39,11 @@ int Solution::mySqrt(int x) { }; double xHalf = 0.5 * x; f = x; - i = 0x5FE6EC85E7DE30DALL - (i >> 1); - f = f * (1.5 - xHalf * f * f); // 牛顿迭代法,重复此句可提高精度 - f = f * (1.5 - xHalf * f * f); - f = f * (1.5 - xHalf * f * f); // 三次迭代 - return int(1.0 / f); + i = 0x1FF7A3BEA91D9B1B + (i >> 1); + f = f * 0.5 + xHalf / f; // 牛顿迭代法,重复此句可提高精度 + f = f * 0.5 + xHalf / f; + f = f * 0.5 + xHalf / f; // 三次迭代 + return f; } diff --git a/go/leetcode.go b/go/leetcode.go index 4b77dc8..c58323c 100644 --- a/go/leetcode.go +++ b/go/leetcode.go @@ -1,5 +1,19 @@ package main +import "math" + +// 69.Sqrt(x) +func mySqrt(x int) int { + var xHalf = 0.5 * float64(x) + var i = math.Float64bits(float64(x)) + i = 0x1FF7A3BEA91D9B1B + (i >> 1) + var f = math.Float64frombits(i) + f = f * 0.5 + xHalf / f + f = f * 0.5 + xHalf / f + f = f * 0.5 + xHalf / f + return int(f) +} + // 268.丢失的数字 func missingNumber(nums []int) int { x := 0 diff --git a/java/src/com/iqiaoxu/code/Solution.java b/java/src/com/iqiaoxu/code/Solution.java index f644118..689fd61 100644 --- a/java/src/com/iqiaoxu/code/Solution.java +++ b/java/src/com/iqiaoxu/code/Solution.java @@ -15,12 +15,12 @@ public class Solution { public int mySqrt(int x) { double xHalf = 0.5 * x; long i = Double.doubleToLongBits(x); - i = 0x5FE6EC85E7DE30DAL - (i >> 1); + i = 0x1FF7A3BEA91D9B1BL + (i >> 1); double f = Double.longBitsToDouble(i); - f = f * (1.5 - xHalf * f * f); - f = f * (1.5 - xHalf * f * f); - f = f * (1.5 - xHalf * f * f); - return (int)(1.0 / f); + f = f * 0.5 + xHalf / f; + f = f * 0.5 + xHalf / f; + f = f * 0.5 + xHalf / f; + return (int) f; } public int deleteAndEarn(int[] nums) { diff --git a/python/Solution.py b/python/Solution.py index 5640999..1bc46b1 100644 --- a/python/Solution.py +++ b/python/Solution.py @@ -37,3 +37,19 @@ class Solution: def missingNumber(self, nums: List[int]) -> int: return [len(nums), 1, len(nums) + 1, 0][len(nums) & 3] ^ functools.reduce(lambda o, n: o ^ n, nums, 0) + + def mySqrt(self, x: int) -> int: + """ + # 69.Sqrt(x) + :param x: x + :return: 平方根 + """ + import struct + x_half = 0.5 * x + i = struct.unpack("Q", struct.pack("d", float(x)))[0] + i = 0x1FF7A3BEA91D9B1B + (i >> 1) + f = struct.unpack("d", struct.pack("Q", i))[0] + f = f * 0.5 + x_half / f + f = f * 0.5 + x_half / f + f = f * 0.5 + x_half / f + return int(f) diff --git a/rust/src/implements/mod.rs b/rust/src/implements/mod.rs index c486820..2227164 100644 --- a/rust/src/implements/mod.rs +++ b/rust/src/implements/mod.rs @@ -12,6 +12,7 @@ mod q0045; mod q0046; mod q0053; mod q0055; +mod q0069; mod q0070; mod q0080; mod q0081; diff --git a/rust/src/implements/q0069.rs b/rust/src/implements/q0069.rs new file mode 100644 index 0000000..72ec1ba --- /dev/null +++ b/rust/src/implements/q0069.rs @@ -0,0 +1,128 @@ +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); + } +} diff --git a/rust/src/leet_code.rs b/rust/src/leet_code.rs index 7387e6a..843e051 100644 --- a/rust/src/leet_code.rs +++ b/rust/src/leet_code.rs @@ -1932,95 +1932,6 @@ impl Solution { ret } - /// 69.x的平方根 - /// - /// [原题链接](https://leetcode-cn.com/problems/sqrtx/) - /// # 方法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.5f64 * x as f64; - let mut i = (x as f64).to_bits(); - i = 0x5FE6EC85E7DE30DA_u64 - (i >> 1); - let mut f = f64::from_bits(i); - f = f * (1.5 - x_half * f * f); - f = f * (1.5 - x_half * f * f); - f = f * (1.5 - x_half * f * f); - (1.0f64 / f) as i32 - } - /// 172.阶乘后的零 /// /// [原题链接](https://leetcode-cn.com/problems/factorial-trailing-zeroes/) @@ -3746,14 +3657,6 @@ mod tests { assert_eq!(d, i32::MAX); } - #[test] - fn test_my_sqrt() { - let x = 2147395599; - let i = Solution::my_sqrt(x); - //println!("{}", i); - assert_eq!(i, 46339); - } - #[test] fn test_remove_stones() { let stones = vec![vec![0, 0], vec![0, 1], vec![1, 0], vec![1, 2], vec![2, 1], vec![2, 2]];