LeetCode-二分查找面试题目总结

原创 2017年01月03日 00:18:33

今天这篇随笔主要是解决前几天在朋友圈分享的《从一道面试题谈谈一线码农应该具备的基本素质》里面的题目,作为一个三线码农,从思考到最后写成,Debug完毕大概用了一个小时。可见自己对基础算法的掌握程度还不够熟练,内功比较薄弱。
题目如下:
实现一个函数, 完成 开根号 的操作, 方法签名如下.
double sqrt(int v, double t)
要求:
1. 不能调用系统库函数, 诸如 Math.sqrt(v) 之类的;
2. 假设计算出的结果为 r, 要求满足如下条件, , 其中 是真实的值, t 为给定的一个误差范围, 例如0.1等, 即你计算出的值要在给定的误差范围内. (哭, 公众号文章里不支持 mathjax)
3. 实现语言不限, 你条件可以比上述更加苛刻, 但不能宽松, 举例而言, 我调用你的接口 sqrt(9, 0.21) 返回值属于 [2.79, 3.21]这个区间的任意一个都满足条件.看到这里, 其实你可以 拿出笔和纸, 尝试解答一下, 强调一下, 一定要注意给定的误差条件, 欢迎沟通交流. 其实这个题目是就是 leetcode 上原题稍加变化得到.
既然不能调用系统库函数,那么给的误差就是最终解决问题的一个关键点。并且最重要的是要摒弃那些你“已经”知道的常识,比如说100开根号就是10,9开根号就是3之类的。因为我们不能调用sqrt,只能尽可能的夹逼到满足误差的情况。
误差的计算公式在题目要求中已经说明,这里我们由于无法提前知道dInput的平方根,所以题目中的结束条件我们用另外一个公式,也就是在下面提到的有可能错误的结束条件 ,毕竟比较好实现。这个结束条件是否正确和t的取值有关,如果t大于1,那么正确,因为t比t的平方要小,反之,不正确。一般情况下,我们输入的误差要求都会是小于1的,那么要将不等式的右边精度进一步提升,因为小数平方后更小,精度更高,设为t的平方。这样一来,不管是什么情况,新的判断条件的精准程度要高于原设精准程度。
至于高多少?一个数量级是没问题的。具体证明略。
现在开始写二分前的第一次first和last的取值。这里采用二分之一的dInput的平方和原值做比较,根据大小决定first和last定位区间。代码如下:

double dFirst = 0;
double dLast = 0;
double dBuf = 0;
double dCompDelt = dDelta * dDelta; //存储当前误差
//首先,判断二分的第一次界限
dBuf = (dInput/2)*(dInput/2);
if (dBuf > dInput)
{
dFirst = 0;
dLast = dInput/2;
}
if (dBuf < dInput)
{
dFirst = dInput/2;
dLast = dInput;
}
//下面这个写法只是为了去掉warning:不是所有的路径都有返回值
if (dBuf == dInput)
{
goto END_PROCESS_FINAL_ANSWER;
}

在第一次写这个部分时,相等的情况直接写了return,但是会发现编译器报警,warning:函数不是所有路径都有返回值。因为函数最外层大括号没有return语句,所以使用了goto语句,把这种情况消除。这也是体现了函数只能有唯一出口的原则。Warning和error并没有什么区别,都是要消除的对象。但这里需要强调的是,VS2008中,调用scanf基本输入函数会报警说这个函数不安全,建议使用scanf_s。如果只是在Windows平台下,可以改,因为scanf_s函数微软自己做的一个安全的输入函数,要求用户显示表明输入数据的长度,防止越界。但是在Linux平台下,没有这个函数。
好,开始最难的地方,通过不停地判断中间值是否符合判断条件,进而对边界值进行修改,这也是这个题目的难点和重点。我在这里就犯傻了,不知道脑子在想什么,把+写成了-,中间值一直算错了……大概是今晚刷盘子刷疯了。

//而后开始二分查找
for (;dFirst!=dLast;)
{
dBuf = ((dLast + dFirst)/2 )* ((dLast + dFirst)/2);
//二分查找关键在于新的左右边界的确定,一定是加号,加号!!
if (dBuf>dInput)
{
if ((dBuf-dInput) > dCompDelt)
{
dLast = (dLast + dFirst)/2;
}
else
{
return (dLast + dFirst)/2;
}
}

    if (dBuf<dInput)
    {
        if ((dInput-dBuf) > dCompDelt)
        {
            dFirst = (dLast + dFirst)/2;
        }
        else
        {
            return (dLast + dFirst)/2;
        }
}

}

其实有心的同志读到这里会发现我的判断写的有点冗长了,尤其是for循环的结束条件,基本没什么用。所以更加精简的写法如下:

//而后开始二分查找
for (;((dBuf-dInput) > dCompDelt)||((dInput-dBuf) > dCompDelt);)
{
dBuf = ((dLast + dFirst)/2 )* ((dLast + dFirst)/2);
//二分查找关键在于新的左右边界的确定,一定是加号,加号!!
if (dBuf>dInput)
{
dLast = (dLast + dFirst)/2;
}

    if (dBuf<dInput)
    {
        dFirst = (dLast + dFirst)/2;
    }

}
return (dLast + dFirst)/2;

这里的判断要是能够调用math.h,直接用fabs()函数即可。所以,代码写完了有机会一定要CodingReview,能够发现很多自己当初没有看到的问题和改进的方法。这往往就是提升性能和写出优美代码的前进之路。
P.S double型变量,双精度浮点型变量对应的格式化输入输出为%lf,这些小知识点自己已经有点忘记了。

版权声明:本文为博主原创文章,未经博主允许不得转载。

[经典面试题]二分查找问题汇总

【题目】 给定一个有序(非降序)数组A,可含有重复元素,求最小的i使得A[i]等于target,不存在则返回-1。 【分析】 此题也就是求target在数组中第一次出现的位置。这里可能会有人想先直接...
  • SunnyYoona
  • SunnyYoona
  • 2015年01月05日 12:16
  • 3279

面试题目-堆排、快排、二分查找

排序面试题目 近期在忙着找工作,由于专业跨度的原因,稍微有些焦头烂额,在方向上有些失衡。有种很奇怪的感觉,我不知道换联网公司到底需要什么样的人才,(/ □ \),好了,吐槽结束了,该继续得还得继续...
  • visionarywind
  • visionarywind
  • 2016年01月09日 15:19
  • 388

二分查找各种情况大总结

二分查找多次刷题时遇到,虽然每次也能写对,但花了蛮多时间,没好好想过。而且网上的太多版本,并不是很简洁,而且边界条件变化情况太多,容易混淆,下面是自己对二分查找的一些思考和总结,尽量写得简单易懂。 ...
  • yefengzhichen
  • yefengzhichen
  • 2016年08月30日 21:40
  • 11743

LintCode二分查找题总结

LC上二分查找那一章有这么些题: 二分查找的题经常用于考,因为它虽然看似简单,但其实要完全正确却不容易,很容易写出死循环的程序。一个二分查找的程序可以很容易判断出一个人功底扎不扎实。 45...
  • luoshengkim
  • luoshengkim
  • 2016年08月03日 15:53
  • 2057

ACM 二分答案 二分查找 hdu4071

二分最短距离 /* * Author: nick wong * Created Time: 2014年08月23日 星期六 13时34分11秒 * File Name: a.cpp */...
  • nickwong_
  • nickwong_
  • 2014年08月23日 18:25
  • 883

二分查找(Binary Search) 常见问题解决方法总结

缘由 今天浏览 何登成的技术博客  无意中发现了写的blog,二分查找(Binary Search)需要注意的问题,以及在数据库内核中的实现。 如下: 问题背景 今年的实习生招聘考试,我出了一道...
  • gfsfg8545
  • gfsfg8545
  • 2013年12月13日 21:48
  • 8574

leetcode题目 二分查找升级版

题目: Given a sorted array of integers, find the starting and ending position of a given target value....
  • cainiaoxiaomin
  • cainiaoxiaomin
  • 2015年10月05日 22:30
  • 289

二分查找法的实例分析

二分查找:折半查找,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如                     果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,...
  • clown05
  • clown05
  • 2016年05月30日 00:56
  • 1820

PTA数据结构与算法题目集(中文)4-10 二分查找 (20分)

本题要求实现二分查找算法。 函数接口定义: Position BinarySearch( List Tbl, ElementType K ); 其中List结构定义如下: typed...
  • cuideman
  • cuideman
  • 2016年12月10日 22:31
  • 1147

HDU——1303Doubles(水题,试手二分查找)

Doubles Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Su...
  • a88770202
  • a88770202
  • 2016年02月13日 21:45
  • 248
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:LeetCode-二分查找面试题目总结
举报原因:
原因补充:

(最多只允许输入30个字)