Leetcode 69. Sqrt(x) Easy

https://leetcode.com/problems/sqrtx/

Implement int sqrt(int x).

Compute and return the square root of x, where x is guaranteed to be a non-negative integer.

Since the return type is an integer, the decimal digits are truncated and only the integer part of the result is returned.

Example 1:

Input: 4
Output: 2

Example 2:

Input: 8
Output: 2
Explanation: The square root of 8 is 2.82842..., and since
  the decimal part is truncated, 2 is returned.

分析:

leetcode上的这个不带精度要求,且输出一个整数即可(其实可以当成精度要求小于等于1)。

方法一:(二分法)

对于本题,最直观的方法就是二分法。使用二分法时,需要注意有三个指针,分别指向前中后(pre、medium、last,在书写、习惯、理解上,一般用left、mid、right进行表示,或者用start、mid、end)。此外,循环结束的条件也需要在书写程序之前想好,当然这也是本题的难点。

边界条件怎么确定呢?
假设left < right时循环,当left等于right时循环结束,并返回left或right,此时有left=right=mid。那么可以取一个整数进行实验:比如8。
第一次循环:
mid = (1 + 8)/2 = 4 (整数除法默认向下取整)
mid > 8/mid
right = mid - 1 = 3
left = 1
第二次循环:
mid = (1 + 3)/2 = 2
mid < 8/mid
left = mid + 1 = 3
right = 3
此时由于left == right 则跳出循环,返回的是3,但是这不应该是正确答案。如果在循环条件中加上等于,即left <= right,那么下一步还会有一次循环:
第三次循环:(新增的)
mid = 3
mid > 8/mid
right = mid - 1 = 2
left = 3
此时left > righ结束循环。写到这里,我们发现,如果在循环结束时,对于此例子,返回right是比较合适的。这是个例吗,还是都是这样?

比如x=10,那么mid的变化过程将是:5->2->3,此时10/3 == 3,直接返回了。再如x=11,那么mid变化过程将是:5->2->3,此时11/3 == 3,直接返回了。

再比如x=12,那么mid变化过程将是:6->3->4(此时left=4,right=5)->4(left=4,right=4)->此时right-1,变为left = 4, right = 3,返回right。
所以right必为返回值(在不存在mid == x / mid的条件下)

至于为什么,可以细想一下,我也没想明白,给出理论解释。直观感觉是开根号为向下取整,而返回right时,right < left,正好算是向下取整。

注意:之所以要写成除法的形式,是因为如果两个大数相乘,容易超内存。

int mySqrt(int x) {
int left = ; // left不能取0;因为如果x=1,那么(0+1)/2 = 0,导致mid等于0,做除法的时候会报错
int right = x;
while (left <= right) {
// int mid = (left + right) / 2; ——> 不要这么写,是因为如果right很大,left+right可能会超过整型最大值
int mid = left + (right - left) / 2;
if (mid == x / mid) {
return mid;
}
else if (mid > x / mid) {
right = mid - ;
}
else { // mid < x / mid
left = mid + ;
}
}
return right;
}

方法二:(牛顿法)

下面介绍牛顿法/牛顿迭代法。使用牛顿法千万不要死记硬背公式,要明白推导过程。牛顿法是用来求方程的近似根。通过使用f(x)的泰勒级数的前几项来寻找f(x)=0的根。(思考,和xgboost中使用牛顿法有什么区别)

关于泰勒级数的介绍:(说的不错)

https://baike.baidu.com/item/%E6%B3%B0%E5%8B%92%E7%BA%A7%E6%95%B0

https://zh.wikipedia.org/wiki/%E6%B3%B0%E5%8B%92%E7%BA%A7%E6%95%B0

关于牛顿法/牛顿迭代法:

https://baike.baidu.com/item/%E7%89%9B%E9%A1%BF%E8%BF%AD%E4%BB%A3%E6%B3%95 (百科介绍的太好了)

https://www.zhihu.com/question/20690553

https://www.cnblogs.com/wangkundentisy/p/8118007.html

(介绍了牛顿迭代法的使用,主要对问题进行求根转化后,然后求切线与x轴交点,并进行迭代更新此处更适合用来求根/零点,和下面这个优化算法是不太一样的)

https://blog.csdn.net/google19890102/article/details/41087931

(作为优化算法的牛顿法,整体思想就是利用迭代点处的一阶导数(梯度)和二阶导数(Hessen矩阵)对目标函数进行二次函数近似然后把二次模型的极小点作为新的迭代点,并不断重复这一过程,直至求得满足精度的近似极小值。这就和XGBoost对损失函数进行二阶泰勒展开是相同的原理,且用目标函数对f_t-1(x)求一阶导数,所以说利用了牛顿法;而且在XGBoost中,求得的f_t-1(x)或者说w_q(x)即是下一次更新的叶子节点的权重。结合着论文和这篇博客还是比较容易懂,值得反复看)

为什么优化和求根都叫牛顿法呢?明明在求根和零点问题上,就是作切线嘛,明明没有泰勒展开啊,看看百度百科的“回答”(让我豁然开朗):

注意的关键词:非线性方程,泰勒级数,取线性部分,近似方程。

下面进行详细分析,推导出迭代关系式(用iPad手写推导过程),并给出代码:

 总结:

由上分析我们可以发现,由牛顿法和切线法得来的递推公式是相同的,我们姑且可以认为切线法是牛顿法的几何表示。

此时,所谓的牛顿法对我已不再神秘,希望对你也一样如此!

int mySqrt(int x) {
long long ans = x;
while (ans * ans > x) { // 其实,我很疑惑:如果ans很大的情况下,ans*ans不应该会报错吗
ans = (ans + x / ans) / ; // 由公式化简得来
}
return ans;
}

至此,Leetcode上的这道 “Easy” 题目已经解决。但是往往在面试或实际问题中,要求最后得到的结果具备一定精度,即ans*ans - x < ε。此外,如果要求 ans值满足某一精度,我们就必须使用sqrt()求出其真实开根号值,然后作为判断条件。下面对一种进行代码书写,整体思路和不带精度相同,但是要注意需要把int型转为double型!

二分法:

double mySqrt(double x, double epsilon) {
double left = 1.0;
double right = x;
double mid = left + (right - left) / ;
while (fabs(mid * mid - x) > epsilon) { // 默认mid * mid不会超过范围,否则这道题就麻烦了
if (mid * mid > x) {
right = mid;
}
else if (mid * mid < x) {
left = mid;
}
else {
return mid;
}
mid = left + (right - left) / ;
}
return mid;
}

牛顿法:

double mySqrt(double x, double epsilon) {
double ans = x;
while (fabs(ans * ans - x) > epsilon) {
ans = (ans + x / ans) / ;
}
return ans;
}

注:

关于数学符号表示的知识,如:epsilon :ε

Leetcode 69. Sqrt(x)及其扩展(有/无精度、二分法、牛顿法)详解的更多相关文章

  1. C++版 - Leetcode 69. Sqrt(x) 解题报告【C库函数sqrt(x)模拟-求平方根】

    69. Sqrt(x) Total Accepted: 93296 Total Submissions: 368340 Difficulty: Medium 提交网址: https://leetcod ...

  2. [LeetCode] 69. Sqrt(x) 求平方根

    Implement int sqrt(int x). Compute and return the square root of x, where x is guaranteed to be a no ...

  3. LeetCode 69. Sqrt(x) (平方根)

    Implement int sqrt(int x). Compute and return the square root of x. x is guaranteed to be a non-nega ...

  4. Leetcode 69. Sqrt(x)

    Implement int sqrt(int x). 思路: Binary Search class Solution(object): def mySqrt(self, x): "&quo ...

  5. (二分查找 拓展) leetcode 69. Sqrt(x)

    Implement int sqrt(int x). Compute and return the square root of x, where x is guaranteed to be a no ...

  6. [LeetCode] 69. Sqrt(x)_Easy tag: Binary Search

    Implement int sqrt(int x). Compute and return the square root of x, where x is guaranteed to be a no ...

  7. Leetcode 69 Sqrt(x) 二分查找(二分答案)

    可怕的同时考数值溢出和二分的酱油题之一,常在各种小公司的笔试中充当大题来给你好看... 题意很简单,在<二分查找综述>中有描述. 重点:使用简单粗暴的long long来避免溢出,二分均方 ...

  8. c++ LeetCode(初级数组篇)十一道算法例题代码详解(一)

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/10940636.html 唉!最近忙着面试找实习,然后都是面试的很多是leetcode的算法题, ...

  9. jQuery实现form表单基于ajax无刷新提交方法详解

    本文实例讲述了jQuery实现form表单基于ajax无刷新提交方法.分享给大家供大家参考,具体如下: 首先,新建Login.html页面: <!DOCTYPE html PUBLIC &quo ...

随机推荐

  1. python高性能编程方法一

    python高性能编程方法一   阅读 Zen of Python,在Python解析器中输入 import this. 一个犀利的Python新手可能会注意到"解析"一词, 认为 ...

  2. C语言学习系列(二)面向过程和面向对象

    一.基本定义 (一).面向过程(procedure oriented programming POP) 面向过程是分析解决问题的步骤,然后用函数把这些步骤一步一步的实现,然后在使用的时候一一调用则可. ...

  3. 9、Spring Boot 2.x 集成 Thymeleaf

    1.9 Spring Boot 2.x 集成 Thymeleaf 完整源码: Spring-Boot-Demos 1.9.1 在pom中引入依赖 <dependency> <grou ...

  4. [Codevs] 矩形面积求并

    http://codevs.cn/problem/3044/ 线段树扫描线矩形面积求并 基本思路就是将每个矩形的长(平行于x轴的边)投影到线段树上 下边+1,上边-1: 然后根据线段树的权值和与相邻两 ...

  5. The 10th Shandong Provincial Collegiate Programming Contest

    目录 Contest Info Solutions A. Calandar B. Flipping Game C. Wandering Robot D. Game on a Graph E. BaoB ...

  6. WPF中,Grid与Table的区别(英文)-转载

    原文地址:http://blog.csdn.net/johnsuna/article/details/1742799 How is Grid Different from Table?Table an ...

  7. 基于nodejs将mongodb的数据实时同步到elasticsearch

    一.前言 因公司需要选用elasticsearch做全文检索,持久化存储选用的是mongodb,但是希望mongodb里面的数据发生改变可以实时同步到elasticsearch上,一开始主要使用ela ...

  8. PyTricks-Differebt ways to test multiple flags at once in

    x, y, z = 0, 1, 0 if x == 1 or y == 1 or z == 1: print('passed') if 1 in (x, y, z): print('passed') ...

  9. 分享一个自己做的SpringMVC的PPT,由于比较忙只写了一些重要的部分

  10. mysql索引分类

    mysql索引分类 一.总结 一句话总结: 主键索引:设定为主键后数据库会自动建立索引,innodb为聚簇索引 单值索引:一个索引只包含单个列,一个表可以有多个单列索引:CREATE INDEX id ...