快捷搜索:  汽车  科技

程序设计中平方根怎么表示(leetcodeC题解系列-068)

程序设计中平方根怎么表示(leetcodeC题解系列-068)if (mid <= x / mid) ret = mid; 整个程序非常简单,而且高效 AC:int l = 1 r = x ret = 0; while (l <= r) { int m = (l r) >> 1; if (m <= x / m) { l = m 1; ret = m; } else r = m-1; } return ret; 这道题算是告一段落,但我们其实占了 integer 的便宜,假使要实现的是 float sqrtf(float x) 我们可能需要考虑一下使用著名的牛顿迭代了。这就基本演变为一道数学题了。具体可见 Matrix67 这篇博文中的解释。

程序设计中平方根怎么表示(leetcodeC题解系列-068)(1)

题目

实现int sqrt(int x)函数。 计算并返回x的平方根,其中x 是非负整数。 由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。 示例 1: 输入: 4 输出: 2 示例 2: 输入: 8 输出: 2 说明: 8 的平方根是 2.82842... 由于返回类型是整数,小数部分将被舍去。 解题代码与测试

// // Created by tannzh on 2020/7/30. // /* * x 的平方根 实现int sqrt(int x)函数。 计算并返回x的平方根,其中x 是非负整数。 由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。 示例 1: 输入: 4 输出: 2 示例 2: 输入: 8 输出: 2 说明: 8 的平方根是 2.82842... 由于返回类型是整数,小数部分将被舍去。 */ #include <iostream> class Solution { public: int mySqrt(int x) { int l = 1 r = x ret = 0; while (l <= r) { int m = (l r) >> 1; if (m <= x / m) { l = m 1; ret = m; } else r = m-1; } return ret; } }; int main(int argc char **argv) { Solution s; std::cout << s.mySqrt(8) << std::endl; std::cout << s.mySqrt(4) << std::endl; return 0; } 解题思路分析

很显然,这又是一道轮子题。有时候我们经常使用某个库函数,的确会偶尔推测它底层是如何实现的。譬如这个 sqrt 它如何做到快准狠?


首先最自然的方案,当然是对对碰。如求 10 的平方根,我可以从 1 开始碰,1*1==1 显然不对,一直到 4*4==16 才发现超出了。于是答案显然是 3.

但这种类似穷举的方式显然很不智,既然是查找能碰对的数,肯定二分搜索要快一些。 如先看 5*5==25 25 > 10 范围向左缩小,并继续中分,有 3*3==9,9 < 10,范围向右缩小,并继续中分,有 4*4==16 16 > 10 right == 3 left == 4. 结束。

那结果应该取哪一次的 middle 呢?显然因为咱们是 integer 的运算,取小不取大,3 可以是结果,4 决计不是。故有:

if (mid <= x / mid) ret = mid;

整个程序非常简单,而且高效 AC:

int l = 1 r = x ret = 0; while (l <= r) { int m = (l r) >> 1; if (m <= x / m) { l = m 1; ret = m; } else r = m-1; } return ret;


这道题算是告一段落,但我们其实占了 integer 的便宜,假使要实现的是 float sqrtf(float x) 我们可能需要考虑一下使用著名的牛顿迭代了。这就基本演变为一道数学题了。具体可见 Matrix67 这篇博文中的解释。

#include <cfloat> #include <cmath> float sqrtf(float x) { float ret; for (float f = 1.f; true; f = ret) { ret = (f x / f) / 2; if (std::abs(f - ret) < FLT_MIN) break; } return ret; }

猜您喜欢: