《编程之美》“程序改错”一文之我见

      原文的大意是这样的,要求写一个二分查找算法,并且当要查找的数出现不止一次时,返回最后那个数的下标。然后给你一段有错的代码,请你改。

    这段有错的代码是这样的(我作了简化):

        文中指出了代码中的错误,一是第7行(l+u)可能溢出,二是当程序运行到l=u-1时,计算出的m就与l相等,如果这时不幸地第8行的条件成立,那么就会进入死循环,因为这次迭代没有改变l和u的值,无论再迭代多少遍也不会了。

        这两点分析都很正确,但接下来作者给出的修改版本,不仅完全不是在上面代码的基础上改,而且给出的代码逻辑复杂、混乱,缺乏一致性。

        下面我将分析上面这段有错代码,给出自己的修改,然后再分析作者给出的版本。

        上面代码的思想是清晰的,维护一个循环不变式:如果要找的数存在的话,它下标一定在区间[ l , u ]中,然后通过迭代,不断缩小区间,直到退化成一个点,最后检测这个点是不是目标值。循环体中对不变式的维护都没有错。问题就是怎样避免第8行的把m直接赋给l。题目要求返回最后一个满足的数,所以在循环体中,当检测到相等时,一不能立刻就返回,二不能缩减区间的后半段。要维护这样一个不变式,这个赋值在所难免。我能想到的唯一的办法就是,当l=u-1时,就退出循环,然后先后检查此时的a[u]和a[l]。

        所以我的修改是这样的:

        接下来,我要分析一下作者的修改,他的代码大意是这样的,注释我没改动:

 

        我们先无视注释,我完全搞不懂注释,文中也不解释清楚。从循环体的if-else语句判断,他要维护的不变式是考察区间[l, u),注意是“左闭右开”,要找的数下标一定在这个区间内,如果存在的话。而看他对区间端点的赋初值,u=e,把a[e]给排除在外了。那要找的数就是a[e]怎么办呢?他有这条语句把关呢,if (a[u] == v) return u;后面还十分堂皇地加了注释。其实如果初值正确的话,只需要检测a[l]即可,因为a[u]这个值根本不在我们要考察的区间里。

        所以我对作者的版本的改法是:

 

        我记得《编程珠玑》上对这类问题有过讨论的。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值